2326 lines
88 KiB
Go
2326 lines
88 KiB
Go
|
package gui
|
||
|
|
||
|
// desiresGui_Physical.go implements pages to manage a user's Physical mate desires
|
||
|
|
||
|
import "fyne.io/fyne/v2"
|
||
|
import "fyne.io/fyne/v2/canvas"
|
||
|
import "fyne.io/fyne/v2/container"
|
||
|
import "fyne.io/fyne/v2/dialog"
|
||
|
import "fyne.io/fyne/v2/layout"
|
||
|
import "fyne.io/fyne/v2/theme"
|
||
|
import "fyne.io/fyne/v2/widget"
|
||
|
|
||
|
import "seekia/internal/allowedText"
|
||
|
import "seekia/internal/desires/mateDesires"
|
||
|
import "seekia/internal/desires/myLocalDesires"
|
||
|
import "seekia/internal/encoding"
|
||
|
import "seekia/internal/genetics/companyAnalysis"
|
||
|
import "seekia/internal/globalSettings"
|
||
|
import "seekia/internal/helpers"
|
||
|
import "seekia/internal/profiles/myLocalProfiles"
|
||
|
|
||
|
import "strings"
|
||
|
import "errors"
|
||
|
import "slices"
|
||
|
|
||
|
|
||
|
func setChooseDesiresCategoryPage_Physical(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresCategoryPage_Physical(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
sexButton := widget.NewButton(translate("Sex"), func(){
|
||
|
setChooseDesiresPage_Sex(window, currentPage)
|
||
|
})
|
||
|
|
||
|
ageButton := widget.NewButton(translate("Age"), func(){
|
||
|
setChooseDesiresPage_Age(window, currentPage)
|
||
|
})
|
||
|
|
||
|
ancestryCompositionButton := widget.NewButton("Ancestry Composition", func(){
|
||
|
setChooseDesiresPage_23andMe_AncestryComposition(window, "User", currentPage)
|
||
|
})
|
||
|
|
||
|
neanderthalVariantsButton := widget.NewButton("Neanderthal Variants", func(){
|
||
|
setChooseDesiresPage_23andMe_NeanderthalVariants(window, currentPage)
|
||
|
})
|
||
|
|
||
|
maternalHaplogroupButton := widget.NewButton("Maternal Haplogroup", func(){
|
||
|
setChooseDesiresPage_23andMe_Haplogroup(window, "Maternal", currentPage)
|
||
|
})
|
||
|
|
||
|
paternalHaplogroupButton := widget.NewButton("Paternal Haplogroup", func(){
|
||
|
setChooseDesiresPage_23andMe_Haplogroup(window, "Paternal", currentPage)
|
||
|
})
|
||
|
|
||
|
monogenicDiseasesButton := widget.NewButton("Monogenic Diseases", func(){
|
||
|
setChooseDesiresPage_MonogenicDiseases(window, currentPage)
|
||
|
})
|
||
|
|
||
|
polygenicDiseasesButton := widget.NewButton("Polygenic Diseases", func(){
|
||
|
//TODO: Filter based on minimum variants tested
|
||
|
// Users will be able to sort matches based on lowest overall disease risk
|
||
|
showUnderConstructionDialog(window)
|
||
|
})
|
||
|
geneticTraitsButton := widget.NewButton("Genetic Traits", func(){
|
||
|
//TODO: Filter based on number of variants tested
|
||
|
// Users will be able to sort matches based on highest probability of blue eyes, brown eyes, straight hair, curly hair, etc..
|
||
|
// Also, users should be able to filter based on outcome points for each trait outcome
|
||
|
showUnderConstructionDialog(window)
|
||
|
})
|
||
|
|
||
|
heightButton := widget.NewButton(translate("Height"), func(){
|
||
|
setChooseDesiresPage_Height(window, currentPage)
|
||
|
})
|
||
|
|
||
|
bodyFatButton := widget.NewButton(translate("Body Fat"), func(){
|
||
|
setChooseDesiresPage_BodyFat(window, currentPage)
|
||
|
})
|
||
|
bodyMuscleButton := widget.NewButton(translate("Body Muscle"), func(){
|
||
|
setChooseDesiresPage_BodyMuscle(window, currentPage)
|
||
|
})
|
||
|
|
||
|
eyeColorButton := widget.NewButton(translate("Eye Color"), func(){
|
||
|
setChooseDesiresPage_EyeColor(window, currentPage)
|
||
|
})
|
||
|
|
||
|
hairColorButton := widget.NewButton(translate("Hair Color"), func(){
|
||
|
setChooseDesiresPage_HairColor(window, currentPage)
|
||
|
})
|
||
|
|
||
|
hairTextureButton := widget.NewButton(translate("Hair Texture"), func(){
|
||
|
setChooseDesiresPage_HairTexture(window, currentPage)
|
||
|
})
|
||
|
|
||
|
skinColorButton := widget.NewButton(translate("Skin Color"), func(){
|
||
|
setChooseDesiresPage_SkinColor(window, currentPage)
|
||
|
})
|
||
|
|
||
|
infectionsButton := widget.NewButton(translate("Infections"), func(){
|
||
|
setChooseDesiresPage_Infections(window, currentPage)
|
||
|
})
|
||
|
|
||
|
buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, sexButton, ageButton, ancestryCompositionButton, neanderthalVariantsButton, maternalHaplogroupButton, paternalHaplogroupButton, monogenicDiseasesButton, polygenicDiseasesButton, geneticTraitsButton, heightButton, bodyFatButton, bodyMuscleButton, eyeColorButton, hairColorButton, hairTextureButton, skinColorButton, infectionsButton))
|
||
|
|
||
|
buttonsGridPadded := container.NewPadded(buttonsGrid)
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), buttonsGridPadded)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_Sex(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Sex(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(translate("Sex"))
|
||
|
|
||
|
descriptionText := widget.NewLabel("Choose the sex(es) that you desire.")
|
||
|
|
||
|
sexHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setSexExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
descriptionRow := container.NewHBox(layout.NewSpacer(), descriptionText, sexHelpButton, layout.NewSpacer())
|
||
|
|
||
|
optionTitlesList := []string{translate("Male"), translate("Female"), translate("Intersex Male"), translate("Intersex Female"), translate("Intersex")}
|
||
|
|
||
|
optionNamesMap := make(map[string][]string)
|
||
|
|
||
|
optionNamesMap[translate("Male")] = []string{"Male"}
|
||
|
optionNamesMap[translate("Female")] = []string{"Female"}
|
||
|
optionNamesMap[translate("Intersex Male")] = []string{"Intersex Male"}
|
||
|
optionNamesMap[translate("Intersex Female")] = []string{"Intersex Female"}
|
||
|
optionNamesMap[translate("Intersex")] = []string{"Intersex"}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "Sex", optionTitlesList, optionNamesMap, false, true, 2)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Sex", "Sex", true, "Donut", "Sex", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), descriptionRow, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_23andMe_AncestryComposition(window fyne.Window, userOrOffspring string, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_23andMe_AncestryComposition(window, userOrOffspring, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Ancestry Composition")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your ancestry composition desires.")
|
||
|
description2 := getLabelCentered("Each location is represented by a desired percentage range.")
|
||
|
|
||
|
getRestrictiveModeIsEnabledBool := func()(bool, error){
|
||
|
|
||
|
myDesireExists, restrictiveModeEnabled, err := myLocalDesires.GetDesire("23andMe_AncestryComposition_RestrictiveModeEnabled")
|
||
|
if (err != nil) { return false, err }
|
||
|
|
||
|
if (myDesireExists == true && restrictiveModeEnabled == "Yes"){
|
||
|
return true, nil
|
||
|
}
|
||
|
|
||
|
return false, nil
|
||
|
}
|
||
|
|
||
|
restrictiveModeIsEnabled, err := getRestrictiveModeIsEnabledBool()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
restrictiveModeCheck := widget.NewCheck("Restrictive Mode", func(response bool){
|
||
|
|
||
|
newValue := helpers.ConvertBoolToYesOrNoString(response)
|
||
|
|
||
|
err := myLocalDesires.SetDesire("23andMe_AncestryComposition_RestrictiveModeEnabled", newValue)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
})
|
||
|
restrictiveModeCheck.Checked = restrictiveModeIsEnabled
|
||
|
|
||
|
restrictiveModeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setAncestryCompositionDesireRestrictiveModeExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
restrictiveModeRow := container.NewHBox(layout.NewSpacer(), restrictiveModeCheck, restrictiveModeHelpButton, layout.NewSpacer())
|
||
|
|
||
|
chooseLocationDesiresButton := getWidgetCentered(widget.NewButtonWithIcon("Choose Location Desires", theme.NavigateNextIcon(), func(){
|
||
|
setChooseDesiresPage_23andMe_ViewAncestryComposition(window, restrictiveModeIsEnabled, "User", currentPage)
|
||
|
}))
|
||
|
|
||
|
getDesireName := func()string{
|
||
|
if (restrictiveModeIsEnabled == false){
|
||
|
return "23andMe_AncestryComposition"
|
||
|
}
|
||
|
return "23andMe_AncestryComposition_Restrictive"
|
||
|
}
|
||
|
|
||
|
desireName := getDesireName()
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, desireName, true)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getDesireTitle := func()string{
|
||
|
|
||
|
if (restrictiveModeIsEnabled == false){
|
||
|
return "23andMe Ancestry Composition"
|
||
|
}
|
||
|
return "23andMe Ancestry Composition (Restrictive)"
|
||
|
}
|
||
|
|
||
|
desireTitle := getDesireTitle()
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, desireTitle, desireName, false, "", "", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), restrictiveModeRow, widget.NewSeparator(), chooseLocationDesiresButton, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_23andMe_ViewAncestryComposition(window fyne.Window, restrictiveModeIsEnabled bool, userOrOffspring string, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_23andMe_ViewAncestryComposition(window, restrictiveModeIsEnabled, userOrOffspring, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
getSubtitleText := func()string{
|
||
|
if (restrictiveModeIsEnabled == false){
|
||
|
return "23andMe - Ancestry Composition"
|
||
|
}
|
||
|
return "23andMe - Ancestry Composition (Restrictive)"
|
||
|
}
|
||
|
|
||
|
subtitleText := getSubtitleText()
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(subtitleText)
|
||
|
|
||
|
description1 := getLabelCentered("You can toggle between viewing your user or offspring desires.")
|
||
|
description2Label := widget.NewLabel("Your offspring desires are calculated using your profile ancestry composition.")
|
||
|
|
||
|
offspringAncestryCompositionHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setOffspringAncestryCompositionExplainerPage(window, currentPage)
|
||
|
})
|
||
|
description2Row := container.NewHBox(layout.NewSpacer(), description2Label, offspringAncestryCompositionHelpButton, layout.NewSpacer())
|
||
|
|
||
|
userOrOffspringList := []string{"User", "Offspring"}
|
||
|
userOrOffspringSelector := widget.NewSelect(userOrOffspringList, func(newUserOrOffspring string){
|
||
|
setChooseDesiresPage_23andMe_ViewAncestryComposition(window, restrictiveModeIsEnabled, newUserOrOffspring, previousPage)
|
||
|
})
|
||
|
userOrOffspringSelector.Selected = userOrOffspring
|
||
|
|
||
|
userOrOffspringSelectorCentered := getWidgetCentered(userOrOffspringSelector)
|
||
|
|
||
|
getDesireName := func()string{
|
||
|
if (restrictiveModeIsEnabled == false){
|
||
|
return "23andMe_AncestryComposition"
|
||
|
}
|
||
|
return "23andMe_AncestryComposition_Restrictive"
|
||
|
}
|
||
|
|
||
|
desireName := getDesireName()
|
||
|
|
||
|
modifyDesiresButton := getWidgetCentered(widget.NewButtonWithIcon("Modify Desires", theme.DocumentCreateIcon(), func(){
|
||
|
setChooseDesiresPage_23andMe_EditAncestryComposition(window, restrictiveModeIsEnabled, false, "", false, "", false, "", currentPage)
|
||
|
}))
|
||
|
|
||
|
myDesireExists, myDesiredAncestryComposition, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
if (myDesireExists == false){
|
||
|
|
||
|
noLocationsAddedLabel := getBoldLabelCentered("No locations added.")
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2Row, widget.NewSeparator(), userOrOffspringSelectorCentered, widget.NewSeparator(), noLocationsAddedLabel, modifyDesiresButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//Outputs:
|
||
|
// -bool: My ancestry composition exists
|
||
|
// -map[string]float64: My continent percentages map
|
||
|
// -map[string]float64: My region percentages map
|
||
|
// -map[string]float64: My subregion percentages map
|
||
|
// -error
|
||
|
getMyAncestryCompositionMaps := func()(bool, map[string]float64, map[string]float64, map[string]float64, error){
|
||
|
|
||
|
myAncestryCompositionExists, myCurrentAncestryComposition, err := myLocalProfiles.GetProfileData("Mate", "23andMe_AncestryComposition")
|
||
|
if (err != nil){ return false, nil, nil, nil, err }
|
||
|
if (myAncestryCompositionExists == false){
|
||
|
return false, nil, nil, nil, nil
|
||
|
}
|
||
|
|
||
|
attributeIsValid, myContinentPercentagesMap, myRegionPercentagesMap, mySubregionPercentagesMap, err := companyAnalysis.ReadAncestryCompositionAttribute_23andMe(true, myCurrentAncestryComposition)
|
||
|
if (err != nil) { return false, nil, nil, nil, err }
|
||
|
if (attributeIsValid == false){
|
||
|
return false, nil, nil, nil, errors.New("MyLocalProfiles contains invalid 23andMe ancestry composition attribute: " + myCurrentAncestryComposition)
|
||
|
}
|
||
|
|
||
|
mapsAreValid, myFilledContinentPercentagesMap, myFilledRegionPercentagesMap, myFilledSubregionPercentagesMap, err := companyAnalysis.AddMissingParentsToAncestryCompositionMaps_23andMe(myContinentPercentagesMap, myRegionPercentagesMap, mySubregionPercentagesMap)
|
||
|
if (err != nil){ return false, nil, nil, nil, err }
|
||
|
if (mapsAreValid == false){
|
||
|
return false, nil, nil, nil, errors.New("ReadAncestryCompositionAttribute_23andMe not verifying maps.")
|
||
|
}
|
||
|
|
||
|
return true, myFilledContinentPercentagesMap, myFilledRegionPercentagesMap, myFilledSubregionPercentagesMap, nil
|
||
|
}
|
||
|
|
||
|
myAncestryCompositionExists, myContinentPercentagesMap, myRegionPercentagesMap, mySubregionPercentagesMap, err := getMyAncestryCompositionMaps()
|
||
|
if (err != nil) {
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (userOrOffspring == "Offspring" && myAncestryCompositionExists == false){
|
||
|
|
||
|
description3 := getBoldLabelCentered("Your ancestry composition does not exist.")
|
||
|
description4 := getLabelCentered("To view your offspring desires, you must add your ancestry composition.")
|
||
|
description5 := getLabelCentered("Add it on the Build Profile - Physical - Race - 23andMe - Ancestry Composition page.")
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2Row, widget.NewSeparator(), modifyDesiresButton, widget.NewSeparator(), userOrOffspringSelectorCentered, widget.NewSeparator(), description3, description4, description5)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//Outputs:
|
||
|
// -map[string][]string: Location description -> List of sub-locations descriptions
|
||
|
// -error
|
||
|
getDesiredLocationTreeMap := func()(map[string][]string, error){
|
||
|
|
||
|
myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap, err := mateDesires.ReadAncestryCompositionDesire_23andMe(myDesiredAncestryComposition)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("MyLocalDesires contains invalid ancestry composition desire: " + err.Error())
|
||
|
}
|
||
|
|
||
|
// This function will convert the range to an offspring range (if userOrOffspring == "Offspring")
|
||
|
getLocationDescription := func(locationType string, locationName string, userMinimumDesiredBound float64, userMaximumDesiredBound float64)(string, error){
|
||
|
|
||
|
if (locationType != "Continent" && locationType != "Region" && locationType != "Subregion"){
|
||
|
return "", errors.New("getLocationDescription called with invalid locationType: " + locationType)
|
||
|
}
|
||
|
|
||
|
getMinimumAndMaximumBounds := func()(float64, float64){
|
||
|
|
||
|
if (userOrOffspring == "User"){
|
||
|
return userMinimumDesiredBound, userMaximumDesiredBound
|
||
|
}
|
||
|
|
||
|
// We calculate offspring range
|
||
|
|
||
|
getMyLocationPercentage := func()float64{
|
||
|
|
||
|
if (locationType == "Continent"){
|
||
|
myPercentage, exists := myContinentPercentagesMap[locationName]
|
||
|
if (exists == false){
|
||
|
return 0
|
||
|
}
|
||
|
return myPercentage
|
||
|
}
|
||
|
if (locationType == "Region"){
|
||
|
myPercentage, exists := myRegionPercentagesMap[locationName]
|
||
|
if (exists == false){
|
||
|
return 0
|
||
|
}
|
||
|
return myPercentage
|
||
|
}
|
||
|
// locationType == "Subregion
|
||
|
myPercentage, exists := mySubregionPercentagesMap[locationName]
|
||
|
if (exists == false){
|
||
|
return 0
|
||
|
}
|
||
|
return myPercentage
|
||
|
}
|
||
|
|
||
|
myLocationPercentage := getMyLocationPercentage()
|
||
|
|
||
|
offspringMinimumBound := (userMinimumDesiredBound + myLocationPercentage)/2
|
||
|
offspringMaximumBound := (userMaximumDesiredBound + myLocationPercentage)/2
|
||
|
|
||
|
return offspringMinimumBound, offspringMaximumBound
|
||
|
}
|
||
|
|
||
|
minimumDesiredBound, maximumDesiredBound := getMinimumAndMaximumBounds()
|
||
|
|
||
|
minimumDesiredBoundString := helpers.ConvertFloat64ToStringRounded(minimumDesiredBound, 1)
|
||
|
maximumDesiredBoundString := helpers.ConvertFloat64ToStringRounded(maximumDesiredBound, 1)
|
||
|
|
||
|
if (minimumDesiredBoundString == maximumDesiredBoundString){
|
||
|
locationDescription := locationName + ": " + minimumDesiredBoundString + "%"
|
||
|
return locationDescription, nil
|
||
|
}
|
||
|
|
||
|
locationDescription := locationName + ": " + minimumDesiredBoundString + "-" + maximumDesiredBoundString + "%"
|
||
|
|
||
|
return locationDescription, nil
|
||
|
}
|
||
|
|
||
|
// We now build the tree map
|
||
|
// This is used to display a fyne tree widget
|
||
|
// Each item is mapped to a list of child items
|
||
|
// The "" item represents the root of the tree
|
||
|
|
||
|
treeMap := make(map[string][]string)
|
||
|
|
||
|
// This list will store the desired continent descriptions
|
||
|
desiredContinentsList := make([]string, 0)
|
||
|
|
||
|
allContinentsList := companyAnalysis.GetAncestryContinentsList_23andMe()
|
||
|
|
||
|
for _, continentName := range allContinentsList{
|
||
|
|
||
|
continentRegionsList, err := companyAnalysis.GetAncestryContinentRegionsList_23andMe(continentName)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("GetAncestryContinentRegionsList_23andMe missing continent regions: " + continentName)
|
||
|
}
|
||
|
|
||
|
if (len(continentRegionsList) == 0){
|
||
|
// Continent has no sublocations
|
||
|
// We see if we desire it
|
||
|
minimumDesiredRange, exists := myContinentMinimumBoundsMap[continentName]
|
||
|
if (exists == false){
|
||
|
// We do not desire this continent
|
||
|
continue
|
||
|
}
|
||
|
maximumDesiredRange, exists := myContinentMaximumBoundsMap[continentName]
|
||
|
if (exists == false){
|
||
|
return nil, errors.New("myContinentMinimumBoundsMap contains continent, myContinentMaximumBoundsMap does not.")
|
||
|
}
|
||
|
|
||
|
continentDescription, err := getLocationDescription("Continent", continentName, minimumDesiredRange, maximumDesiredRange)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desiredContinentsList = append(desiredContinentsList, continentDescription)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// These represent the minimum and maximum desired ranges for this continent
|
||
|
// For example, if the user desires Japanese between 0-50%, and Korean between 50-100%, we say they desire East Asian from 0-100%
|
||
|
|
||
|
// This list will store the desired region descriptions for this continent
|
||
|
desiredContinentRegionsList := make([]string, 0)
|
||
|
|
||
|
continentMinimumDesiredBound := float64(100)
|
||
|
continentMaximumDesiredBound := float64(0)
|
||
|
|
||
|
for _, regionName := range continentRegionsList{
|
||
|
|
||
|
regionSubregionsList, err := companyAnalysis.GetAncestryRegionSubregionsList_23andMe(continentName, regionName)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("GetAncestryRegionSubregionsList_23andMe missing region subregions: " + regionName)
|
||
|
}
|
||
|
|
||
|
if (len(regionSubregionsList) == 0){
|
||
|
|
||
|
// This region has no sublocations
|
||
|
// Check if we desire it
|
||
|
|
||
|
regionMinimumDesiredBound, exists := myRegionMinimumBoundsMap[regionName]
|
||
|
if (exists == false){
|
||
|
// We do not desire this region
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
regionMaximumDesiredBound, exists := myRegionMaximumBoundsMap[regionName]
|
||
|
if (exists == false){
|
||
|
return nil, errors.New("myRegionMinimumBoundsMap contains region name, myRegionMaximumBoundsMap does not.")
|
||
|
}
|
||
|
|
||
|
if (regionMinimumDesiredBound < continentMinimumDesiredBound){
|
||
|
continentMinimumDesiredBound = regionMinimumDesiredBound
|
||
|
}
|
||
|
|
||
|
if (regionMaximumDesiredBound > continentMaximumDesiredBound){
|
||
|
continentMaximumDesiredBound = regionMaximumDesiredBound
|
||
|
}
|
||
|
|
||
|
regionDescription, err := getLocationDescription("Region", regionName, regionMinimumDesiredBound, regionMaximumDesiredBound)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desiredContinentRegionsList = append(desiredContinentRegionsList, regionDescription)
|
||
|
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// This list will store the descriptions for our desired subregions of this region
|
||
|
desiredRegionSubregionsList := make([]string, 0)
|
||
|
|
||
|
regionMinimumDesiredBound := float64(100)
|
||
|
regionMaximumDesiredBound := float64(0)
|
||
|
|
||
|
for _, subregionName := range regionSubregionsList{
|
||
|
|
||
|
// All subregions have no sublocations
|
||
|
// We see if we desire this subregion
|
||
|
|
||
|
subregionMinimumDesiredBound, exists := mySubregionMinimumBoundsMap[subregionName]
|
||
|
if (exists == false){
|
||
|
// We do not desire this subregion
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
subregionMaximumDesiredBound, exists := mySubregionMaximumBoundsMap[subregionName]
|
||
|
if (exists == false){
|
||
|
return nil, errors.New("subregionMinimumBoundsMap contains subregion name, subregionMaximumBoundsMap does not.")
|
||
|
}
|
||
|
|
||
|
if (subregionMinimumDesiredBound < continentMinimumDesiredBound){
|
||
|
continentMinimumDesiredBound = subregionMinimumDesiredBound
|
||
|
}
|
||
|
|
||
|
if (subregionMaximumDesiredBound > continentMaximumDesiredBound){
|
||
|
continentMaximumDesiredBound = subregionMaximumDesiredBound
|
||
|
}
|
||
|
|
||
|
if (subregionMinimumDesiredBound < regionMinimumDesiredBound){
|
||
|
regionMinimumDesiredBound = subregionMinimumDesiredBound
|
||
|
}
|
||
|
|
||
|
if (subregionMaximumDesiredBound > regionMaximumDesiredBound){
|
||
|
regionMaximumDesiredBound = subregionMaximumDesiredBound
|
||
|
}
|
||
|
|
||
|
subregionDescription, err := getLocationDescription("Subregion", subregionName, subregionMinimumDesiredBound, subregionMaximumDesiredBound)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desiredRegionSubregionsList = append(desiredRegionSubregionsList, subregionDescription)
|
||
|
}
|
||
|
|
||
|
if (len(desiredRegionSubregionsList) != 0){
|
||
|
|
||
|
regionDescription, err := getLocationDescription("Region", regionName, regionMinimumDesiredBound, regionMaximumDesiredBound)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desiredContinentRegionsList = append(desiredContinentRegionsList, regionDescription)
|
||
|
treeMap[regionDescription] = desiredRegionSubregionsList
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (len(desiredContinentRegionsList) != 0){
|
||
|
|
||
|
continentDescription, err := getLocationDescription("Continent", continentName, continentMinimumDesiredBound, continentMaximumDesiredBound)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desiredContinentsList = append(desiredContinentsList, continentDescription)
|
||
|
treeMap[continentDescription] = desiredContinentRegionsList
|
||
|
}
|
||
|
}
|
||
|
|
||
|
treeMap[""] = desiredContinentsList
|
||
|
|
||
|
return treeMap, nil
|
||
|
}
|
||
|
|
||
|
desiredLocationTreeMap, err := getDesiredLocationTreeMap()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
locationDesireWidgetTree := widget.NewTreeWithStrings(desiredLocationTreeMap)
|
||
|
locationDesireWidgetTree.OpenAllBranches()
|
||
|
|
||
|
header := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2Row, widget.NewSeparator(), modifyDesiresButton, widget.NewSeparator(), userOrOffspringSelectorCentered, widget.NewSeparator())
|
||
|
|
||
|
page := container.NewBorder(header, nil, nil, nil, locationDesireWidgetTree)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_23andMe_EditAncestryComposition(
|
||
|
window fyne.Window,
|
||
|
restrictiveModeIsEnabled bool,
|
||
|
continentProvided bool,
|
||
|
currentContinent string,
|
||
|
regionProvided bool,
|
||
|
currentRegion string,
|
||
|
subregionProvided bool,
|
||
|
currentSubregion string,
|
||
|
previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_23andMe_EditAncestryComposition(window, restrictiveModeIsEnabled, continentProvided, currentContinent, regionProvided, currentRegion, subregionProvided, currentSubregion, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - Physical")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
getSubtitleText := func()string{
|
||
|
if (restrictiveModeIsEnabled == true){
|
||
|
return "23andMe Ancestry Composition (Restrictive)"
|
||
|
}
|
||
|
|
||
|
return "23andMe Ancestry Composition"
|
||
|
}
|
||
|
|
||
|
subtitleText := getSubtitleText()
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(subtitleText)
|
||
|
|
||
|
description := getLabelCentered("Choose the percentage range for each location you desire.")
|
||
|
|
||
|
getPageContent := func()(*fyne.Container, error){
|
||
|
|
||
|
getRangeEditor := func(locationType string)(*fyne.Container, error){
|
||
|
|
||
|
if (locationType != "Continent" && locationType != "Region" && locationType != "Subregion"){
|
||
|
return nil, errors.New("getRangeEditor called with invalid locationType: " + locationType)
|
||
|
}
|
||
|
|
||
|
getDesireName := func()string{
|
||
|
if (restrictiveModeIsEnabled == false){
|
||
|
return "23andMe_AncestryComposition"
|
||
|
}
|
||
|
return "23andMe_AncestryComposition_Restrictive"
|
||
|
}
|
||
|
|
||
|
desireName := getDesireName()
|
||
|
|
||
|
//Outputs:
|
||
|
// -map[string]float64: Continent minimum bounds map
|
||
|
// -map[string]float64: Continent maximum bounds map
|
||
|
// -map[string]float64: Region minimum bounds map
|
||
|
// -map[string]float64: Region maximum bounds map
|
||
|
// -map[string]float64: Subregion minimum bounds map
|
||
|
// -map[string]float64: Subregion maximum bounds map
|
||
|
// -error
|
||
|
getMyDesiredAncestryCompositionMaps := func()(map[string]float64, map[string]float64, map[string]float64, map[string]float64, map[string]float64, map[string]float64, error){
|
||
|
|
||
|
myDesireExists, myDesiredAncestryComposition, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil){ return nil, nil, nil, nil, nil, nil, err }
|
||
|
if (myDesireExists == false){
|
||
|
emptyMap1 := make(map[string]float64)
|
||
|
emptyMap2 := make(map[string]float64)
|
||
|
emptyMap3 := make(map[string]float64)
|
||
|
emptyMap4 := make(map[string]float64)
|
||
|
emptyMap5 := make(map[string]float64)
|
||
|
emptyMap6 := make(map[string]float64)
|
||
|
return emptyMap1, emptyMap2, emptyMap3, emptyMap4, emptyMap5, emptyMap6, nil
|
||
|
}
|
||
|
|
||
|
myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap, err := mateDesires.ReadAncestryCompositionDesire_23andMe(myDesiredAncestryComposition)
|
||
|
if (err != nil){
|
||
|
return nil, nil, nil, nil, nil, nil, errors.New("MyLocalDesires contains invalid " + desireName + " desire: " + err.Error())
|
||
|
}
|
||
|
|
||
|
return myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap, nil
|
||
|
}
|
||
|
|
||
|
myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap, err := getMyDesiredAncestryCompositionMaps()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
// Outputs:
|
||
|
// -bool: Range bounds exist (any desire exists for current location)
|
||
|
// -float64: Minimum bound
|
||
|
// -float64: Maximum bound
|
||
|
// -error
|
||
|
getMyDesiredRangeBounds := func()(bool, float64, float64, error){
|
||
|
|
||
|
if (locationType == "Continent"){
|
||
|
|
||
|
continentMinimumBound, exists := myContinentMinimumBoundsMap[currentContinent]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, nil
|
||
|
}
|
||
|
|
||
|
continentMaximumBound, exists := myContinentMaximumBoundsMap[currentContinent]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, errors.New("myContinentMinimumBoundsMap contains continent, maximumBoundsMap does not: " + currentContinent)
|
||
|
}
|
||
|
|
||
|
return true, continentMinimumBound, continentMaximumBound, nil
|
||
|
}
|
||
|
if (locationType == "Region"){
|
||
|
|
||
|
regionMinimumBound, exists := myRegionMinimumBoundsMap[currentRegion]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, nil
|
||
|
}
|
||
|
|
||
|
regionMaximumBound, exists := myRegionMaximumBoundsMap[currentRegion]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, errors.New("myRegionMinimumBoundsMap contains region, maximumBoundsMap does not: " + currentRegion)
|
||
|
}
|
||
|
|
||
|
return true, regionMinimumBound, regionMaximumBound, nil
|
||
|
}
|
||
|
// locationType == "Subregion"
|
||
|
|
||
|
subregionMinimumBound, exists := mySubregionMinimumBoundsMap[currentSubregion]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, nil
|
||
|
}
|
||
|
|
||
|
subregionMaximumBound, exists := mySubregionMaximumBoundsMap[currentSubregion]
|
||
|
if (exists == false){
|
||
|
return false, 0, 0, errors.New("mySubregionMinimumBoundsMap contains subregion, maximumBoundsMap does not: " + currentSubregion)
|
||
|
}
|
||
|
|
||
|
return true, subregionMinimumBound, subregionMaximumBound, nil
|
||
|
}
|
||
|
|
||
|
myDesireExists, myMinimumBound, myMaximumBound, err := getMyDesiredRangeBounds()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
getMyDesireDisplaySection := func()(*fyne.Container, error){
|
||
|
|
||
|
myDesireTitle := getItalicLabelCentered("My Desire:")
|
||
|
|
||
|
getMyDesireText := func()string{
|
||
|
|
||
|
if (myDesireExists == false){
|
||
|
return "None"
|
||
|
}
|
||
|
myMinimumBoundString := helpers.ConvertFloat64ToStringRounded(myMinimumBound, 1)
|
||
|
myMaximumBoundString := helpers.ConvertFloat64ToStringRounded(myMaximumBound, 1)
|
||
|
|
||
|
if (myMinimumBoundString == myMaximumBoundString){
|
||
|
result := myMinimumBoundString + "%"
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
result := myMinimumBoundString + "-" + myMaximumBoundString + "%"
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
myDesireText := getMyDesireText()
|
||
|
|
||
|
myDesireLabel := getBoldLabelCentered(myDesireText)
|
||
|
|
||
|
if (myDesireExists == false){
|
||
|
|
||
|
displaySection := container.NewVBox(myDesireTitle, myDesireLabel)
|
||
|
return displaySection, nil
|
||
|
}
|
||
|
|
||
|
// We check to see if we should display offspring range
|
||
|
myAncestryCompositionExists, myCurrentAncestryComposition, err := myLocalProfiles.GetProfileData("Mate", "23andMe_AncestryComposition")
|
||
|
if (err != nil){ return nil, err }
|
||
|
if (myAncestryCompositionExists == false){
|
||
|
|
||
|
// We have not added our ancestry composition
|
||
|
// Thus, we cannot determine the offspring location composition
|
||
|
|
||
|
displaySection := container.NewVBox(myDesireTitle, myDesireLabel)
|
||
|
return displaySection, nil
|
||
|
}
|
||
|
|
||
|
// This returns the percentage of the location that we are, as described in our profile
|
||
|
getMyLocationPercentage := func()(float64, error){
|
||
|
|
||
|
attributeIsValid, myContinentPercentagesMap, myRegionPercentagesMap, mySubregionPercentagesMap, err := companyAnalysis.ReadAncestryCompositionAttribute_23andMe(true, myCurrentAncestryComposition)
|
||
|
if (err != nil) { return 0, err }
|
||
|
if (attributeIsValid == false){
|
||
|
return 0, errors.New("MyLocalProfiles contains invalid 23andMe ancestry composition attribute: " + myCurrentAncestryComposition)
|
||
|
}
|
||
|
|
||
|
if (locationType == "Continent"){
|
||
|
myPercentage, exists := myContinentPercentagesMap[currentContinent]
|
||
|
if (exists == false){
|
||
|
return 0, nil
|
||
|
}
|
||
|
return myPercentage, nil
|
||
|
}
|
||
|
if (locationType == "Region"){
|
||
|
myPercentage, exists := myRegionPercentagesMap[currentRegion]
|
||
|
if (exists == false){
|
||
|
return 0, nil
|
||
|
}
|
||
|
return myPercentage, nil
|
||
|
}
|
||
|
// LocationType == "Subregion"
|
||
|
myPercentage, exists := mySubregionPercentagesMap[currentSubregion]
|
||
|
if (exists == false){
|
||
|
return 0, nil
|
||
|
}
|
||
|
return myPercentage, nil
|
||
|
}
|
||
|
|
||
|
myLocationPercentage, err := getMyLocationPercentage()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
offspringMinimumBound := (myLocationPercentage + myMinimumBound)/2
|
||
|
offspringMaximumBound := (myLocationPercentage + myMaximumBound)/2
|
||
|
|
||
|
offspringMinimumBoundString := helpers.ConvertFloat64ToStringRounded(offspringMinimumBound, 1)
|
||
|
offspringMaximumBoundString := helpers.ConvertFloat64ToStringRounded(offspringMaximumBound, 1)
|
||
|
|
||
|
getOffspringDesiredRangeString := func()string{
|
||
|
|
||
|
if (offspringMinimumBoundString == offspringMaximumBoundString){
|
||
|
result := offspringMinimumBoundString + "%"
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
result := offspringMinimumBoundString + "-" + offspringMaximumBoundString + "%"
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
offspringDesiredRangeString := getOffspringDesiredRangeString()
|
||
|
|
||
|
offspringRangeLabel := getItalicLabelCentered("(My Offspring: ~" + offspringDesiredRangeString + ")")
|
||
|
|
||
|
displaySection := container.NewVBox(myDesireTitle, myDesireLabel, offspringRangeLabel)
|
||
|
return displaySection, nil
|
||
|
}
|
||
|
|
||
|
myDesireDisplaySection, err := getMyDesireDisplaySection()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
minimumLabel := getBoldLabelCentered("Minimum:")
|
||
|
minimumEntry := widget.NewEntry()
|
||
|
if (myDesireExists == true){
|
||
|
myMinimumBoundString := helpers.ConvertFloat64ToStringRounded(myMinimumBound, 1)
|
||
|
minimumEntry.Text = myMinimumBoundString
|
||
|
} else {
|
||
|
minimumEntry.SetPlaceHolder("Enter Minimum...")
|
||
|
}
|
||
|
minimumEntryBoxed := getWidgetBoxed(minimumEntry)
|
||
|
minimumEntryColumn := container.NewGridWithColumns(1, minimumLabel, minimumEntryBoxed)
|
||
|
|
||
|
maximumLabel := getBoldLabelCentered("Maximum:")
|
||
|
maximumEntry := widget.NewEntry()
|
||
|
if (myDesireExists == true){
|
||
|
myMaximumBoundString := helpers.ConvertFloat64ToStringRounded(myMaximumBound, 1)
|
||
|
maximumEntry.Text = myMaximumBoundString
|
||
|
} else {
|
||
|
maximumEntry.SetPlaceHolder("Enter Maximum...")
|
||
|
}
|
||
|
maximumEntryBoxed := getWidgetBoxed(maximumEntry)
|
||
|
maximumEntryColumn := container.NewGridWithColumns(1, maximumLabel, maximumEntryBoxed)
|
||
|
|
||
|
minimumMaximumEntryColumnsRow := getContainerCentered(container.NewGridWithRows(1, minimumEntryColumn, maximumEntryColumn))
|
||
|
|
||
|
submitButton := getWidgetCentered(widget.NewButtonWithIcon("Submit", theme.ConfirmIcon(), func(){
|
||
|
|
||
|
newMinimum := minimumEntry.Text
|
||
|
newMaximum := maximumEntry.Text
|
||
|
|
||
|
newMinimumBoundFloat64, err := helpers.ConvertStringToFloat64(newMinimum)
|
||
|
if (err != nil) {
|
||
|
dialogTitle := translate("Invalid Minimum Bound")
|
||
|
dialogMessageA := getLabelCentered(translate("Your minimum bound is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be a number between 0 and 100."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
newMaximumBoundFloat64, err := helpers.ConvertStringToFloat64(newMaximum)
|
||
|
if (err != nil) {
|
||
|
dialogTitle := translate("Invalid Maximum Bound")
|
||
|
dialogMessageA := getLabelCentered(translate("Your maximum bound is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be a number between 0 and 100."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
if (newMinimumBoundFloat64 < 0 || newMinimumBoundFloat64 > 100){
|
||
|
dialogTitle := translate("Invalid Minimum Bound")
|
||
|
dialogMessageA := getLabelCentered(translate("Your minimum bound is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be a number between 0 and 100."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
if (newMaximumBoundFloat64 < 0 || newMaximumBoundFloat64 > 100){
|
||
|
dialogTitle := translate("Invalid Maximum Bound")
|
||
|
dialogMessageA := getLabelCentered(translate("Your maximum bound is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be a number between 0 and 100."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (newMinimumBoundFloat64 > newMaximumBoundFloat64){
|
||
|
dialogTitle := translate("Invalid Range")
|
||
|
dialogMessageA := getLabelCentered(translate("Your range is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("The minimum must be less than the maximum."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (newMinimumBoundFloat64 == 0 && newMaximumBoundFloat64 == 100){
|
||
|
|
||
|
dialogTitle := translate("Invalid Range")
|
||
|
dialogMessageA := getLabelCentered(translate("Your range is invalid."))
|
||
|
dialogMessageB := getLabelCentered(translate("You cannot set a desired range of 0-100%."))
|
||
|
dialogMessageC := getLabelCentered(translate("All users will pass this range."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB, dialogMessageC)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (locationType == "Continent"){
|
||
|
|
||
|
myContinentMinimumBoundsMap[currentContinent] = newMinimumBoundFloat64
|
||
|
myContinentMaximumBoundsMap[currentContinent] = newMaximumBoundFloat64
|
||
|
|
||
|
} else if (locationType == "Region"){
|
||
|
|
||
|
myRegionMinimumBoundsMap[currentRegion] = newMinimumBoundFloat64
|
||
|
myRegionMaximumBoundsMap[currentRegion] = newMaximumBoundFloat64
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// locationType == "Subregion"
|
||
|
mySubregionMinimumBoundsMap[currentSubregion] = newMinimumBoundFloat64
|
||
|
mySubregionMaximumBoundsMap[currentSubregion] = newMaximumBoundFloat64
|
||
|
}
|
||
|
|
||
|
newDesireValue, err := mateDesires.CreateAncestryCompositionDesire_23andMe(myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = myLocalDesires.SetDesire(desireName, newDesireValue)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
}))
|
||
|
|
||
|
noDesireButton := getWidgetCentered(widget.NewButtonWithIcon("No Desire", theme.CancelIcon(), func(){
|
||
|
|
||
|
if (locationType == "Continent"){
|
||
|
|
||
|
delete(myContinentMinimumBoundsMap, currentContinent)
|
||
|
delete(myContinentMaximumBoundsMap, currentContinent)
|
||
|
|
||
|
} else if (locationType == "Region"){
|
||
|
|
||
|
delete(myRegionMinimumBoundsMap, currentRegion)
|
||
|
delete(myRegionMaximumBoundsMap, currentRegion)
|
||
|
} else {
|
||
|
|
||
|
// locationType == "Subregion"
|
||
|
|
||
|
delete(mySubregionMinimumBoundsMap, currentSubregion)
|
||
|
delete(mySubregionMaximumBoundsMap, currentSubregion)
|
||
|
}
|
||
|
|
||
|
if (len(myContinentMinimumBoundsMap) == 0 && len(myContinentMaximumBoundsMap) == 0 && len(myRegionMinimumBoundsMap) == 0 && len(myRegionMaximumBoundsMap) == 0 && len(mySubregionMinimumBoundsMap) == 0 && len(mySubregionMaximumBoundsMap) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireValue, err := mateDesires.CreateAncestryCompositionDesire_23andMe(myContinentMinimumBoundsMap, myContinentMaximumBoundsMap, myRegionMinimumBoundsMap, myRegionMaximumBoundsMap, mySubregionMinimumBoundsMap, mySubregionMaximumBoundsMap)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = myLocalDesires.SetDesire(desireName, newDesireValue)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
}))
|
||
|
|
||
|
rangeEditor := container.NewVBox(myDesireDisplaySection, widget.NewSeparator(), minimumMaximumEntryColumnsRow, submitButton, noDesireButton)
|
||
|
|
||
|
return rangeEditor, nil
|
||
|
}
|
||
|
|
||
|
continentLabel := getBoldLabel("Continent:")
|
||
|
|
||
|
allContinentsList := companyAnalysis.GetAncestryContinentsList_23andMe()
|
||
|
|
||
|
handleContinentSelectFunction := func(newContinent string){
|
||
|
if (continentProvided == true && newContinent == currentContinent){
|
||
|
return
|
||
|
}
|
||
|
|
||
|
setChooseDesiresPage_23andMe_EditAncestryComposition(window, restrictiveModeIsEnabled, true, newContinent, false, "", false, "", previousPage)
|
||
|
}
|
||
|
|
||
|
continentSelector := widget.NewSelect(allContinentsList, handleContinentSelectFunction)
|
||
|
if (continentProvided == true){
|
||
|
continentSelector.Selected = currentContinent
|
||
|
}
|
||
|
|
||
|
continentRow := container.NewHBox(layout.NewSpacer(), continentLabel, continentSelector, layout.NewSpacer())
|
||
|
|
||
|
if (continentProvided == false){
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow)
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
regionsList, err := companyAnalysis.GetAncestryContinentRegionsList_23andMe(currentContinent)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (len(regionsList) == 0){
|
||
|
|
||
|
rangeEditor, err := getRangeEditor("Continent")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow, widget.NewSeparator(), rangeEditor)
|
||
|
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
regionLabel := getBoldLabel("Region:")
|
||
|
|
||
|
handleRegionSelectFunction := func(newRegion string){
|
||
|
|
||
|
if (regionProvided == true && currentRegion == newRegion){
|
||
|
return
|
||
|
}
|
||
|
|
||
|
setChooseDesiresPage_23andMe_EditAncestryComposition(window, restrictiveModeIsEnabled, true, currentContinent, true, newRegion, false, "", previousPage)
|
||
|
}
|
||
|
|
||
|
regionSelector := widget.NewSelect(regionsList, handleRegionSelectFunction)
|
||
|
|
||
|
if (regionProvided == true){
|
||
|
regionSelector.Selected = currentRegion
|
||
|
}
|
||
|
|
||
|
regionRow := container.NewHBox(layout.NewSpacer(), regionLabel, regionSelector, layout.NewSpacer())
|
||
|
|
||
|
if (regionProvided == false){
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow, widget.NewSeparator(), regionRow)
|
||
|
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
subregionsList, err := companyAnalysis.GetAncestryRegionSubregionsList_23andMe(currentContinent, currentRegion)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (len(subregionsList) == 0){
|
||
|
|
||
|
rangeEditor, err := getRangeEditor("Region")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow, widget.NewSeparator(), regionRow, widget.NewSeparator(), rangeEditor)
|
||
|
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
subregionLabel := getBoldLabel("Subregion:")
|
||
|
|
||
|
handleSubregionSelectFunction := func(newSubregion string){
|
||
|
|
||
|
if (subregionProvided == true && currentSubregion == newSubregion){
|
||
|
return
|
||
|
}
|
||
|
|
||
|
setChooseDesiresPage_23andMe_EditAncestryComposition(window, restrictiveModeIsEnabled, true, currentContinent, true, currentRegion, true, newSubregion, previousPage)
|
||
|
}
|
||
|
|
||
|
subregionSelector := widget.NewSelect(subregionsList, handleSubregionSelectFunction)
|
||
|
if (subregionProvided == true){
|
||
|
subregionSelector.Selected = currentSubregion
|
||
|
}
|
||
|
|
||
|
subregionRow := container.NewHBox(layout.NewSpacer(), subregionLabel, subregionSelector, layout.NewSpacer())
|
||
|
|
||
|
if (subregionProvided == false){
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow, widget.NewSeparator(), regionRow, widget.NewSeparator(), subregionRow)
|
||
|
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
rangeEditor, err := getRangeEditor("Subregion")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
pageContent := container.NewVBox(continentRow, widget.NewSeparator(), regionRow, widget.NewSeparator(), subregionRow, widget.NewSeparator(), rangeEditor)
|
||
|
|
||
|
return pageContent, nil
|
||
|
}
|
||
|
|
||
|
pageContent, err := getPageContent()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description, widget.NewSeparator(), pageContent)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_23andMe_NeanderthalVariants(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_23andMe_NeanderthalVariants(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Neanderthal Variants")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your neanderthal variant desires.")
|
||
|
description2 := getLabelCentered("Enter the neanderthal variant count you desire in your matches.")
|
||
|
description3 := getLabelCentered("The data is provided by 23andMe.")
|
||
|
description4 := getLabelCentered("More companies will be added soon.")
|
||
|
|
||
|
myVariantCountExists, myCurrentNeanderthalVariants, err := myLocalProfiles.GetProfileData("Mate", "23andMe_NeanderthalVariants")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getOffspringVariantsCount := func(userVariantsCount float64)(float64, error){
|
||
|
|
||
|
if (myVariantCountExists == false){
|
||
|
return 0, errors.New("Trying to get offspring neanderthal variants count when my count does not exist.")
|
||
|
}
|
||
|
myVariantsCountFloat64, err := helpers.ConvertStringToFloat64(myCurrentNeanderthalVariants)
|
||
|
if (err != nil) {
|
||
|
return 0, errors.New("MyLocalProfile neanderthal variants count is invalid: " + myCurrentNeanderthalVariants)
|
||
|
}
|
||
|
|
||
|
offspringVariantsCount := (userVariantsCount + myVariantsCountFloat64)/2
|
||
|
|
||
|
return offspringVariantsCount, nil
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Numeric(window, currentPage, "23andMe_NeanderthalVariants", 0, 7462, "variants", 0, false, nil, nil, myVariantCountExists, "My Offspring", "~", getOffspringVariantsCount)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "23andMe Neanderthal Variants", "23andMe_NeanderthalVariants", true, "Bar", "23andMe_NeanderthalVariants", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_23andMe_Haplogroup(window fyne.Window, maternalOrPaternal string, previousPage func()){
|
||
|
|
||
|
if (maternalOrPaternal != "Maternal" && maternalOrPaternal != "Paternal"){
|
||
|
setErrorEncounteredPage(window, errors.New("setChooseDesiresPage_23andMe_Haplogroup called with invalid maternalOrPaternal: " + maternalOrPaternal), previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_23andMe_Haplogroup(window, maternalOrPaternal, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(maternalOrPaternal + " Haplogroup")
|
||
|
|
||
|
maternalOrPaternalLowercase := strings.ToLower(maternalOrPaternal)
|
||
|
|
||
|
description1 := getLabelCentered("Choose your " + maternalOrPaternalLowercase + " haplogroup desires.")
|
||
|
description2 := getLabelCentered("Add each " + maternalOrPaternalLowercase + " haplogroup you desire.")
|
||
|
description3 := getLabelCentered("You can choose from the known haplogroups, or enter ones that are not listed.")
|
||
|
description4 := getLabelCentered("The haplogroups are provided by 23andMe. More companies will be added soon.")
|
||
|
|
||
|
desireName := "23andMe_" + maternalOrPaternal + "Haplogroup"
|
||
|
|
||
|
getSelectedHaplogroupsSection := func()(*fyne.Container, error){
|
||
|
|
||
|
getCurrentDesiredChoicesList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList, nil
|
||
|
}
|
||
|
//currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
return currentDesiredChoicesList, nil
|
||
|
}
|
||
|
|
||
|
currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
getKnownHaplogroupsList := func()[]string{
|
||
|
|
||
|
if (maternalOrPaternal == "Maternal"){
|
||
|
maternalHaplogroupsList := companyAnalysis.GetKnownMaternalHaplogroupsList_23andMe()
|
||
|
return maternalHaplogroupsList
|
||
|
}
|
||
|
|
||
|
paternalHaplogroupsList := companyAnalysis.GetKnownPaternalHaplogroupsList_23andMe()
|
||
|
return paternalHaplogroupsList
|
||
|
}
|
||
|
|
||
|
knownHaplogroupsList := getKnownHaplogroupsList()
|
||
|
|
||
|
haplogroupEntry := widget.NewSelectEntry(knownHaplogroupsList)
|
||
|
haplogroupEntry.SetPlaceHolder("Enter haplogroup...")
|
||
|
|
||
|
addHaplogroupButton := getWidgetCentered(widget.NewButtonWithIcon("Add Haplogroup", theme.ContentAddIcon(), func(){
|
||
|
|
||
|
newHaplogroupName := haplogroupEntry.Text
|
||
|
|
||
|
if (newHaplogroupName == ""){
|
||
|
return
|
||
|
}
|
||
|
isAllowed := allowedText.VerifyStringIsAllowed(newHaplogroupName)
|
||
|
if (isAllowed == false){
|
||
|
dialogTitle := translate("Invalid Haplogroup Name")
|
||
|
dialogMessageA := getLabelCentered(translate("Your haplogroup contains an invalid character."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be encoded in UTF-8."))
|
||
|
dialogMessageC := getLabelCentered(translate("Remove this character and resubmit."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB, dialogMessageC)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
containsTabsOrNewlines := helpers.CheckIfStringContainsTabsOrNewlines(newHaplogroupName)
|
||
|
if (containsTabsOrNewlines == true){
|
||
|
dialogTitle := translate("Invalid Haplogroup Name")
|
||
|
dialogMessageA := getLabelCentered(translate("Your haplogroup contains a tab or a newline."))
|
||
|
dialogMessageB := getLabelCentered(translate("Remove the tab or newline and resubmit."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
if (len(newHaplogroupName) > 25){
|
||
|
|
||
|
currentBytesLengthString := helpers.ConvertIntToString(len(newHaplogroupName))
|
||
|
|
||
|
dialogTitle := translate("Invalid Haplogroup Name")
|
||
|
dialogMessageA := getLabelCentered(translate("Your haplogroup name is too long."))
|
||
|
dialogMessageB := getLabelCentered(translate("It cannot exceed 25 bytes."))
|
||
|
dialogMessageC := getLabelCentered(translate("Current Length:") + " " + currentBytesLengthString)
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB, dialogMessageC)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
haplogroupNameBase64 := encoding.EncodeBytesToBase64String([]byte(newHaplogroupName))
|
||
|
|
||
|
newDesireList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, haplogroupNameBase64)
|
||
|
newDesireAttributeValue := strings.Join(newDesireList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire(desireName, newDesireAttributeValue)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
}))
|
||
|
|
||
|
addHaplogroupRow := getContainerCentered(container.NewGridWithRows(1, haplogroupEntry, addHaplogroupButton))
|
||
|
|
||
|
otherSelectCheck := widget.NewCheck("Allow Other", func(selection bool){
|
||
|
|
||
|
//Outputs:
|
||
|
// -[]string: New desire attribute list (list of base64 option names)
|
||
|
getNewDesireAttributeList := func()[]string{
|
||
|
|
||
|
if (selection == false){
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
// This should not happen, because "Other" had to have been selected for it to be deselected
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList
|
||
|
}
|
||
|
|
||
|
newAttributeList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, "Other")
|
||
|
|
||
|
return newAttributeList
|
||
|
}
|
||
|
//selection == true
|
||
|
|
||
|
newAttributeList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, "Other")
|
||
|
|
||
|
return newAttributeList
|
||
|
}
|
||
|
|
||
|
newDesireAttributeList := getNewDesireAttributeList()
|
||
|
if (len(newDesireAttributeList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
newDesireAttribute := strings.Join(newDesireAttributeList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire(desireName, newDesireAttribute)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
otherIsSelected := slices.Contains(currentDesiredChoicesList, "Other")
|
||
|
if (otherIsSelected == true){
|
||
|
otherSelectCheck.Checked = true
|
||
|
}
|
||
|
|
||
|
allowOtherHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setAllowOtherExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
otherSelectCheckRow := container.NewHBox(layout.NewSpacer(), otherSelectCheck, allowOtherHelpButton, layout.NewSpacer())
|
||
|
|
||
|
checkIfAnyHaplogroupsAreSelected := func()bool{
|
||
|
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
return false
|
||
|
}
|
||
|
if (len(currentDesiredChoicesList) == 1){
|
||
|
onlySelection := currentDesiredChoicesList[0]
|
||
|
if (onlySelection == "Other"){
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
anyHaplogroupsAreSelected := checkIfAnyHaplogroupsAreSelected()
|
||
|
if (anyHaplogroupsAreSelected == false){
|
||
|
|
||
|
noHaplogroupsExistLabel := getBoldLabelCentered("No Haplogroups Chosen.")
|
||
|
|
||
|
selectedHaplogroupsSection := container.NewVBox(addHaplogroupRow, widget.NewSeparator(), noHaplogroupsExistLabel, widget.NewSeparator(), otherSelectCheckRow)
|
||
|
|
||
|
return selectedHaplogroupsSection, nil
|
||
|
}
|
||
|
|
||
|
myDesiredHaplogroupsLabel := getItalicLabelCentered("My Desired Haplogroups:")
|
||
|
|
||
|
haplogroupNameColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
deleteButtonsColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
for _, haplogroupNameBase64 := range currentDesiredChoicesList{
|
||
|
|
||
|
if (haplogroupNameBase64 == "Other"){
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
haplogroupName, err := encoding.DecodeBase64StringToUnicodeString(haplogroupNameBase64)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile " + maternalOrPaternal + " haplogroup desire is malformed: Contains invalid haplogroup: " + haplogroupNameBase64)
|
||
|
}
|
||
|
|
||
|
haplogroupNameLabel := getBoldLabelCentered(haplogroupName)
|
||
|
|
||
|
deleteHaplogroupButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){
|
||
|
|
||
|
newDesiredHaplogroupsList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, haplogroupNameBase64)
|
||
|
|
||
|
if (len(newDesiredHaplogroupsList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireValueString := strings.Join(newDesiredHaplogroupsList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire(desireName, newDesireValueString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
haplogroupNameColumn.Add(haplogroupNameLabel)
|
||
|
deleteButtonsColumn.Add(deleteHaplogroupButton)
|
||
|
|
||
|
haplogroupNameColumn.Add(widget.NewSeparator())
|
||
|
deleteButtonsColumn.Add(widget.NewSeparator())
|
||
|
}
|
||
|
|
||
|
haplogroupsGrid := container.NewHBox(layout.NewSpacer(), haplogroupNameColumn, deleteButtonsColumn, layout.NewSpacer())
|
||
|
|
||
|
selectedHaplogroupsSection := container.NewVBox(addHaplogroupRow, widget.NewSeparator(), myDesiredHaplogroupsLabel, haplogroupsGrid, widget.NewSeparator(), otherSelectCheckRow)
|
||
|
|
||
|
return selectedHaplogroupsSection, nil
|
||
|
}
|
||
|
|
||
|
selectedHaplogroupsSection, err := getSelectedHaplogroupsSection()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, desireName, true)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "23andMe " + maternalOrPaternal + " Haplogroup", desireName, true, "Bar", desireName, currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), selectedHaplogroupsSection, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_Age(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Age(window, previousPage)}
|
||
|
|
||
|
pageTitle := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(translate("Age"))
|
||
|
|
||
|
description := getLabelCentered("Choose your age desires.")
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Numeric(window, currentPage, "Age", 18, 200, "Years", 0, false, nil, nil, false, "", "", nil)
|
||
|
if (err != nil) {
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Age", "Age", true, "Bar", "Age", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(pageTitle, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_MonogenicDiseases(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_MonogenicDiseases(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("My Offspring Monogenic Disease Desires")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your offspring monogenic disease probability desires.")
|
||
|
description2 := getLabelCentered("You must link your genome person on the Build Profile - Genetic Analysis page.")
|
||
|
description3 := getLabelCentered("This desire will filter users based upon the probability that your offspring will have any monogenic disease.")
|
||
|
description4 := widget.NewLabel("If you use genetic testing, you can ensure your offspring will not have any monogenic diseases.")
|
||
|
|
||
|
geneticTestingHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setGeneticTestingExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
description4Row := container.NewHBox(layout.NewSpacer(), description4, geneticTestingHelpButton, layout.NewSpacer())
|
||
|
|
||
|
description5 := getBoldLabel("Choose the monogenic disease probability for your offspring that you desire.")
|
||
|
desireHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setOffspringMonogenicDiseaseProbabilityDesireExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
description5Row := container.NewHBox(layout.NewSpacer(), description5, desireHelpButton, layout.NewSpacer())
|
||
|
|
||
|
description6 := getLabelCentered("Be aware that if you select 0%, all users with dominant monogenic diseases will be filtered.")
|
||
|
description7 := getLabelCentered("You should not select 0% if you have a dominant monogenic disease.")
|
||
|
|
||
|
getCurrentDesireStatus := func()(string, error){
|
||
|
|
||
|
currentValueExists, currentValue, err := myLocalDesires.GetDesire("OffspringProbabilityOfAnyMonogenicDisease_Maximum")
|
||
|
if (err != nil){ return "", err }
|
||
|
if (currentValueExists == false || currentValue == "100"){
|
||
|
|
||
|
result := translate("0-100% (No Preference)")
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
if (currentValue == "99"){
|
||
|
return "0-99%", nil
|
||
|
}
|
||
|
if (currentValue != "0"){
|
||
|
return "", errors.New("MyLocalDesires malformed: Invalid OffspringProbabilityOfAnyMonogenicDisease_Maximum: " + currentValue)
|
||
|
}
|
||
|
|
||
|
return "0%", nil
|
||
|
}
|
||
|
|
||
|
currentDesireStatus, err := getCurrentDesireStatus()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
myDesireLabel := widget.NewLabel("My Desire:")
|
||
|
|
||
|
currentStatusText := getBoldLabel(currentDesireStatus)
|
||
|
|
||
|
currentStatusRow := container.NewHBox(layout.NewSpacer(), myDesireLabel, currentStatusText, layout.NewSpacer())
|
||
|
|
||
|
desireOptionsList := []string{"0%", "0-99%", "0-100%"}
|
||
|
|
||
|
desireSelector := widget.NewSelect(desireOptionsList, func(newSelection string){
|
||
|
|
||
|
if (newSelection == "0-100%"){
|
||
|
err = myLocalDesires.DeleteDesire("OffspringProbabilityOfAnyMonogenicDisease_Maximum")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getNewMaximumBound := func()string{
|
||
|
if (newSelection == "0%"){
|
||
|
return "0"
|
||
|
}
|
||
|
// newSelection == "0-99%"
|
||
|
return "99"
|
||
|
}
|
||
|
|
||
|
newMaximumBound := getNewMaximumBound()
|
||
|
|
||
|
err = myLocalDesires.SetDesire("OffspringProbabilityOfAnyMonogenicDisease_Maximum", newMaximumBound)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
if (currentDesireStatus == translate("0-100% (No Preference)")){
|
||
|
desireSelector.Selected = "0-100%"
|
||
|
} else {
|
||
|
desireSelector.Selected = currentDesireStatus
|
||
|
}
|
||
|
|
||
|
desireSelectorCentered := getWidgetCentered(desireSelector)
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "OffspringProbabilityOfAnyMonogenicDisease", false)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Offspring Has Any Monogenic Disease Probability", "OffspringProbabilityOfAnyMonogenicDisease", true, "Donut", "OffspringProbabilityOfAnyMonogenicDisease", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4Row, widget.NewSeparator(), description5Row, description6, description7, widget.NewSeparator(), currentStatusRow, desireSelectorCentered, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_Height(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Height(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Height")
|
||
|
|
||
|
description := getLabelCentered("Choose your desired height.")
|
||
|
|
||
|
metricOrImperialSwitchButton, err := getMetricImperialSwitchButton(window, currentPage)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentUnitsLabel := getItalicLabel("Current Units:")
|
||
|
|
||
|
currentUnitsRow := container.NewHBox(layout.NewSpacer(), currentUnitsLabel, metricOrImperialSwitchButton, layout.NewSpacer())
|
||
|
|
||
|
getMyMetricOrImperial := func()(string, error){
|
||
|
|
||
|
exists, metricOrImperial, err := globalSettings.GetSetting("MetricOrImperial")
|
||
|
if (err != nil) { return "", err }
|
||
|
if (exists == false){
|
||
|
return "Metric", nil
|
||
|
}
|
||
|
if (metricOrImperial != "Metric" && metricOrImperial != "Imperial"){
|
||
|
return "", errors.New("Malformed globalSettings: Invalid metricOrImperial: " + metricOrImperial)
|
||
|
}
|
||
|
|
||
|
return metricOrImperial, nil
|
||
|
}
|
||
|
|
||
|
myMetricOrImperial, err := getMyMetricOrImperial()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getBoundColumn := func(minimumOrMaximum string)(*fyne.Container, error){
|
||
|
|
||
|
if (minimumOrMaximum != "Minimum" && minimumOrMaximum != "Maximum"){
|
||
|
return nil, errors.New("getBoundColumn called with invalid minimumOrMaximum: " + minimumOrMaximum)
|
||
|
}
|
||
|
|
||
|
desireBoundName := "Height_" + minimumOrMaximum
|
||
|
|
||
|
boundLabel := getBoldLabelCentered(minimumOrMaximum)
|
||
|
|
||
|
myBoundExists, myCurrentBound, err := myLocalDesires.GetDesire(desireBoundName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
getMyBoundLabel := func()(*fyne.Container, error){
|
||
|
|
||
|
if (myBoundExists == false){
|
||
|
noneLabel := getBoldItalicLabelCentered(translate("None"))
|
||
|
return noneLabel, nil
|
||
|
}
|
||
|
|
||
|
myCurrentBoundFloat64, err := helpers.ConvertStringToFloat64(myCurrentBound)
|
||
|
if (err != nil) {
|
||
|
return nil, errors.New("My current height " + minimumOrMaximum + " desire is invalid: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
if (myMetricOrImperial == "Metric"){
|
||
|
|
||
|
myCurrentBoundRounded := helpers.ConvertFloat64ToStringRounded(myCurrentBoundFloat64, 2)
|
||
|
|
||
|
myBoundLabel := getBoldLabelCentered(myCurrentBoundRounded + " " + translate("centimeters"))
|
||
|
return myBoundLabel, nil
|
||
|
}
|
||
|
|
||
|
feetInchesString, err := helpers.ConvertCentimetersToFeetInchesTranslatedString(myCurrentBoundFloat64)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
myBoundLabel := getBoldLabelCentered(feetInchesString)
|
||
|
return myBoundLabel, nil
|
||
|
}
|
||
|
|
||
|
myBoundLabel, err := getMyBoundLabel()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
minimumOrMaximumLowercase := strings.ToLower(minimumOrMaximum)
|
||
|
|
||
|
//Outputs:
|
||
|
// -fyne.Container: Bound entry (either metric or imperial)
|
||
|
// -fyne.Widget: Submit button
|
||
|
// -error
|
||
|
getBoundEntryAndSubmitButton := func()(*fyne.Container, fyne.Widget, error){
|
||
|
|
||
|
if (myMetricOrImperial == "Metric"){
|
||
|
|
||
|
boundEntry := widget.NewEntry()
|
||
|
|
||
|
boundEntryBoxed := getWidgetBoxed(boundEntry)
|
||
|
|
||
|
if (myBoundExists == true){
|
||
|
currentBoundFloat64, err := helpers.ConvertStringToFloat64(myCurrentBound)
|
||
|
if (err != nil) { return nil, nil, err }
|
||
|
if (currentBoundFloat64 < 30 || currentBoundFloat64 > 400) {
|
||
|
return nil, nil, errors.New("My desires malformed: Contains invalid height desire: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
myCurrentBoundRounded := helpers.ConvertFloat64ToStringRounded(currentBoundFloat64, 2)
|
||
|
|
||
|
boundEntry.SetText(myCurrentBoundRounded)
|
||
|
} else {
|
||
|
boundEntry.SetPlaceHolder(translate("Enter " + minimumOrMaximumLowercase + "..."))
|
||
|
}
|
||
|
|
||
|
saveBoundButton := widget.NewButtonWithIcon(translate("Save"), theme.ConfirmIcon(), func(){
|
||
|
|
||
|
newHeightBound := boundEntry.Text
|
||
|
|
||
|
if (newHeightBound == ""){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireBoundName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//TODO: If min is greater than max, delete min
|
||
|
|
||
|
newHeightBoundFloat64, err := helpers.ConvertStringToFloat64(newHeightBound)
|
||
|
if (err != nil){
|
||
|
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Height")
|
||
|
dialogMessage := getLabelCentered(translate("Your height bound must be a number."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
if (newHeightBoundFloat64 < 30 || newHeightBoundFloat64 > 400){
|
||
|
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Height")
|
||
|
dialogMessage := getLabelCentered(translate("Your height desire must be a number between 30 and 400."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = myLocalDesires.SetDesire(desireBoundName, newHeightBound)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
return boundEntryBoxed, saveBoundButton, nil
|
||
|
}
|
||
|
|
||
|
feetEntry := widget.NewEntry()
|
||
|
inchesEntry := widget.NewEntry()
|
||
|
|
||
|
feetLabel := getBoldLabel(translate("feet"))
|
||
|
inchesLabel := getBoldLabel(translate("inches"))
|
||
|
|
||
|
entryRow := container.NewGridWithRows(1, feetEntry, feetLabel, inchesEntry, inchesLabel)
|
||
|
|
||
|
if (myBoundExists == true){
|
||
|
currentBoundFloat64, err := helpers.ConvertStringToFloat64(myCurrentBound)
|
||
|
if (err != nil) { return nil, nil, err }
|
||
|
if (currentBoundFloat64 < 30 || currentBoundFloat64 > 400) {
|
||
|
return nil, nil, errors.New("My desires malformed: Contains invalid height desire: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
feetInt, inchesFloat, err := helpers.ConvertCentimetersToFeetInches(currentBoundFloat64)
|
||
|
if (err != nil) {
|
||
|
return nil, nil, errors.New("My desires malformed: Contains invalid height desire: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
feetString := helpers.ConvertIntToString(feetInt)
|
||
|
inchesString := helpers.ConvertFloat64ToStringRounded(inchesFloat, 1)
|
||
|
|
||
|
feetEntry.SetText(feetString)
|
||
|
inchesEntry.SetText(inchesString)
|
||
|
} else {
|
||
|
feetEntry.SetPlaceHolder(translate("Enter " + minimumOrMaximumLowercase + "..."))
|
||
|
inchesEntry.SetPlaceHolder(translate("Enter " + minimumOrMaximumLowercase + "..."))
|
||
|
}
|
||
|
|
||
|
saveBoundButton := widget.NewButtonWithIcon(translate("Save"), theme.ConfirmIcon(), func(){
|
||
|
|
||
|
newHeightFeetBound := feetEntry.Text
|
||
|
newHeightInchesBound := inchesEntry.Text
|
||
|
|
||
|
if (newHeightFeetBound == "" && newHeightInchesBound == ""){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireBoundName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newFeetBoundInt, err := helpers.ConvertStringToInt(newHeightFeetBound)
|
||
|
if (err != nil){
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Feet")
|
||
|
dialogMessage := getLabelCentered(translate("Your feet bound must be a number."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newInchesBoundFloat64, err := helpers.ConvertStringToFloat64(newHeightInchesBound)
|
||
|
if (err != nil){
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Inches")
|
||
|
dialogMessage := getLabelCentered(translate("Your inches bound must be a number."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newCentimetersBound, err := helpers.ConvertFeetInchesToCentimeters(newFeetBoundInt, newInchesBoundFloat64)
|
||
|
if (err != nil){
|
||
|
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Height")
|
||
|
dialogMessage := getLabelCentered(translate("Your height bound must be a positive number."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (newCentimetersBound < 30 || newCentimetersBound > 400){
|
||
|
|
||
|
title := translate("Invalid " + minimumOrMaximum + " Height")
|
||
|
dialogMessage := getLabelCentered(translate("Your height bound must be between 30 and 400 centimeters."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newCentimetersBoundString := helpers.ConvertFloat64ToString(newCentimetersBound)
|
||
|
|
||
|
err = myLocalDesires.SetDesire(desireBoundName, newCentimetersBoundString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
return entryRow, saveBoundButton, nil
|
||
|
}
|
||
|
|
||
|
boundEntryRow, saveBoundButton, err := getBoundEntryAndSubmitButton()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
deleteBoundButton := widget.NewButtonWithIcon(translate("No Preference"), theme.CancelIcon(), func(){
|
||
|
|
||
|
if (myBoundExists == false){
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireBoundName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
boundColumn := getContainerCentered(container.NewVBox(boundLabel, widget.NewSeparator(), myBoundLabel, widget.NewSeparator(), boundEntryRow, saveBoundButton, deleteBoundButton))
|
||
|
return boundColumn, nil
|
||
|
}
|
||
|
|
||
|
minimumColumn, err := getBoundColumn("Minimum")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
maximumColumn, err := getBoundColumn("Maximum")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
boundColumns := getContainerCentered(container.NewGridWithRows(1, minimumColumn, maximumColumn))
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "Height", true)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Height", "Height", true, "Bar", "Height", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description, widget.NewSeparator(), currentUnitsRow, widget.NewSeparator(), boundColumns, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_BodyFat(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_BodyFat(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Body Fat")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your body fat desires.")
|
||
|
description2 := getLabelCentered("Select each rating which you desire.")
|
||
|
description3 := getLabelCentered("1/4 = Least body fat, 4/4 = Most body fat.")
|
||
|
|
||
|
optionTitlesList := []string{"1/4", "2/4", "3/4", "4/4"}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
"1/4": []string{"1"},
|
||
|
"2/4": []string{"2"},
|
||
|
"3/4": []string{"3"},
|
||
|
"4/4": []string{"4"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "BodyFat", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Body Fat", "BodyFat", true, "Donut", "BodyFat", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_BodyMuscle(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_BodyMuscle(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Body Muscle")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your body muscle desires.")
|
||
|
description2 := getLabelCentered("Select each rating which you desire.")
|
||
|
description3 := getLabelCentered("1/4 = Least body muscle, 4/4 = Most body muscle.")
|
||
|
|
||
|
optionTitlesList := []string{"1/4", "2/4", "3/4", "4/4"}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
"1/4": []string{"1"},
|
||
|
"2/4": []string{"2"},
|
||
|
"3/4": []string{"3"},
|
||
|
"4/4": []string{"4"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "BodyMuscle", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Body Muscle", "BodyMuscle", true, "Donut", "BodyMuscle", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_EyeColor(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_EyeColor(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Eye Color")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your eye color desires.")
|
||
|
description2 := getLabelCentered("Select each eye color that you desire.")
|
||
|
|
||
|
optionTitlesList := []string{"Blue", "Green", "Brown", "Amber", "Blue+Green", "Blue+Brown", "Blue+Amber", "Amber+Brown", "Green+Brown", "Green+Amber", "Green+Amber+Brown", "Blue+Amber+Brown", "Blue+Green+Brown", "Blue+Green+Amber", "Blue+Green+Amber+Brown"}
|
||
|
|
||
|
optionNamesMap := make(map[string][]string)
|
||
|
|
||
|
optionNamesMap["Blue"] = []string{"Blue"}
|
||
|
optionNamesMap["Green"] = []string{"Green"}
|
||
|
optionNamesMap["Brown"] = []string{"Brown"}
|
||
|
optionNamesMap["Amber"] = []string{"Amber"}
|
||
|
optionNamesMap["Blue+Green"] = []string{"Blue+Green", "Green+Blue"}
|
||
|
optionNamesMap["Blue+Brown"] = []string{"Blue+Brown", "Brown+Blue"}
|
||
|
optionNamesMap["Blue+Amber"] = []string{"Blue+Amber", "Amber+Blue"}
|
||
|
optionNamesMap["Amber+Brown"] = []string{"Amber+Brown", "Brown+Amber"}
|
||
|
optionNamesMap["Green+Brown"] = []string{"Green+Brown", "Brown+Green"}
|
||
|
optionNamesMap["Green+Amber"] = []string{"Green+Amber", "Amber+Green"}
|
||
|
|
||
|
optionNamesMap["Green+Amber+Brown"] = []string{"Green+Amber+Brown", "Green+Brown+Amber", "Amber+Green+Brown", "Amber+Brown+Green", "Brown+Amber+Green", "Brown+Green+Amber"}
|
||
|
|
||
|
optionNamesMap["Blue+Amber+Brown"] = []string{"Blue+Amber+Brown", "Blue+Brown+Amber", "Amber+Blue+Brown", "Amber+Brown+Blue", "Brown+Amber+Blue", "Brown+Blue+Amber"}
|
||
|
|
||
|
optionNamesMap["Blue+Green+Brown"] = []string{"Blue+Green+Brown", "Blue+Brown+Green", "Green+Blue+Brown", "Green+Brown+Blue", "Brown+Green+Blue", "Brown+Blue+Green"}
|
||
|
|
||
|
optionNamesMap["Blue+Green+Amber"] = []string{"Blue+Green+Amber", "Blue+Amber+Green", "Green+Blue+Amber", "Green+Amber+Blue", "Amber+Green+Blue", "Amber+Blue+Green"}
|
||
|
|
||
|
optionNamesMap["Blue+Green+Amber+Brown"] = []string{"Blue+Green+Brown+Amber", "Blue+Green+Amber+Brown", "Blue+Brown+Green+Amber", "Blue+Brown+Amber+Green", "Blue+Amber+Green+Brown", "Blue+Amber+Brown+Green", "Green+Blue+Brown+Amber", "Green+Blue+Amber+Brown", "Green+Brown+Blue+Amber", "Green+Brown+Amber+Blue", "Green+Amber+Blue+Brown", "Green+Amber+Brown+Blue", "Brown+Blue+Green+Amber", "Brown+Blue+Amber+Green", "Brown+Green+Blue+Amber", "Brown+Green+Amber+Blue", "Brown+Amber+Blue+Green", "Brown+Amber+Green+Blue", "Amber+Blue+Green+Brown", "Amber+Blue+Brown+Green", "Amber+Green+Blue+Brown", "Amber+Green+Brown+Blue", "Amber+Brown+Blue+Green", "Amber+Brown+Green+Blue"}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "EyeColor", optionTitlesList, optionNamesMap, false, true, 2)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Eye Color", "EyeColor", true, "Donut", "EyeColor", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_HairColor(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_HairColor(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Hair Color")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your natural hair color desires.")
|
||
|
description2 := getLabelCentered("Select each natural hair color that you desire.")
|
||
|
|
||
|
optionTitlesList := []string{"Black", "Brown", "Blonde", "Orange", "Black+Brown", "Black+Blonde", "Black+Orange", "Brown+Blonde", "Brown+Orange", "Blonde+Orange"}
|
||
|
|
||
|
//TODO: Add color guide page, so users can see the colors
|
||
|
// We already have this on the Build Profile page for hair/eye color
|
||
|
|
||
|
optionNamesMap := make(map[string][]string)
|
||
|
optionNamesMap["Black"] = []string{"Black"}
|
||
|
optionNamesMap["Brown"] = []string{"Brown"}
|
||
|
optionNamesMap["Blonde"] = []string{"Blonde"}
|
||
|
optionNamesMap["Orange"] = []string{"Orange"}
|
||
|
optionNamesMap["Black+Brown"] = []string{"Black+Brown", "Brown+Black"}
|
||
|
optionNamesMap["Black+Blonde"] = []string{"Black+Blonde", "Blonde+Black"}
|
||
|
optionNamesMap["Black+Orange"] = []string{"Black+Orange", "Orange+Black"}
|
||
|
optionNamesMap["Brown+Blonde"] = []string{"Brown+Blonde", "Blonde+Brown"}
|
||
|
optionNamesMap["Brown+Orange"] = []string{"Brown+Orange", "Orange+Brown"}
|
||
|
optionNamesMap["Blonde+Orange"] = []string{"Blonde+Orange", "Orange+Blonde"}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HairColor", optionTitlesList, optionNamesMap, false, true, 2)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Hair Color", "HairColor", true, "Donut", "HairColor", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_HairTexture(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_HairTexture(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Hair Texture")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your hair texture desires.")
|
||
|
description2 := getLabelCentered("Select each hair texture that you desire.")
|
||
|
|
||
|
// These descriptions are taken from 23andMe.
|
||
|
|
||
|
option1Translated := translate("1 - Straight Hair")
|
||
|
option2Translated := translate("2 - Slightly Wavy Hair")
|
||
|
option3Translated := translate("3 - Wavy Hair")
|
||
|
option4Translated := translate("4 - Big Curls")
|
||
|
option5Translated := translate("5 - Small Curls")
|
||
|
option6Translated := translate("6 - Very Tight Curls")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated, option3Translated, option4Translated, option5Translated, option6Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"1"},
|
||
|
option2Translated: []string{"2"},
|
||
|
option3Translated: []string{"3"},
|
||
|
option4Translated: []string{"4"},
|
||
|
option5Translated: []string{"5"},
|
||
|
option6Translated: []string{"6"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HairTexture", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Hair Texture", "HairTexture", true, "Donut", "HairTexture", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_SkinColor(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_SkinColor(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Skin Color")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your skin color desires.")
|
||
|
description2 := getLabelCentered("Select each skin color that you desire.")
|
||
|
description3 := getLabelCentered("Skin color can change under different conditions.")
|
||
|
description4 := getLabelCentered("You may want to select multiple options to account for this.")
|
||
|
|
||
|
getSkinColorExampleColumn := func(colorIdentifier string, colorCode string)(*fyne.Container, error){
|
||
|
|
||
|
colorSquare, err := getColorSquareAsFyneImage(colorCode)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
colorSquare.FillMode = canvas.ImageFillStretch
|
||
|
|
||
|
colorIdentifierLabel := getBoldLabelCentered(colorIdentifier)
|
||
|
|
||
|
colorColumn := container.NewGridWithColumns(1, colorSquare, colorIdentifierLabel)
|
||
|
|
||
|
return colorColumn, nil
|
||
|
}
|
||
|
|
||
|
skinColorColumn_1, err := getSkinColorExampleColumn("1", "f4e3da")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorColumn_2, err := getSkinColorExampleColumn("2", "f5d6b9")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorColumn_3, err := getSkinColorExampleColumn("3", "dabe91")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorColumn_4, err := getSkinColorExampleColumn("4", "ba9175")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorColumn_5, err := getSkinColorExampleColumn("5", "916244")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorColumn_6, err := getSkinColorExampleColumn("6", "744d2d")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
skinColorExamplesRow := container.NewHBox(layout.NewSpacer(), skinColorColumn_1, skinColorColumn_2, skinColorColumn_3, skinColorColumn_4, skinColorColumn_5, skinColorColumn_6, layout.NewSpacer())
|
||
|
|
||
|
optionTitlesList := []string{"1", "2", "3", "4", "5", "6"}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
"1": []string{"1"},
|
||
|
"2": []string{"2"},
|
||
|
"3": []string{"3"},
|
||
|
"4": []string{"4"},
|
||
|
"5": []string{"5"},
|
||
|
"6": []string{"6"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "SkinColor", optionTitlesList, optionNamesMap, false, true, 6)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Skin Color", "SkinColor", true, "Donut", "SkinColor", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), skinColorExamplesRow, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_Infections(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Infections(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Infections")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your infection desires.")
|
||
|
|
||
|
hivButton := widget.NewButton("HIV", func(){
|
||
|
setChooseDesiresPage_HIV(window, currentPage)
|
||
|
})
|
||
|
|
||
|
genitalHerpesButton := widget.NewButton("Genital Herpes", func(){
|
||
|
setChooseDesiresPage_GenitalHerpes(window, currentPage)
|
||
|
})
|
||
|
|
||
|
buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, hivButton, genitalHerpesButton))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, widget.NewSeparator(), buttonsGrid)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_HIV(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_HIV(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("HIV")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your HIV desires.")
|
||
|
description2 := getLabelCentered("Select each option which you desire.")
|
||
|
description3 := getLabelCentered("Positive = Has disease, Negative = Does not have disease.")
|
||
|
|
||
|
optionTitlesList := []string{"HIV Positive", "HIV Negative"}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
"HIV Positive": []string{"Yes"},
|
||
|
"HIV Negative": []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HasHIV", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Has HIV", "HasHIV", true, "Donut", "HasHIV", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_GenitalHerpes(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_GenitalHerpes(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - Physical"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Genital Herpes")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your Genital Herpes desires.")
|
||
|
description2 := getLabelCentered("Select each option which you desire.")
|
||
|
description3 := getLabelCentered("Positive = Has disease, Negative = Does not have disease.")
|
||
|
|
||
|
optionTitlesList := []string{"Genital Herpes Positive", "Genital Herpes Negative"}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
"Genital Herpes Positive": []string{"Yes"},
|
||
|
"Genital Herpes Negative": []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HasGenitalHerpes", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Has Genital Herpes", "HasGenitalHerpes", true, "Donut", "HasGenitalHerpes", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|