Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
ximper-shell-notification-center
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ximper Linux
ximper-shell-notification-center
Commits
c5a049f2
Verified
Commit
c5a049f2
authored
Mar 24, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
quick-settings: add widget with tile base class and grid layout
parent
4ecd858c
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
353 additions
and
0 deletions
+353
-0
style.scss
data/style/style.scss
+2
-0
quick-settings.scss
data/style/widgets/quick-settings.scss
+33
-0
factory.vala
src/controlCenter/widgets/factory.vala
+3
-0
quickSettings.vala
src/controlCenter/widgets/quickSettings/quickSettings.vala
+196
-0
quickSettingsTile.vala
...ontrolCenter/widgets/quickSettings/quickSettingsTile.vala
+119
-0
No files found.
data/style/style.scss
View file @
c5a049f2
...
...
@@ -396,5 +396,7 @@ notificationwindow, blankwindow {
@import
"widgets/slider"
;
/* Backlight widget */
@import
"widgets/backlight"
;
/* Quick Settings widget */
@import
"widgets/quick-settings"
;
/* Inhibitors widget */
@import
"widgets/inhibitors"
;
data/style/widgets/quick-settings.scss
0 → 100644
View file @
c5a049f2
.widget-quick-settings
{
padding
:
0
;
}
.quick-settings-row
{
margin
:
6px
0
;
}
.quick-settings-tile
{
border-radius
:
999px
;
overflow
:
hidden
;
.tile-toggle
{
padding
:
4px
12px
;
border
:
none
;
box-shadow
:
none
;
background
:
transparent
;
}
.tile-arrow
{
padding
:
4px
;
min-width
:
24px
;
border
:
none
;
box-shadow
:
none
;
background
:
transparent
;
}
}
.quick-settings-submenu
{
border-radius
:
var
(
--
border-radius
);
margin
:
4px
0
;
padding
:
4px
;
}
src/controlCenter/widgets/factory.vala
View file @
c5a049f2
...
...
@@ -34,6 +34,9 @@ namespace XimperShellNotificationCenter.Widgets {
case
"buttons-grid"
:
widget
=
new
ButtonsGrid
(
suffix
);
break
;
case
"quick-settings"
:
widget
=
new
QuickSettings
(
suffix
);
break
;
case
"slider"
:
widget
=
new
Slider
(
suffix
);
break
;
...
...
src/controlCenter/widgets/quickSettings/quickSettings.vala
0 → 100644
View file @
c5a049f2
namespace
XimperShellNotificationCenter.Widgets
{
private
struct
TileRow
{
Gtk
.
Revealer
revealer
;
QuickSettingsTile
?
active_submenu_tile
;
}
private
static
QuickSettingsTile
?
create_tile
(
string
type_id
,
Json
.
Object
?
cfg
)
{
QuickSettingsTile
?
tile
=
null
;
switch
(
type_id
)
{
case
"dnd"
:
tile
=
new
DndTile
(
cfg
);
break
;
case
"dark-mode"
:
tile
=
new
DarkModeTile
(
cfg
);
break
;
case
"power-profiles"
:
tile
=
new
PowerProfilesTile
(
cfg
);
break
;
case
"command"
:
tile
=
new
CommandTile
(
cfg
);
break
;
default
:
warning
(
"Unknown quick-settings tile: %s"
,
type_id
);
return
null
;
}
if
(!
tile
.
is_available
())
{
return
null
;
}
return
tile
;
}
public
class
QuickSettings
:
BaseWidget
{
public
override
string
widget_name
{
get
{
return
"quick-settings"
;
}
}
List
<
QuickSettingsTile
>
tiles
=
new
List
<
QuickSettingsTile
>
();
TileRow
[]
rows
=
{};
int
columns
=
2
;
public
QuickSettings
(
string
suffix
)
{
base
(
suffix
);
set_orientation
(
Gtk
.
Orientation
.
VERTICAL
);
Json
.
Object
?
config
=
get_config
(
this
);
if
(
config
==
null
)
{
return
;
}
Json
.
Array
?
tile_configs
=
get_prop_array
(
config
,
"tiles"
);
if
(
tile_configs
==
null
||
tile_configs
.
get_length
()
==
0
)
{
return
;
}
// Create tiles
for
(
uint
i
=
0
;
i
<
tile_configs
.
get_length
();
i
++)
{
Json
.
Object
?
tile_cfg
=
tile_configs
.
get_object_element
(
i
);
if
(
tile_cfg
==
null
)
{
continue
;
}
string
?
type_id
=
tile_cfg
.
get_string_member_with_default
(
"type"
,
null
);
if
(
type_id
==
null
)
{
continue
;
}
QuickSettingsTile
?
tile
=
create_tile
(
type_id
,
tile_cfg
);
if
(
tile
==
null
)
{
continue
;
}
tiles
.
append
(
tile
);
}
build_grid
();
}
private
void
build_grid
()
{
int
row_index
=
0
;
unowned
List
<
QuickSettingsTile
>
iter
=
tiles
;
var
size_group
=
new
Gtk
.
SizeGroup
(
Gtk
.
SizeGroupMode
.
VERTICAL
);
while
(
iter
!=
null
)
{
var
row_box
=
new
Gtk
.
Box
(
Gtk
.
Orientation
.
HORIZONTAL
,
8
);
row_box
.
set_homogeneous
(
true
);
row_box
.
add_css_class
(
"quick-settings-row"
);
var
revealer
=
new
Gtk
.
Revealer
();
revealer
.
set_transition_type
(
Gtk
.
RevealerTransitionType
.
SLIDE_DOWN
);
revealer
.
set_transition_duration
(
200
);
rows
+=
TileRow
()
{
revealer
=
revealer
,
active_submenu_tile
=
null
,
};
int
current_row
=
row_index
;
for
(
int
col
=
0
;
col
<
columns
;
col
++)
{
if
(
iter
==
null
)
{
// Pad with empty box for alignment
var
spacer
=
new
Gtk
.
Box
(
Gtk
.
Orientation
.
HORIZONTAL
,
0
);
row_box
.
append
(
spacer
);
break
;
}
unowned
QuickSettingsTile
tile
=
iter
.
data
;
size_group
.
add_widget
(
tile
);
row_box
.
append
(
tile
);
// Connect submenu signals
tile
.
submenu_requested
.
connect
(()
=>
{
on_submenu_requested
(
tile
,
current_row
);
});
tile
.
submenu_update_requested
.
connect
(()
=>
{
update_submenu
(
tile
,
current_row
);
});
iter
=
iter
.
next
;
}
append
(
row_box
);
append
(
revealer
);
row_index
++;
}
}
private
void
on_submenu_requested
(
QuickSettingsTile
tile
,
int
row_idx
)
{
// Close all other revealers
for
(
int
i
=
0
;
i
<
rows
.
length
;
i
++)
{
if
(
i
!=
row_idx
)
{
rows
[
i
].
revealer
.
set_reveal_child
(
false
);
rows
[
i
].
active_submenu_tile
=
null
;
}
}
// Toggle same tile — close
if
(
rows
[
row_idx
].
active_submenu_tile
==
tile
)
{
rows
[
row_idx
].
revealer
.
set_reveal_child
(
false
);
rows
[
row_idx
].
active_submenu_tile
=
null
;
return
;
}
// Open new submenu (always recreate for fresh data)
Gtk
.
Widget
?
submenu
=
tile
.
create_submenu
();
if
(
submenu
==
null
)
{
return
;
}
rows
[
row_idx
].
revealer
.
set_child
(
submenu
);
rows
[
row_idx
].
revealer
.
set_reveal_child
(
true
);
rows
[
row_idx
].
active_submenu_tile
=
tile
;
}
private
void
update_submenu
(
QuickSettingsTile
tile
,
int
row_idx
)
{
if
(
rows
[
row_idx
].
active_submenu_tile
!=
tile
)
{
return
;
}
Gtk
.
Widget
?
submenu
=
tile
.
create_submenu
();
if
(
submenu
!=
null
)
{
rows
[
row_idx
].
revealer
.
set_child
(
submenu
);
}
}
public
override
void
on_cc_visibility_change
(
bool
val
)
{
if
(!
val
)
{
// Close all submenus
for
(
int
i
=
0
;
i
<
rows
.
length
;
i
++)
{
rows
[
i
].
revealer
.
set_reveal_child
(
false
);
rows
[
i
].
active_submenu_tile
=
null
;
}
}
foreach
(
unowned
QuickSettingsTile
tile
in
tiles
)
{
tile
.
on_cc_visibility_change
(
val
);
}
}
}
}
src/controlCenter/widgets/quickSettings/quickSettingsTile.vala
0 → 100644
View file @
c5a049f2
namespace
XimperShellNotificationCenter.Widgets
{
public
abstract
class
QuickSettingsTile
:
Gtk
.
Box
{
protected
Gtk
.
Button
toggle_button
;
protected
Gtk
.
Image
icon
;
protected
Gtk
.
Label
title_label
;
protected
Gtk
.
Label
subtitle_label
;
protected
Gtk
.
Button
?
arrow_button
=
null
;
private
bool
_active
=
false
;
public
bool
active
{
get
{
return
_active
;
}
set
{
_active
=
value
;
if
(
_active
)
{
add_css_class
(
"active"
);
}
else
{
remove_css_class
(
"active"
);
}
}
}
public
signal
void
submenu_requested
();
public
signal
void
submenu_update_requested
();
protected
QuickSettingsTile
(
string
icon_name
,
string
title
,
string
?
subtitle
=
null
)
{
Object
(
orientation
:
Gtk
.
Orientation
.
HORIZONTAL
);
set_hexpand
(
true
);
set_valign
(
Gtk
.
Align
.
FILL
);
add_css_class
(
"quick-settings-tile"
);
// Toggle button — main clickable area
toggle_button
=
new
Gtk
.
Button
();
toggle_button
.
add_css_class
(
"tile-toggle"
);
toggle_button
.
set_hexpand
(
true
);
var
btn_content
=
new
Gtk
.
Box
(
Gtk
.
Orientation
.
HORIZONTAL
,
8
);
btn_content
.
set_valign
(
Gtk
.
Align
.
CENTER
);
icon
=
new
Gtk
.
Image
.
from_icon_name
(
icon_name
);
icon
.
add_css_class
(
"tile-icon"
);
var
text_box
=
new
Gtk
.
Box
(
Gtk
.
Orientation
.
VERTICAL
,
0
);
text_box
.
set_valign
(
Gtk
.
Align
.
CENTER
);
text_box
.
set_halign
(
Gtk
.
Align
.
START
);
title_label
=
new
Gtk
.
Label
(
title
);
title_label
.
set_halign
(
Gtk
.
Align
.
START
);
title_label
.
set_ellipsize
(
Pango
.
EllipsizeMode
.
END
);
title_label
.
add_css_class
(
"tile-title"
);
subtitle_label
=
new
Gtk
.
Label
(
subtitle
);
subtitle_label
.
set_halign
(
Gtk
.
Align
.
START
);
subtitle_label
.
set_ellipsize
(
Pango
.
EllipsizeMode
.
END
);
subtitle_label
.
add_css_class
(
"tile-subtitle"
);
subtitle_label
.
add_css_class
(
"dim-label"
);
subtitle_label
.
add_css_class
(
"caption"
);
subtitle_label
.
set_visible
(
subtitle
!=
null
);
text_box
.
append
(
title_label
);
text_box
.
append
(
subtitle_label
);
btn_content
.
append
(
icon
);
btn_content
.
append
(
text_box
);
toggle_button
.
set_child
(
btn_content
);
toggle_button
.
clicked
.
connect
(()
=>
{
on_toggle
();
});
append
(
toggle_button
);
}
protected
void
setup_arrow
()
{
add_css_class
(
"has-submenu"
);
var
separator
=
new
Gtk
.
Separator
(
Gtk
.
Orientation
.
VERTICAL
);
separator
.
add_css_class
(
"tile-separator"
);
arrow_button
=
new
Gtk
.
Button
();
arrow_button
.
add_css_class
(
"tile-arrow"
);
arrow_button
.
set_child
(
new
Gtk
.
Image
.
from_icon_name
(
"pan-end-symbolic"
));
arrow_button
.
clicked
.
connect
(()
=>
{
submenu_requested
();
});
append
(
separator
);
append
(
arrow_button
);
}
public
void
set_subtitle
(
string
?
text
)
{
if
(
text
!=
null
)
{
subtitle_label
.
set_text
(
text
);
subtitle_label
.
set_visible
(
true
);
}
else
{
subtitle_label
.
set_visible
(
false
);
}
}
public
virtual
bool
is_available
()
{
return
true
;
}
public
abstract
void
on_toggle
();
public
virtual
Gtk
.
Widget
?
create_submenu
()
{
return
null
;
}
public
virtual
void
on_cc_visibility_change
(
bool
visible
)
{
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment