2024-04-11 15:51:56 +02:00
package gui
// buildProfileGui_Physical.go implements pages to build the Physical portion of a user's mate profile
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/resources/geneticReferences/traits"
import "seekia/resources/geneticReferences/monogenicDiseases"
import "seekia/resources/geneticReferences/polygenicDiseases"
import "seekia/internal/allowedText"
import "seekia/internal/genetics/companyAnalysis"
import "seekia/internal/genetics/myChosenAnalysis"
import "seekia/internal/genetics/myGenomes"
import "seekia/internal/genetics/myPeople"
import "seekia/internal/globalSettings"
import "seekia/internal/helpers"
import "seekia/internal/profiles/myLocalProfiles"
import "slices"
import "strings"
import "errors"
func setBuildMateProfileCategoryPage_Physical ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfileCategoryPage_Physical ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
sexButton := widget . NewButton ( translate ( "Sex" ) , func ( ) {
setBuildMateProfilePage_Sex ( window , currentPage )
} )
ageButton := widget . NewButton ( translate ( "Age" ) , func ( ) {
setBuildMateProfilePage_Age ( window , currentPage )
} )
ancestryCompositionButton := widget . NewButton ( "Ancestry Composition" , func ( ) {
setBuildMateProfilePage_23andMe_AncestryComposition ( window , currentPage )
} )
neanderthalVariantsButton := widget . NewButton ( "Neanderthal Variants" , func ( ) {
setBuildMateProfilePage_23andMe_NeanderthalVariants ( window , currentPage )
} )
maternalHaplogroupButton := widget . NewButton ( "Maternal Haplogroup" , func ( ) {
setBuildMateProfilePage_23andMe_Haplogroup ( window , "Maternal" , currentPage )
} )
paternalHaplogroupButton := widget . NewButton ( "Paternal Haplogroup" , func ( ) {
setBuildMateProfilePage_23andMe_Haplogroup ( window , "Paternal" , currentPage )
} )
geneticInformationButton := widget . NewButton ( translate ( "Genetic Information" ) , func ( ) {
setBuildMateProfilePage_GeneticInformation ( window , currentPage )
} )
heightButton := widget . NewButton ( translate ( "Height" ) , func ( ) {
setBuildMateProfilePage_Height ( window , currentPage )
} )
bodyButton := widget . NewButton ( translate ( "Body" ) , func ( ) {
setBuildMateProfilePage_Body ( window , currentPage )
} )
eyeColorButton := widget . NewButton ( translate ( "Eye Color" ) , func ( ) {
setBuildMateProfilePage_EyeColor ( window , currentPage )
} )
hairColorButton := widget . NewButton ( translate ( "Hair Color" ) , func ( ) {
setBuildMateProfilePage_HairColor ( window , currentPage )
} )
hairTextureButton := widget . NewButton ( translate ( "Hair Texture" ) , func ( ) {
setBuildMateProfilePage_HairTexture ( window , currentPage )
} )
skinColorButton := widget . NewButton ( translate ( "Skin Color" ) , func ( ) {
setBuildMateProfilePage_SkinColor ( window , currentPage )
} )
infectionsButton := widget . NewButton ( translate ( "Infections" ) , func ( ) {
setBuildMateProfilePage_Infections ( window , currentPage )
} )
buttonsGrid := container . NewGridWithColumns ( 1 , sexButton , ageButton , ancestryCompositionButton , neanderthalVariantsButton , maternalHaplogroupButton , paternalHaplogroupButton , geneticInformationButton , heightButton , bodyButton , eyeColorButton , hairColorButton , hairTextureButton , skinColorButton , infectionsButton )
buttonsGridCentered := getContainerCentered ( buttonsGrid )
buttonsGridPadded := container . NewPadded ( buttonsGridCentered )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , buttonsGridPadded )
setPageContent ( page , window )
}
func setBuildMateProfilePage_Sex ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_Sex ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Sex" ) )
sexDescription := widget . NewLabel ( translate ( "What is your physical sex?" ) )
sexHelpButton := widget . NewButtonWithIcon ( "" , theme . QuestionIcon ( ) , func ( ) {
setSexExplainerPage ( window , currentPage )
} )
sexDescriptionRow := container . NewHBox ( layout . NewSpacer ( ) , sexDescription , sexHelpButton , layout . NewSpacer ( ) )
option1Translated := translate ( "Male" )
option2Translated := translate ( "Female" )
option3Translated := translate ( "Intersex Male" )
option4Translated := translate ( "Intersex Female" )
option5Translated := translate ( "Intersex" )
untranslatedOptionsMap := map [ string ] string {
option1Translated : "Male" ,
option2Translated : "Female" ,
option3Translated : "Intersex Male" ,
option4Translated : "Intersex Female" ,
option5Translated : "Intersex" ,
}
sexSelectorOptions := [ ] string { option1Translated , option2Translated , option3Translated , option4Translated , option5Translated }
sexSelector := widget . NewRadioGroup ( sexSelectorOptions , func ( response string ) {
if ( response == "" ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "Sex" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
return
}
responseUntranslated , exists := untranslatedOptionsMap [ response ]
if ( exists == false ) {
setErrorEncounteredPage ( window , errors . New ( "untranslatedOptionsMap missing response: " + response ) , currentPage )
return
}
err := myLocalProfiles . SetProfileData ( "Mate" , "Sex" , responseUntranslated )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
} )
exists , currentSex , err := myLocalProfiles . GetProfileData ( "Mate" , "Sex" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( exists == true ) {
if ( currentSex != "Male" && currentSex != "Female" && currentSex != "Intersex Male" && currentSex != "Intersex Female" && currentSex != "Intersex" ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid Sex: " + currentSex ) , previousPage )
return
}
sexSelector . Selected = translate ( currentSex )
}
sexSelectorCentered := getWidgetCentered ( sexSelector )
sexNoResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "Sex" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , sexDescriptionRow , sexSelectorCentered , sexNoResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_AncestryComposition ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_23andMe_AncestryComposition ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "23andMe Ancestry Composition" )
description := getLabelCentered ( "Enter your 23andMe ancestry location composition." )
exists , myAncestryCompositionAttribute , err := myLocalProfiles . GetProfileData ( "Mate" , "23andMe_AncestryComposition" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( exists == false ) {
noCompositionFoundLabel := getBoldLabelCentered ( "No ancestry composition exists." )
addCompositionButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Add Composition" , theme . ContentAddIcon ( ) , func ( ) {
emptyMapA := make ( map [ string ] float64 )
emptyMapB := make ( map [ string ] float64 )
emptyMapC := make ( map [ string ] float64 )
setBuildMateProfilePage_23andMe_EditAncestryComposition ( window , emptyMapA , emptyMapB , emptyMapC , currentPage , currentPage )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , noCompositionFoundLabel , addCompositionButton )
setPageContent ( page , window )
return
}
visibilityLabel := getBoldLabel ( "Visibility:" )
visibilityOptions := [ ] string { translate ( "Show On Profile" ) , translate ( "Hide From Profile" ) }
visibilitySelector := widget . NewSelect ( visibilityOptions , func ( newVisibility string ) {
getNewVisibilityStatus := func ( ) string {
if ( newVisibility == translate ( "Show On Profile" ) ) {
return "Yes"
}
return "No"
}
newVisibilityStatus := getNewVisibilityStatus ( )
err := myLocalProfiles . SetProfileData ( "Mate" , "VisibilityStatus_23andMe_AncestryComposition" , newVisibilityStatus )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
} )
exists , visibilityStatus , err := myLocalProfiles . GetProfileData ( "Mate" , "VisibilityStatus_23andMe_AncestryComposition" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( exists == true && visibilityStatus == "No" ) {
visibilitySelector . Selected = translate ( "Hide From Profile" )
} else {
visibilitySelector . Selected = translate ( "Show On Profile" )
}
profileVisibilityHelpButton := widget . NewButtonWithIcon ( "" , theme . QuestionIcon ( ) , func ( ) {
setMateProfileAttributeVisibilityExplainerPage ( window , currentPage )
} )
visibilitySelectorRow := container . NewHBox ( layout . NewSpacer ( ) , visibilityLabel , visibilitySelector , profileVisibilityHelpButton , layout . NewSpacer ( ) )
attributeIsValid , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , err := companyAnalysis . ReadAncestryCompositionAttribute_23andMe ( true , myAncestryCompositionAttribute )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
if ( attributeIsValid == false ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles 23andMe ancestry composition attribute is invalid." ) , currentPage )
return
}
editCompositionButton := widget . NewButtonWithIcon ( "Edit" , theme . DocumentCreateIcon ( ) , func ( ) {
setBuildMateProfilePage_23andMe_EditAncestryComposition ( window , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , currentPage , currentPage )
} )
noResponseButton := widget . NewButtonWithIcon ( "No Response" , theme . CancelIcon ( ) , func ( ) {
setBuildMateProfilePage_23andMe_ConfirmDeleteAncestryComposition ( window , currentPage , currentPage )
} )
buttonsGrid := getContainerCentered ( container . NewGridWithColumns ( 1 , editCompositionButton , noResponseButton ) )
myCompositionLabel := getBoldLabelCentered ( "My Composition:" )
myCompositionDisplay , err := get23andMeAncestryCompositionDisplay ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
header := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , visibilitySelectorRow , widget . NewSeparator ( ) , buttonsGrid , widget . NewSeparator ( ) , myCompositionLabel )
page := container . NewBorder ( header , nil , nil , nil , myCompositionDisplay )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_ConfirmDeleteAncestryComposition ( window fyne . Window , previousPage func ( ) , nextPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_23andMe_ConfirmDeleteAncestryComposition ( window , previousPage , nextPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
description1 := getBoldLabelCentered ( "Delete Ancestry Composition?" )
description2 := getLabelCentered ( "Confirm to delete your 23andMe ancestry composition?" )
confirmButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Confirm" , theme . ConfirmIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "23andMe_AncestryComposition" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
nextPage ( )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , description1 , description2 , confirmButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_EditAncestryComposition ( window fyne . Window , myContinentPercentagesMap map [ string ] float64 , myRegionPercentagesMap map [ string ] float64 , mySubregionPercentagesMap map [ string ] float64 , previousPage func ( ) , afterCompletePage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_23andMe_EditAncestryComposition ( window , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , previousPage , afterCompletePage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButtonFunction := func ( ) {
confirmDialogCallbackFunction := func ( response bool ) {
if ( response == true ) {
previousPage ( )
}
}
dialogTitle := translate ( "Confirm Go Back" )
dialogMessageA := getLabelCentered ( "Confirm to go back?" )
dialogMessageB := getLabelCentered ( "You will lose any changes you made." )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustomConfirm ( dialogTitle , translate ( "Yes" ) , translate ( "No" ) , dialogContent , confirmDialogCallbackFunction , window )
}
backButton := getBackButtonCentered ( backButtonFunction )
subtitle := getPageSubtitleCentered ( "Build 23andMe Ancestry Composition" )
// We use this function to make changes and return to this page
currentPageWithNewPercentagesFunction := func ( newContinentPercentagesMap map [ string ] float64 , newRegionPercentagesMap map [ string ] float64 , newSubregionPercentagesMap map [ string ] float64 ) {
setBuildMateProfilePage_23andMe_EditAncestryComposition ( window , newContinentPercentagesMap , newRegionPercentagesMap , newSubregionPercentagesMap , previousPage , afterCompletePage )
}
addLocationButton := widget . NewButtonWithIcon ( "Add Location" , theme . ContentAddIcon ( ) , func ( ) {
setBuildMateProfilePage_23andMe_AncestryComposition_AddLocation ( window , false , "" , false , "" , false , "" , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , currentPage , currentPageWithNewPercentagesFunction )
} )
if ( len ( myContinentPercentagesMap ) == 0 && len ( myRegionPercentagesMap ) == 0 && len ( mySubregionPercentagesMap ) == 0 ) {
addLocationButtonCentered := getWidgetCentered ( addLocationButton )
noCompositionExistsLabel := getBoldLabelCentered ( "No locations added." )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , addLocationButtonCentered , widget . NewSeparator ( ) , noCompositionExistsLabel )
setPageContent ( page , window )
return
}
deleteLocationButton := widget . NewButtonWithIcon ( "Delete Location" , theme . DeleteIcon ( ) , func ( ) {
setBuildMateProfilePage_23andMe_AncestryComposition_DeleteLocation ( window , "Continent" , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , currentPage , currentPageWithNewPercentagesFunction )
} )
addAndDeleteLocationButtons := getContainerCentered ( container . NewGridWithRows ( 1 , addLocationButton , deleteLocationButton ) )
submitButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
inputsAreValid , newAncestryCompositionAttribute , err := companyAnalysis . CreateAncestryCompositionAttribute_23andMe ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
if ( inputsAreValid == false ) {
dialogTitle := translate ( "Invalid Ancestry Composition" )
dialogMessageA := getBoldLabelCentered ( translate ( "The ancestry composition you entered is invalid." ) )
dialogMessageB := getLabelCentered ( translate ( "All continent percentages must add to 100." ) )
dialogMessageC := getLabelCentered ( translate ( "All region percentages must add up to their continent percentage." ) )
dialogMessageD := getLabelCentered ( translate ( "All subregion percentages must add up to their region percentage." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB , dialogMessageC , dialogMessageD )
dialog . ShowCustom ( dialogTitle , translate ( "Close" ) , dialogContent , window )
return
}
setBuildMateProfilePage_23andMe_ConfirmUpdateAncestryComposition ( window , newAncestryCompositionAttribute , currentPage , afterCompletePage )
} ) )
emptyLabel := widget . NewLabel ( "" )
footer := container . NewVBox ( widget . NewSeparator ( ) , submitButton , emptyLabel )
myCompositionTree , err := get23andMeAncestryCompositionDisplay ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
header := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , addAndDeleteLocationButtons , widget . NewSeparator ( ) )
page := container . NewBorder ( header , footer , nil , nil , myCompositionTree )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_ConfirmUpdateAncestryComposition ( window fyne . Window , newAncestryCompositionAttribute string , previousPage func ( ) , nextPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_23andMe_ConfirmUpdateAncestryComposition ( window , newAncestryCompositionAttribute , previousPage , nextPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
description1 := getBoldLabelCentered ( "Add Ancestry Composition?" )
description2 := getLabelCentered ( "Confirm update your ancestry composition?" )
description3 := getLabelCentered ( "This will be visible on your profile." )
confirmButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Confirm" , theme . ConfirmIcon ( ) , func ( ) {
err := myLocalProfiles . SetProfileData ( "Mate" , "23andMe_AncestryComposition" , newAncestryCompositionAttribute )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
nextPage ( )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , description1 , description2 , description3 , confirmButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_AncestryComposition_AddLocation (
window fyne . Window ,
continentProvided bool ,
currentContinent string ,
regionProvided bool ,
currentRegion string ,
subregionProvided bool ,
currentSubregion string ,
myContinentPercentagesMap map [ string ] float64 ,
myRegionPercentagesMap map [ string ] float64 ,
mySubregionPercentagesMap map [ string ] float64 ,
previousPage func ( ) ,
nextPage func ( map [ string ] float64 , map [ string ] float64 , map [ string ] float64 ) ) {
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Add 23andMe Ancestry Location" )
getPageContent := func ( ) ( * fyne . Container , error ) {
continentLabel := getBoldLabel ( "Continent:" )
allContinentsList := companyAnalysis . GetAncestryContinentsList_23andMe ( )
handleContinentSelectFunction := func ( newContinent string ) {
if ( continentProvided == true && newContinent == currentContinent ) {
return
}
setBuildMateProfilePage_23andMe_AncestryComposition_AddLocation ( window , true , newContinent , false , "" , false , "" , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , previousPage , nextPage )
}
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
}
percentageLabel := getBoldLabelCentered ( "Percentage:" )
percentageEntry := widget . NewEntry ( )
percentageEntry . SetPlaceHolder ( "Enter percentage." )
percentageRow := getContainerCentered ( container . NewGridWithRows ( 1 , percentageLabel , percentageEntry ) )
showInvalidPercentageDialog := func ( ) {
dialogTitle := translate ( "Invalid Percentage" )
dialogMessageA := getLabelCentered ( translate ( "The location percentage is invalid." ) )
dialogMessageB := getLabelCentered ( translate ( "You must enter a number between 0 and 100." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( dialogTitle , translate ( "Close" ) , dialogContent , window )
}
regionsList , err := companyAnalysis . GetAncestryContinentRegionsList_23andMe ( currentContinent )
if ( err != nil ) { return nil , err }
if ( len ( regionsList ) == 0 ) {
submitButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newPercentageRaw := percentageEntry . Text
newPercentage := strings . TrimSuffix ( newPercentageRaw , "%" )
newPercentageFloat64 , err := helpers . ConvertStringToFloat64 ( newPercentage )
if ( err != nil ) {
showInvalidPercentageDialog ( )
return
}
if ( newPercentageFloat64 <= 0 || newPercentageFloat64 > 100 ) {
showInvalidPercentageDialog ( )
return
}
addContinentFunction := func ( ) {
myContinentPercentagesMap [ currentContinent ] = newPercentageFloat64
nextPage ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
}
existingPercentage , exists := myContinentPercentagesMap [ currentContinent ]
if ( exists == false ) {
addContinentFunction ( )
return
}
// We allow user to confirm they want to overwrite existing value
currentPercentageString := helpers . ConvertFloat64ToStringRounded ( existingPercentage , 1 )
confirmDialogCallbackFunction := func ( response bool ) {
if ( response == true ) {
addContinentFunction ( )
}
}
dialogTitle := translate ( "Confirm Overwrite Existing" )
dialogMessageA := getLabelCentered ( "You already have a percentage for " + currentContinent )
dialogMessageB := getLabelCentered ( "Current Percentage: " + currentPercentageString + "%" )
dialogMessageC := getLabelCentered ( "Confirm to overwrite this percentage?" )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB , dialogMessageC )
dialog . ShowCustomConfirm ( dialogTitle , translate ( "Yes" ) , translate ( "No" ) , dialogContent , confirmDialogCallbackFunction , window )
} ) )
pageContent := container . NewVBox ( continentRow , widget . NewSeparator ( ) , percentageRow , submitButton )
return pageContent , nil
}
regionLabel := getBoldLabel ( "Region:" )
handleRegionSelectFunction := func ( newRegion string ) {
if ( regionProvided == true && currentRegion == newRegion ) {
return
}
setBuildMateProfilePage_23andMe_AncestryComposition_AddLocation ( window , true , currentContinent , true , newRegion , false , "" , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , previousPage , nextPage )
}
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 ) {
submitButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newPercentageRaw := percentageEntry . Text
newPercentage := strings . TrimSuffix ( newPercentageRaw , "%" )
newPercentageFloat64 , err := helpers . ConvertStringToFloat64 ( newPercentage )
if ( err != nil ) {
showInvalidPercentageDialog ( )
return
}
if ( newPercentageFloat64 <= 0 || newPercentageFloat64 > 100 ) {
showInvalidPercentageDialog ( )
return
}
addRegionFunction := func ( ) {
myRegionPercentagesMap [ currentRegion ] = newPercentageFloat64
nextPage ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
}
existingPercentage , exists := myRegionPercentagesMap [ currentRegion ]
if ( exists == false ) {
addRegionFunction ( )
return
}
// We allow user to confirm they want to overwrite existing value
currentPercentageString := helpers . ConvertFloat64ToStringRounded ( existingPercentage , 1 )
confirmDialogCallbackFunction := func ( response bool ) {
if ( response == true ) {
addRegionFunction ( )
}
}
dialogTitle := translate ( "Confirm Overwrite Existing" )
dialogMessageA := getLabelCentered ( "You already have a percentage for " + currentRegion )
dialogMessageB := getLabelCentered ( "Current Percentage: " + currentPercentageString + "%" )
dialogMessageC := getLabelCentered ( "Confirm to overwrite this percentage?" )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB , dialogMessageC )
dialog . ShowCustomConfirm ( dialogTitle , translate ( "Yes" ) , translate ( "No" ) , dialogContent , confirmDialogCallbackFunction , window )
} ) )
pageContent := container . NewVBox ( continentRow , widget . NewSeparator ( ) , regionRow , widget . NewSeparator ( ) , percentageRow , submitButton )
return pageContent , nil
}
subregionLabel := getBoldLabel ( "Subregion:" )
handleSubregionSelectFunction := func ( newSubregion string ) {
if ( subregionProvided == true && currentSubregion == newSubregion ) {
return
}
setBuildMateProfilePage_23andMe_AncestryComposition_AddLocation ( window , true , currentContinent , true , currentRegion , true , newSubregion , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , previousPage , nextPage )
}
subregionSelector := widget . NewSelect ( subregionsList , handleSubregionSelectFunction )
if ( subregionProvided == true ) {
subregionSelector . Selected = currentSubregion
}
subregionRow := container . NewHBox ( layout . NewSpacer ( ) , subregionLabel , subregionSelector , layout . NewSpacer ( ) )
submitButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
if ( subregionProvided == false ) {
dialogTitle := translate ( "Missing Subregion" )
dialogMessage := getLabelCentered ( translate ( "You must select a subregion." ) )
dialogContent := container . NewVBox ( dialogMessage )
dialog . ShowCustom ( dialogTitle , translate ( "Close" ) , dialogContent , window )
return
}
newPercentageRaw := percentageEntry . Text
newPercentage := strings . TrimSuffix ( newPercentageRaw , "%" )
newPercentageFloat64 , err := helpers . ConvertStringToFloat64 ( newPercentage )
if ( err != nil ) {
showInvalidPercentageDialog ( )
return
}
if ( newPercentageFloat64 <= 0 || newPercentageFloat64 > 100 ) {
showInvalidPercentageDialog ( )
return
}
addSubregionFunction := func ( ) {
mySubregionPercentagesMap [ currentSubregion ] = newPercentageFloat64
nextPage ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
}
existingPercentage , exists := mySubregionPercentagesMap [ currentSubregion ]
if ( exists == false ) {
addSubregionFunction ( )
return
}
// We allow user to confirm they want to overwrite existing value
currentPercentageString := helpers . ConvertFloat64ToStringRounded ( existingPercentage , 1 )
confirmDialogCallbackFunction := func ( response bool ) {
if ( response == true ) {
addSubregionFunction ( )
}
}
dialogTitle := translate ( "Confirm Overwrite Existing" )
dialogMessageA := getLabelCentered ( "You already have a percentage for " + currentSubregion )
dialogMessageB := getLabelCentered ( "Current Percentage: " + currentPercentageString + "%" )
dialogMessageC := getLabelCentered ( "Confirm to overwrite this percentage?" )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB , dialogMessageC )
dialog . ShowCustomConfirm ( dialogTitle , translate ( "Yes" ) , translate ( "No" ) , dialogContent , confirmDialogCallbackFunction , window )
} ) )
pageContent := container . NewVBox ( continentRow , widget . NewSeparator ( ) , regionRow , widget . NewSeparator ( ) , subregionRow , widget . NewSeparator ( ) , percentageRow , submitButton )
return pageContent , nil
}
pageContent , err := getPageContent ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , pageContent )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_AncestryComposition_DeleteLocation (
window fyne . Window ,
locationType string ,
myContinentPercentagesMap map [ string ] float64 ,
myRegionPercentagesMap map [ string ] float64 ,
mySubregionPercentagesMap map [ string ] float64 ,
previousPage func ( ) ,
nextPage func ( map [ string ] float64 , map [ string ] float64 , map [ string ] float64 ) ) {
if ( locationType != "Continent" && locationType != "Region" && locationType != "Subregion" ) {
setErrorEncounteredPage ( window , errors . New ( "setBuildMateProfilePage_23andMe_AncestryComposition_DeleteLocation called with invalid locationType: " + locationType ) , previousPage )
return
}
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
description := getLabelCentered ( "Select a location to delete." )
locationTypeLabel := getBoldLabelCentered ( "Location Type" )
locationTypesList := [ ] string { "Continent" , "Region" , "Subregion" }
handleLocationTypeSelectFunction := func ( newLocationType string ) {
if ( newLocationType == locationType ) {
return
}
setBuildMateProfilePage_23andMe_AncestryComposition_DeleteLocation ( window , newLocationType , myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap , previousPage , nextPage )
}
locationTypeSelector := widget . NewSelect ( locationTypesList , handleLocationTypeSelectFunction )
locationTypeSelector . Selected = locationType
locationTypeSelectorCentered := getWidgetCentered ( locationTypeSelector )
// This function either returns a "No (locationType) Exists" label or the locations grid.
getLocationsSection := func ( ) ( * fyne . Container , error ) {
if ( locationType == "Continent" && len ( myContinentPercentagesMap ) == 0 ) {
locationsSection := getBoldLabelCentered ( "No continents exist." )
return locationsSection , nil
}
if ( locationType == "Region" && len ( myRegionPercentagesMap ) == 0 ) {
locationsSection := getBoldLabelCentered ( "No regions exist." )
return locationsSection , nil
}
if ( locationType == "Subregion" && len ( mySubregionPercentagesMap ) == 0 ) {
locationsSection := getBoldLabelCentered ( "No subregions exist." )
return locationsSection , nil
}
locationLabel := getItalicLabelCentered ( locationType )
percentageLabel := getItalicLabelCentered ( "Percentage" )
emptyLabel := widget . NewLabel ( "" )
locationNameColumn := container . NewVBox ( locationLabel , widget . NewSeparator ( ) )
locationPercentageColumn := container . NewVBox ( percentageLabel , widget . NewSeparator ( ) )
deleteButtonsColumn := container . NewVBox ( emptyLabel , widget . NewSeparator ( ) )
addLocationRow := func ( locationName string , locationPercentage float64 ) error {
locationNameLabel := getBoldLabelCentered ( locationName )
locationPercentageString := helpers . ConvertFloat64ToStringRounded ( locationPercentage , 1 )
locationPercentageFormatted := locationPercentageString + "%"
locationPercentageLabel := getBoldLabelCentered ( locationPercentageFormatted )
deleteLocationButton := widget . NewButtonWithIcon ( "" , theme . DeleteIcon ( ) , func ( ) {
if ( locationType == "Continent" ) {
delete ( myContinentPercentagesMap , locationName )
} else if ( locationType == "Region" ) {
delete ( myRegionPercentagesMap , locationName )
} else if ( locationType == "Subregion" ) {
delete ( mySubregionPercentagesMap , locationName )
}
nextPage ( myContinentPercentagesMap , myRegionPercentagesMap , mySubregionPercentagesMap )
} )
locationNameColumn . Add ( locationNameLabel )
locationPercentageColumn . Add ( locationPercentageLabel )
deleteButtonsColumn . Add ( deleteLocationButton )
locationNameColumn . Add ( widget . NewSeparator ( ) )
locationPercentageColumn . Add ( widget . NewSeparator ( ) )
deleteButtonsColumn . Add ( widget . NewSeparator ( ) )
return nil
}
if ( locationType == "Continent" ) {
for continentName , continentPercentage := range myContinentPercentagesMap {
err := addLocationRow ( continentName , continentPercentage )
if ( err != nil ) { return nil , err }
}
} else if ( locationType == "Region" ) {
for regionName , regionPercentage := range myRegionPercentagesMap {
err := addLocationRow ( regionName , regionPercentage )
if ( err != nil ) { return nil , err }
}
} else if ( locationType == "Subregion" ) {
for subregionName , subregionPercentage := range mySubregionPercentagesMap {
err := addLocationRow ( subregionName , subregionPercentage )
if ( err != nil ) { return nil , err }
}
}
locationsGrid := container . NewHBox ( layout . NewSpacer ( ) , locationNameColumn , locationPercentageColumn , deleteButtonsColumn , layout . NewSpacer ( ) )
return locationsGrid , nil
}
locationsSection , err := getLocationsSection ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , locationTypeLabel , locationTypeSelectorCentered , widget . NewSeparator ( ) , locationsSection )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_NeanderthalVariants ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_23andMe_NeanderthalVariants ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "23andMe - Neanderthal Variants" ) )
description := getLabelCentered ( translate ( "Enter how many neanderthal variants you have." ) )
neanderthalVariantsEntry := widget . NewEntry ( )
variantCountExists , currentNeanderthalVariants , err := myLocalProfiles . GetProfileData ( "Mate" , "23andMe_NeanderthalVariants" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( variantCountExists == true ) {
isValid , err := helpers . VerifyStringIsIntWithinRange ( currentNeanderthalVariants , 0 , 7462 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( isValid == false ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfile contains invalid 23andMe neanderthalvariants." ) , previousPage )
return
}
neanderthalVariantsEntry . SetText ( currentNeanderthalVariants )
} else {
neanderthalVariantsEntry . SetPlaceHolder ( translate ( "Enter Variant Count" ) )
}
getCurrentNeanderthalVariantsCountLabel := func ( ) fyne . Widget {
if ( variantCountExists == false ) {
result := translate ( "No Response" )
variantsLabel := getBoldItalicLabel ( result )
return variantsLabel
}
variantsLabel := getBoldLabel ( currentNeanderthalVariants )
return variantsLabel
}
currentVariantCountLabel := getCurrentNeanderthalVariantsCountLabel ( )
myVariantCountLabel := widget . NewLabel ( "My Variant Count:" )
currentVariantsCountRow := container . NewHBox ( layout . NewSpacer ( ) , myVariantCountLabel , currentVariantCountLabel , layout . NewSpacer ( ) )
submitChangesButton := widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newVariantsCount := neanderthalVariantsEntry . Text
isValid , err := helpers . VerifyStringIsIntWithinRange ( newVariantsCount , 0 , 7462 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
if ( isValid == false ) {
neanderthalVariantsEntry . SetText ( "" )
neanderthalVariantsEntry . SetPlaceHolder ( translate ( "Enter Variant Count" ) )
dialogTitle := translate ( "Invalid Variant Count" )
dialogMessageA := getLabelCentered ( translate ( "Invalid neanderthal variants count entered." ) )
dialogMessageB := getLabelCentered ( translate ( "You must provide a number between 0 and 7462 variants." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( dialogTitle , translate ( "Close" ) , dialogContent , window )
return
}
err = myLocalProfiles . SetProfileData ( "Mate" , "23andMe_NeanderthalVariants" , newVariantsCount )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
variantsEntryWithSubmitButton := getContainerCentered ( container . NewGridWithRows ( 1 , neanderthalVariantsEntry , submitChangesButton ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "23andMe_NeanderthalVariants" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , currentVariantsCountRow , widget . NewSeparator ( ) , variantsEntryWithSubmitButton , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_23andMe_Haplogroup ( window fyne . Window , maternalOrPaternal string , previousPage func ( ) ) {
if ( maternalOrPaternal != "Maternal" && maternalOrPaternal != "Paternal" ) {
setErrorEncounteredPage ( window , errors . New ( "setBuildMateProfilePage_23andMe_Haplogroup called with invalid maternalOrPaternal: " + maternalOrPaternal ) , previousPage )
return
}
currentPage := func ( ) { setBuildMateProfilePage_23andMe_Haplogroup ( window , maternalOrPaternal , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "23andMe - " + maternalOrPaternal + " Haplogroup" ) )
maternalOrPaternalLowercase := strings . ToLower ( maternalOrPaternal )
description1 := getLabelCentered ( "Choose your " + maternalOrPaternalLowercase + " haplogroup." )
description2 := getLabelCentered ( "If it is not listed, enter it in manually." )
getKnownHaplogroupsList := func ( ) [ ] string {
if ( maternalOrPaternal == "Maternal" ) {
maternalHaplogroupsList := companyAnalysis . GetKnownMaternalHaplogroupsList_23andMe ( )
return maternalHaplogroupsList
}
paternalHaplogroupsList := companyAnalysis . GetKnownPaternalHaplogroupsList_23andMe ( )
return paternalHaplogroupsList
}
knownHaplogroupsList := getKnownHaplogroupsList ( )
haplogroupEntry := widget . NewSelectEntry ( knownHaplogroupsList )
attributeName := "23andMe_" + maternalOrPaternal + "Haplogroup"
haplogroupExists , currentHaplogroup , err := myLocalProfiles . GetProfileData ( "Mate" , attributeName )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( haplogroupExists == true ) {
if ( len ( currentHaplogroup ) > 25 ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid haplogroup: " + currentHaplogroup ) , previousPage )
return
}
haplogroupEntry . SetText ( currentHaplogroup )
} else {
haplogroupEntry . SetPlaceHolder ( translate ( "Select or enter haplogroup..." ) )
}
getCurrentHaplogroupLabel := func ( ) fyne . Widget {
if ( haplogroupExists == false ) {
result := translate ( "No Response" )
haplogroupLabel := getBoldItalicLabel ( result )
return haplogroupLabel
}
haplogroupLabel := getBoldLabel ( currentHaplogroup )
return haplogroupLabel
}
currentHaplogroupLabel := getCurrentHaplogroupLabel ( )
myHaplogroupLabel := widget . NewLabel ( "My " + maternalOrPaternal + " Haplogroup:" )
currentHaplogroupRow := container . NewHBox ( layout . NewSpacer ( ) , myHaplogroupLabel , currentHaplogroupLabel , layout . NewSpacer ( ) )
submitChangesButton := widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newHaplogroup := haplogroupEntry . Text
if ( newHaplogroup == "" ) {
title := translate ( "Invalid Haplogroup" )
dialogMessageA := getLabelCentered ( translate ( "Invalid haplogroup entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Your haplogroup cannot be empty." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
if ( len ( newHaplogroup ) > 25 ) {
haplogroupEntry . SetText ( "" )
haplogroupEntry . SetPlaceHolder ( translate ( "Select or enter haplogroup..." ) )
title := translate ( "Invalid Haplogroup" )
dialogMessageA := getLabelCentered ( translate ( "Invalid haplogroup entered." ) )
dialogMessageB := getLabelCentered ( translate ( "It must be less than 25 bytes." ) )
dialogMessageC := getLabelCentered ( translate ( "Contact the Seekia developers if this is too short to fit your haplogroup." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB , dialogMessageC )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
isAllowed := allowedText . VerifyStringIsAllowed ( newHaplogroup )
if ( isAllowed == false ) {
title := translate ( "Invalid Haplogroup" )
dialogMessageA := getLabelCentered ( translate ( "Your haplogroup contains an invalid character." ) )
dialogMessageB := getLabelCentered ( translate ( "It must be encoded in UTF-8." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
containsTabsOrNewlines := helpers . CheckIfStringContainsTabsOrNewlines ( newHaplogroup )
if ( containsTabsOrNewlines == true ) {
title := translate ( "Invalid Haplogroup" )
dialogMessageA := getLabelCentered ( translate ( "Your haplogroup contains a tab or a newline." ) )
dialogMessageB := getLabelCentered ( translate ( "Remove the character and resubmit." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
err := myLocalProfiles . SetProfileData ( "Mate" , attributeName , newHaplogroup )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
haplogroupEntryWithSubmitButton := getContainerCentered ( container . NewGridWithRows ( 1 , haplogroupEntry , submitChangesButton ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , attributeName )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description1 , description2 , widget . NewSeparator ( ) , currentHaplogroupRow , widget . NewSeparator ( ) , haplogroupEntryWithSubmitButton , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_Age ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_Age ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Age" ) )
description1 := getLabelCentered ( translate ( "Enter your age. You must be at least 18." ) )
description2 := getLabelCentered ( translate ( "You should update your age as you get older." ) )
ageEntry := widget . NewEntry ( )
ageExists , currentAge , err := myLocalProfiles . GetProfileData ( "Mate" , "Age" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( ageExists == true ) {
isValid , err := helpers . VerifyStringIsIntWithinRange ( currentAge , 18 , 150 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( isValid == false ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid age." ) , previousPage )
return
}
ageEntry . SetText ( currentAge )
} else {
ageEntry . SetPlaceHolder ( translate ( "Enter Age" ) )
}
getCurrentAgeLabel := func ( ) fyne . Widget {
if ( ageExists == false ) {
result := translate ( "No Response" )
ageLabel := getBoldItalicLabel ( result )
return ageLabel
}
ageLabel := getBoldLabel ( currentAge )
return ageLabel
}
currentAgeLabel := getCurrentAgeLabel ( )
myAgeLabel := widget . NewLabel ( "My Age:" )
currentAgeRow := container . NewHBox ( layout . NewSpacer ( ) , myAgeLabel , currentAgeLabel , layout . NewSpacer ( ) )
submitChangesButton := widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newAge := ageEntry . Text
isValid , err := helpers . VerifyStringIsIntWithinRange ( newAge , 18 , 150 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
if ( isValid == false ) {
ageEntry . SetText ( "" )
ageEntry . SetPlaceHolder ( translate ( "Enter Age" ) )
title := translate ( "Invalid Age" )
dialogMessageA := getLabelCentered ( translate ( "Invalid age entered." ) )
dialogMessageB := getLabelCentered ( translate ( "You must be at least 18 to use Seekia." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
err = myLocalProfiles . SetProfileData ( "Mate" , "Age" , newAge )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
ageEntryWithSubmitButton := getContainerCentered ( container . NewGridWithRows ( 1 , ageEntry , submitChangesButton ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "Age" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description1 , description2 , widget . NewSeparator ( ) , currentAgeRow , widget . NewSeparator ( ) , ageEntryWithSubmitButton , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_GeneticInformation ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_GeneticInformation ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( translate ( "Genetic Information" ) )
description1 := widget . NewLabel ( "You can display your genetic information on your profile." )
shareGeneticInfoHelpButton := widget . NewButtonWithIcon ( "" , theme . QuestionIcon ( ) , func ( ) {
setProfileGenomeInfoExplainerPage ( window , currentPage )
} )
description1Row := container . NewHBox ( layout . NewSpacer ( ) , description1 , shareGeneticInfoHelpButton , layout . NewSpacer ( ) )
description2 := getLabelCentered ( "You must link your genome person to your profile." )
description3 := getLabelCentered ( "You can hide some or all of your genetic information." )
myGenomePersonIdentifierExists , myGenomePersonIdentifier , err := myLocalProfiles . GetProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( myGenomePersonIdentifierExists == true ) {
personFound , _ , _ , _ , err := myPeople . GetPersonInfo ( myGenomePersonIdentifier )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( personFound == false ) {
// Genome person was deleted
// We will delete the missing person and refresh the page
// We show a loading screen so the user can tell if this wrongfully keeps happening
setLoadingScreen ( window , "Build Mate Profile - Physical" , "Deleting old genome person identifier..." )
err := myLocalProfiles . DeleteProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentPage ( )
return
}
}
myPersonLabel := widget . NewLabel ( "My Person:" )
getCurrentPersonNameLabel := func ( ) ( fyne . Widget , error ) {
if ( myGenomePersonIdentifierExists == false ) {
noneLabel := getBoldItalicLabel ( translate ( "None" ) )
return noneLabel , nil
}
personFound , personName , _ , _ , err := myPeople . GetPersonInfo ( myGenomePersonIdentifier )
if ( err != nil ) { return nil , err }
if ( personFound == false ) {
return nil , errors . New ( "Genome person not found after being found already." )
}
personNameLabel := getBoldLabel ( personName )
return personNameLabel , nil
}
currentPersonNameLabel , err := getCurrentPersonNameLabel ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentPersonNameRow := container . NewHBox ( layout . NewSpacer ( ) , myPersonLabel , currentPersonNameLabel , layout . NewSpacer ( ) )
getChooseOrChangeButtonTextAndIcon := func ( ) ( string , fyne . Resource ) {
if ( myGenomePersonIdentifierExists == false ) {
result := translate ( "Choose Person" )
return result , theme . NavigateNextIcon ( )
}
result := translate ( "Change Person" )
return result , theme . DocumentCreateIcon ( )
}
chooseOrChangeButtonText , chooseOrChangeButtonIcon := getChooseOrChangeButtonTextAndIcon ( )
chooseOrChangePersonButton := getWidgetCentered ( widget . NewButtonWithIcon ( chooseOrChangeButtonText , chooseOrChangeButtonIcon , func ( ) {
setBuildMateProfilePage_EditGenomePerson ( window , currentPage , currentPage )
} ) )
if ( myGenomePersonIdentifierExists == false ) {
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1Row , description2 , description3 , widget . NewSeparator ( ) , currentPersonNameRow , chooseOrChangePersonButton )
setPageContent ( page , window )
return
}
currentlySharingLabel := getItalicLabelCentered ( "Currently Sharing:" )
//Outputs:
// -int: Total number of monogenic diseases
// -int: Number of monogenic diseases being shared
// -error
getNumberOfMonogenicDiseasesBeingSharedInfo := func ( ) ( int , int , error ) {
monogenicDiseaseNamesList , err := monogenicDiseases . GetMonogenicDiseaseNamesList ( )
if ( err != nil ) { return 0 , 0 , err }
totalMonogenicDiseases := len ( monogenicDiseaseNamesList )
totalMonogenicDiseasesBeingShared := 0
for _ , diseaseName := range monogenicDiseaseNamesList {
shareDiseaseInfoAttributeName := "ShareMonogenicDiseaseInfo_" + diseaseName
currentSharePreferenceExists , currentSharePreference , err := myLocalProfiles . GetProfileData ( "Mate" , shareDiseaseInfoAttributeName )
if ( err != nil ) { return 0 , 0 , err }
if ( currentSharePreferenceExists == true && currentSharePreference == "Yes" ) {
totalMonogenicDiseasesBeingShared += 1
}
}
return totalMonogenicDiseases , totalMonogenicDiseasesBeingShared , nil
}
//Outputs:
// -int: Total number of polygenic diseases
// -int: Number of polygenic diseases being shared
// -error
getNumberOfPolygenicDiseasesBeingSharedInfo := func ( ) ( int , int , error ) {
polygenicDiseaseNamesList , err := polygenicDiseases . GetPolygenicDiseaseNamesList ( )
if ( err != nil ) { return 0 , 0 , err }
totalPolygenicDiseases := len ( polygenicDiseaseNamesList )
totalPolygenicDiseasesBeingShared := 0
for _ , diseaseName := range polygenicDiseaseNamesList {
sharePolygenicDiseaseInfoAttributeName := "SharePolygenicDiseaseInfo_" + diseaseName
currentSharePreferenceExists , currentSharePreference , err := myLocalProfiles . GetProfileData ( "Mate" , sharePolygenicDiseaseInfoAttributeName )
if ( err != nil ) { return 0 , 0 , err }
if ( currentSharePreferenceExists == true && currentSharePreference == "Yes" ) {
totalPolygenicDiseasesBeingShared += 1
}
}
return totalPolygenicDiseases , totalPolygenicDiseasesBeingShared , nil
}
//Outputs:
// -int: Total number of traits
// -int: Number of traits being shared
// -error
getNumberOfTraitsBeingSharedInfo := func ( ) ( int , int , error ) {
traitNamesList , err := traits . GetTraitNamesList ( )
if ( err != nil ) { return 0 , 0 , err }
totalTraits := len ( traitNamesList )
totalTraitsBeingShared := 0
for _ , traitName := range traitNamesList {
shareTraitInfoAttributeName := "ShareTraitInfo_" + traitName
currentSharePreferenceExists , currentSharePreference , err := myLocalProfiles . GetProfileData ( "Mate" , shareTraitInfoAttributeName )
if ( err != nil ) { return 0 , 0 , err }
if ( currentSharePreferenceExists == true && currentSharePreference == "Yes" ) {
totalTraitsBeingShared += 1
}
}
return totalTraits , totalTraitsBeingShared , nil
}
totalMonogenicDiseases , numberOfMonogenicDiseasesBeingShared , err := getNumberOfMonogenicDiseasesBeingSharedInfo ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
totalPolygenicDiseases , numberOfPolygenicDiseasesBeingShared , err := getNumberOfPolygenicDiseasesBeingSharedInfo ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
totalTraits , numberOfTraitsBeingShared , err := getNumberOfTraitsBeingSharedInfo ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
totalMonogenicDiseasesString := helpers . ConvertIntToString ( totalMonogenicDiseases )
numberOfMonogenicDiseasesBeingSharedString := helpers . ConvertIntToString ( numberOfMonogenicDiseasesBeingShared )
numberOfMonogenicDiseasesBeingSharedLabel := getBoldLabelCentered ( "Monogenic Diseases: " + numberOfMonogenicDiseasesBeingSharedString + "/" + totalMonogenicDiseasesString )
totalPolygenicDiseasesString := helpers . ConvertIntToString ( totalPolygenicDiseases )
numberOfPolygenicDiseasesBeingSharedString := helpers . ConvertIntToString ( numberOfPolygenicDiseasesBeingShared )
numberOfPolygenicDiseasesBeingSharedLabel := getBoldLabelCentered ( "Polygenic Diseases: " + numberOfPolygenicDiseasesBeingSharedString + "/" + totalPolygenicDiseasesString )
totalTraitsString := helpers . ConvertIntToString ( totalTraits )
numberOfTraitsBeingSharedString := helpers . ConvertIntToString ( numberOfTraitsBeingShared )
numberOfTraitsBeingSharedLabel := getBoldLabelCentered ( "Traits: " + numberOfTraitsBeingSharedString + "/" + totalTraitsString )
changeVisibilityButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Change Visibility" , theme . DocumentCreateIcon ( ) , func ( ) {
setBuildMateProfilePage_ChangeGeneticInformationVisibility ( window , "MonogenicDiseases" , currentPage )
} ) )
currentGenomeLabel := widget . NewLabel ( "Current Genome:" )
getCurrentGenomeText := func ( ) ( string , error ) {
myGenomesMapList , err := myGenomes . GetAllPersonGenomesMapList ( myGenomePersonIdentifier )
if ( err != nil ) { return "" , err }
if ( len ( myGenomesMapList ) == 0 ) {
genomeText := translate ( "None" )
return genomeText , nil
}
if ( len ( myGenomesMapList ) == 1 ) {
myGenomeMap := myGenomesMapList [ 0 ]
myGenomeCompanyName , exists := myGenomeMap [ "CompanyName" ]
if ( exists == false ) {
return "" , errors . New ( "MyGenomesMapList is malformed: Genome map missing CompanyName" )
}
return myGenomeCompanyName , nil
}
currentCombinedGenomeToUse , err := myChosenAnalysis . GetMyCombinedGenomeToUse ( )
if ( err != nil ) { return "" , err }
result := translate ( currentCombinedGenomeToUse )
return result , nil
}
currentGenomeText , err := getCurrentGenomeText ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentGenomeTextLabel := getBoldLabel ( currentGenomeText )
currentGenomeRow := container . NewHBox ( layout . NewSpacer ( ) , currentGenomeLabel , currentGenomeTextLabel , layout . NewSpacer ( ) )
chooseGenomeButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Choose Genome" , theme . DocumentCreateIcon ( ) , func ( ) {
setBuildMateProfilePage_ChooseGeneticInformationGenome ( window , currentPage )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1Row , description2 , description3 , widget . NewSeparator ( ) , currentPersonNameRow , chooseOrChangePersonButton , widget . NewSeparator ( ) , currentlySharingLabel , numberOfMonogenicDiseasesBeingSharedLabel , numberOfPolygenicDiseasesBeingSharedLabel , numberOfTraitsBeingSharedLabel , changeVisibilityButton , widget . NewSeparator ( ) , currentGenomeRow , chooseGenomeButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_EditGenomePerson ( window fyne . Window , previousPage func ( ) , nextPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_EditGenomePerson ( window , previousPage , nextPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Choose Genome Person" )
description1 := getLabelCentered ( "Choose your genome person." )
description2 := getLabelCentered ( "You must first import your genome(s) on the Genetics page." )
description3 := getLabelCentered ( "As you import or remove genomes, the changes will be reflected in your profile." )
description4 := getLabelCentered ( "To avoid sharing information, you can hide some or all of your genetic information." )
description5 := getLabelCentered ( "Linking your genome person will enable you to view offspring analyses when viewing matches." )
myGenomePersonIdentifierExists , currentGenomePersonIdentifier , err := myLocalProfiles . GetProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( myGenomePersonIdentifierExists == true ) {
personFound , _ , _ , _ , err := myPeople . GetPersonInfo ( currentGenomePersonIdentifier )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( personFound == false ) {
// Genome person was deleted
// We will delete the missing person and refresh the page
// We show a loading screen so the user can tell if this wrongfully keeps happening
setLoadingScreen ( window , "Build Mate Profile - Physical" , "Deleting old genome person identifier..." )
err := myLocalProfiles . DeleteProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentPage ( )
return
}
}
getCurrentPersonNameLabel := func ( ) ( fyne . Widget , error ) {
if ( myGenomePersonIdentifierExists == false ) {
result := translate ( "None" )
noResponseLabel := getBoldItalicLabel ( result )
return noResponseLabel , nil
}
personFound , personName , _ , _ , err := myPeople . GetPersonInfo ( currentGenomePersonIdentifier )
if ( err != nil ) { return nil , err }
if ( personFound == false ) {
return nil , errors . New ( "Genome person not found after being found already." )
}
personNameLabel := getBoldLabel ( personName )
return personNameLabel , nil
}
currentPersonNameLabel , err := getCurrentPersonNameLabel ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentPersonLabel := widget . NewLabel ( "Current Person:" )
currentPersonNameRow := container . NewHBox ( layout . NewSpacer ( ) , currentPersonLabel , currentPersonNameLabel , layout . NewSpacer ( ) )
getSelectGenomePersonSection := func ( ) ( * fyne . Container , error ) {
allMyGenomePeopleMapList , err := myPeople . GetMyGenomePeopleMapList ( )
if ( err != nil ) { return nil , err }
if ( len ( allMyGenomePeopleMapList ) == 0 ) {
noPeopleExistLabel := getBoldLabel ( "No People Exist." )
createAPersonLabel := getLabelCentered ( "Create a person and import their genomes on the Genetics page." )
selectPersonSection := container . NewVBox ( noPeopleExistLabel , createAPersonLabel )
return selectPersonSection , nil
}
// Map Structure: Person Name -> Person Identifier
allGenomePersonNamesMap := make ( map [ string ] string )
for _ , personMap := range allMyGenomePeopleMapList {
personName , exists := personMap [ "PersonName" ]
if ( exists == false ) {
return nil , errors . New ( "MyGenomePeople map list is malformed: Item missing PersonName" )
}
personIdentifier , exists := personMap [ "PersonIdentifier" ]
if ( exists == false ) {
return nil , errors . New ( "MyGenomePeople map list is malformed: Item missing PersonIdentifier" )
}
_ , exists = allGenomePersonNamesMap [ personName ]
if ( exists == true ) {
return nil , errors . New ( "MyGenomePeople map list is malformed: Duplicate person names exist." )
}
allGenomePersonNamesMap [ personName ] = personIdentifier
}
allGenomePersonNamesList := helpers . GetListOfMapKeys ( allGenomePersonNamesMap )
personSelector := widget . NewSelect ( allGenomePersonNamesList , nil )
if ( myGenomePersonIdentifierExists == true ) {
personFound , personName , _ , _ , err := myPeople . GetPersonInfo ( currentGenomePersonIdentifier )
if ( err != nil ) { return nil , err }
if ( personFound == false ) {
return nil , errors . New ( "Genome person not found after being found already." )
}
personSelector . Selected = personName
} else {
personSelector . PlaceHolder = translate ( "Select Person..." )
}
submitButton := widget . NewButtonWithIcon ( "Submit" , theme . ConfirmIcon ( ) , func ( ) {
newPersonName := personSelector . Selected
if ( newPersonName == "" ) {
dialogTitle := translate ( "No Person Chosen" )
dialogMessageA := getLabelCentered ( translate ( "No person was chosen." ) )
dialogMessageB := getLabelCentered ( translate ( "Select a person from the selector." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( dialogTitle , translate ( "Close" ) , dialogContent , window )
return
}
newPersonIdentifier , exists := allGenomePersonNamesMap [ newPersonName ]
if ( exists == false ) {
setErrorEncounteredPage ( window , errors . New ( "New genome person identifier not found." ) , currentPage )
return
}
err := myLocalProfiles . SetProfileData ( "Mate" , "GenomePersonIdentifier" , newPersonIdentifier )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
nextPage ( )
} )
personSelectorWithSubmitButtonRow := container . NewHBox ( layout . NewSpacer ( ) , personSelector , submitButton , layout . NewSpacer ( ) )
removePersonButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "Remove Person" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
nextPage ( )
} ) )
selectGenomePersonSection := container . NewVBox ( personSelectorWithSubmitButtonRow , removePersonButton )
return selectGenomePersonSection , nil
}
selectGenomePersonSection , err := getSelectGenomePersonSection ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1 , description2 , description3 , description4 , description5 , widget . NewSeparator ( ) , currentPersonNameRow , widget . NewSeparator ( ) , selectGenomePersonSection )
setPageContent ( page , window )
}
func setBuildMateProfilePage_ChangeGeneticInformationVisibility ( window fyne . Window , informationCategory string , previousPage func ( ) ) {
if ( informationCategory != "MonogenicDiseases" && informationCategory != "PolygenicDiseases" && informationCategory != "Traits" ) {
setErrorEncounteredPage ( window , errors . New ( "setBuildMateProfilePage_ChangeGeneticInformationVisibility called with invalid informationCategory: " + informationCategory ) , previousPage )
return
}
currentPage := func ( ) { setBuildMateProfilePage_ChangeGeneticInformationVisibility ( window , informationCategory , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Change Genetic Information Visibility" )
description1 := getLabelCentered ( "Choose which information from your genome you want to share on your profile." )
description2 := getLabelCentered ( "You will still always be able to view offspring analyses for your matches." )
privacyWarningButton := getWidgetCentered ( widget . NewButtonWithIcon ( "Privacy Warning" , theme . WarningIcon ( ) , func ( ) {
setMateProfileGeneticInformationPrivacyWarningPage ( window , currentPage )
} ) )
currentCategoryLabel := getItalicLabelCentered ( "Current Category:" )
monogenicDiseasesTranslated := translate ( "Monogenic Diseases" )
polygenicDiseasesTranslated := translate ( "Polygenic Diseases" )
traitsTranslated := translate ( "Traits" )
categoriesList := [ ] string { monogenicDiseasesTranslated , polygenicDiseasesTranslated , traitsTranslated }
handleSelectFunction := func ( newChoice string ) {
getNewCategory := func ( ) string {
if ( newChoice == monogenicDiseasesTranslated ) {
return "MonogenicDiseases"
}
if ( newChoice == polygenicDiseasesTranslated ) {
return "PolygenicDiseases"
}
return "Traits"
}
newCategory := getNewCategory ( )
setBuildMateProfilePage_ChangeGeneticInformationVisibility ( window , newCategory , previousPage )
}
categorySelector := widget . NewSelect ( categoriesList , handleSelectFunction )
if ( informationCategory == "MonogenicDiseases" ) {
categorySelector . Selected = monogenicDiseasesTranslated
} else if ( informationCategory == "PolygenicDiseases" ) {
categorySelector . Selected = polygenicDiseasesTranslated
} else {
categorySelector . Selected = traitsTranslated
}
categorySelectorCentered := getWidgetCentered ( categorySelector )
// This returns a list of all MonogenicDiseaseNames, PolygenicDiseaseNames, or TraitNames
getItemNamesList := func ( ) ( [ ] string , error ) {
if ( informationCategory == "MonogenicDiseases" ) {
monogenicDiseaseNamesList , err := monogenicDiseases . GetMonogenicDiseaseNamesList ( )
if ( err != nil ) { return nil , err }
return monogenicDiseaseNamesList , nil
}
if ( informationCategory == "PolygenicDiseases" ) {
polygenicDiseaseNamesList , err := polygenicDiseases . GetPolygenicDiseaseNamesList ( )
if ( err != nil ) { return nil , err }
return polygenicDiseaseNamesList , nil
}
// informationCategory == "Traits"
traitNamesList , err := traits . GetTraitNamesList ( )
if ( err != nil ) { return nil , err }
return traitNamesList , nil
}
allItemNamesList , err := getItemNamesList ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
getCategoryTypeShareInfoPrefix := func ( ) string {
if ( informationCategory == "MonogenicDiseases" ) {
return "ShareMonogenicDiseaseInfo_"
}
if ( informationCategory == "PolygenicDiseases" ) {
return "SharePolygenicDiseaseInfo_"
}
return "ShareTraitInfo_"
}
categoryTypeShareInfoPrefix := getCategoryTypeShareInfoPrefix ( )
setAllItemShareAttributesToValue := func ( yesOrNo string ) error {
if ( yesOrNo != "Yes" && yesOrNo != "No" ) {
return errors . New ( "setAllItemShareAttributesToValue called with invalid yesOrNo: " + yesOrNo )
}
for _ , itemName := range allItemNamesList {
itemAttributeName := categoryTypeShareInfoPrefix + itemName
err := myLocalProfiles . SetProfileData ( "Mate" , itemAttributeName , yesOrNo )
if ( err != nil ) { return err }
}
return nil
}
shareAllButton := widget . NewButtonWithIcon ( "Share All" , theme . VisibilityIcon ( ) , func ( ) {
err := setAllItemShareAttributesToValue ( "Yes" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
hideAllButton := widget . NewButtonWithIcon ( "Hide All" , theme . VisibilityOffIcon ( ) , func ( ) {
err := setAllItemShareAttributesToValue ( "No" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
shareAndHideButtons := getContainerCentered ( container . NewGridWithRows ( 1 , shareAllButton , hideAllButton ) )
getCategoryItemsGrid := func ( ) ( * fyne . Container , error ) {
getItemTypeName := func ( ) string {
if ( informationCategory == "MonogenicDiseases" ) {
result := translate ( "Monogenic Disease" )
return result
}
if ( informationCategory == "PolygenicDiseases" ) {
result := translate ( "Polygenic Disease" )
return result
}
result := translate ( "Trait" )
return result
}
itemTypeName := getItemTypeName ( )
itemTypeNameLabel := getItalicLabelCentered ( itemTypeName + " " + translate ( "Name" ) )
shareInformationLabel := getItalicLabelCentered ( translate ( "Share Information?" ) )
itemNameColumn := container . NewVBox ( itemTypeNameLabel , widget . NewSeparator ( ) )
itemChecksColumn := container . NewVBox ( shareInformationLabel , widget . NewSeparator ( ) )
for _ , itemName := range allItemNamesList {
itemNameLabel := getBoldLabelCentered ( itemName )
itemAttributeName := categoryTypeShareInfoPrefix + itemName
itemCheck := widget . NewCheck ( "" , func ( newResponse bool ) {
newValueString := helpers . ConvertBoolToYesOrNoString ( newResponse )
err := myLocalProfiles . SetProfileData ( "Mate" , itemAttributeName , newValueString )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
} )
currentSharePreferenceExists , currentSharePreference , err := myLocalProfiles . GetProfileData ( "Mate" , itemAttributeName )
if ( err != nil ) { return nil , err }
if ( currentSharePreferenceExists == true && currentSharePreference == "Yes" ) {
itemCheck . Checked = true
}
itemCheckCentered := getWidgetCentered ( itemCheck )
itemNameColumn . Add ( itemNameLabel )
itemChecksColumn . Add ( itemCheckCentered )
itemNameColumn . Add ( widget . NewSeparator ( ) )
itemChecksColumn . Add ( widget . NewSeparator ( ) )
}
itemsGrid := container . NewHBox ( layout . NewSpacer ( ) , itemNameColumn , itemChecksColumn , layout . NewSpacer ( ) )
return itemsGrid , nil
}
categoryItemsGrid , err := getCategoryItemsGrid ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1 , description2 , privacyWarningButton , widget . NewSeparator ( ) , currentCategoryLabel , categorySelectorCentered , widget . NewSeparator ( ) , shareAndHideButtons , widget . NewSeparator ( ) , categoryItemsGrid )
setPageContent ( page , window )
}
func setMateProfileGeneticInformationPrivacyWarningPage ( window fyne . Window , previousPage func ( ) ) {
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Genetic Information Privacy Warning" )
description1 := getLabelCentered ( "By sharing genome information, users can read an analysis of an offspring created from you and them." )
description2 := getLabelCentered ( "When you share Polygenic Disease and Trait information, you are sharing specific locations on your genome." )
description3 := getLabelCentered ( "These locations represent a tiny fraction of your entire genome." )
description4 := getLabelCentered ( "These locations can still be used to create a unique genetic fingerprint, which can identify you." )
description5 := getLabelCentered ( "People will also be able to read your trait and polygenic disease risk information." )
description6 := getLabelCentered ( "For example, if you share Breast Cancer, users will know your Breast Cancer risk." )
description7 := getLabelCentered ( "When sharing Monogenic Disease information, you do not share specific locations." )
description8 := getLabelCentered ( "You instead share the probability of passing a monogenic disease variant to your offspring." )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1 , description2 , description3 , description4 , description5 , description6 , description7 , description8 )
setPageContent ( page , window )
}
func setBuildMateProfilePage_ChooseGeneticInformationGenome ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_ChooseGeneticInformationGenome ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Choose Genetic Information Genome" )
description1 := getLabelCentered ( "A single genome from your genetic analysis will be used for genetic calculations with other users." )
description2 := getLabelCentered ( "Your profile will also contain information from this genome if you choose to share any information." )
description3 := getLabelCentered ( "If you have only imported one genome, that will be the genome whose information is used." )
description4 := getLabelCentered ( "If you have multiple genomes, only 1 of the two combined genomes will be used." )
description5 := getLabelCentered ( "You can choose below which genome you want to use if you have imported multiple genomes." )
currentGenomeLabel := widget . NewLabel ( "Current Genome:" )
myGenomePersonIdentifierExists , myGenomePersonIdentifier , err := myLocalProfiles . GetProfileData ( "Mate" , "GenomePersonIdentifier" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( myGenomePersonIdentifierExists == false ) {
setErrorEncounteredPage ( window , errors . New ( "setBuildMateProfilePage_ChooseGeneticInformationGenome called when genome person is not established." ) , previousPage )
return
}
currentCombinedGenomeToUse , err := myChosenAnalysis . GetMyCombinedGenomeToUse ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
getCurrentGenomeText := func ( ) ( string , error ) {
myGenomesMapList , err := myGenomes . GetAllPersonGenomesMapList ( myGenomePersonIdentifier )
if ( err != nil ) { return "" , err }
if ( len ( myGenomesMapList ) == 0 ) {
genomeText := translate ( "None" )
return genomeText , nil
}
if ( len ( myGenomesMapList ) == 1 ) {
myGenomeMap := myGenomesMapList [ 0 ]
myGenomeCompanyName , exists := myGenomeMap [ "CompanyName" ]
if ( exists == false ) {
return "" , errors . New ( "MyGenomesMapList is malformed: Genome map missing CompanyName" )
}
return myGenomeCompanyName , nil
}
result := translate ( currentCombinedGenomeToUse )
return result , nil
}
currentGenomeText , err := getCurrentGenomeText ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentGenomeTextLabel := getBoldLabel ( currentGenomeText )
currentGenomeRow := container . NewHBox ( layout . NewSpacer ( ) , currentGenomeLabel , currentGenomeTextLabel , layout . NewSpacer ( ) )
combinedGenomeToUseLabel := getItalicLabel ( "Combined Genome To Use:" )
option1Translated := translate ( "Only Include Shared" )
option2Translated := translate ( "Only Exclude Conflicts" )
untranslatedOptionsMap := map [ string ] string {
option1Translated : "Only Include Shared" ,
option2Translated : "Only Exclude Conflicts" ,
}
selectorOptionsList := [ ] string { option1Translated , option2Translated }
combinedGenomeSelector := widget . NewSelect ( selectorOptionsList , func ( newSelection string ) {
newSelectionUntranslated , exists := untranslatedOptionsMap [ newSelection ]
if ( exists == false ) {
setErrorEncounteredPage ( window , errors . New ( "untranslatedOptionsMap missing selection: " + newSelection ) , currentPage )
return
}
err = myChosenAnalysis . SetMyCombinedGenomeToUse ( newSelectionUntranslated )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
combinedGenomeSelector . Selected = translate ( currentCombinedGenomeToUse )
combinedGenomeHelpButton := widget . NewButtonWithIcon ( "" , theme . QuestionIcon ( ) , func ( ) {
setCombinedGenomesExplainerPage ( window , currentPage )
} )
combinedGenomeSelectorWithHelpButton := container . NewBorder ( nil , nil , nil , combinedGenomeHelpButton , combinedGenomeSelector )
combinedGenomeSelectorWithLabel := getContainerCentered ( container . NewGridWithColumns ( 1 , combinedGenomeToUseLabel , combinedGenomeSelectorWithHelpButton ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1 , description2 , description3 , description4 , description5 , widget . NewSeparator ( ) , currentGenomeRow , widget . NewSeparator ( ) , combinedGenomeSelectorWithLabel )
setPageContent ( page , window )
}
func setBuildMateProfilePage_Height ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_Height ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Height" ) )
description := getLabelCentered ( translate ( "Enter your height." ) )
getCurrentMetricOrImperial := 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
}
currentMetricOrImperial , err := getCurrentMetricOrImperial ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
changeMetricOrImperialButton , err := getMetricImperialSwitchButton ( window , currentPage )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
currentUnitsLabel := getItalicLabel ( translate ( "Current Units:" ) )
metricOrImperialRow := container . NewHBox ( layout . NewSpacer ( ) , currentUnitsLabel , changeMetricOrImperialButton , layout . NewSpacer ( ) )
currentHeightExists , currentHeightCentimeters , err := myLocalProfiles . GetProfileData ( "Mate" , "Height" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
getCurrentHeightLabel := func ( ) ( fyne . Widget , error ) {
if ( currentHeightExists == false ) {
labelText := translate ( "No Response" )
label := getBoldItalicLabel ( labelText )
return label , nil
}
myHeightCentimetersFloat64 , err := helpers . ConvertStringToFloat64 ( currentHeightCentimeters )
if ( err != nil ) {
return nil , errors . New ( "MyLocalProfiles malformed: Contains invalid Height" )
}
if ( currentMetricOrImperial == "Metric" ) {
myHeightRounded := helpers . ConvertFloat64ToStringRounded ( myHeightCentimetersFloat64 , 2 )
centimetersTranslated := translate ( "centimeters" )
formattedResult := myHeightRounded + " " + centimetersTranslated
label := getBoldLabel ( formattedResult )
return label , nil
}
feetInchesString , err := helpers . ConvertCentimetersToFeetInchesTranslatedString ( myHeightCentimetersFloat64 )
if ( err != nil ) { return nil , err }
label := getBoldLabel ( feetInchesString )
return label , nil
}
currentHeightLabel , err := getCurrentHeightLabel ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
myHeightLabel := widget . NewLabel ( "My Height:" )
currentHeightRow := container . NewHBox ( layout . NewSpacer ( ) , myHeightLabel , currentHeightLabel , layout . NewSpacer ( ) )
getEnterHeightRow := func ( ) ( * fyne . Container , error ) {
if ( currentMetricOrImperial == "Metric" ) {
centimetersEntry := widget . NewEntry ( )
if ( currentHeightExists == false ) {
centimetersEntry . SetPlaceHolder ( translate ( "Enter Centimeters" ) )
} else {
centimetersEntry . SetText ( currentHeightCentimeters )
}
centimetersSubmitButton := widget . NewButtonWithIcon ( translate ( "Submit" ) , theme . ConfirmIcon ( ) , func ( ) {
newHeightCentimeters := centimetersEntry . Text
isValid , err := helpers . VerifyStringIsFloatWithinRange ( newHeightCentimeters , 30 , 400 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
if ( isValid == false ) {
centimetersEntry . SetText ( "" )
centimetersEntry . SetPlaceHolder ( translate ( "Enter Centimeters" ) )
title := translate ( "Invalid Height" )
dialogMessageA := getLabelCentered ( translate ( "Invalid height entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Height must be between 30 and 400 centimeters." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
err = myLocalProfiles . SetProfileData ( "Mate" , "Height" , newHeightCentimeters )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
centimetersLabel := widget . NewLabel ( translate ( "Centimeters" ) )
centimetersEntryWithLabel := container . NewGridWithRows ( 1 , centimetersEntry , centimetersLabel )
enterHeightRow := container . NewHBox ( layout . NewSpacer ( ) , centimetersEntryWithLabel , centimetersSubmitButton , layout . NewSpacer ( ) )
return enterHeightRow , nil
}
// MetricOrImperial == "Imperial"
/// Feet + Inches
feetLabel := widget . NewLabel ( translate ( "Feet" ) )
inchesLabel := widget . NewLabel ( translate ( "Inches" ) )
feetEntry := widget . NewEntry ( )
inchesEntry := widget . NewEntry ( )
if ( currentHeightExists == false ) {
feetEntry . SetPlaceHolder ( translate ( "Enter Feet" ) )
inchesEntry . SetPlaceHolder ( translate ( "Enter Inches" ) )
} else {
isValid , err := helpers . VerifyStringIsFloatWithinRange ( currentHeightCentimeters , 30 , 400 )
if ( err != nil ) { return nil , err }
if ( isValid == false ) { return nil , errors . New ( "MyLocalProfiles is malformed: Contains invalid height." ) }
currentHeightCentimetersFloat64 , err := helpers . ConvertStringToFloat64 ( currentHeightCentimeters )
if ( err != nil ) { return nil , err }
currentHeightFeet , currentHeightInches , err := helpers . ConvertCentimetersToFeetInches ( currentHeightCentimetersFloat64 )
if ( err != nil ) { return nil , err }
currentHeightFeetString := helpers . ConvertIntToString ( currentHeightFeet )
currentHeightInchesString := helpers . ConvertFloat64ToStringRounded ( currentHeightInches , 1 )
feetEntry . SetText ( currentHeightFeetString )
inchesEntry . SetText ( currentHeightInchesString )
}
feetInchesSubmitButton := widget . NewButtonWithIcon ( translate ( "Submit" ) , theme . ConfirmIcon ( ) , func ( ) {
newHeightFeet := feetEntry . Text
newHeightInches := inchesEntry . Text
newHeightFeetInt , err := helpers . ConvertStringToInt ( newHeightFeet )
if ( err != nil ) {
title := translate ( "Invalid Height" )
dialogMessageA := getLabelCentered ( translate ( "Invalid feet entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Feet must be a number." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
newHeightInchesFloat64 , err := helpers . ConvertStringToFloat64 ( newHeightInches )
if ( err != nil ) {
title := translate ( "Invalid Height" )
dialogMessageA := getLabelCentered ( translate ( "Invalid inches entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Inches must be a number." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
newHeightCentimeters , err := helpers . ConvertFeetInchesToCentimeters ( newHeightFeetInt , newHeightInchesFloat64 )
if ( err != nil ) {
title := translate ( "Invalid Height" )
dialogMessageA := getLabelCentered ( translate ( "Invalid height entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Height must be between 30 and 400 centimeters." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
if ( newHeightCentimeters < 30 || newHeightCentimeters > 400 ) {
title := translate ( "Invalid Height" )
dialogMessageA := getLabelCentered ( translate ( "Invalid height entered." ) )
dialogMessageB := getLabelCentered ( translate ( "Height must be between 30 and 400 centimeters." ) )
dialogContent := container . NewVBox ( dialogMessageA , dialogMessageB )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
newHeightCentimetersString := helpers . ConvertFloat64ToString ( newHeightCentimeters )
err = myLocalProfiles . SetProfileData ( "Mate" , "Height" , newHeightCentimetersString )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
feetEntryWithLabel := container . NewGridWithRows ( 1 , feetEntry , feetLabel )
inchesEntryWithLabel := container . NewGridWithRows ( 1 , inchesEntry , inchesLabel )
feetInchesEntryRow := getContainerCentered ( container . NewHBox ( layout . NewSpacer ( ) , feetEntryWithLabel , inchesEntryWithLabel , feetInchesSubmitButton , layout . NewSpacer ( ) ) )
return feetInchesEntryRow , nil
}
enterHeightRow , err := getEnterHeightRow ( )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "Height" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , metricOrImperialRow , widget . NewSeparator ( ) , currentHeightRow , widget . NewSeparator ( ) , enterHeightRow , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_Body ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_Body ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
subtitle := getPageSubtitleCentered ( "Body" )
description1 := getLabelCentered ( "Describe your body." )
description2 := getLabelCentered ( "Choose a value between 1 and 4 to describe each characteristic." )
description3 := getLabelCentered ( "1 = least fat/muscular human, 4 = most fat/muscular human." )
fatLabel := getBoldLabelCentered ( "Fat" )
fatSelector := widget . NewSelect ( [ ] string { "1" , "2" , "3" , "4" } , func ( newChoice string ) {
err := myLocalProfiles . SetProfileData ( "Mate" , "BodyFat" , newChoice )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
} )
fatSelector . PlaceHolder = "Select one..."
fatNoResponseButton := widget . NewButtonWithIcon ( "No Response" , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "BodyFat" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
fatColumn := container . NewVBox ( fatLabel , fatSelector , fatNoResponseButton )
currentFatValueExists , currentFatValue , err := myLocalProfiles . GetProfileData ( "Mate" , "BodyFat" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( currentFatValueExists == true ) {
fatSelector . Selected = currentFatValue
}
muscleLabel := getBoldLabelCentered ( "Muscle" )
muscleSelector := widget . NewSelect ( [ ] string { "1" , "2" , "3" , "4" } , func ( newChoice string ) {
err := myLocalProfiles . SetProfileData ( "Mate" , "BodyMuscle" , newChoice )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
} )
muscleSelector . PlaceHolder = "Select one..."
muscleNoResponseButton := widget . NewButtonWithIcon ( "No Response" , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "BodyMuscle" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
muscleColumn := container . NewVBox ( muscleLabel , muscleSelector , muscleNoResponseButton )
currentMuscleValueExists , currentMuscleValue , err := myLocalProfiles . GetProfileData ( "Mate" , "BodyMuscle" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( currentMuscleValueExists == true ) {
muscleSelector . Selected = currentMuscleValue
}
pageColumns := container . NewHBox ( layout . NewSpacer ( ) , widget . NewSeparator ( ) , fatColumn , widget . NewSeparator ( ) , muscleColumn , widget . NewSeparator ( ) , layout . NewSpacer ( ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , subtitle , widget . NewSeparator ( ) , description1 , description2 , description3 , widget . NewSeparator ( ) , pageColumns )
setPageContent ( page , window )
}
func setBuildMateProfilePage_EyeColor ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_EyeColor ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Eye Color" ) )
description1 := getLabelCentered ( translate ( "Select your eye color." ) )
description2 := getLabelCentered ( translate ( "Select more than 1 color if your eyes contain multiple colors." ) )
eyeColorExists , currentEyeColorAttribute , err := myLocalProfiles . GetProfileData ( "Mate" , "EyeColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
getCurrentEyeColorList := func ( ) [ ] string {
if ( eyeColorExists == false ) {
emptyList := make ( [ ] string , 0 )
return emptyList
}
currentEyeColorList := strings . Split ( currentEyeColorAttribute , "+" )
return currentEyeColorList
}
currentEyeColorList := getCurrentEyeColorList ( )
if ( len ( currentEyeColorList ) > 4 ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid eye color attribute" ) , previousPage )
return
}
getCurrentEyeColorLabel := func ( ) fyne . Widget {
if ( eyeColorExists == false ) {
result := translate ( "No Response" )
eyeColorLabel := getBoldItalicLabel ( result )
return eyeColorLabel
}
currentEyeColorFormatted := strings . Join ( currentEyeColorList , ", " )
eyeColorLabel := getBoldLabel ( currentEyeColorFormatted )
return eyeColorLabel
}
currentEyeColorLabel := getCurrentEyeColorLabel ( )
myEyeColorLabel := widget . NewLabel ( "My Eye Color:" )
currentEyeColorRow := container . NewHBox ( layout . NewSpacer ( ) , myEyeColorLabel , currentEyeColorLabel , layout . NewSpacer ( ) )
getEyeColorColumn := func ( colorName string , colorsList [ ] string ) ( * fyne . Container , error ) {
colorColumn := container . NewGridWithColumns ( 1 )
for _ , colorCode := range colorsList {
colorSquare , err := getColorSquareAsFyneImage ( colorCode )
if ( err != nil ) { return nil , err }
colorSquare . FillMode = canvas . ImageFillStretch
colorColumn . Add ( colorSquare )
}
chooseColorCheck := widget . NewCheck ( colorName , func ( newChoice bool ) {
getNewAttributeList := func ( ) [ ] string {
if ( newChoice == false ) {
2024-08-11 14:31:40 +02:00
newList , _ := helpers . DeleteAllMatchingItemsFromList ( currentEyeColorList , colorName )
2024-04-11 15:51:56 +02:00
return newList
}
newList := helpers . AddItemToStringListAndAvoidDuplicate ( currentEyeColorList , colorName )
return newList
}
newAttributeList := getNewAttributeList ( )
if ( len ( newAttributeList ) == 0 ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "EyeColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
return
}
newEyeColorAttribute := strings . Join ( newAttributeList , "+" )
err := myLocalProfiles . SetProfileData ( "Mate" , "EyeColor" , newEyeColorAttribute )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
colorSelected := slices . Contains ( currentEyeColorList , colorName )
if ( colorSelected == true ) {
chooseColorCheck . Checked = true
}
colorColumn . Add ( chooseColorCheck )
return colorColumn , nil
}
//TODO: Add Gray
blueColorsList := [ ] string { "4d71a6" , "9fa8a8" , "345269" }
greenColorsList := [ ] string { "333b26" , "6d712b" , "505216" }
amberColorsList := [ ] string { "6e5c18" , "694c19" , "684818" }
brownColorsList := [ ] string { "522613" , "47240f" , "2a110c" }
blueEyeColorColumn , err := getEyeColorColumn ( "Blue" , blueColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
greenEyeColorColumn , err := getEyeColorColumn ( "Green" , greenColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
amberEyeColorColumn , err := getEyeColorColumn ( "Amber" , amberColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
brownEyeColorColumn , err := getEyeColorColumn ( "Brown" , brownColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
selectEyeColorGrid := getContainerCentered ( container . NewGridWithColumns ( 4 , blueEyeColorColumn , greenEyeColorColumn , amberEyeColorColumn , brownEyeColorColumn ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "EyeColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description1 , description2 , widget . NewSeparator ( ) , currentEyeColorRow , widget . NewSeparator ( ) , selectEyeColorGrid , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_HairColor ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_HairColor ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Hair Color" ) )
description1 := getLabelCentered ( translate ( "Select your natural hair color." ) )
description2 := getLabelCentered ( translate ( "Select 2 colors if your hair color is an average of two colors." ) )
//TODO: What if hair is gray/white
// Users should probably select the color their hair was when they were a young adult. We should add gray or white as an option?
hairColorExists , currentHairColorAttribute , err := myLocalProfiles . GetProfileData ( "Mate" , "HairColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
getCurrentHairColorList := func ( ) [ ] string {
if ( hairColorExists == false ) {
emptyList := make ( [ ] string , 0 )
return emptyList
}
currentHairColorList := strings . Split ( currentHairColorAttribute , "+" )
return currentHairColorList
}
currentHairColorList := getCurrentHairColorList ( )
if ( len ( currentHairColorList ) > 4 ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid hair color attribute: " + currentHairColorAttribute ) , previousPage )
return
}
getCurrentHairColorLabel := func ( ) fyne . Widget {
if ( hairColorExists == false ) {
result := translate ( "No Response" )
hairColorLabel := getBoldItalicLabel ( result )
return hairColorLabel
}
currentHairColorFormatted := strings . Join ( currentHairColorList , "-" )
hairColorLabel := getBoldLabel ( currentHairColorFormatted )
return hairColorLabel
}
currentHairColorLabel := getCurrentHairColorLabel ( )
myHairColorLabel := widget . NewLabel ( "My Hair Color:" )
currentHairColorRow := container . NewHBox ( layout . NewSpacer ( ) , myHairColorLabel , currentHairColorLabel , layout . NewSpacer ( ) )
getHairColorColumn := func ( colorName string , colorsList [ ] string ) ( * fyne . Container , error ) {
colorColumn := container . NewGridWithColumns ( 1 )
for _ , colorCode := range colorsList {
colorSquare , err := getColorSquareAsFyneImage ( colorCode )
if ( err != nil ) { return nil , err }
colorSquare . FillMode = canvas . ImageFillStretch
colorColumn . Add ( colorSquare )
}
chooseColorCheck := widget . NewCheck ( colorName , func ( newChoice bool ) {
getNewAttributeList := func ( ) [ ] string {
if ( newChoice == false ) {
2024-08-11 14:31:40 +02:00
newList , _ := helpers . DeleteAllMatchingItemsFromList ( currentHairColorList , colorName )
2024-04-11 15:51:56 +02:00
return newList
}
newList := helpers . AddItemToStringListAndAvoidDuplicate ( currentHairColorList , colorName )
return newList
}
newAttributeList := getNewAttributeList ( )
if ( len ( newAttributeList ) > 2 ) {
currentPage ( )
title := translate ( "Too Many Colors" )
dialogMessageA := getLabelCentered ( translate ( "You can only select two colors." ) )
dialogContent := container . NewVBox ( dialogMessageA )
dialog . ShowCustom ( title , translate ( "Close" ) , dialogContent , window )
return
}
if ( len ( newAttributeList ) == 0 ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "HairColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
return
}
newHairColorAttribute := strings . Join ( newAttributeList , "+" )
err := myLocalProfiles . SetProfileData ( "Mate" , "HairColor" , newHairColorAttribute )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
colorSelected := slices . Contains ( currentHairColorList , colorName )
if ( colorSelected == true ) {
chooseColorCheck . Checked = true
}
colorColumn . Add ( chooseColorCheck )
return colorColumn , nil
}
blackColorsList := [ ] string { "242424" , "1d1719" , "070300" }
brownColorsList := [ ] string { "5d3629" , "362219" , "472c24" }
blondeColorsList := [ ] string { "efd8a6" , "edd096" , "a57d4d" }
orangeColorsList := [ ] string { "f5743a" , "8c5125" , "883713" }
blackHairColorColumn , err := getHairColorColumn ( "Black" , blackColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
brownHairColorColumn , err := getHairColorColumn ( "Brown" , brownColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
blondeHairColorColumn , err := getHairColorColumn ( "Blonde" , blondeColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
orangeHairColorColumn , err := getHairColorColumn ( "Orange" , orangeColorsList )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
selectHairColorGrid := getContainerCentered ( container . NewGridWithColumns ( 4 , blackHairColorColumn , brownHairColorColumn , blondeHairColorColumn , orangeHairColorColumn ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "HairColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description1 , description2 , widget . NewSeparator ( ) , currentHairColorRow , widget . NewSeparator ( ) , selectHairColorGrid , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_HairTexture ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_HairTexture ( window , previousPage ) }
title := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Hair Texture" ) )
description := getLabelCentered ( translate ( "Enter your natural hair texture." ) )
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" )
hairTextureOptionsMap := map [ string ] string {
option1Translated : "1" ,
option2Translated : "2" ,
option3Translated : "3" ,
option4Translated : "4" ,
option5Translated : "5" ,
option6Translated : "6" ,
}
hairTextureSelectorOptionsList := [ ] string { option1Translated , option2Translated , option3Translated , option4Translated , option5Translated , option6Translated }
hairTextureSelector := widget . NewRadioGroup ( hairTextureSelectorOptionsList , func ( response string ) {
if ( response == "" ) {
myLocalProfiles . DeleteProfileData ( "Mate" , "HairTexture" )
return
}
attributeValue , exists := hairTextureOptionsMap [ response ]
if ( exists == false ) {
setErrorEncounteredPage ( window , errors . New ( "hairTextureOptionsMap missing translated option: " + response ) , currentPage )
return
}
myLocalProfiles . SetProfileData ( "Mate" , "HairTexture" , attributeValue )
} )
exists , currentHairTexture , err := myLocalProfiles . GetProfileData ( "Mate" , "HairTexture" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( exists == true ) {
isValid , err := helpers . VerifyStringIsIntWithinRange ( currentHairTexture , 1 , 6 )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( isValid == false ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles contains invalid hair texture: " + currentHairTexture ) , previousPage )
return
}
if ( currentHairTexture == "1" ) {
hairTextureSelector . Selected = option1Translated
} else if ( currentHairTexture == "2" ) {
hairTextureSelector . Selected = option2Translated
} else if ( currentHairTexture == "3" ) {
hairTextureSelector . Selected = option3Translated
} else if ( currentHairTexture == "4" ) {
hairTextureSelector . Selected = option4Translated
} else if ( currentHairTexture == "5" ) {
hairTextureSelector . Selected = option5Translated
} else if ( currentHairTexture == "6" ) {
hairTextureSelector . Selected = option6Translated
}
}
hairTextureSelectorCentered := getWidgetCentered ( hairTextureSelector )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
myLocalProfiles . DeleteProfileData ( "Mate" , "HairTexture" )
currentPage ( )
} ) )
page := container . NewVBox ( title , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , hairTextureSelectorCentered , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_SkinColor ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_SkinColor ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Skin Color" ) )
description1 := getLabelCentered ( translate ( "Select your skin color." ) )
description2 := getLabelCentered ( translate ( "This may be difficult because skin color changes under different conditions." ) )
description3 := getLabelCentered ( translate ( "Try your best to choose the best option." ) )
description4 := getLabelCentered ( translate ( "Users are reminded of this when choosing their skin color desires." ) )
mySkinColorExists , currentSkinColorAttribute , err := myLocalProfiles . GetProfileData ( "Mate" , "SkinColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
if ( mySkinColorExists == true ) {
currentSkinColorInt , err := helpers . ConvertStringToInt ( currentSkinColorAttribute )
if ( err != nil ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles SkinColor is invalid: " + currentSkinColorAttribute ) , previousPage )
return
}
if ( currentSkinColorInt < 1 || currentSkinColorInt > 6 ) {
setErrorEncounteredPage ( window , errors . New ( "MyLocalProfiles SkinColor is invalid: " + currentSkinColorAttribute ) , previousPage )
return
}
}
getCurrentSkinColorLabel := func ( ) fyne . Widget {
if ( mySkinColorExists == false ) {
result := translate ( "No Response" )
skinColorLabel := getBoldItalicLabel ( result )
return skinColorLabel
}
skinColorLabel := getBoldLabel ( currentSkinColorAttribute )
return skinColorLabel
}
currentSkinColorLabel := getCurrentSkinColorLabel ( )
mySkinColorLabel := widget . NewLabel ( "My Skin Color:" )
currentSkinColorRow := container . NewHBox ( layout . NewSpacer ( ) , mySkinColorLabel , currentSkinColorLabel , layout . NewSpacer ( ) )
getSkinColorColumn := func ( colorIdentifier string , colorCode string ) ( * fyne . Container , error ) {
colorSquare , err := getColorSquareAsFyneImage ( colorCode )
if ( err != nil ) { return nil , err }
colorSquare . FillMode = canvas . ImageFillStretch
chooseColorCheck := widget . NewCheck ( colorIdentifier , func ( newChoice bool ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "SkinColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
err = myLocalProfiles . SetProfileData ( "Mate" , "SkinColor" , colorIdentifier )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} )
if ( colorIdentifier == currentSkinColorAttribute ) {
chooseColorCheck . Checked = true
}
colorColumn := container . NewGridWithColumns ( 1 , colorSquare , chooseColorCheck )
return colorColumn , nil
}
skinColorColumn_1 , err := getSkinColorColumn ( "1" , "f4e3da" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
skinColorColumn_2 , err := getSkinColorColumn ( "2" , "f5d6b9" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
skinColorColumn_3 , err := getSkinColorColumn ( "3" , "dabe91" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
skinColorColumn_4 , err := getSkinColorColumn ( "4" , "ba9175" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
skinColorColumn_5 , err := getSkinColorColumn ( "5" , "916244" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
skinColorColumn_6 , err := getSkinColorColumn ( "6" , "744d2d" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
selectSkinColorGrid := getContainerCentered ( container . NewGridWithColumns ( 6 , skinColorColumn_1 , skinColorColumn_2 , skinColorColumn_3 , skinColorColumn_4 , skinColorColumn_5 , skinColorColumn_6 ) )
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , "SkinColor" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description1 , description2 , description3 , description4 , widget . NewSeparator ( ) , currentSkinColorRow , widget . NewSeparator ( ) , selectSkinColorGrid , noResponseButton )
setPageContent ( page , window )
}
func setBuildMateProfilePage_Infections ( window fyne . Window , previousPage func ( ) ) {
currentPage := func ( ) { setBuildMateProfilePage_Infections ( window , previousPage ) }
pageTitle := getPageTitleCentered ( translate ( "Build Mate Profile - Physical" ) )
backButton := getBackButtonCentered ( previousPage )
pageSubtitle := getPageSubtitleCentered ( translate ( "Infections" ) )
description := getLabelCentered ( translate ( "Select the infections that you have." ) )
infectionNameColumn := container . NewVBox ( widget . NewSeparator ( ) )
radioButtonsColumn := container . NewVBox ( widget . NewSeparator ( ) )
noResponseButtonsColumn := container . NewVBox ( widget . NewSeparator ( ) )
addInfectionRow := func ( infectionName string , infectionAttributeName string ) error {
infectionNameLabel := getBoldLabelCentered ( infectionName )
yesTranslated := translate ( "Yes" )
noTranslated := translate ( "No" )
untranslatedOptionsMap := map [ string ] string {
yesTranslated : "Yes" ,
noTranslated : "No" ,
}
optionsList := [ ] string { yesTranslated , noTranslated }
yesNoSelector := widget . NewRadioGroup ( optionsList , func ( response string ) {
if ( response == "" ) {
_ = myLocalProfiles . DeleteProfileData ( "Mate" , infectionAttributeName )
return
}
responseUntranslated , exists := untranslatedOptionsMap [ response ]
if ( exists == false ) {
setErrorEncounteredPage ( window , errors . New ( "untranslatedOptionsMap missing response: " + response ) , currentPage )
return
}
_ = myLocalProfiles . SetProfileData ( "Mate" , infectionAttributeName , responseUntranslated )
} )
yesNoSelector . Horizontal = true
myCurrentStatusExists , myCurrentInfectionStatus , err := myLocalProfiles . GetProfileData ( "Mate" , infectionAttributeName )
if ( err != nil ) { return err }
if ( myCurrentStatusExists == true ) {
yesNoSelector . Selected = translate ( myCurrentInfectionStatus )
}
noResponseButton := getWidgetCentered ( widget . NewButtonWithIcon ( translate ( "No Response" ) , theme . CancelIcon ( ) , func ( ) {
err := myLocalProfiles . DeleteProfileData ( "Mate" , infectionAttributeName )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , currentPage )
return
}
currentPage ( )
} ) )
infectionNameColumn . Add ( infectionNameLabel )
radioButtonsColumn . Add ( yesNoSelector )
noResponseButtonsColumn . Add ( noResponseButton )
infectionNameColumn . Add ( widget . NewSeparator ( ) )
radioButtonsColumn . Add ( widget . NewSeparator ( ) )
noResponseButtonsColumn . Add ( widget . NewSeparator ( ) )
return nil
}
err := addInfectionRow ( "HIV" , "HasHIV" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
err = addInfectionRow ( "Genital Herpes" , "HasGenitalHerpes" )
if ( err != nil ) {
setErrorEncounteredPage ( window , err , previousPage )
return
}
infectionsGrid := container . NewHBox ( layout . NewSpacer ( ) , infectionNameColumn , radioButtonsColumn , noResponseButtonsColumn , layout . NewSpacer ( ) )
page := container . NewVBox ( pageTitle , backButton , widget . NewSeparator ( ) , pageSubtitle , widget . NewSeparator ( ) , description , widget . NewSeparator ( ) , infectionsGrid )
setPageContent ( page , window )
}