Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color updates #368

Merged
merged 10 commits into from
May 24, 2022
32 changes: 28 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Date format: DD/MM/YYYY

## [3.x.0]
## [next]

- Show menu button on automatic minimal display mode ([#350](https://github.com/bdlukaa/fluent_ui/pull/350))
- **BREAKING** `Map<ShortcutActivator, Intent>?` is now the typed used on `FluentApp.shortcuts` ([#351](https://github.com/bdlukaa/fluent_ui/pull/351))
Expand All @@ -15,13 +15,37 @@ Date format: DD/MM/YYYY
- Updated card's background colors
- **BREAKING** Removed `Card.elevation`
- Added `Card.margin`, which is the margin around the card
- `InfoBar` updates:
- Added `InfoBar.isIconVisible`
- Updated its design to follow the new Win UI 3 guidelines
- Updated `Combobox` and `Button` designs
- Reviewed `DatePicker` and `TimePicker` ([#357](https://github.com/bdlukaa/fluent_ui/pull/357))
- Correctly apply dimensions and positions to both pickers
- Update the picker popup style and behavior
- Colors Update ([#368](https://github.com/bdlukaa/fluent_ui/pull/368)):
- Added `ResourceDictionary`, which provides default colors to be used on components
- (forms) Updated `Combobox` style. It now uses `Acrylic` on the combobox popup menu
- (buttons) Updated `Button`, `FilledButton`, `IconButton` and `TextButton` styles
- (toggleable inputs) Updated `Checkbox`, `Chip`, `RadioButton`, `RatingBar`, `ToggleButton` and `ToggleSwitch`
- **BREAKING** Updated `Slider`:
- `SliderThemeData.thumbColor`, `SliderThemeData.activeColor` and `SliderThemeData.inactiveColor` now are of type `ButtonState<Color?>?`, which handles the button color on different states. `SliderThemeData.disabledThumbColor`, `SliderThemeData.disabledActiveColor` and `SliderThemeData.disabledInactiveColor` were removed
- Before:
```dart
SliderThemeData(
thumbColor: Colors.green,
),
```
- Now:
```dart
SliderThemeData(
// Apply Colors.green for all button states. Instead you can use ButtonState.resolveWith to use different values according to the current state
thumbColor: ButtonState.all(Colors.green),
),
```
- (navigation) Updated `NavigationView`, `PaneItem` and `ScaffoldPage`
- Updated `TabView` and its tabs styles. A `FocusBorder` is now used to display the focus highlight of the tabs
- All combinations of `BorderRadius` can now be used on `FocusBorder`
- (surfaces) Updated `Card`, `ContentDialog`, `InfoBar`, `Expander`, `Flyout` and `Divider``
- Added `InfoBar.isIconVisible`
- (indicators) Updated `ProgressBar`, `ProgressRing` and `InfoBadge`
- (other) Added helper methods for `AccentColor`: `AccentColor.defaultBrushFor`, `AccentColor.secondaryBrushFor` and `AccentColor.tertiaryBrushFor`

## [3.12.0] - Flutter 3.0 - [13/05/2022]

Expand Down
176 changes: 176 additions & 0 deletions bin/dictionary_generator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// ignore_for_file: avoid_print

import 'dart:io';

import 'icon_generator.dart' show pathSeparator;
import 'resource_dictionary.dart';

const String fileHeader = """
// GENERATED FILE, DO NOT EDIT
// This generates the values from https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/Common_themeresources_any.xaml

// ignore_for_file: constant_identifier_names

import 'package:flutter/widgets.dart' show Color, ColorProperty;
import 'package:flutter/foundation.dart';

""";

const String header = '''
/// A dictionary of colors used by all the components.
///
/// Use `ResourceDictionary.dark` or `ResourceDictionary.light` to get colors
/// adapted to dark and light mode, respectively
///
/// See also:
///
/// * <https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/Common_themeresources_any.xaml>
class ResourceDictionary with Diagnosticable {
''';

/// How to generate the resources:
/// - Go on `https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/Common_themeresources_any.xaml`
/// - Copy the colors under <Default> and paste them on [defaultResourceDirectionary]
/// - Copy the colors under <Light> and paste them on [lightResourceDictionary]
/// - Run the generator with `dart bin/dictionary_generator.dart.dart` while being
/// on the `lib/` directory as PWD
/// - Enjoy
///
/// This only support the <Color> tag
void main(List<String> args) async {
if (Directory.current.path.split(pathSeparator).last == "bin") {
print("Run the generator from the lib/ folder");
return;
}

final StringBuffer dartFileBuffer = StringBuffer(fileHeader);

// Generates
void generateFor(String dictionary, String constructor) {
dartFileBuffer.writeln('\n // Colors adapted for $constructor mode');
dartFileBuffer.writeln(' const ResourceDictionary.$constructor({');
for (final resourceLine in dictionary.split('\n')) {
if (resourceLine.trim().isEmpty) continue;
final resourceName = () {
final split = resourceLine.trim().split('"');
return split[1];
}();

String resourceHex = () {
final result = resourceLine
.replaceAll('<Color x:Key="$resourceName">', '')
.replaceAll('</Color>', '')
.trim();
return result;
}()
.replaceAll('#', '')
.toLowerCase();

if (resourceHex.length == 6) {
resourceHex = 'FF$resourceHex';
}

dartFileBuffer.writeln(
' this.${resourceName.lowercaseFirst()} = const Color(0x$resourceHex),',
);
}
dartFileBuffer.writeln(" });");
}

// generates abstract dictionary
dartFileBuffer.writeln(header);
for (final resourceLine in defaultResourceDirectionary.split('\n')) {
if (resourceLine.trim().isEmpty) continue;
final resourceName = () {
final split = resourceLine.trim().split('"');
return split[1];
}();

dartFileBuffer.writeln(
' final Color ${resourceName.lowercaseFirst()};',
);
}

dartFileBuffer.writeln('\n const ResourceDictionary.raw({');
for (final resourceLine in defaultResourceDirectionary.split('\n')) {
if (resourceLine.trim().isEmpty) continue;
final resourceName = () {
final split = resourceLine.trim().split('"');
return split[1];
}()
.lowercaseFirst();

dartFileBuffer.writeln(
' required this.$resourceName,',
);
}

dartFileBuffer.writeln(" });");

// generate default dictionary
generateFor(defaultResourceDirectionary, 'dark');

// generate light resource dictionary
generateFor(lightResourceDictionary, 'light');

// generate lerp method
dartFileBuffer.writeln(
'\n static ResourceDictionary lerp(ResourceDictionary a, ResourceDictionary b, double t,) {');
dartFileBuffer.writeln(' return ResourceDictionary.raw(');
for (final resourceLine in defaultResourceDirectionary.split('\n')) {
if (resourceLine.trim().isEmpty) continue;
final resourceName = () {
final split = resourceLine.trim().split('"');
return split[1];
}()
.lowercaseFirst();

dartFileBuffer.writeln(
' $resourceName: Color.lerp(a.$resourceName, b.$resourceName, t,)!,',
);
}
dartFileBuffer.writeln(' );');
dartFileBuffer.writeln(' }');

// generate debugFillProperties method

dartFileBuffer.writeln(
'\n @override\n void debugFillProperties(DiagnosticPropertiesBuilder properties) {');
dartFileBuffer.writeln(' super.debugFillProperties(properties);');
dartFileBuffer.writeln('properties');
for (final resourceLine in defaultResourceDirectionary.split('\n')) {
if (resourceLine.trim().isEmpty) continue;
final resourceName = () {
final split = resourceLine.trim().split('"');
return split[1];
}()
.lowercaseFirst();

dartFileBuffer.writeln(
' ..add(ColorProperty(\'${resourceName.lowercaseFirst()}\', $resourceName))',
);
}
dartFileBuffer.writeln(';');
dartFileBuffer.writeln(' }');

dartFileBuffer.writeln("}");

final outputFile = File("lib/src/styles/color_resources.dart");
final formatProcess = await Process.start(
'flutter',
['format', outputFile.path],
runInShell: true,
);
stdout.addStream(formatProcess.stdout);
await outputFile.writeAsString(dartFileBuffer.toString());
}

extension StringExtension on String {
/// Results this string with the first char uppercased
///
/// January -> january
String lowercaseFirst() {
final first = substring(0, 1);
return first.toLowerCase() + substring(1);
}
}
3 changes: 2 additions & 1 deletion bin/icon_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void main(List<String> args) async {
}

// NEW Map of all glyphs (adds iteration capabilities)
dartFileBuffer.writeln(" static const Map<String,IconData> allIcons = {");
dartFileBuffer.writeln(" static const Map<String, IconData> allIcons = {");
for (final Glyph glyph in glyphs) {
dartFileBuffer.writeln(
" '${glyph.name}': ${glyph.name},",
Expand All @@ -56,6 +56,7 @@ void main(List<String> args) async {
final formatProcess = await Process.start(
'flutter',
['format', outputFile.path],
runInShell: true,
);
stdout.addStream(formatProcess.stdout);
await outputFile.writeAsString(dartFileBuffer.toString());
Expand Down
Loading