feat(ags): use new widget prop cursor
This commit is contained in:
parent
6603902687
commit
c5859fa87b
9 changed files with 173 additions and 193 deletions
|
@ -2,11 +2,8 @@ import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
|
|||
import { Button, Icon, Label, Stack, Slider, CenterBox, Box } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { execAsync, lookUpIcon, readFileAsync } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
import Gdk from 'gi://Gdk';
|
||||
const display = Gdk.Display.get_default();
|
||||
|
||||
import Separator from '../misc/separator.js';
|
||||
import EventBox from '../misc/cursorbox.js';
|
||||
import EventBox from '../misc/cursorbox.js';
|
||||
|
||||
const icons = {
|
||||
mpris: {
|
||||
|
@ -148,58 +145,54 @@ export const PlayerIcon = (player, { symbolic = true, ...props } = {}) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const PositionSlider = (player, props) => EventBox({
|
||||
child: Slider({
|
||||
...props,
|
||||
className: 'position-slider',
|
||||
hexpand: true,
|
||||
drawValue: false,
|
||||
onChange: ({ value }) => {
|
||||
player.position = player.length * value;
|
||||
},
|
||||
properties: [['update', slider => {
|
||||
if (slider.dragging) {
|
||||
slider.get_parent().window.set_cursor(Gdk.Cursor
|
||||
.new_from_name(display, 'grabbing'));
|
||||
export const PositionSlider = (player, props) => Slider({
|
||||
...props,
|
||||
className: 'position-slider',
|
||||
cursor: 'pointer',
|
||||
vpack: 'center',
|
||||
hexpand: true,
|
||||
drawValue: false,
|
||||
onChange: ({ value }) => {
|
||||
player.position = player.length * value;
|
||||
},
|
||||
properties: [['update', slider => {
|
||||
if (!slider.dragging) {
|
||||
slider.visible = player.length > 0;
|
||||
if (player.length > 0)
|
||||
slider.value = player.position / player.length;
|
||||
}
|
||||
}]],
|
||||
connections: [
|
||||
[player, s => s._update(s), 'position'],
|
||||
[1000, s => s._update(s)],
|
||||
[player.colors, s => {
|
||||
const c = player.colors.value;
|
||||
if (player.colors.value) {
|
||||
s.setCss(`
|
||||
highlight { background-color: ${c.buttonAccent}; }
|
||||
slider { background-color: ${c.buttonAccent}; }
|
||||
slider:hover { background-color: ${c.hoverAccent}; }
|
||||
trough { background-color: ${c.buttonText}; }
|
||||
`);
|
||||
}
|
||||
else {
|
||||
slider.get_parent()?.window?.set_cursor(Gdk.Cursor
|
||||
.new_from_name(display, 'pointer'));
|
||||
}],
|
||||
|
||||
slider.visible = player.length > 0;
|
||||
if (player.length > 0)
|
||||
slider.value = player.position / player.length;
|
||||
}
|
||||
}]],
|
||||
connections: [
|
||||
[player, s => s._update(s), 'position'],
|
||||
[1000, s => s._update(s)],
|
||||
[player.colors, s => {
|
||||
const c = player.colors.value;
|
||||
if (player.colors.value) {
|
||||
s.setCss(`
|
||||
highlight { background-color: ${c.buttonAccent}; }
|
||||
slider { background-color: ${c.buttonAccent}; }
|
||||
slider:hover { background-color: ${c.hoverAccent}; }
|
||||
trough { background-color: ${c.buttonText}; }
|
||||
`);
|
||||
}
|
||||
}],
|
||||
],
|
||||
}),
|
||||
['button-press-event', s => { s.cursor = 'grabbing'; }],
|
||||
['button-release-event', s => { s.cursor = 'pointer'; }],
|
||||
],
|
||||
});
|
||||
|
||||
const PlayerButton = ({ player, items, onClick, prop }) => Button({
|
||||
child: Stack({ items }),
|
||||
onPrimaryClickRelease: () => player[onClick](),
|
||||
properties: [['hovered', false]],
|
||||
onHover: self => {
|
||||
self._hovered = true;
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer'));
|
||||
const PlayerButton = ({ player, items, onClick, prop }) => EventBox({
|
||||
child: Button({
|
||||
child: Stack({ items }),
|
||||
onPrimaryClickRelease: () => player[onClick](),
|
||||
properties: [['hovered', false]],
|
||||
onHover: self => {
|
||||
self._hovered = true;
|
||||
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
background-color: ${player.colors.value.hoverAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 40px;
|
||||
|
@ -207,37 +200,36 @@ const PlayerButton = ({ player, items, onClick, prop }) => Button({
|
|||
margin-bottom: 1px;
|
||||
margin-right: 1px;
|
||||
`);
|
||||
});
|
||||
}
|
||||
},
|
||||
onHoverLost: self => {
|
||||
self._hovered = false;
|
||||
self.window.set_cursor(null);
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
});
|
||||
}
|
||||
},
|
||||
onHoverLost: self => {
|
||||
self._hovered = false;
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
background-color: ${player.colors.value.buttonAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 42px;
|
||||
min-width: 38px;
|
||||
`);
|
||||
});
|
||||
}
|
||||
},
|
||||
connections: [
|
||||
[player, button => {
|
||||
button.child.shown = `${player[prop]}`;
|
||||
}],
|
||||
});
|
||||
}
|
||||
},
|
||||
connections: [
|
||||
[player, button => {
|
||||
button.child.shown = `${player[prop]}`;
|
||||
}],
|
||||
|
||||
[player.colors, button => {
|
||||
if (!Mpris.players.find(p => player === p))
|
||||
return;
|
||||
[player.colors, button => {
|
||||
if (!Mpris.players.find(p => player === p))
|
||||
return;
|
||||
|
||||
if (player.colors.value) {
|
||||
if (prop == 'playBackStatus') {
|
||||
if (button._hovered) {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
if (player.colors.value) {
|
||||
if (prop == 'playBackStatus') {
|
||||
if (button._hovered) {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
background-color: ${player.colors.value.hoverAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 40px;
|
||||
|
@ -245,27 +237,28 @@ const PlayerButton = ({ player, items, onClick, prop }) => Button({
|
|||
margin-bottom: 1px;
|
||||
margin-right: 1px;
|
||||
`);
|
||||
});
|
||||
}
|
||||
else {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
});
|
||||
}
|
||||
else {
|
||||
items.forEach(item => {
|
||||
item[1].setCss(`
|
||||
background-color: ${player.colors.value.buttonAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 42px;
|
||||
min-width: 38px;`);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
button.setCss(`
|
||||
else {
|
||||
button.setCss(`
|
||||
* { color: ${player.colors.value.buttonAccent}; }
|
||||
*:hover { color: ${player.colors.value.hoverAccent}; }
|
||||
`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
export const ShuffleButton = player => PlayerButton({
|
||||
|
|
|
@ -2,16 +2,11 @@ import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
|||
import { Button, EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
import Gtk from 'gi://Gtk';
|
||||
import Gdk from 'gi://Gdk';
|
||||
const display = Gdk.Display.get_default();
|
||||
|
||||
|
||||
// TODO: wrap in another EventBox for disabled cursor
|
||||
export default ({
|
||||
isButton = false,
|
||||
reset = true,
|
||||
onHover = () => {},
|
||||
onHoverLost = () => {},
|
||||
onPrimaryClickRelease = () => {},
|
||||
...props
|
||||
}) => {
|
||||
|
@ -21,6 +16,7 @@ export default ({
|
|||
|
||||
const properties = {
|
||||
...props,
|
||||
cursor: 'pointer',
|
||||
onPrimaryClickRelease: self => {
|
||||
// Every click, do a one shot connect to
|
||||
// CanRun to wait for location of click
|
||||
|
@ -31,21 +27,6 @@ export default ({
|
|||
CanRun.disconnect(id);
|
||||
});
|
||||
},
|
||||
onHover: self => {
|
||||
if (!self.child.sensitive || !self.sensitive)
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed'));
|
||||
|
||||
else
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer'));
|
||||
|
||||
onHover(self);
|
||||
},
|
||||
onHoverLost: self => {
|
||||
if (reset)
|
||||
self.window.set_cursor(null);
|
||||
|
||||
onHoverLost(self);
|
||||
},
|
||||
};
|
||||
|
||||
let widget;
|
||||
|
|
|
@ -179,7 +179,6 @@ export const Notification = ({
|
|||
label: setTime(notif.time),
|
||||
}),
|
||||
EventBox({
|
||||
reset: false,
|
||||
child: Button({
|
||||
className: 'close-button',
|
||||
vpack: 'start',
|
||||
|
|
|
@ -5,8 +5,6 @@ import { timeout } from 'resource:///com/github/Aylur/ags/utils.js';
|
|||
import { HasNotifs } from './base.js';
|
||||
|
||||
import Gtk from 'gi://Gtk';
|
||||
import Gdk from 'gi://Gdk';
|
||||
const display = Gdk.Display.get_default();
|
||||
|
||||
|
||||
export default ({
|
||||
|
@ -20,13 +18,12 @@ export default ({
|
|||
}) => {
|
||||
const widget = EventBox({
|
||||
...props,
|
||||
cursor: 'grab',
|
||||
onHover: self => {
|
||||
self.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
if (!self._hovered)
|
||||
self._hovered = true;
|
||||
},
|
||||
onHoverLost: self => {
|
||||
self.window.set_cursor(null);
|
||||
if (self._hovered)
|
||||
self._hovered = false;
|
||||
},
|
||||
|
@ -85,9 +82,11 @@ export default ({
|
|||
// When dragging
|
||||
[gesture, self => {
|
||||
var offset = gesture.get_offset()[1];
|
||||
if (offset === 0)
|
||||
return;
|
||||
|
||||
// Slide right
|
||||
if (offset >= 0) {
|
||||
if (offset > 0) {
|
||||
self.setCss(`
|
||||
margin-top: 0px; margin-bottom: 0px; opacity: 1; transition: none;
|
||||
margin-left: ${Number(offset + startMargin)}px;
|
||||
|
@ -107,7 +106,7 @@ export default ({
|
|||
|
||||
// Put a threshold on if a click is actually dragging
|
||||
widget._dragging = Math.abs(offset) > 10;
|
||||
widget.window?.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
|
||||
widget.cursor = 'grabbing';
|
||||
}, 'drag-update'],
|
||||
|
||||
|
||||
|
@ -137,8 +136,7 @@ export default ({
|
|||
}
|
||||
else {
|
||||
self.setCss(defaultStyle);
|
||||
widget.window?.set_cursor(Gdk.Cursor.new_from_name(display, 'grab'));
|
||||
|
||||
widget.cursor = 'grab',
|
||||
widget._dragging = false;
|
||||
}
|
||||
}, 'drag-end'],
|
||||
|
|
|
@ -7,42 +7,46 @@ import PopupWindow from '../misc/popup.js';
|
|||
import ToggleButton from './toggle-button.js';
|
||||
|
||||
|
||||
const QuickSettingsWidget = () => Box({
|
||||
className: 'qs-container',
|
||||
vertical: true,
|
||||
children: [
|
||||
const QuickSettingsWidget = () => {
|
||||
const rev = Revealer({
|
||||
transition: 'slide_down',
|
||||
child: Player(),
|
||||
});
|
||||
|
||||
Box({
|
||||
className: 'quick-settings',
|
||||
vertical: true,
|
||||
children: [
|
||||
return Box({
|
||||
className: 'qs-container',
|
||||
vertical: true,
|
||||
children: [
|
||||
|
||||
Label({
|
||||
label: 'Control Center',
|
||||
className: 'title',
|
||||
hpack: 'start',
|
||||
css: `
|
||||
Box({
|
||||
className: 'quick-settings',
|
||||
vertical: true,
|
||||
children: [
|
||||
|
||||
Label({
|
||||
label: 'Control Center',
|
||||
className: 'title',
|
||||
hpack: 'start',
|
||||
css: `
|
||||
margin-left: 20px;
|
||||
margin-bottom: 30px;
|
||||
`,
|
||||
}),
|
||||
}),
|
||||
|
||||
ButtonGrid(),
|
||||
ButtonGrid(),
|
||||
|
||||
SliderBox(),
|
||||
SliderBox(),
|
||||
|
||||
ToggleButton(),
|
||||
ToggleButton(rev),
|
||||
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
||||
Revealer({
|
||||
transition: 'slide_down',
|
||||
child: Player(),
|
||||
}),
|
||||
rev,
|
||||
|
||||
],
|
||||
});
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
export default () => PopupWindow({
|
||||
name: 'quick-settings',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
import { Box, Slider, Icon, EventBox } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import { Box, Slider, Icon } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
import { SpeakerIcon } from '../misc/audio-icons.js';
|
||||
|
||||
|
@ -22,10 +22,16 @@ export default () => Box({
|
|||
}),
|
||||
|
||||
Slider({
|
||||
connections: [[Audio, slider => {
|
||||
if (Audio.speaker)
|
||||
slider.value = Audio.speaker.volume;
|
||||
}, 'speaker-changed']],
|
||||
cursor: 'pointer',
|
||||
vpack: 'center',
|
||||
connections: [
|
||||
[Audio, slider => {
|
||||
slider.value = Audio.speaker?.volume;
|
||||
}, 'speaker-changed'],
|
||||
|
||||
['button-press-event', s => { s.cursor = 'grabbing'; }],
|
||||
['button-release-event', s => { s.cursor = 'pointer'; }],
|
||||
],
|
||||
onChange: ({ value }) => Audio.speaker.volume = value,
|
||||
max: 0.999,
|
||||
draw_value: false,
|
||||
|
@ -43,22 +49,19 @@ export default () => Box({
|
|||
icon: 'display-brightness-symbolic',
|
||||
}),
|
||||
|
||||
EventBox({
|
||||
onHover: box => box.child._canChange = false,
|
||||
onHoverLost: box => box.child._canChange = true,
|
||||
child: Slider({
|
||||
properties: [
|
||||
['canChange', true],
|
||||
],
|
||||
onChange: ({ value }) => {
|
||||
Brightness.screen = value;
|
||||
},
|
||||
connections: [[Brightness, slider => {
|
||||
if (slider._canChange)
|
||||
slider.value = Brightness.screen;
|
||||
}, 'screen']],
|
||||
draw_value: false,
|
||||
}),
|
||||
Slider({
|
||||
cursor: 'pointer',
|
||||
vpack: 'center',
|
||||
onChange: ({ value }) => Brightness.screen = value,
|
||||
connections: [
|
||||
[Brightness, slider => {
|
||||
slider.value = Brightness.screen;
|
||||
}, 'screen'],
|
||||
|
||||
['button-press-event', s => { s.cursor = 'grabbing'; }],
|
||||
['button-release-event', s => { s.cursor = 'pointer'; }],
|
||||
],
|
||||
draw_value: false,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
|
||||
import { Icon, ToggleButton } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
import EventBox from '../misc/cursorbox.js';
|
||||
import { CenterBox, Icon, ToggleButton } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
|
||||
|
||||
export default () => EventBox({
|
||||
child: ToggleButton({
|
||||
export default rev => CenterBox({
|
||||
center_widget: ToggleButton({
|
||||
cursor: 'pointer',
|
||||
setup: self => {
|
||||
// Open at startup if there are players
|
||||
const id = Mpris.connect('changed', () => {
|
||||
|
@ -16,8 +15,6 @@ export default () => EventBox({
|
|||
},
|
||||
|
||||
connections: [['toggled', self => {
|
||||
const rev = self.get_parent().get_parent().get_parent().children[1];
|
||||
|
||||
if (self.get_active()) {
|
||||
self.get_children()[0]
|
||||
.setCss('-gtk-icon-transform: rotate(0deg);');
|
||||
|
@ -36,4 +33,6 @@ export default () => EventBox({
|
|||
css: '-gtk-icon-transform: rotate(180deg);',
|
||||
}),
|
||||
}),
|
||||
start_widget: null,
|
||||
end_widget: null,
|
||||
});
|
||||
|
|
|
@ -132,35 +132,38 @@
|
|||
margin-right: -20px;
|
||||
}
|
||||
|
||||
scale {
|
||||
.slider {
|
||||
min-height: 55px;
|
||||
min-width: 400px;
|
||||
margin-left: 18px;
|
||||
margin-right: 20px;
|
||||
|
||||
highlight {
|
||||
margin: 0;
|
||||
background-color: #79659f;
|
||||
border-radius: 2em;
|
||||
}
|
||||
scale {
|
||||
min-width: 400px;
|
||||
margin-left: 18px;
|
||||
margin-right: 20px;
|
||||
|
||||
trough {
|
||||
background-color: #363847;
|
||||
border-radius: 2em;
|
||||
}
|
||||
highlight {
|
||||
margin: 0;
|
||||
background-color: #79659f;
|
||||
border-radius: 2em;
|
||||
}
|
||||
|
||||
slider {
|
||||
margin: -4px;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
background: #3e4153;
|
||||
border-radius: 100%;
|
||||
transition: background-color 0.5s ease-in-out;
|
||||
}
|
||||
trough {
|
||||
background-color: #363847;
|
||||
border-radius: 2em;
|
||||
}
|
||||
|
||||
slider:hover {
|
||||
background-color: #303240;
|
||||
transition: background-color 0.5s ease-in-out;
|
||||
slider {
|
||||
margin: -4px;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
background: #3e4153;
|
||||
border-radius: 100%;
|
||||
transition: background-color 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
slider:hover {
|
||||
background-color: #303240;
|
||||
transition: background-color 0.5s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
flake.lock
BIN
flake.lock
Binary file not shown.
Loading…
Reference in a new issue