@@ -11,15 +11,16 @@ use cosmic::config::CosmicTk;
11
11
use cosmic:: cosmic_config:: { Config , ConfigSet , CosmicConfigEntry } ;
12
12
use cosmic:: cosmic_theme:: palette:: { FromColor , Hsv , Srgb , Srgba } ;
13
13
use cosmic:: cosmic_theme:: {
14
- CornerRadii , Theme , ThemeBuilder , ThemeMode , DARK_THEME_BUILDER_ID , LIGHT_THEME_BUILDER_ID ,
14
+ CornerRadii , Spacing , Theme , ThemeBuilder , ThemeMode , DARK_THEME_BUILDER_ID ,
15
+ LIGHT_THEME_BUILDER_ID ,
15
16
} ;
16
17
use cosmic:: iced_core:: { alignment, Background , Color , Length } ;
17
18
use cosmic:: iced_widget:: scrollable;
18
19
use cosmic:: prelude:: CollectionWidget ;
19
20
use cosmic:: widget:: icon:: { self , from_name, icon} ;
20
21
use cosmic:: widget:: {
21
- button, color_picker:: ColorPickerUpdate , container, flex_row, horizontal_space, row , settings ,
22
- spin_button, text, ColorPickerModel ,
22
+ button, color_picker:: ColorPickerUpdate , container, flex_row, horizontal_space, radio , row ,
23
+ settings , spin_button, text, ColorPickerModel ,
23
24
} ;
24
25
use cosmic:: Apply ;
25
26
use cosmic:: { command, Command , Element } ;
@@ -83,6 +84,7 @@ pub struct Page {
83
84
interface_text : ColorPickerModel ,
84
85
control_component : ColorPickerModel ,
85
86
roundness : Roundness ,
87
+ density : Density ,
86
88
87
89
icon_theme_active : Option < usize > ,
88
90
icon_themes : IconThemes ,
169
171
theme_builder_needs_update : false ,
170
172
context_view : None ,
171
173
roundness : theme_builder. corner_radii . into ( ) ,
174
+ density : theme_builder. spacing . into ( ) ,
172
175
custom_accent : ColorPickerModel :: new (
173
176
& * HEX ,
174
177
& * RGB ,
@@ -286,6 +289,7 @@ pub enum Message {
286
289
ControlComponent ( ColorPickerUpdate ) ,
287
290
CustomAccent ( ColorPickerUpdate ) ,
288
291
DarkMode ( bool ) ,
292
+ Density ( Density ) ,
289
293
Entered ( ( IconThemes , IconHandles ) ) ,
290
294
ExperimentalContextDrawer ,
291
295
ExportError ,
@@ -315,6 +319,13 @@ pub enum Roundness {
315
319
Square ,
316
320
}
317
321
322
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
323
+ pub enum Density {
324
+ Comfortable ,
325
+ Compact ,
326
+ Spacious ,
327
+ }
328
+
318
329
impl From < Roundness > for CornerRadii {
319
330
fn from ( value : Roundness ) -> Self {
320
331
match value {
@@ -358,6 +369,61 @@ impl From<CornerRadii> for Roundness {
358
369
}
359
370
}
360
371
372
+ impl From < Density > for Spacing {
373
+ fn from ( value : Density ) -> Self {
374
+ match value {
375
+ Density :: Comfortable => Spacing {
376
+ space_none : 0 ,
377
+ space_xxxs : 4 ,
378
+ space_xxs : 8 ,
379
+ space_xs : 12 ,
380
+ space_s : 16 ,
381
+ space_m : 24 ,
382
+ space_l : 32 ,
383
+ space_xl : 48 ,
384
+ space_xxl : 64 ,
385
+ space_xxxl : 128 ,
386
+ } ,
387
+ Density :: Compact => Spacing {
388
+ space_none : 0 ,
389
+ space_xxxs : 4 ,
390
+ space_xxs : 8 ,
391
+ space_xs : 10 ,
392
+ space_s : 12 ,
393
+ space_m : 16 ,
394
+ space_l : 24 ,
395
+ space_xl : 32 ,
396
+ space_xxl : 48 ,
397
+ space_xxxl : 72 ,
398
+ } ,
399
+ Density :: Spacious => Spacing {
400
+ space_none : 0 ,
401
+ space_xxxs : 4 ,
402
+ space_xxs : 8 ,
403
+ space_xs : 16 ,
404
+ space_s : 20 ,
405
+ space_m : 32 ,
406
+ space_l : 40 ,
407
+ space_xl : 56 ,
408
+ space_xxl : 72 ,
409
+ space_xxxl : 144 ,
410
+ } ,
411
+ }
412
+ }
413
+ }
414
+
415
+ impl From < Spacing > for Density {
416
+ fn from ( value : Spacing ) -> Self {
417
+ if ( value. space_m - 32 ) < 1 {
418
+ Self :: Spacious
419
+ } else if ( value. space_m - 24 ) < 1 {
420
+ Self :: Comfortable
421
+ } else {
422
+ Self :: Compact
423
+ }
424
+ }
425
+ }
426
+
361
427
impl Page {
362
428
/// Syncs changes for dark and light theme.
363
429
/// Roundness and window management settings should be consistent between dark / light mode.
@@ -420,6 +486,17 @@ impl Page {
420
486
tracing:: error!( ?err, "Error setting corner radii" ) ;
421
487
}
422
488
}
489
+ if theme_builder. spacing != self . theme_builder . spacing {
490
+ if let Err ( err) =
491
+ theme_builder. set_spacing ( & other_builder_config, self . theme_builder . spacing )
492
+ {
493
+ tracing:: error!( ?err, "Error setting spacing" ) ;
494
+ }
495
+
496
+ if let Err ( err) = theme. set_spacing ( & other_theme_config, self . theme_builder . spacing ) {
497
+ tracing:: error!( ?err, "Error setting spacing" ) ;
498
+ }
499
+ }
423
500
424
501
Ok ( ( ) )
425
502
}
@@ -590,6 +667,13 @@ impl Page {
590
667
Self :: update_panel_radii ( r) ;
591
668
Command :: none ( )
592
669
}
670
+ Message :: Density ( d) => {
671
+ needs_sync = true ;
672
+ self . density = d;
673
+ self . theme_builder . spacing = self . density . into ( ) ;
674
+ self . theme_builder_needs_update = true ;
675
+ Command :: none ( )
676
+ }
593
677
Message :: Entered ( ( icon_themes, icon_handles) ) => {
594
678
* self = Self :: default ( ) ;
595
679
@@ -1011,6 +1095,7 @@ impl page::Page<crate::pages::Message> for Page {
1011
1095
Some ( vec ! [
1012
1096
sections. insert( mode_and_colors( ) ) ,
1013
1097
sections. insert( style( ) ) ,
1098
+ sections. insert( interface_density( ) ) ,
1014
1099
sections. insert( window_management( ) ) ,
1015
1100
sections. insert( experimental( ) ) ,
1016
1101
sections. insert( reset_button( ) ) ,
@@ -1456,6 +1541,49 @@ pub fn style() -> Section<crate::pages::Message> {
1456
1541
} )
1457
1542
}
1458
1543
1544
+ pub fn interface_density ( ) -> Section < crate :: pages:: Message > {
1545
+ let mut descriptions = Slab :: new ( ) ;
1546
+
1547
+ let comfortable = descriptions. insert ( fl ! ( "interface-density" , "comfortable" ) ) ;
1548
+ let compact = descriptions. insert ( fl ! ( "interface-density" , "compact" ) ) ;
1549
+ let spacious = descriptions. insert ( fl ! ( "interface-density" , "spacious" ) ) ;
1550
+
1551
+ Section :: default ( )
1552
+ . title ( fl ! ( "interface-density" ) )
1553
+ . descriptions ( descriptions)
1554
+ . view :: < Page > ( move |_binder, page, section| {
1555
+ let descriptions = & section. descriptions ;
1556
+
1557
+ settings:: view_section ( & section. title )
1558
+ . add ( settings:: item_row ( vec ! [ radio(
1559
+ text:: body( & descriptions[ comfortable] ) ,
1560
+ Density :: Comfortable ,
1561
+ Some ( page. density) ,
1562
+ Message :: Density ,
1563
+ )
1564
+ . width( Length :: Fill )
1565
+ . into( ) ] ) )
1566
+ . add ( settings:: item_row ( vec ! [ radio(
1567
+ text:: body( & descriptions[ compact] ) ,
1568
+ Density :: Compact ,
1569
+ Some ( page. density) ,
1570
+ Message :: Density ,
1571
+ )
1572
+ . width( Length :: Fill )
1573
+ . into( ) ] ) )
1574
+ . add ( settings:: item_row ( vec ! [ radio(
1575
+ text:: body( & descriptions[ spacious] ) ,
1576
+ Density :: Spacious ,
1577
+ Some ( page. density) ,
1578
+ Message :: Density ,
1579
+ )
1580
+ . width( Length :: Fill )
1581
+ . into( ) ] ) )
1582
+ . apply ( Element :: from)
1583
+ . map ( crate :: pages:: Message :: Appearance )
1584
+ } )
1585
+ }
1586
+
1459
1587
#[ allow( clippy:: too_many_lines) ]
1460
1588
pub fn window_management ( ) -> Section < crate :: pages:: Message > {
1461
1589
let mut descriptions = Slab :: new ( ) ;
0 commit comments