@@ -9,6 +9,9 @@ import android.content.ClipData;
import android.content.ClipboardManager ;
import android.content.Context ;
import android.content.SharedPreferences ;
import android.graphics.Color ;
import android.graphics.drawable.GradientDrawable ;
import android.net.Uri ;
import android.graphics.Typeface ;
import android.os.Bundle ;
import android.text.Editable ;
@@ -31,26 +34,44 @@ import android.widget.Toast;
import androidx.annotation.NonNull ;
import androidx.annotation.Nullable ;
import androidx.appcompat.app.AlertDialog ;
import androidx.core.content.ContextCompat ;
import androidx.fragment.app.Fragment ;
import com.google.android.material.button.MaterialButton ;
import com.google.android.material.card.MaterialCardView ;
import com.google.android.material.dialog.MaterialAlertDialogBuilder ;
import java.text.SimpleDateFormat ;
import java.util.ArrayList ;
import java.util.Date ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
public final class ClockFragment extends Fragment {
private static final String PATTERN_ORIGIN_STATUSBAR = " statusbar " ;
private static final String PATTERN_ORIGIN_DRAWER_CLOCK = " drawer_clock " ;
private static final String PATTERN_ORIGIN_DRAWER_DATE = " drawer_date " ;
private static final int COLOR_STATUSBAR = 0xffe85050 ;
private static final int COLOR_DRAWER_CLOCK = 0xff4caf50 ;
private static final int COLOR_DRAWER_DATE = 0xff4f8cff ;
private static final int CARD_STROKE_DP = 2 ;
private final ArrayList < PreviewBinding > previewBindings = new ArrayList < > ( ) ;
private final ArrayList < StoredPatternBinding > storedPatternBindings = new ArrayList < > ( ) ;
private final ArrayList < StoredPatternRowBinding > storedPatternRowBindings = new ArrayList < > ( ) ;
private final Runnable previewTicker = new Runnable ( ) {
@Override
public void run ( ) {
boolean needsNextTick = false ;
HashMap < String , ClockPatternPreviewRenderer . Result > renderCache = new HashMap < > ( ) ;
for ( PreviewBinding binding : previewBindings ) {
needsNextTick | = updatePreview ( binding ) ;
}
for ( StoredPatternRowBinding binding : storedPatternRowBindings ) {
needsNextTick | = updateStoredPatternPreview ( binding , renderCache ) ;
}
if ( needsNextTick & & getView ( ) ! = null ) {
getView ( ) . postDelayed ( this , nextSecondDelayMillis ( ) ) ;
}
@@ -66,11 +87,14 @@ public final class ClockFragment extends Fragment {
SharedPreferences prefs = requireContext ( )
. getSharedPreferences ( SbtSettings . PREFS_NAME , Context . MODE_PRIVATE ) ;
MaterialCardView customFormatCard = root . findViewById ( R . id . clock_custom_format_card ) ;
CheckBox customFormatEnabled = root . findViewById ( R . id . clock_custom_format_enabled ) ;
View customFormatContainer = root . findViewById ( R . id . clock_custom_format_container ) ;
EditText customFormatInput = root . findViewById ( R . id . clock_custom_format_input ) ;
ClockPatternPreviewView customFormatPreview =
root . findViewById ( R . id . clock_custom_format_preview ) ;
MaterialCardView drawerClockCustomFormatCard =
root . findViewById ( R . id . drawer_clock_custom_format_card ) ;
CheckBox drawerClockCustomFormatEnabled =
root . findViewById ( R . id . drawer_clock_custom_format_enabled ) ;
View drawerClockCustomFormatContainer =
@@ -79,6 +103,8 @@ public final class ClockFragment extends Fragment {
root . findViewById ( R . id . drawer_clock_custom_format_input ) ;
ClockPatternPreviewView drawerClockCustomFormatPreview =
root . findViewById ( R . id . drawer_clock_custom_format_preview ) ;
MaterialCardView drawerDateCustomFormatCard =
root . findViewById ( R . id . drawer_date_custom_format_card ) ;
CheckBox drawerDateCustomFormatEnabled =
root . findViewById ( R . id . drawer_date_custom_format_enabled ) ;
View drawerDateCustomFormatContainer =
@@ -88,6 +114,8 @@ public final class ClockFragment extends Fragment {
ClockPatternPreviewView drawerDateCustomFormatPreview =
root . findViewById ( R . id . drawer_date_custom_format_preview ) ;
MaterialButton fontPickerButton = root . findViewById ( R . id . clock_font_picker_button ) ;
MaterialButton restoreStoredPatternsButton =
root . findViewById ( R . id . clock_restore_stored_patterns_button ) ;
TextView customFormatHelpToggle = root . findViewById ( R . id . clock_custom_format_help_toggle ) ;
View customFormatHelpContainer = root . findViewById ( R . id . clock_custom_format_help_container ) ;
TextView customFormatHelpCommon = root . findViewById ( R . id . clock_custom_format_help ) ;
@@ -115,12 +143,17 @@ public final class ClockFragment extends Fragment {
SbtDefaults . DRAWER_DATE_CUSTOM_FORMAT_DEFAULT ) ;
previewBindings . clear ( ) ;
storedPatternBindings . clear ( ) ;
ensureDefaultStoredPatterns ( prefs ) ;
bindCustomFormat (
prefs ,
customFormatCard ,
customFormatEnabled ,
customFormatContainer ,
customFormatInput ,
customFormatPreview ,
PATTERN_ORIGIN_STATUSBAR ,
COLOR_STATUSBAR ,
SbtSettings . KEY_CLOCK_CUSTOM_FORMAT_ENABLED ,
SbtSettings . KEY_CLOCK_CUSTOM_FORMAT ,
customFormatEnabledValue ,
@@ -129,10 +162,13 @@ public final class ClockFragment extends Fragment {
true ) ;
bindCustomFormat (
prefs ,
drawerClockCustomFormatCard ,
drawerClockCustomFormatEnabled ,
drawerClockCustomFormatContainer ,
drawerClockCustomFormatInput ,
drawerClockCustomFormatPreview ,
PATTERN_ORIGIN_DRAWER_CLOCK ,
COLOR_DRAWER_CLOCK ,
SbtSettings . KEY_DRAWER_CLOCK_CUSTOM_FORMAT_ENABLED ,
SbtSettings . KEY_DRAWER_CLOCK_CUSTOM_FORMAT ,
drawerClockCustomFormatEnabledValue ,
@@ -141,10 +177,13 @@ public final class ClockFragment extends Fragment {
false ) ;
bindCustomFormat (
prefs ,
drawerDateCustomFormatCard ,
drawerDateCustomFormatEnabled ,
drawerDateCustomFormatContainer ,
drawerDateCustomFormatInput ,
drawerDateCustomFormatPreview ,
PATTERN_ORIGIN_DRAWER_DATE ,
COLOR_DRAWER_DATE ,
SbtSettings . KEY_DRAWER_DATE_CUSTOM_FORMAT_ENABLED ,
SbtSettings . KEY_DRAWER_DATE_CUSTOM_FORMAT ,
drawerDateCustomFormatEnabledValue ,
@@ -169,6 +208,12 @@ public final class ClockFragment extends Fragment {
if ( fontPickerButton ! = null ) {
fontPickerButton . setOnClickListener ( v - > showFontPickerDialog ( ) ) ;
}
if ( restoreStoredPatternsButton ! = null ) {
restoreStoredPatternsButton . setOnClickListener ( v - > {
persistStoredPatterns ( prefs , mergeDefaultPatterns ( loadStoredPatterns ( prefs ) ) ) ;
renderAllStoredPatternLists ( prefs ) ;
} ) ;
}
return root ;
}
@@ -181,10 +226,13 @@ public final class ClockFragment extends Fragment {
}
private void bindCustomFormat ( SharedPreferences prefs ,
MaterialCardView card ,
CheckBox enabledView ,
View container ,
EditText input ,
ClockPatternPreviewView preview ,
String origin ,
int accentColor ,
String enabledKey ,
String formatKey ,
boolean enabled ,
@@ -194,6 +242,9 @@ public final class ClockFragment extends Fragment {
if ( enabledView = = null | | input = = null ) {
return ;
}
styleClockCard ( card , accentColor ) ;
styleBorderedView ( input , accentColor , 6 , 8 , 6 ) ;
styleBorderedView ( preview , accentColor , 8 , 10 , 8 ) ;
enabledView . setChecked ( enabled ) ;
input . setText ( format ! = null ? format : " " ) ;
if ( preview ! = null ) {
@@ -204,6 +255,17 @@ public final class ClockFragment extends Fragment {
updateCustomFormatVisibility ( container , enabled ) ;
PreviewBinding binding = new PreviewBinding ( enabledView , input , preview , multilinePreview ) ;
previewBindings . add ( binding ) ;
StoredPatternBinding storedBinding = createStoredPatternSection (
prefs ,
container ,
input ,
origin ,
accentColor ,
multilinePreview ) ;
if ( storedBinding ! = null ) {
storedPatternBindings . add ( storedBinding ) ;
renderStoredPatternList ( prefs , storedBinding ) ;
}
updatePreview ( binding ) ;
enabledView . setOnCheckedChangeListener ( ( buttonView , isChecked ) - > {
updateCustomFormatVisibility ( container , isChecked ) ;
@@ -233,6 +295,369 @@ public final class ClockFragment extends Fragment {
} ) ;
}
private void styleClockCard ( MaterialCardView card , int accentColor ) {
if ( card = = null ) {
return ;
}
card . setStrokeWidth ( ViewTreeSupport . dp ( card . getContext ( ) , CARD_STROKE_DP ) ) ;
card . setStrokeColor ( accentColor ) ;
}
private void styleBorderedView ( View view ,
int accentColor ,
int radiusDp ,
int horizontalPaddingDp ,
int verticalPaddingDp ) {
if ( view = = null ) {
return ;
}
Context context = view . getContext ( ) ;
GradientDrawable background = new GradientDrawable ( ) ;
background . setColor ( Color . TRANSPARENT ) ;
background . setCornerRadius ( ViewTreeSupport . dp ( context , radiusDp ) ) ;
background . setStroke ( ViewTreeSupport . dp ( context , CARD_STROKE_DP ) , accentColor ) ;
view . setBackground ( background ) ;
view . setPadding (
ViewTreeSupport . dp ( context , horizontalPaddingDp ) ,
ViewTreeSupport . dp ( context , verticalPaddingDp ) ,
ViewTreeSupport . dp ( context , horizontalPaddingDp ) ,
ViewTreeSupport . dp ( context , verticalPaddingDp ) ) ;
}
private StoredPatternBinding createStoredPatternSection (
SharedPreferences prefs ,
View container ,
EditText input ,
String origin ,
int accentColor ,
boolean multilinePreview
) {
if ( ! ( container instanceof LinearLayout parent ) | | input = = null ) {
return null ;
}
Context context = parent . getContext ( ) ;
MaterialButton toggle = new MaterialButton (
context ,
null ,
com . google . android . material . R . attr . materialButtonOutlinedStyle ) ;
toggle . setText ( R . string . clock_stored_patterns_show ) ;
LinearLayout . LayoutParams toggleParams = new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . WRAP_CONTENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ;
toggleParams . topMargin = ViewTreeSupport . dp ( context , 12 ) ;
parent . addView ( toggle , toggleParams ) ;
LinearLayout section = new LinearLayout ( context ) ;
section . setOrientation ( LinearLayout . VERTICAL ) ;
section . setVisibility ( View . GONE ) ;
parent . addView ( section , new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . MATCH_PARENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ) ;
TextView hint = new TextView ( context ) ;
hint . setText ( R . string . clock_stored_patterns_hint ) ;
hint . setTextAppearance ( android . R . style . TextAppearance_Material_Body2 ) ;
LinearLayout . LayoutParams hintParams = new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . MATCH_PARENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ;
hintParams . topMargin = ViewTreeSupport . dp ( context , 8 ) ;
section . addView ( hint , hintParams ) ;
LinearLayout list = new LinearLayout ( context ) ;
list . setOrientation ( LinearLayout . VERTICAL ) ;
section . addView ( list , new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . MATCH_PARENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ) ;
MaterialButton storeButton = new MaterialButton (
context ,
null ,
com . google . android . material . R . attr . materialButtonOutlinedStyle ) ;
storeButton . setText ( R . string . clock_store_current_pattern ) ;
LinearLayout . LayoutParams storeParams = new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . WRAP_CONTENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ;
storeParams . topMargin = ViewTreeSupport . dp ( context , 8 ) ;
section . addView ( storeButton , storeParams ) ;
StoredPatternBinding binding = new StoredPatternBinding (
input ,
origin ,
accentColor ,
multilinePreview ,
toggle ,
section ,
list ) ;
toggle . setOnClickListener ( v - > {
boolean show = section . getVisibility ( ) ! = View . VISIBLE ;
section . setVisibility ( show ? View . VISIBLE : View . GONE ) ;
toggle . setText ( show
? R . string . clock_stored_patterns_hide
: R . string . clock_stored_patterns_show ) ;
if ( show ) {
renderStoredPatternList ( prefs , binding ) ;
} else {
removeStoredPatternRowsFor ( binding ) ;
list . removeAllViews ( ) ;
schedulePreviewTickerIfNeeded ( ) ;
}
} ) ;
storeButton . setOnClickListener ( v - > {
String pattern = input . getText ( ) ! = null ? input . getText ( ) . toString ( ) : " " ;
storePattern ( prefs , pattern , origin ) ;
renderAllStoredPatternLists ( prefs ) ;
} ) ;
return binding ;
}
private void renderAllStoredPatternLists ( SharedPreferences prefs ) {
for ( StoredPatternBinding binding : storedPatternBindings ) {
renderStoredPatternList ( prefs , binding ) ;
}
}
private void renderStoredPatternList ( SharedPreferences prefs , StoredPatternBinding binding ) {
if ( binding = = null | | binding . listContainer = = null ) {
return ;
}
Context context = binding . listContainer . getContext ( ) ;
removeStoredPatternRowsFor ( binding ) ;
binding . listContainer . removeAllViews ( ) ;
if ( binding . section = = null | | binding . section . getVisibility ( ) ! = View . VISIBLE ) {
schedulePreviewTickerIfNeeded ( ) ;
return ;
}
ArrayList < StoredPattern > patterns = loadStoredPatterns ( prefs ) ;
for ( StoredPattern pattern : patterns ) {
binding . listContainer . addView ( createStoredPatternRow ( context , prefs , binding , pattern ) ) ;
}
schedulePreviewTickerIfNeeded ( ) ;
}
private View createStoredPatternRow (
Context context ,
SharedPreferences prefs ,
StoredPatternBinding binding ,
StoredPattern pattern
) {
LinearLayout row = new LinearLayout ( context ) ;
row . setOrientation ( LinearLayout . HORIZONTAL ) ;
row . setGravity ( android . view . Gravity . CENTER_VERTICAL ) ;
LinearLayout . LayoutParams rowParams = new LinearLayout . LayoutParams (
ViewGroup . LayoutParams . MATCH_PARENT ,
ViewGroup . LayoutParams . WRAP_CONTENT ) ;
rowParams . topMargin = ViewTreeSupport . dp ( context , 8 ) ;
row . setLayoutParams ( rowParams ) ;
ClockPatternPreviewView preview = new ClockPatternPreviewView ( context ) ;
preview . setPreviewTextAppearance (
requireContext ( ) . getColor ( R . color . sbt_on_surface ) ,
previewTextSizeForOrigin ( pattern . origin ) ) ;
styleBorderedView ( preview , colorForOrigin ( pattern . origin ) , 8 , 10 , 8 ) ;
StoredPatternRowBinding rowBinding = new StoredPatternRowBinding (
binding ,
preview ,
pattern . pattern ,
normaliseOrigin ( pattern . origin ) ,
binding . multilinePreview ) ;
storedPatternRowBindings . add ( rowBinding ) ;
updateStoredPatternPreview ( rowBinding , new HashMap < > ( ) ) ;
preview . setOnClickListener ( v - > {
binding . input . setText ( pattern . pattern ) ;
binding . input . setSelection ( binding . input . getText ( ) ! = null
? binding . input . getText ( ) . length ( )
: 0 ) ;
} ) ;
row . addView ( preview , new LinearLayout . LayoutParams (
0 ,
ViewGroup . LayoutParams . WRAP_CONTENT ,
1f ) ) ;
MaterialButton deleteButton = new MaterialButton ( context ) ;
deleteButton . setText ( " × " ) ;
deleteButton . setTextColor ( Color . WHITE ) ;
deleteButton . setBackgroundTintList ( android . content . res . ColorStateList . valueOf (
ContextCompat . getColor ( context , R . color . sbt_danger ) ) ) ;
deleteButton . setMinWidth ( 0 ) ;
deleteButton . setMinHeight ( 0 ) ;
deleteButton . setPadding ( 0 , 0 , 0 , 0 ) ;
deleteButton . setOnClickListener ( v - > {
deleteStoredPattern ( prefs , pattern . pattern ) ;
renderAllStoredPatternLists ( prefs ) ;
} ) ;
LinearLayout . LayoutParams deleteParams = new LinearLayout . LayoutParams (
ViewTreeSupport . dp ( context , 44 ) ,
ViewTreeSupport . dp ( context , 44 ) ) ;
deleteParams . leftMargin = ViewTreeSupport . dp ( context , 8 ) ;
row . addView ( deleteButton , deleteParams ) ;
return row ;
}
private void removeStoredPatternRowsFor ( StoredPatternBinding binding ) {
for ( int i = storedPatternRowBindings . size ( ) - 1 ; i > = 0 ; i - - ) {
if ( storedPatternRowBindings . get ( i ) . owner = = binding ) {
storedPatternRowBindings . remove ( i ) ;
}
}
}
private void ensureDefaultStoredPatterns ( SharedPreferences prefs ) {
if ( prefs = = null | | prefs . contains ( SbtSettings . KEY_CLOCK_STORED_PATTERNS ) ) {
return ;
}
persistStoredPatterns ( prefs , defaultStoredPatterns ( ) ) ;
}
private ArrayList < StoredPattern > mergeDefaultPatterns ( ArrayList < StoredPattern > current ) {
ArrayList < StoredPattern > result = current ! = null ? current : new ArrayList < > ( ) ;
for ( StoredPattern pattern : defaultStoredPatterns ( ) ) {
upsertPattern ( result , pattern . pattern , pattern . origin ) ;
}
return result ;
}
private ArrayList < StoredPattern > defaultStoredPatterns ( ) {
ArrayList < StoredPattern > patterns = new ArrayList < > ( ) ;
patterns . add ( new StoredPattern ( " H:mm:ss " , PATTERN_ORIGIN_STATUSBAR ) ) ;
patterns . add ( new StoredPattern ( " {big}H:mm:{/big color(#batterybar)}ss " , PATTERN_ORIGIN_STATUSBAR ) ) ;
patterns . add ( new StoredPattern (
" {@sans-serif-condensed-light color(#fff;#000)}|d{ \\ n30 big}H:mm:|{/big color(#batterybar invRGB 0.5 *RGB invRGB;#batterybar 0.5 *RGB)}ss " ,
PATTERN_ORIGIN_STATUSBAR ) ) ;
patterns . add ( new StoredPattern ( " {@sans-serif-condensed-light}H:mm:{small}ss " , PATTERN_ORIGIN_DRAWER_CLOCK ) ) ;
patterns . add ( new StoredPattern ( " EEE, d MMM " , PATTERN_ORIGIN_DRAWER_DATE ) ) ;
patterns . add ( new StoredPattern ( " EEE, MMM d " , PATTERN_ORIGIN_DRAWER_DATE ) ) ;
patterns . add ( new StoredPattern ( " {@sans-serif-condensed-light}EEEE, MMMM d " , PATTERN_ORIGIN_DRAWER_DATE ) ) ;
patterns . add ( new StoredPattern ( " {@sans-serif-condensed-light}EEEE, d MMMM " , PATTERN_ORIGIN_DRAWER_DATE ) ) ;
return patterns ;
}
private void storePattern ( SharedPreferences prefs , String pattern , String origin ) {
String value = pattern ! = null ? pattern . trim ( ) : " " ;
if ( value . isEmpty ( ) ) {
return ;
}
ArrayList < StoredPattern > patterns = loadStoredPatterns ( prefs ) ;
upsertPattern ( patterns , value , origin ) ;
persistStoredPatterns ( prefs , patterns ) ;
}
private void upsertPattern ( ArrayList < StoredPattern > patterns , String pattern , String origin ) {
if ( patterns = = null | | pattern = = null | | pattern . trim ( ) . isEmpty ( ) ) {
return ;
}
String value = pattern . trim ( ) ;
String resolvedOrigin = normaliseOrigin ( origin ) ;
for ( int i = 0 ; i < patterns . size ( ) ; i + + ) {
StoredPattern existing = patterns . get ( i ) ;
if ( existing ! = null & & value . equals ( existing . pattern ) ) {
patterns . set ( i , new StoredPattern ( value , resolvedOrigin ) ) ;
return ;
}
}
patterns . add ( new StoredPattern ( value , resolvedOrigin ) ) ;
}
private void deleteStoredPattern ( SharedPreferences prefs , String pattern ) {
ArrayList < StoredPattern > patterns = loadStoredPatterns ( prefs ) ;
for ( int i = patterns . size ( ) - 1 ; i > = 0 ; i - - ) {
StoredPattern existing = patterns . get ( i ) ;
if ( existing ! = null & & existing . pattern . equals ( pattern ) ) {
patterns . remove ( i ) ;
}
}
persistStoredPatterns ( prefs , patterns ) ;
}
private ArrayList < StoredPattern > loadStoredPatterns ( SharedPreferences prefs ) {
ArrayList < StoredPattern > patterns = new ArrayList < > ( ) ;
if ( prefs = = null ) {
return patterns ;
}
String encoded = prefs . getString ( SbtSettings . KEY_CLOCK_STORED_PATTERNS , " " ) ;
if ( encoded = = null | | encoded . isEmpty ( ) ) {
return patterns ;
}
String [ ] lines = encoded . split ( " \\ n " , - 1 ) ;
for ( String line : lines ) {
StoredPattern pattern = decodeStoredPattern ( line ) ;
if ( pattern = = null ) {
continue ;
}
upsertPattern ( patterns , pattern . pattern , pattern . origin ) ;
}
return patterns ;
}
private void persistStoredPatterns ( SharedPreferences prefs , ArrayList < StoredPattern > patterns ) {
if ( prefs = = null ) {
return ;
}
StringBuilder encoded = new StringBuilder ( ) ;
if ( patterns ! = null ) {
for ( StoredPattern pattern : patterns ) {
if ( pattern = = null | | pattern . pattern = = null | | pattern . pattern . trim ( ) . isEmpty ( ) ) {
continue ;
}
if ( encoded . length ( ) > 0 ) {
encoded . append ( '\n' ) ;
}
encoded . append ( normaliseOrigin ( pattern . origin ) )
. append ( '|' )
. append ( Uri . encode ( pattern . pattern ) ) ;
}
}
prefs . edit ( ) . putString ( SbtSettings . KEY_CLOCK_STORED_PATTERNS , encoded . toString ( ) ) . apply ( ) ;
}
private StoredPattern decodeStoredPattern ( String line ) {
if ( line = = null | | line . isEmpty ( ) ) {
return null ;
}
int split = line . indexOf ( '|' ) ;
if ( split < = 0 | | split > = line . length ( ) - 1 ) {
return null ;
}
String origin = normaliseOrigin ( line . substring ( 0 , split ) ) ;
String pattern = Uri . decode ( line . substring ( split + 1 ) ) ;
if ( pattern = = null | | pattern . trim ( ) . isEmpty ( ) ) {
return null ;
}
return new StoredPattern ( pattern . trim ( ) , origin ) ;
}
private String normaliseOrigin ( String origin ) {
if ( PATTERN_ORIGIN_DRAWER_CLOCK . equals ( origin )
| | PATTERN_ORIGIN_DRAWER_DATE . equals ( origin )
| | PATTERN_ORIGIN_STATUSBAR . equals ( origin ) ) {
return origin ;
}
return PATTERN_ORIGIN_STATUSBAR ;
}
private int colorForOrigin ( String origin ) {
switch ( normaliseOrigin ( origin ) ) {
case PATTERN_ORIGIN_DRAWER_CLOCK :
return COLOR_DRAWER_CLOCK ;
case PATTERN_ORIGIN_DRAWER_DATE :
return COLOR_DRAWER_DATE ;
case PATTERN_ORIGIN_STATUSBAR :
default :
return COLOR_STATUSBAR ;
}
}
private float previewTextSizeForOrigin ( String origin ) {
switch ( normaliseOrigin ( origin ) ) {
case PATTERN_ORIGIN_DRAWER_CLOCK :
return 24f ;
case PATTERN_ORIGIN_DRAWER_DATE :
return 16f ;
case PATTERN_ORIGIN_STATUSBAR :
default :
return 18f ;
}
}
private boolean updatePreview ( PreviewBinding binding ) {
if ( binding = = null | | binding . preview = = null ) {
return false ;
@@ -260,6 +685,36 @@ public final class ClockFragment extends Fragment {
return result . containsSeconds ( ) ;
}
private boolean updateStoredPatternPreview (
StoredPatternRowBinding binding ,
Map < String , ClockPatternPreviewRenderer . Result > cache
) {
if ( binding = = null
| | binding . preview = = null
| | binding . owner = = null
| | binding . owner . section = = null
| | binding . owner . section . getVisibility ( ) ! = View . VISIBLE ) {
return false ;
}
String key = binding . origin + " \ u0000 " + binding . multilinePreview + " \ u0000 " + binding . pattern ;
ClockPatternPreviewRenderer . Result result = cache ! = null ? cache . get ( key ) : null ;
if ( result = = null ) {
result = ClockPatternPreviewRenderer . render (
binding . preview . getContext ( ) ,
binding . pattern ,
binding . preview . getPreviewTextColor ( ) ) ;
if ( ! binding . multilinePreview ) {
result = flattenRows ( result ) ;
}
if ( cache ! = null ) {
cache . put ( key , result ) ;
}
}
binding . preview . setPreview ( result ) ;
binding . preview . setContentDescription ( result . contentDescription ( ) ) ;
return result . containsSeconds ( ) ;
}
private ClockPatternPreviewRenderer . Result flattenRows ( ClockPatternPreviewRenderer . Result result ) {
if ( result = = null | | result . rows ( ) = = null | | result . rows ( ) . size ( ) < = 1 ) {
return result ;
@@ -324,6 +779,8 @@ public final class ClockFragment extends Fragment {
view . removeCallbacks ( previewTicker ) ;
}
previewBindings . clear ( ) ;
storedPatternBindings . clear ( ) ;
storedPatternRowBindings . clear ( ) ;
super . onDestroyView ( ) ;
}
@@ -478,6 +935,29 @@ public final class ClockFragment extends Fragment {
private record PreviewBinding ( CheckBox enabled , EditText input , ClockPatternPreviewView preview , boolean multilinePreview ) {
}
private record StoredPatternBinding (
EditText input ,
String origin ,
int accentColor ,
boolean multilinePreview ,
MaterialButton toggle ,
View section ,
LinearLayout listContainer
) {
}
private record StoredPatternRowBinding (
StoredPatternBinding owner ,
ClockPatternPreviewView preview ,
String pattern ,
String origin ,
boolean multilinePreview
) {
}
private record StoredPattern ( String pattern , String origin ) {
}
private static final class FontFamilyAdapter extends BaseAdapter {
private static final String SAMPLE_PATTERN = " EEEE HH:mm:ss " ;