File: Frigcal/code/Frigcal--source/common.kv
#===============================================================================
# Kivy-lang code common to / shared by multiple .kv files that #:include it
#===============================================================================
# Include this just once (#:include) before code that uses it; any .kv
# code loaded/run after this code is loaded/run has access to its names.
# Use kivy-lang variables (#:set) for repeated constants
# Use kivy-lang classes (<name@super>) for repeated code or common appearance
# Use Factory.name() or class name(super) in .py to access <name> class in .kv
# Use <name> in .kv to access [class name:] class defined in .py (via Factory)
#------------------------------------------------------------------------------
# Global imports and settings
#------------------------------------------------------------------------------
# for refs in py code here (TBD: unused?)
#:import os os
#:import sys sys
#:import Clock kivy.clock.Clock
# for phone/pc-specific tweaks (TBD: used?)
#:set RunningOnAndroid hasattr(sys, 'getandroidapilevel')
#:set RunningOnMacos sys.platform.startswith('darwin')
#:set RunningOnWindows sys.platform.startswith('win')
# for disabling glitchy overscroll effects
# ScrollView.effect_cls can be a class (here) or a string (looked up in Factory)
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
#------------------------------------------------------------------------------
# Global font size
#------------------------------------------------------------------------------
# Global font size, applied to _every_ Widget subclass by inheritance.
# Yes, it works, if bound to property app.dynamic_font_size, not self|root.
# TL;DR: font_size works but with KivyMD requires post-create rebinds and does
# not apply to drop-down menus. Ditto for font_name, but it was cut because
# (1) setting Widget's font_name globally also breaks the hamburger button
# and main-menu icons, and not setting it means already-displayed text isn't
# updated; and (2) font_name doesn't apply to all widgets, unlike font_size.
# KIVYMD OVERRIDES:
# Apps using KivyMD must also explicitly set font_size in .py code _after_
# creation for KivyMD widgets that override it per MD theme defaults or styles
# in their construction code. This is not required for base Kivy widgets, but
# is for some KivyMD widgets, including MDLabel and OneLineListItem used in
# this app. Set this in a widget-subclass instance, like LabelTextDisplay.
# For OneLineListItem, this must access the MDLabel embedded in the FloatLayout
# package by private _x widget id, which is subpar, but beats reimplementing OLLI.
# DROP-DOWNS CAVEAT:
# KivyMD drop-down menus in this app do not respect the Widget font size here,
# because there seems no way to access their OneLineListItems after their creation.
# Menus use a declarative dict, not widgets, and RecycleView may defer their widget
# builds. Hence, an open TBD, but punt for now: drop-down font size follows MD
# guidelines, for better or worse. See main.py and *_screen.py for setter code.
# FONT-NAME TRY:
# A related font name was later added on the settings screen. The font_name it
# sets globally in Widget is similarly overriden by KivyMD and must be reset post
# construction in all the same contexts as font_size to take effect. (This arose
# from an attempt at Emoji fonts, which seem a fail in 4.0: see monthgui.py.)
# FONT-NAME FAIL:
# Unlike font_size, we cannot set font_name for all Widget instances here,
# because KivyMD icons are implemented as characters in a specific icon font
# (Material Design Icons). These characters are not present in other fonts,
# so changing global font_name here breaks both the hamburger button and
# main-menu icons. Moreover, even with an all-widget setting here, font_name
# is not applied to every Widget like font_size but only to those expicitly
# bound to it post creation. This is likely due to other KivyMD overrides.
#
# THE VERDICT:
# Hence, keep the font_size setting, but drop font_name. For the latter, the
# best we could do is not set it in Widget here, but then it would apply only
# to new text, not to already-displayed text, and even so it would work only
# for a handful of widgets. This is inconsistent with font_size and convoluted
# to explain in Help, which are both bad signs. Given that its few built-in
# fonts make it marginal in the first place, it's not worth keeping or honing.
<Widget>:
font_size: app.dynamic_font_size # applied to every Widget-subclass instance (!)
#font_name: app.dynamic_font_name # likewise, with same KivyMD requirements (nope)
#------------------------------------------------------------------------------
# Text display fields
#------------------------------------------------------------------------------
<LabelTextDisplay@MDLabel>:
# for showing text in labels: dialogs, large-text splits
# TextInput/Field handles larger text, but has no markup
# use MDLabel for features, not TextInputNoSelect in .py
# font_size+name must be bound after created in .py else auto-set per MD
markup: True # use '[]' for bold, italic, under, etc.
multiline: True
do_wrap: True # also splits text on embedded \n
adaptive_height: True # enables scrolling: = [size_hint_y: None] + [height: self.minimum_height]
theme_text_color: 'Primary' # see also foreground_color, background_color
halign: 'left'
padding: dp(10) # h=v, or [h, v], was (8, 0, 8, 0) before density scaling
# other tries...
# readonly: True # labels have no readonly property
# adaptive_width: True # = [size_hint_x: None] + [width: self.minimum_width]
# font_size: app.dynamic_font_size # bind after create else kivymd overrides
# font_name: 'RobotoMono-Regular' # monospace (later a user Setting, also rebound)
<FormTextField@MDTextField_FixSelectPasteBubble>:
# for text input fields, with help-text labels
# use kivymd textfield for its label+styling
# override defaults here in concrete widgets
# uses main.py MDTextField with bubble workariund
text: '' # content set/fetched explicity in monthgui.py
mode: 'fill' # 'rectangle' broken in kivymd 2.3.1: use fill
adaptive_height: True # sizes to content, enables note vscrolls
multiline: False
text_color_normal: app.manual_theme_color_fg()
text_color_focus: app.manual_theme_color_fg()
use_handles: False # selection handles on taps
use_bubble: False # select/copy bubbles taps+longpress
#mode: 'rectangle', 'round', 'fill', 'line' (not 'outline')
#mode: 'rectangle' <= kivymd 1.2.0 bug: border line overlaps label, wrong bg
#pos_hint: {'center_x': .5, 'center_y': .5}
#padding: [dp(10), dp(10)] # scale to screen density
#------------------------------------------------------------------------------
# Multi-label text splits
#------------------------------------------------------------------------------
# Custom paddings and container for Label halves of Help and About screens
# A workaround to unreasonable Label text-size limts (see allscreens.kv)
<SplitTextBoxLayout@MDBoxLayout>:
orientation: 'vertical' # stack children on top of each other
adaptive_height: True # adjust height based on children's content
# NO LONGER USED: generalized for any size text and number labels in main.py
# Done to make Label textures smaller for old phones and pause/resume blanks
#
#<LabelTextDisplayHalf1@LabelTextDisplay>:
# padding: (dp(10), dp(10), dp(10), 0) # [left, top, right, bottom]
#
#<LabelTextDisplayHalf2@LabelTextDisplay>:
# padding: (dp(10), 0, dp(10), dp(10))
#
#<HalvesBoxLayout@MDBoxLayout>:
# orientation: 'vertical' # stack children on top of each other
# adaptive_height: True # adjust height based on children's content
#------------------------------------------------------------------------------
# Web-link and action buttons
#------------------------------------------------------------------------------
# Tbd: row height is a % relative to window size; use absolute dp() instead?
# or, use [height: buttonheight] to make rows consistent everywhere
# yes: a % grows/shrinks with window size on PCs oddly; use abs dp()
# use density-scaled pixels for varying displays
#:set buttonheight dp(40)
# use reponsive sizing for varying displays (now unused)
#:set dialogButtonRowHeight 0.08
<DialogButton@Button>
background_color: app.theme_cls.primary_color # was 'navy' pre kivymd
#border: (2, 2, 2, 2) # borders require canvas code
<DialogButtonsRows1@GridLayout>:
rows: 1
size_hint_y: None
height: buttonheight # and add N DialogButton, cols = N
<DialogButtonsRows2@GridLayout>:
rows: 2
size_hint_y: None
height: buttonheight * 2 # and add N DialogButton, cols = ceil(N / 2)
# was...
# GridLayout:
# cols: 2
# size_hint_y: dialogButtonRowHeight
# ...2 items, rows=1
#
# GridLayout:
# cols: 2
# size_hint_y: dialogButtonRowHeight * 2
# ...4 items, rows=2
#
# BoxLayout:
# size_hint_y: None
# height: buttonheight
# orientation: 'horizontal'
#------------------------------------------------------------------------------
# Temp dev notes
#------------------------------------------------------------------------------
# adaptive_height: True (in kivymd only)
# sizes to content, enables scrolls, and is the same as kivy's:
#
# size_hint_y: None # disable vertical size hint
# height: self.minimum_height # set to the sum of children's heights
#
# for labels, height may also be equivalently set to:
# height: self.texture_size[1] # adjust height based on widget's content