#=============================================================================== # 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. : 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 : 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 # #: # 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; #: # 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... #: # orientation: 'vertical' # # binds the line_color to the theme's primary color # line_color: app.theme_cls.primary_color # line_width: 2 #------------------------------------------------------------------------------ # MONTH SCREEN #------------------------------------------------------------------------------ : # 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 #------------------------------------------------------------------------------ size_hint_y: None height: 20 # TBD: dp()? : # 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: # # # 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 #------------------------------------------------------------------------------ : # 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 #------------------------------------------------------------------------------ : # 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 #------------------------------------------------------------------------------ : # 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')