3035 lines
106 KiB
Go
3035 lines
106 KiB
Go
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){
|
|
newList, _ := helpers.DeleteAllMatchingItemsFromList(currentEyeColorList, colorName)
|
|
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){
|
|
newList, _ := helpers.DeleteAllMatchingItemsFromList(currentHairColorList, colorName)
|
|
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)
|
|
}
|
|
|
|
|