File: Frigcal/code/Frigcal--source/allscreens.kv

#===============================================================================
# Define GUI screens, included in main.kv, used in main.kv and main.py
#
# Screens are primary windows in the App.  They are not modal, but only
# one screen can be shown at a time in Kivy apps (and mobile, generally).
# In FC, they are switched by main-menu options, unlike PPUS's tabs.
# See _dev-misc/kivy-dev-notes.txt for notes and temp code trimmed here.
#===============================================================================



#------------------------------------------------------------------------------
# LOCAL CLASSES
#------------------------------------------------------------------------------


# for shared LabelTextDisplay: get in main.kv only, else warning
##:include common.kv



# HAMBURGER-BUTTON PADDING

# To avoid overlaying the hamburger-button with screen content, define
# the screen label redundantly on each screen, and insert a small amount 
# of padding to the top of of each screen's content layout (not to its
# label: that skews the label too much).

# Caveat: space is a premium in this app and the padding both heuristic
# and platform dependent.  On Android, dp(8) nearly sufficed, but one of 
# ~ten test devices required >= dp(10).  On Windows, there is more wasted
# top space, but there is more room in general.  Kivy dp() accounts for 
# screen density and sp() also accounts for host-device font-size settings,
# but the latter seems no different in this context.


<ScreenLayout@MDBoxLayout>:
    orientation: 'vertical'
    pos_hint: {'top': 1}               # required to place at top of window
    padding: [0, dp(12), 0, 0]         # [l, t, r, b]: over hb button overlays
    #adaptive_height: True             # kills Month, unneeded in Help/About


<ScreenLabel@MDLabel>:
    markup: True                       # use [] for bold, italic, under, etc.
    halign: 'center'
    theme_text_color: 'Primary'        # white or black to keep ('Secondary' is grey)
    size_hint_y: None

    #adaptive_height: True
    #text: f'{root.height=}, {topbar.height=}, {navlayout.height=}' 



# DEV NOTES

# Single tap on MonthScreen label == Today == double tap on screen
# Fail: cannot tap hamburger button, and it's not worth resolving
#
#<TappableScreenLabel@ButtonBehavior+ScreenLabel>:
#    on_release: None



# DAY-CELL BORDERS (docs only)

# BorderedDayLayout is now defined in Python only (monthgui.py) because
# it is used to create widgets dynamically in Python code.  It was formerly
# here for its canvas.after border code, but this can be done in .py too,
# and, unlike widgets, coding the class _both_ here an in .py generated a 
# startup warning and ignored the version here.  It may work in both sans
# the superclass or differening property values; unknown and undocumented.

# border_width could be 1 to minimize its space taken, but this rendered 
# borders unevely on tested phones, with some borders slightly wider than 
# others (like CSS).  Using dp(1) was the same as abs 2 on tested phones.

# BoxLayout stacks fixed-size items from bottom up (sans a size_hint=(1, 1)
# dummy widget at bottom to fill the space that precludes later extension),
# and an AnchorLayout doesn't do top-down layouts; use a 1-col Grid in Grid; 

#<BorderedDayLayout@MDGridLayout>:
#    cols: 1
#    border_width: 2                              # Border width in pixels: 2px is a min
#    border_color: app.theme_cls.primary_color    # e.g., [1, 0, 0, 1] red border color (RGBA)
#
#    canvas.after:
#        Color:
#            rgba: root.border_color
#        Line:
#            width: root.border_width
#            rectangle: self.x, self.y, self.width, self.height
#
#    # plus subwidgets added in .py

# unused/incomplete/punt...
#<ThemedBorderBox@MDBoxLayout+BackgroundColorBehavior>:
#    orientation: 'vertical'
#    # binds the line_color to the theme's primary color
#    line_color: app.theme_cls.primary_color
#    line_width: 2



#------------------------------------------------------------------------------
# MONTH SCREEN
#------------------------------------------------------------------------------


<MonthScreen>:    

    # Super is MDScreen in .py
    # The app's main screen: month with days, days with events

    name: 'month'

    ScreenLayout:

        ScreenLabel:                       # swipable: see main.py
            id: screenlabel                # to access in .py 
            text: '[i]Month Year[/i]'      # set in .py

            # fail: cannot tap hamburger button 
            # on_release: app.on_menu_today(app.menuMonthItem) 

        GridLayout:
            id: monthgrid
            cols: 7

            # main.py adds bordered day cells
            # day cells have tappable numbers and scrolled+overlined events



#------------------------------------------------------------------------------
# SEARCH SCREEN
#------------------------------------------------------------------------------


<Spacing@MDLabel>
    size_hint_y: None
    height: 20           # TBD: dp()?



<SearchScreen>:    

    # Super is MDScreen in .py
    # Calendar search inputs and tappable results 

    name: 'search'
    #spacing: 20         # doesn't work here

    ScreenLayout:

        ScreenLabel:
            text: '[i]Search Calendars[/i]'

        FormTextField:                         # allpopups.kv: MDTextField, adaptive
            id: searchfor
            hint_text: 'Search for'

            # see notes at event-edit dialog
            use_handles: app.editbubbles == 'Enabled'    # select handles?
            use_bubble:  app.editbubbles == 'Enabled'    # select/longpress bubbles?

        Spacing:
        FormTextField:
            id: searchin
            hint_text: 'Search in'
            readonly: True                                            # no on-screen keyboard
            on_touch_down: 
                app.searchgui.on_search_field_touched(args[1], root)  # popup options menu

            #see allpopups.kv: k_m botches focus, o_f not run on android
            #keyboard_mode: 'managed'
            #on_focus: if self.focus: app.searchgui.on_search_field_focus(root)

        Spacing:
        MDLabel:
            id: resultslabel
            text: ''                        # set on search results in .py
            adaptive_height: True
            halign: 'center'
            disabled: True

        MDScrollView:

            # caveat: List doesn't hscroll - and trying was a big pita;
            # the builtin List.kv code does this to truncate instead:
            #
            # <BaseListItem>     # OneLineListItem's super
            #     BoxLayout:
            #         MDLabel:
            #             ...etc...
            #             shorten_from: "right"
            #             shorten: True
            #
            # which rules out hscroll: a [shorten: False] here or in .py
            # does not help given the nested structure, and hscroll likely 
            # requires kivy-code mods, which is a non-starter;  RecycleView 
            # may or may not hscroll but it's obfuscated;  web searches just
            # yield bogus size-setting chides (don't trust AI gossip, kids...)

            size_hint: (1, 1)
            do_scroll_y: True
            do_scroll_x: True                 # this doesn't work: see above
 
            effect_cls: ScrollEffect          # avoid snap-back animation throb: moot here?
            always_overscroll: False          # Kivy scroll-defect workaround: moot here?

            MDList:                           # in its code: an MDGridLayout
                id: searchresults

                adaptive_height: True         # enable scrolling, also set in MDList class
                #adaptive_width: True         # this doesn't work: see above
     
                # searchgui.py clears+adds list items on Search
                # adds OneLineListItem: a FloatLayout, with behaviors

        DialogButtonsRows1:

            DialogButton:
                text: 'Search'
                on_release: app.searchgui.on_search_button(root)



#------------------------------------------------------------------------------
# SETTINGS SCREEN
#------------------------------------------------------------------------------


<SettingsScreen>:    

   # Super is MDScreen in .py
   # User-setting configuration and saves

    name: 'settings'

    ScreenLayout:

        ScreenLabel:
            text: '[i]Configure Frigcal[/i]'

        ScrollView:

            id: settingsscroll
            do_scroll_y: True
            do_scroll_x: False               # vertical only
            effect_cls: 'ScrollEffect'       # don't overscroll/snapback (class or str)

            BoxLayout:
                id: settingsbox
                orientation: 'vertical'

                size_hint_y: None
                height: self.minimum_height

                spacing: 20                              # works here; TBD: use dp()?
                padding: [dp(8), dp(8), dp(8), dp(8)]    # [l, t, r, b]
  
                FormTextField:
                    id: colortheme
                    hint_text: 'Color theme'
                    readonly: True
                    on_touch_down: app.settingsgui.on_colortheme_touch(args[1])
                    #text: root.colortheme

                FormTextField:
                    id: globalfontsize            # too trivial for handles/bubbles
                    hint_text: 'Font size'
                    on_focus: if not self.focus: app.settingsgui.on_fontsize_defocus()
                    #text: root.globalfontsize

                # font-name setting was cut because setting Widget's font_name
                # globally breaks hamburger button and main-menu icons, and not
                # setting it means already-displayed text is not updated; and
                # font_name settings don't apply to all widgets, unlike font_size

                #FormTextField:
                #    id: globalfontname
                #    hint_text: 'Font name (new text)'
                #    readonly: True
                #    on_touch_down: app.settingsgui.on_fontname_touch(args[1])
                #    #text: root.globalfontname

                FormTextField:
                    id: maxbackups                # too trivial for handles/bubbles
                    hint_text: 'Max Backups'
                    on_focus: if not self.focus: app.settingsgui.on_maxbackups_defocus()
                    #text: root.maxbackups
  
                FormTextField:
                    id: editbubbles
                    hint_text: 'Edit bubbles'
                    readonly: True
                    on_touch_down: app.settingsgui.on_editbubbles_touch(args[1])
                    #text: root.editwidgets
               
                # punt on a ScrollView here: could not get text to hscroll
                # despite hours of trying - including the same just-awful 
                # private-member width calcs used in PPUS for its logs tab; 
                # this may have been because it used nested ScrollViews (?);
                #
                # instead, use multiline, which breaks at width and adds lines
                # as needed and may be better than scrolling in hindsight;
                # [shorten: True, shorten_from: 'right'] is another option, 
                # but phone users would not be able to see the truncated text;
                #
                # getting a ScollView to appear at all was a major ordeal: 
                # [size_hint_y: None] did the trick in the end, but Kivy 
                # widget layout settings can be frustrating and arduous;
                
                FormTextField:
                    id: calendarsfolder
                    hint_text: 'Calendars folder'
                    readonly: True                     # ro=no android kbd, but no focus
                    multiline: True
                    on_touch_down: app.settingsgui.on_calendarsfolder_touch(args[1])
                    #on_focus: if self.focus: app.settingsgui.on_calendarsfolder_focus()
                    #text: root.calendarsfolder
 
                # update: calendar colors dropped, categories/colors unchangeble;
                # lifting either constraint requires settings syncs across devices

                #FormTextField:
                #    id: calendarcolors
                #    hint_text: 'Calendar Colors'
                #    readonly: True
                #    on_touch_down: app.settingsgui.on_calendarcolors_touch(args[1])
                #    #text: root.calendarcolors

        DialogButtonsRows1:

            DialogButton:
                text: 'Save'
                on_release: app.settingsgui.on_settings_save(root)

            DialogButton:
                text: 'Restore'
                on_release: app.settingsgui.on_settings_restore(root)




#------------------------------------------------------------------------------
# HELP SCREEN
#------------------------------------------------------------------------------

<HelpScreen>:    

    # Super is MDScreen in .py
    # In-app helps as mark-up text and web links 

    name: 'help'

    ScreenLayout:

        ScreenLabel:
            text: '[i]Frigcal Help[/i]'

        MDScrollView:
            id: helptextscroll
            do_scroll_x: False

            # Labels display as empty black for any trivially-large
            # text, and Text fields don't do markup.  To workaround, 
            # split text into parts and span across multiple Labels. 

            SplitTextBoxLayout:
                id: helptextbox

                # main.py adds >= 1 LabelTextDisplay for split text
 
        DialogButtonsRows1:

            DialogButton:
                text: 'Docs'
                on_release: 
                    app.open_web_page('https://quixotely.com/Frigcal/User-Guide.html')

            DialogButton:
                text: 'Website'
                on_release: 
                    app.open_web_page('https://quixotely.com/Frigcal/index.html')

            DialogButton:
                text: 'Files'
                on_release: 
                    app.launch_file_explorer(folder=None)



#------------------------------------------------------------------------------
# ABOUT SCREEN
#------------------------------------------------------------------------------


<AboutScreen>:    

    # Super is MDScreen in .py
    # In-app logistics info as mark-up text and web links

    name: 'about'

    ScreenLayout:

        ScreenLabel:
            text: '[i]About Frigcal[/i]'

        MDScrollView:
            id: abouttextscroll
            do_scroll_x: False

            # Labels display as empty black for any trivially-large
            # text, and Text fields don't do markup.  To workaround, 
            # split text into parts and span across multiple Labels. 

            SplitTextBoxLayout:
                id: abouttextbox

                # main.py adds >= 1 LabelTextDisplay for split text

        DialogButtonsRows1:

            DialogButton:
                text: 'Play Store'
                on_release: 
                    app.open_web_page('https://play.google.com/store/apps/details?id=com.quixotely.frigcal')
            
            DialogButton
                text: 'Downloads'
                on_release: 
                    app.open_web_page('https://quixotely.com/Frigcal/App-Packages.html')

            DialogButton:
                text: 'Frigcal3'
                on_release: 
                    app.open_web_page('https://learning-python.com/frigcal.html')