@@ -142,33 +142,41 @@ class YaruTheme extends StatefulWidget {
142142class _YaruThemeState extends State <YaruTheme > {
143143 YaruVariant ? _variant;
144144 YaruSettings ? _settings;
145- StreamSubscription <String ?>? _themeNameSubscription;
146- StreamSubscription <String ?>? _accentColorSubScription;
145+ final Map <String , List <String >?> _customTitleButtonLayout = {
146+ 'left' : null ,
147+ 'right' : null ,
148+ };
149+ StreamSubscription <String ?>? _themeNameSub;
150+ StreamSubscription <String ?>? _accentColorSub;
151+ StreamSubscription <String ?>? _buttonLayoutSub;
147152
148153 @override
149154 void initState () {
150155 super .initState ();
151- if (widget.data.variant == null && canDetectVariant ()) {
156+ if (canDetectGnome ()) {
152157 _settings = widget._settings ?? YaruSettings ();
153158 _settings? .init ();
154- _variant = resolveAccentColorVariant (_settings? .getAccentColor ()) ??
155- resolveGtkThemeVariant (_settings? .getThemeName ());
156- _accentColorSubScription ?? =
157- _settings! .accentColorChanged.listen (updateVariant);
158- _themeNameSubscription ?? =
159- _settings! .themeNameChanged.listen (updateVariant);
159+ if (widget.data.variant == null ) {
160+ _variant = resolveAccentColorVariant (_settings? .getAccentColor ()) ??
161+ resolveGtkThemeVariant (_settings? .getThemeName ());
162+ _accentColorSub ?? = _settings! .accentColorChanged.listen (updateVariant);
163+ _themeNameSub ?? = _settings! .themeNameChanged.listen (updateVariant);
164+ _buttonLayoutSub ?? =
165+ _settings! .buttonLayoutChanged.listen (updateButtonLayout);
166+ }
160167 }
161168 }
162169
163170 @override
164171 void dispose () {
165- _themeNameSubscription? .cancel ();
166- _accentColorSubScription? .cancel ();
172+ _themeNameSub? .cancel ();
173+ _accentColorSub? .cancel ();
174+ _buttonLayoutSub? .cancel ();
167175 _settings? .dispose ();
168176 super .dispose ();
169177 }
170178
171- bool canDetectVariant () {
179+ bool canDetectGnome () {
172180 return ! kIsWeb &&
173181 widget._platform.isLinux &&
174182 ! widget._platform.environment.containsKey ('FLUTTER_TEST' );
@@ -221,7 +229,7 @@ class _YaruThemeState extends State<YaruTheme> {
221229 };
222230
223231 void updateVariant ([String ? value]) {
224- assert (canDetectVariant ());
232+ assert (canDetectGnome ());
225233 final gtkThemeName = value ?? _settings? .getThemeName ();
226234 final accentColor = value ?? _settings? .getAccentColor ();
227235 setState (
@@ -230,6 +238,24 @@ class _YaruThemeState extends State<YaruTheme> {
230238 );
231239 }
232240
241+ void updateButtonLayout ([String ? value]) {
242+ assert (canDetectGnome ());
243+ final buttonLayout = value ?? _settings? .getButtonLayout ();
244+
245+ final buttons = buttonLayout? .split (':' );
246+
247+ setState (() {
248+ _customTitleButtonLayout.update (
249+ 'left' ,
250+ (value) => buttons? .firstOrNull? .split (',' ) ?? < String > [],
251+ );
252+ _customTitleButtonLayout.update (
253+ 'right' ,
254+ (value) => buttons? .lastOrNull? .split (',' ) ?? [],
255+ );
256+ });
257+ }
258+
233259 ThemeMode resolveMode () {
234260 final mode = widget.data.themeMode ?? ThemeMode .system;
235261 if (mode == ThemeMode .system) {
@@ -246,6 +272,8 @@ class _YaruThemeState extends State<YaruTheme> {
246272 highContrast:
247273 widget.data.highContrast ?? MediaQuery .highContrastOf (context),
248274 themeMode: resolveMode (),
275+ customTitleButtonLayout:
276+ widget.data.customTitleButtonLayout ?? _customTitleButtonLayout,
249277 );
250278 }
251279
@@ -262,7 +290,7 @@ class _YaruThemeState extends State<YaruTheme> {
262290
263291 @override
264292 Widget build (BuildContext context) {
265- if (_settings != null && _themeNameSubscription == null ) {
293+ if (_settings != null && _themeNameSub == null ) {
266294 return const SizedBox .shrink (); // #231
267295 }
268296 final data = resolveData ();
@@ -287,11 +315,14 @@ class YaruThemeData with Diagnosticable {
287315 this .pageTransitionsTheme,
288316 this .useMaterial3,
289317 this .visualDensity,
318+ this .customTitleButtonLayout,
290319 });
291320
292321 /// Specifies the theme variant.
293322 final YaruVariant ? variant;
294323
324+ final Map <String , List <String >?>? customTitleButtonLayout;
325+
295326 /// Whether to use high contrast colors.
296327 final bool ? highContrast;
297328
@@ -328,6 +359,7 @@ class YaruThemeData with Diagnosticable {
328359 PageTransitionsTheme ? pageTransitionsTheme,
329360 bool ? useMaterial3,
330361 VisualDensity ? visualDensity,
362+ Map <String , List <String >?>? customTitleButtonLayout,
331363 }) {
332364 return YaruThemeData (
333365 variant: variant ?? this .variant,
@@ -337,6 +369,8 @@ class YaruThemeData with Diagnosticable {
337369 pageTransitionsTheme: pageTransitionsTheme ?? this .pageTransitionsTheme,
338370 useMaterial3: useMaterial3 ?? this .useMaterial3,
339371 visualDensity: visualDensity ?? this .visualDensity,
372+ customTitleButtonLayout:
373+ customTitleButtonLayout ?? this .customTitleButtonLayout,
340374 );
341375 }
342376
@@ -351,6 +385,9 @@ class YaruThemeData with Diagnosticable {
351385 .add (DiagnosticsProperty ('pageTransitionsTheme' , pageTransitionsTheme));
352386 properties.add (DiagnosticsProperty ('useMaterial3' , useMaterial3));
353387 properties.add (DiagnosticsProperty ('visualDensity' , visualDensity));
388+ properties.add (
389+ DiagnosticsProperty ('customTitleButtonLayout' , customTitleButtonLayout),
390+ );
354391 }
355392
356393 @override
@@ -364,7 +401,8 @@ class YaruThemeData with Diagnosticable {
364401 iterableEquals (other.extensions, extensions) &&
365402 other.pageTransitionsTheme == pageTransitionsTheme &&
366403 other.useMaterial3 == useMaterial3 &&
367- other.visualDensity == visualDensity;
404+ other.visualDensity == visualDensity &&
405+ other.customTitleButtonLayout == customTitleButtonLayout;
368406 }
369407
370408 @override
@@ -377,6 +415,7 @@ class YaruThemeData with Diagnosticable {
377415 pageTransitionsTheme,
378416 useMaterial3,
379417 visualDensity,
418+ customTitleButtonLayout,
380419 );
381420 }
382421}
0 commit comments