2024-04-11 15:51:56 +02:00
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
}
2024-08-11 14:31:40 +02:00
newAttributeList , _ := helpers . DeleteAllMatchingItemsFromList ( currentDesiredChoicesList , "Other" )
2024-04-11 15:51:56 +02:00
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 ( ) {
2024-08-11 14:31:40 +02:00
newDesiredHaplogroupsList , _ := helpers . DeleteAllMatchingItemsFromList ( currentDesiredChoicesList , haplogroupNameBase64 )
2024-04-11 15:51:56 +02:00
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 )
}