1
0
mirror of https://github.com/h7x4/Jisho-Study-Tool.git synced 2025-01-22 10:24:46 +01:00
Jisho-Study-Tool/lib/components/common/kanji_box.dart

185 lines
5.3 KiB
Dart
Raw Permalink Normal View History

2023-02-24 09:55:55 +01:00
import 'dart:math';
import 'package:flutter/material.dart';
import '../../bloc/theme/theme_bloc.dart';
import '../../settings.dart';
// TODO: Check that it looks right in
// - saved
/// The ratio is defined as 'the amount of space the text should take'
/// divided by 'the amount of space the padding should take'.
///
/// So if the KanjiBox should span 50 pixels, and you wanted 10 of those pixels
/// to be used for padding (5 on each side), and 40 to be used for the text,
/// you could write:
///
/// ```dart
/// KanjiBox.withRatioAndFontSize({
/// kanji: '例',
/// ratio: 4 / 1,
/// fontSize: 40,
/// })
/// ```
///
class KanjiBox extends StatelessWidget {
final String kanji;
final double? fontSize;
final double? padding;
final Color? foreground;
final Color? background;
final double? contentPaddingRatio;
final double borderRadius;
static const double defaultRatio = 3 / 1;
static const double defaultBorderRadius = 10;
double get ratio => contentPaddingRatio ?? fontSize! / padding!;
double get fontSizeFactor => ratio / (ratio + 1);
double get paddingSizeFactor => 1 / (ratio + 1);
bool get isExpanded => contentPaddingRatio != null;
double? get size => isExpanded ? null : fontSize! + (2 * padding!);
double? get oneSidePadding => padding != null ? padding! / 2 : null;
const KanjiBox._({
Key? key,
required this.kanji,
this.fontSize,
this.padding,
this.contentPaddingRatio,
this.foreground,
this.background,
this.borderRadius = defaultBorderRadius,
}) : assert(
kanji.length == 1,
'KanjiBox can not show more than one character at a time',
),
assert(
contentPaddingRatio != null || (fontSize != null && padding != null),
'Either contentPaddingRatio or both the fontSize and padding need to be '
'explicitly defined in order for the box to be able to render correctly',
),
super(key: key);
const factory KanjiBox.withFontSizeAndPadding({
required String kanji,
required double fontSize,
required double padding,
Color? foreground,
Color? background,
double borderRadius,
}) = KanjiBox._;
factory KanjiBox.withFontSize({
required String kanji,
required double fontSize,
double ratio = defaultRatio,
Color? foreground,
Color? background,
double borderRadius = defaultBorderRadius,
}) =>
KanjiBox._(
kanji: kanji,
fontSize: fontSize,
padding: pow(ratio * (1 / fontSize), -1).toDouble(),
foreground: foreground,
background: background,
borderRadius: borderRadius,
);
factory KanjiBox.withPadding({
required String kanji,
double ratio = defaultRatio,
required double padding,
Color? foreground,
Color? background,
double borderRadius = defaultBorderRadius,
}) =>
KanjiBox._(
kanji: kanji,
fontSize: ratio * padding,
padding: padding,
foreground: foreground,
background: background,
borderRadius: borderRadius,
);
factory KanjiBox.expanded({
required String kanji,
double ratio = defaultRatio,
Color? foreground,
Color? background,
double borderRadius = defaultBorderRadius,
}) =>
KanjiBox._(
kanji: kanji,
contentPaddingRatio: ratio,
foreground: foreground,
background: background,
borderRadius: borderRadius,
);
/// A shortcut
factory KanjiBox.headline4({
required BuildContext context,
required String kanji,
double ratio = defaultRatio,
Color? foreground,
Color? background,
double borderRadius = defaultBorderRadius,
}) =>
KanjiBox.withFontSize(
kanji: kanji,
fontSize: Theme.of(context).textTheme.headline4!.fontSize!,
ratio: ratio,
foreground: foreground,
background: background,
borderRadius: borderRadius,
);
@override
Widget build(BuildContext context) {
return BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state) {
final calculatedForeground =
foreground ?? state.theme.menuGreyLight.foreground;
final calculatedBackground =
background ?? state.theme.menuGreyLight.background;
return LayoutBuilder(
builder: (context, constraints) {
final sizeConstraint =
min(constraints.maxHeight, constraints.maxWidth);
final calculatedFontSize =
fontSize ?? sizeConstraint * fontSizeFactor;
final calculatedPadding =
oneSidePadding ?? (sizeConstraint * paddingSizeFactor) / 2;
return Container(
padding: EdgeInsets.all(calculatedPadding),
alignment: Alignment.center,
width: size,
height: size,
decoration: BoxDecoration(
color: calculatedBackground,
borderRadius: BorderRadius.circular(borderRadius),
),
child: FittedBox(
child: Text(
kanji,
textScaleFactor: 1,
style: TextStyle(
color: calculatedForeground,
fontSize: calculatedFontSize,
).merge(japaneseFont.textStyle),
),
),
);
},
);
},
);
}
}