mirror of
https://github.com/zoriya/ags.git
synced 2026-06-01 10:15:15 +00:00
example
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Aylur's Gtk Shell
|
||||
|
||||
The goal of this project is to be something like [EWW](https://github.com/elkowar/eww), but offer predifined components instead of barebone widgets, so that you don't have to build your desktop from scratch, but still have the option to build custom components without any constraints.
|
||||
~~The goal of this project is to be something like [EWW](https://github.com/elkowar/eww), but offer predifined components instead of barebone widgets, so that you don't have to build your desktop from scratch, but still have the option to build custom components without any constraints.~~
|
||||
|
||||
## Get started
|
||||
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// importing
|
||||
const { Hyprland, Notifications, Mpris, Audio, Battery } = ags.Service;
|
||||
const { exec, CONFIG_DIR } = ags.Utils;
|
||||
|
||||
const workspaces = {
|
||||
type: 'box',
|
||||
className: 'workspaces',
|
||||
// box is an instance of Gtk.Box
|
||||
connections: [[Hyprland, box => {
|
||||
// remove every children
|
||||
box.get_children().forEach(ch => ch.destroy());
|
||||
|
||||
// add a button for each workspace
|
||||
const workspaces = 10;
|
||||
for (let i = 1; i <= workspaces; ++i) {
|
||||
box.add(ags.Widget({
|
||||
type: 'button',
|
||||
onClick: () => execAsync(`hyprctl dispatch workspace ${i}`),
|
||||
child: i.toString(),
|
||||
className: Hyprland.active.workspace.id == i ? 'focused' : '',
|
||||
}));
|
||||
}
|
||||
|
||||
// make the box render it
|
||||
box.show_all();
|
||||
}]],
|
||||
};
|
||||
|
||||
const clientTitle = {
|
||||
type: 'label',
|
||||
className: 'client-title',
|
||||
// label is an instance of Gtk.Label
|
||||
connections: [[Hyprland, label => {
|
||||
label.label = Hyprland.active.client.title || '';
|
||||
}]],
|
||||
};
|
||||
|
||||
const clock = {
|
||||
type: 'label',
|
||||
className: 'clock',
|
||||
// trim is for the whitespace at the end of the date output
|
||||
// but doing this is actually bad practice
|
||||
// because exec() will block the main thread, but in case of runnig date
|
||||
// I don't think it matters
|
||||
connections: [[1000, label => label.label = exec('date "+%H:%M:%S %b %e."').trim()]],
|
||||
};
|
||||
|
||||
// we don't need dunst or any other notification daemon
|
||||
// because ags has a notification daemon built in
|
||||
const notification = {
|
||||
type: 'box',
|
||||
className: 'notification',
|
||||
children: [
|
||||
{
|
||||
type: 'icon',
|
||||
icon: 'preferences-system-notifications-symbolic',
|
||||
// icon is an instance of Gtk.Image
|
||||
connections: [[Notifications, icon => icon.visible = Notifications.popups.size > 0]]
|
||||
},
|
||||
{
|
||||
type: 'label',
|
||||
connections: [[Notifications, label => {
|
||||
// notifications is a map, to get the last elememnt lets make an array
|
||||
label.label = Array.from(Notifications.popups)?.pop()?.[1].summary || '';
|
||||
}]],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const media = {
|
||||
type: 'label',
|
||||
className: 'media',
|
||||
connections: [[Mpris, label => {
|
||||
const mpris = Mpris.getPlayer('');
|
||||
if (mpris)
|
||||
label.label = `${mpris.trackArtists.join(', ')} - ${mpris.trackTitle}`;
|
||||
else
|
||||
label.label = 'Nothing is playing';
|
||||
}]],
|
||||
};
|
||||
|
||||
const volume = {
|
||||
type: 'box',
|
||||
className: 'volume',
|
||||
style: 'min-width: 180px',
|
||||
children: [
|
||||
{
|
||||
type: 'dynamic',
|
||||
items: [
|
||||
{ value: 101, widget: { type: 'icon', icon: 'audio-volume-overamplified-symbolic' } },
|
||||
{ value: 67, widget: { type: 'icon', icon: 'audio-volume-high-symbolic' } },
|
||||
{ value: 34, widget: { type: 'icon', icon: 'audio-volume-medium-symbolic' } },
|
||||
{ value: 1, widget: { type: 'icon', icon: 'audio-volume-low-symbolic' } },
|
||||
{ value: 0, widget: { type: 'icon', icon: 'audio-volume-muted-symbolic' } },
|
||||
],
|
||||
// dynamic is a Gtk.Box with an extra update method
|
||||
connections: [[Audio, dynamic => dynamic.update(value => {
|
||||
if (!Audio.speaker)
|
||||
return;
|
||||
|
||||
if (Audio.speaker.isMuted)
|
||||
return value === 0;
|
||||
|
||||
return value <= (Audio.speaker.volume*100);
|
||||
}), 'speaker-changed']],
|
||||
},
|
||||
{
|
||||
type: 'slider',
|
||||
hexpand: true,
|
||||
onChange: value => Audio.speaker.volume = value,
|
||||
connections: [[Audio, slider => {
|
||||
if (!Audio.speaker)
|
||||
return;
|
||||
|
||||
slider.adjustment.value = Audio.speaker.volume;
|
||||
}, 'speaker-changed']],
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
const battery = {
|
||||
type: 'box',
|
||||
className: 'battery',
|
||||
children: [
|
||||
{
|
||||
type: 'icon',
|
||||
connections: [[Battery, icon => {
|
||||
// icon is an instance of Gtk.Image
|
||||
icon.icon_name = `battery-level-${Math.floor(Battery.percent/10)*10}-symbolic`;
|
||||
}]]
|
||||
},
|
||||
{
|
||||
type: 'progressbar',
|
||||
valign: 'center',
|
||||
// progressbar is a Gtk.ProgressBar, setValue() just calls set_fraction()
|
||||
connections: [[Battery, progress => progress.setValue(Battery.percent/100)]],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// layout of the bar
|
||||
const left = {
|
||||
type: 'box',
|
||||
children: [
|
||||
workspaces,
|
||||
clientTitle,
|
||||
],
|
||||
};
|
||||
|
||||
const center = {
|
||||
type: 'box',
|
||||
className: 'center',
|
||||
children: [
|
||||
media,
|
||||
notification,
|
||||
],
|
||||
};
|
||||
|
||||
const right = {
|
||||
type: 'box',
|
||||
className: 'right',
|
||||
halign: 'end',
|
||||
children: [
|
||||
volume,
|
||||
battery,
|
||||
clock,
|
||||
],
|
||||
};
|
||||
|
||||
const bar = {
|
||||
name: 'bar',
|
||||
anchor: ['top', 'left', 'right'],
|
||||
exclusive: true,
|
||||
child: {
|
||||
type: 'centerbox',
|
||||
children: [
|
||||
left,
|
||||
center,
|
||||
right,
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
// exporting the config
|
||||
var config = {
|
||||
style: CONFIG_DIR+'/style.css',
|
||||
windows: [bar],
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.workspaces button {
|
||||
background-color: transparent;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.workspaces button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: #efefef;
|
||||
}
|
||||
|
||||
.workspaces button:active {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.workspaces button.focused {
|
||||
border-bottom: 3px solid aqua;
|
||||
}
|
||||
|
||||
.client-title {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.client-title {
|
||||
color: aqua;
|
||||
}
|
||||
|
||||
.notification image {
|
||||
color: yellow;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.battery progressbar {
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.clock {
|
||||
margin: 0 6px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
progress, highlight {
|
||||
background-color: aqua;
|
||||
min-height: 8px;
|
||||
}
|
||||
+1
-1
@@ -428,10 +428,10 @@ export function ProgressBar({ type,
|
||||
const bar = new Gtk.ProgressBar({
|
||||
orientation: _orientation(orientation),
|
||||
inverted,
|
||||
fraction: value,
|
||||
});
|
||||
|
||||
bar.setValue = v => bar.set_fraction(v);
|
||||
bar.setValue(value);
|
||||
return bar;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user