Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Date format: DD/MM/YYYY
- Improved fidelity of the suggestions overlay
- When a suggestion is picked, the overlay is automatically closed and the text box is unfocused
- Clear button now only shows when the text box is focused
- Add directionality support ([#184](https://github.com/bdlukaa/fluent_ui/pull/184))

## [3.9.0] - Fidelity - [10/02/2022]

Expand Down
11 changes: 10 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_acrylic/flutter_acrylic.dart' as flutter_acrylic;
import 'package:provider/provider.dart';
import 'package:system_theme/system_theme.dart';
import 'package:url_launcher/link.dart';
import 'package:url_strategy/url_strategy.dart';

Expand Down Expand Up @@ -31,6 +32,8 @@ bool get isDesktop {
void main() async {
WidgetsFlutterBinding.ensureInitialized();

SystemTheme.accentInstance;

setPathUrlStrategy();

if (isDesktop) {
Expand Down Expand Up @@ -82,6 +85,12 @@ class MyApp extends StatelessWidget {
glowFactor: is10footScreen() ? 2.0 : 0.0,
),
),
builder: (context, child) {
return Directionality(
textDirection: appTheme.textDirection,
child: child!,
);
},
);
},
);
Expand Down Expand Up @@ -118,7 +127,7 @@ class _MyHomePageState extends State<MyHomePage> {
if (kIsWeb) return const Text(appTitle);
return MoveWindow(
child: const Align(
alignment: Alignment.centerLeft,
alignment: AlignmentDirectional.centerStart,
child: Text(appTitle),
),
);
Expand Down
2 changes: 1 addition & 1 deletion example/lib/screens/forms.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class _FormsState extends State<Forms> {
},
textInputAction: TextInputAction.next,
prefix: const Padding(
padding: EdgeInsets.only(left: 8.0),
padding: EdgeInsetsDirectional.only(start: 8.0),
child: Icon(FluentIcons.edit_mail),
),
),
Expand Down
4 changes: 2 additions & 2 deletions example/lib/screens/inputs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ class _InputsPageState extends State<InputsPage> {
color: disabled
? FluentTheme.of(context).accentColor.darker
: FluentTheme.of(context).accentColor,
borderRadius: const BorderRadius.horizontal(
left: Radius.circular(4.0),
borderRadius: const BorderRadiusDirectional.horizontal(
start: Radius.circular(4.0),
),
),
height: 24,
Expand Down
24 changes: 24 additions & 0 deletions example/lib/screens/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,30 @@ class Settings extends StatelessWidget {
);
}),
],
biggerSpacer,
Text('Text Direction',
style: FluentTheme.of(context).typography.subtitle),
spacer,
...List.generate(TextDirection.values.length, (index) {
final direction = TextDirection.values[index];
return Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: RadioButton(
checked: appTheme.textDirection == direction,
onChanged: (value) {
if (value) {
appTheme.textDirection = direction;
}
},
content: Text(
'$direction'
.replaceAll('TextDirection.', '')
.replaceAll('rtl', 'Right to left')
.replaceAll('ltr', 'Left to right'),
),
),
);
}).reversed,
],
);
}
Expand Down
7 changes: 7 additions & 0 deletions example/lib/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class AppTheme extends ChangeNotifier {
_acrylicEffect = acrylicEffect;
notifyListeners();
}

TextDirection _textDirection = TextDirection.ltr;
TextDirection get textDirection => _textDirection;
set textDirection(TextDirection direction) {
_textDirection = direction;
notifyListeners();
}
}

AccentColor get systemAccentColor {
Expand Down
9 changes: 8 additions & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
meta:
dependency: transitive
description:
Expand Down Expand Up @@ -321,7 +328,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.3"
version: "0.4.8"
typed_data:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion lib/src/controls/form/auto_suggest_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ class __AutoSuggestBoxOverlayTileState extends State<_AutoSuggestBoxOverlayTile>
states.isDisabled ? {ButtonStates.none} : states,
),
),
alignment: Alignment.centerLeft,
alignment: AlignmentDirectional.centerStart,
child: EntrancePageTransition(
child: Text(
widget.text,
Expand Down
18 changes: 9 additions & 9 deletions lib/src/controls/inputs/dropdown_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import 'package:flutter/foundation.dart';

const double _kVerticalOffset = 20.0;
const double _kInnerPadding = 5.0;
const Widget _kDefaultDropdownButtonTrailing = Icon(
FluentIcons.chevron_down,
size: 10,
);

/// A DropDownButton is a button that shows a chevron as a visual indicator that
/// it has an attached flyout that contains more options. It has the same
Expand Down Expand Up @@ -203,20 +207,16 @@ class _DropDownButtonState extends State<DropDownButton>
final buttonChildren = <Widget>[
if (widget.leading != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsetsDirectional.only(end: 8.0),
child: IconTheme.merge(
data: const IconThemeData(size: 20.0),
child: widget.leading!,
),
),
if (widget.title != null) widget.title!,
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: widget.trailing ??
const Icon(
FluentIcons.chevron_down,
size: 10,
),
padding: const EdgeInsetsDirectional.only(end: 8.0),
child: widget.trailing ?? _kDefaultDropdownButtonTrailing,
),
];

Expand Down Expand Up @@ -313,12 +313,12 @@ class DropDownButtonItem {
child: Row(mainAxisSize: MainAxisSize.min, children: [
if (leading != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsetsDirectional.only(end: 8.0),
child: leading!,
),
if (title != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsetsDirectional.only(end: 8.0),
child: title!,
),
if (trailing != null) trailing!,
Expand Down
4 changes: 2 additions & 2 deletions lib/src/controls/inputs/pill_button_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PillButtonBarItem {
/// See also:
///
/// * [PillButtonBarItem], the item used by pill button bar
/// * [PillButtonTheme], used to style the pill button bar
/// * [PillButtonBarTheme], used to style the pill button bar
class PillButtonBar extends StatelessWidget {
/// Creates a pill button bar.
///
Expand Down Expand Up @@ -86,7 +86,7 @@ class PillButtonBar extends StatelessWidget {
}),
),
);
return Align(alignment: Alignment.topLeft, child: bar);
return Align(alignment: AlignmentDirectional.topStart, child: bar);
}
}

Expand Down
14 changes: 11 additions & 3 deletions lib/src/controls/inputs/rating.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';

const IconData kRatingBarIcon = FluentIcons.favorite_star_fill;
Expand Down Expand Up @@ -36,6 +37,7 @@ class RatingBar extends StatefulWidget {
this.focusNode,
this.autofocus = false,
this.starSpacing = 0,
this.dragStartBehavior = DragStartBehavior.down,
}) : assert(rating >= 0 && rating <= amount),
assert(starSpacing >= 0),
assert(amount > 0),
Expand Down Expand Up @@ -88,6 +90,9 @@ class RatingBar extends StatefulWidget {
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;

/// Determines the way that drag start behavior is handled.
final DragStartBehavior dragStartBehavior;

@override
_RatingBarState createState() => _RatingBarState();

Expand All @@ -113,6 +118,11 @@ class RatingBar extends StatefulWidget {
ifFalse: 'manual focus',
));
properties.add(DoubleProperty('starSpacing', starSpacing, defaultValue: 0));
properties.add(EnumProperty(
'dragStartBehavior',
dragStartBehavior,
defaultValue: DragStartBehavior.down,
));
}
}

Expand Down Expand Up @@ -229,6 +239,7 @@ class _RatingBarState extends State<RatingBar> {
setState(() => _showFocusHighlight = v);
},
child: GestureDetector(
dragStartBehavior: widget.dragStartBehavior,
onTapDown: (d) => _handleUpdate(d.localPosition.dx, size),
onHorizontalDragStart: (d) => _handleUpdate(d.localPosition.dx, size),
onHorizontalDragUpdate: (d) =>
Expand Down Expand Up @@ -265,9 +276,6 @@ class _RatingBarState extends State<RatingBar> {
}
return icon;
});
if (Directionality.of(context) == TextDirection.rtl) {
return items.reversed.toList();
}
return items;
}(),
);
Expand Down
40 changes: 32 additions & 8 deletions lib/src/controls/inputs/slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ class _SliderState extends m.State<Slider> {
@override
Widget build(BuildContext context) {
assert(debugCheckHasFluentTheme(context));
assert(debugCheckHasDirectionality(context));
final style = SliderTheme.of(context).merge(widget.style);
final direction = Directionality.of(context);
Widget child = HoverButton(
onPressed: widget.onChanged == null ? null : () {},
margin: style.margin ?? EdgeInsets.zero,
Expand Down Expand Up @@ -273,6 +275,7 @@ class _SliderState extends m.State<Slider> {
valueIndicatorShape: _RectangularSliderValueIndicatorShape(
backgroundColor: style.labelBackgroundColor,
vertical: widget.vertical,
ltr: direction == TextDirection.ltr,
),
trackHeight: 1.75,
trackShape: _CustomTrackShape(),
Expand Down Expand Up @@ -316,7 +319,7 @@ class _SliderState extends m.State<Slider> {
);
if (widget.vertical) {
return RotatedBox(
quarterTurns: 3,
quarterTurns: direction == TextDirection.ltr ? 3 : 5,
child: child,
);
}
Expand Down Expand Up @@ -630,14 +633,19 @@ class SliderThemeData with Diagnosticable {
class _RectangularSliderValueIndicatorShape extends m.SliderComponentShape {
final Color? backgroundColor;
final bool vertical;
final bool ltr;

/// Create a slider value indicator that resembles a rectangular tooltip.
const _RectangularSliderValueIndicatorShape({
this.backgroundColor,
this.vertical = false,
this.ltr = false,
});

get _pathPainter => _RectangularSliderValueIndicatorPathPainter(vertical);
get _pathPainter => _RectangularSliderValueIndicatorPathPainter(
vertical,
ltr,
);

@override
Size getPreferredSize(
Expand Down Expand Up @@ -684,7 +692,13 @@ class _RectangularSliderValueIndicatorShape extends m.SliderComponentShape {
class _RectangularSliderValueIndicatorPathPainter {
final bool vertical;

const _RectangularSliderValueIndicatorPathPainter([this.vertical = false]);
/// Whether the current [Directionality] is [TextDirection.ltr]
final bool ltr;

const _RectangularSliderValueIndicatorPathPainter([
this.vertical = false,
this.ltr = false,
]);

static const double _triangleHeight = 8.0;
static const double _labelPadding = 8.0;
Expand Down Expand Up @@ -796,18 +810,28 @@ class _RectangularSliderValueIndicatorPathPainter {
const Radius.circular(_upperRectRadius),
);
trianglePath.addRRect(upperRRect);

canvas.save();
// Prepare the canvas for the base of the tooltip, which is relative to the
// center of the thumb.
const verticalFactor = 20;
final double verticalFactor = ltr ? 20.0 : 10.0;
canvas.translate(
center.dx + (vertical ? -verticalFactor : 0),
center.dy - _bottomTipYOffset + (vertical ? -verticalFactor : 0),
center.dx +
(vertical
? ltr
? -verticalFactor
: verticalFactor * 2
: 0),
center.dy -
_bottomTipYOffset +
(vertical
? ltr
? -verticalFactor
: -verticalFactor * 2
: 0),
);
canvas.scale(scale, scale);
// Rotate the label if it's vertical
if (vertical) canvas.rotate(math.pi / 2);
if (vertical) canvas.rotate((ltr ? 1 : -1) * math.pi / 2);
if (strokePaintColor != null) {
final Paint strokePaint = Paint()
..color = strokePaintColor
Expand Down
8 changes: 4 additions & 4 deletions lib/src/controls/inputs/split_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ class SplitButtonBar extends StatelessWidget {
color: theme.disabledColor.withOpacity(0.75),
width: 0.1,
),
borderRadius: BorderRadius.horizontal(
left: index == 0
borderRadius: BorderRadiusDirectional.horizontal(
start: index == 0
? style.borderRadius?.topLeft ?? Radius.zero
: Radius.zero,
right: index == buttons.length - 1
end: index == buttons.length - 1
? style.borderRadius?.topRight ?? Radius.zero
: Radius.zero,
),
Expand All @@ -82,7 +82,7 @@ class SplitButtonBar extends StatelessWidget {
);
if (index == 0) return button;
return Padding(
padding: EdgeInsets.only(left: style.interval ?? 0),
padding: EdgeInsetsDirectional.only(start: style.interval ?? 0),
child: button,
);
}),
Expand Down
Loading