Skip to content

Commit

Permalink
ContextMenuTheme
Browse files Browse the repository at this point in the history
Create theme extension for ContextMenu
  • Loading branch information
chesnoksatan committed Jul 9, 2022
1 parent 3b23bff commit f0a1109
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 35 deletions.
4 changes: 4 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'dart:async';
import 'package:animations/animations.dart';
import 'package:files/backend/providers.dart';
import 'package:files/backend/utils.dart';
import 'package:files/widgets/context_menu/context_menu_theme.dart';
import 'package:files/widgets/side_pane.dart';
import 'package:files/widgets/tab_strip.dart';
import 'package:files/widgets/workspace.dart';
Expand Down Expand Up @@ -67,6 +68,9 @@ class Files extends StatelessWidget {
mainAxisMargin: 0,
radius: Radius.zero,
),
extensions: [
ContextMenuTheme(),
],
),
scrollBehavior: const MaterialScrollBehavior().copyWith(
scrollbars: false,
Expand Down
7 changes: 5 additions & 2 deletions lib/widgets/context_menu/context_menu.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:files/widgets/context_menu/context_menu_entry.dart';
import 'package:files/widgets/context_menu/context_menu_theme.dart';
import 'package:flutter/material.dart';

/// [ContextMenu] provides popup menu for the [child] widget and contains [entries].
Expand Down Expand Up @@ -50,6 +51,8 @@ void openContextMenu(
Offset position,
List<PopupMenuEntry<dynamic>> entries,
) {
final menuTheme = Theme.of(context).extension<ContextMenuTheme>()!;

showMenu(
context: context,
position: RelativeRect.fromLTRB(
Expand All @@ -59,7 +62,7 @@ void openContextMenu(
position.dy,
),
items: entries,
color: Theme.of(context).colorScheme.surface,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
color: menuTheme.backgroundColor,
shape: menuTheme.shape,
);
}
30 changes: 12 additions & 18 deletions lib/widgets/context_menu/context_menu_entry.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:files/widgets/context_menu/context_menu_theme.dart';
import 'package:files/widgets/context_menu/context_sub_menu_entry.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -63,6 +64,8 @@ class ContextMenuEntry extends BaseContextMenuEntry {
class _ContextMenuEntryState extends State<ContextMenuEntry> {
@override
Widget build(BuildContext context) {
final menuTheme = Theme.of(context).extension<ContextMenuTheme>()!;

return InkWell(
onTap: widget.enabled
? () {
Expand All @@ -78,13 +81,10 @@ class _ContextMenuEntryState extends State<ContextMenuEntry> {
if (widget.leading != null) ...[
IconTheme.merge(
data: IconThemeData(
size: 20,
size: menuTheme.iconSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.7)
: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.3),
? menuTheme.iconColor
: menuTheme.disabledTextColor,
),
child: widget.leading!,
),
Expand All @@ -93,13 +93,10 @@ class _ContextMenuEntryState extends State<ContextMenuEntry> {
Expanded(
child: DefaultTextStyle(
style: TextStyle(
fontSize: 16,
fontSize: menuTheme.fontSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.7)
: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.3),
? menuTheme.textColor
: menuTheme.disabledTextColor,
),
overflow: TextOverflow.ellipsis,
child: widget.title,
Expand All @@ -108,13 +105,10 @@ class _ContextMenuEntryState extends State<ContextMenuEntry> {
if (widget.shortcut != null)
DefaultTextStyle(
style: TextStyle(
fontSize: 16,
fontSize: menuTheme.fontSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.5)
: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.1),
? menuTheme.shortcutColor
: menuTheme.disabledShortcutColor,
),
overflow: TextOverflow.ellipsis,
child: widget.shortcut!,
Expand Down
86 changes: 86 additions & 0 deletions lib/widgets/context_menu/context_menu_theme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'dart:ui' show lerpDouble;

import 'package:flutter/material.dart';

class ContextMenuTheme extends ThemeExtension<ContextMenuTheme> {
final Color backgroundColor;
final Color textColor;
final Color iconColor;
final Color shortcutColor;

final double iconSize;
final double fontSize;

final double disabledOpacity;

final ShapeBorder? shape;

ContextMenuTheme({
Color? backgroundColor,
Color? textColor,
Color? iconColor,
Color? shortcutColor,
double? fontSize,
double? iconSize,
double? disabledOpacity,
ShapeBorder? shape,
}) : backgroundColor = backgroundColor ?? const Color(0xFF212121),
textColor = textColor ?? Colors.white.withOpacity(0.7),
iconColor = iconColor ?? Colors.white.withOpacity(0.7),
shortcutColor = shortcutColor ?? Colors.white.withOpacity(0.5),
fontSize = fontSize ?? 16,
iconSize = iconSize ?? 20,
disabledOpacity = disabledOpacity ?? 0.1,
shape = shape ??
RoundedRectangleBorder(borderRadius: BorderRadius.circular(4));

Color get disabledTextColor => textColor.withOpacity(disabledOpacity);
Color get disabledIconColor => iconColor.withOpacity(disabledOpacity);
Color get disabledShortcutColor => shortcutColor.withOpacity(disabledOpacity);

@override
ThemeExtension<ContextMenuTheme> copyWith({
Color? backgroundColor,
Color? textColor,
Color? iconColor,
Color? shortcutColor,
double? fontSize,
double? iconSize,
double? disabledOpacity,
ShapeBorder? shape,
}) {
return ContextMenuTheme(
backgroundColor: backgroundColor ?? this.backgroundColor,
textColor: textColor ?? this.textColor,
iconColor: iconColor ?? this.iconColor,
shortcutColor: shortcutColor ?? this.shortcutColor,
fontSize: fontSize ?? this.fontSize,
iconSize: iconSize ?? this.iconSize,
disabledOpacity: disabledOpacity ?? this.disabledOpacity,
shape: shape ?? this.shape,
);
}

@override
ThemeExtension<ContextMenuTheme> lerp(
ThemeExtension<ContextMenuTheme>? other, double t) {
if (other == null) {
return this;
}

if (other is! ContextMenuTheme) {
return this;
}

return ContextMenuTheme(
backgroundColor: Color.lerp(backgroundColor, other.backgroundColor, t),
textColor: Color.lerp(textColor, other.textColor, t),
iconColor: Color.lerp(iconColor, other.iconColor, t),
shortcutColor: Color.lerp(shortcutColor, other.shortcutColor, t),
fontSize: lerpDouble(fontSize, other.fontSize, t),
iconSize: lerpDouble(iconSize, other.iconSize, t),
disabledOpacity: lerpDouble(disabledOpacity, other.disabledOpacity, t),
shape: ShapeBorder.lerp(shape, other.shape, t),
);
}
}
27 changes: 12 additions & 15 deletions lib/widgets/context_menu/context_sub_menu_entry.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:files/widgets/context_menu/context_menu.dart';
import 'package:files/widgets/context_menu/context_menu_entry.dart';
import 'package:files/widgets/context_menu/context_menu_theme.dart';
import 'package:flutter/material.dart';

/// [ContextSubMenuEntry] is a [PopupMenuEntry] that displays a submenu with [entries].
Expand Down Expand Up @@ -36,6 +37,8 @@ class ContextSubMenuEntry extends BaseContextMenuEntry {
class _ContextSubMenuEntryState extends State<ContextSubMenuEntry> {
@override
Widget build(BuildContext context) {
final menuTheme = Theme.of(context).extension<ContextMenuTheme>()!;

return InkWell(
onTap: widget.enabled
? () {
Expand All @@ -57,13 +60,10 @@ class _ContextSubMenuEntryState extends State<ContextSubMenuEntry> {
if (widget.leading != null) ...[
IconTheme.merge(
data: IconThemeData(
size: 20,
size: menuTheme.iconSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.7)
: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.3),
? menuTheme.iconColor
: menuTheme.disabledTextColor,
),
child: widget.leading!,
),
Expand All @@ -72,24 +72,21 @@ class _ContextSubMenuEntryState extends State<ContextSubMenuEntry> {
Expanded(
child: DefaultTextStyle(
style: TextStyle(
fontSize: 16,
fontSize: menuTheme.fontSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.7)
: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.3),
? menuTheme.textColor
: menuTheme.disabledTextColor,
),
overflow: TextOverflow.ellipsis,
child: widget.title,
),
),
IconTheme.merge(
data: IconThemeData(
size: 20,
size: menuTheme.iconSize,
color: widget.enabled
? Theme.of(context).colorScheme.onSurface.withOpacity(0.7)
: Theme.of(context).colorScheme.onSurface.withOpacity(0.3),
? menuTheme.iconColor
: menuTheme.disabledTextColor,
),
child: const Icon(Icons.chevron_right),
)
Expand Down

0 comments on commit f0a1109

Please sign in to comment.