✨ feat(control-center/tiles): update tiles look and structure
This commit is contained in:
@@ -199,78 +199,67 @@
|
|||||||
.tiles-container {
|
.tiles-container {
|
||||||
@include mixins.reset-props;
|
@include mixins.reset-props;
|
||||||
|
|
||||||
& > flowbox {
|
& .tile {
|
||||||
& > flowboxchild .tile {
|
|
||||||
$radius: 18px;
|
$radius: 18px;
|
||||||
|
$padding: 4px;
|
||||||
|
|
||||||
&:not(.toggled) > .toggle-button,
|
background: rgba(colors.$bg-primary, .5);
|
||||||
&:not(.toggled) > button.more {
|
|
||||||
background: colors.$bg-primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.toggled) > .toggle-button:hover,
|
|
||||||
&:not(.toggled) > button.more:hover {
|
|
||||||
background: color.scale($color: colors.$bg-primary, $lightness: 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.toggled .toggle-button:hover,
|
|
||||||
&.toggled button.more:hover {
|
|
||||||
background: colors.$bg-tertiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.toggled > .toggle-button,
|
|
||||||
&.toggled > button.more {
|
|
||||||
background: colors.$bg-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.has-more > .toggle-button,
|
|
||||||
&.has-more > button.toggle-button:active {
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > button.toggle-button {
|
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
|
padding: $padding;
|
||||||
|
min-height: 40px;
|
||||||
|
|
||||||
|
& .icon {
|
||||||
|
transition: 120ms ease-in;
|
||||||
|
border-radius: calc($radius - $padding);
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin-right: 6px;
|
||||||
|
background: color.scale($color: colors.$bg-primary, $lightness: 10%);
|
||||||
|
|
||||||
|
& image {
|
||||||
|
-gtk-icon-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: color.scale($color: colors.$bg-primary, $lightness: 15%);
|
||||||
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
border-radius: calc($radius - 4px);
|
border-radius: calc($radius - $padding - 2px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& .content {
|
& .content {
|
||||||
padding: 8px;
|
& .title {
|
||||||
|
|
||||||
& > .icon {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .text {
|
|
||||||
& > .title {
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 15.1px;
|
font-size: 15.1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .description {
|
& .description {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: colors.$fg-disabled;
|
color: colors.$fg-disabled;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
& .arrow {
|
||||||
|
-gtk-icon-size: 12px;
|
||||||
|
color: rgba(colors.$fg-disabled, .4);
|
||||||
}
|
}
|
||||||
|
|
||||||
& > button.more {
|
&:hover {
|
||||||
border-top-right-radius: $radius;
|
background: color.scale($color: colors.$bg-primary, $lightness: 5%);
|
||||||
border-bottom-right-radius: $radius;
|
}
|
||||||
|
|
||||||
|
&.enabled .icon {
|
||||||
|
background: colors.$bg-secondary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: colors.$bg-tertiary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
border-top-right-radius: calc($radius - 4px);
|
border-radius: calc($radius - 2px);
|
||||||
border-bottom-right-radius: calc($radius - 4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { generalConfig, Shell } from "../app";
|
|||||||
|
|
||||||
import AstalIO from "gi://AstalIO";
|
import AstalIO from "gi://AstalIO";
|
||||||
import AstalMpris from "gi://AstalMpris";
|
import AstalMpris from "gi://AstalMpris";
|
||||||
|
import { Gtk } from "ags/gtk4";
|
||||||
|
|
||||||
|
|
||||||
export type RemoteCaller = {
|
export type RemoteCaller = {
|
||||||
@@ -35,7 +36,10 @@ made using GTK4, AGS, Gnim and Astal libraries by Aylur.
|
|||||||
|
|
||||||
Media Controls:
|
Media Controls:
|
||||||
media: manage colorshell's active player, see "media help".
|
media: manage colorshell's active player, see "media help".
|
||||||
|
${DEVEL ? `
|
||||||
|
Development Tools:
|
||||||
|
dev: tools to help debugging colorshell
|
||||||
|
` : ""}
|
||||||
Other options:
|
Other options:
|
||||||
runner [initial_text]: open the application runner, optionally add an initial search.
|
runner [initial_text]: open the application runner, optionally add an initial search.
|
||||||
peek-workspace-num [millis]: peek the workspace numbers on bar window.
|
peek-workspace-num [millis]: peek the workspace numbers on bar window.
|
||||||
@@ -44,7 +48,7 @@ made using GTK4, AGS, Gnim and Astal libraries by Aylur.
|
|||||||
|
|
||||||
2025 (c) retrozinndev's colorshell, licensed under the MIT License.
|
2025 (c) retrozinndev's colorshell, licensed under the MIT License.
|
||||||
https://github.com/retrozinndev/colorshell
|
https://github.com/retrozinndev/colorshell
|
||||||
`.split('\n').map(l => l.replace(/^ {8}/, "")).join('\n');
|
`.trim();
|
||||||
|
|
||||||
export function handleArguments(cmd: RemoteCaller, args: Array<string>): number {
|
export function handleArguments(cmd: RemoteCaller, args: Array<string>): number {
|
||||||
switch(args[0]) {
|
switch(args[0]) {
|
||||||
@@ -59,6 +63,9 @@ export function handleArguments(cmd: RemoteCaller, args: Array<string>): number
|
|||||||
}${DEVEL ? " (devel)" : ""}\nhttps://github.com/retrozinndev/colorshell`);
|
}${DEVEL ? " (devel)" : ""}\nhttps://github.com/retrozinndev/colorshell`);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case "dev":
|
||||||
|
return handleDevArgs(cmd, args);
|
||||||
|
|
||||||
case "open":
|
case "open":
|
||||||
case "close":
|
case "close":
|
||||||
case "toggle":
|
case "toggle":
|
||||||
@@ -115,6 +122,28 @@ export function handleArguments(cmd: RemoteCaller, args: Array<string>): number
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleDevArgs(cmd: RemoteCaller, args: Array<string>): number {
|
||||||
|
if(/h|help/.test(args[1])) {
|
||||||
|
cmd.print_literal(`
|
||||||
|
Debugging tools for colorshell.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
inspector: open GTK's visual debugger
|
||||||
|
`.trim());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(args[1]) {
|
||||||
|
case "inspector":
|
||||||
|
cmd.print_literal("Opening inspector...");
|
||||||
|
Gtk.Window.set_interactive_debugging(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.printerr_literal("Error: command not found! try checking `dev help`");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
function handleMediaArgs(cmd: RemoteCaller, args: Array<string>): number {
|
function handleMediaArgs(cmd: RemoteCaller, args: Array<string>): number {
|
||||||
if(/h|help/.test(args[1])) {
|
if(/h|help/.test(args[1])) {
|
||||||
const mediaHelp = `
|
const mediaHelp = `
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ export const TileBluetooth = () =>
|
|||||||
} description={createBinding(AstalBluetooth.get_default(), "isConnected").as((connected) => {
|
} description={createBinding(AstalBluetooth.get_default(), "isConnected").as((connected) => {
|
||||||
const connectedDev = AstalBluetooth.get_default().devices.filter(dev => dev.connected)?.[0];
|
const connectedDev = AstalBluetooth.get_default().devices.filter(dev => dev.connected)?.[0];
|
||||||
return connected && connectedDev ? connectedDev.get_alias() : ""
|
return connected && connectedDev ? connectedDev.get_alias() : ""
|
||||||
})} onToggledOn={() => AstalBluetooth.get_default().adapter?.set_powered(true)}
|
})}
|
||||||
onToggledOff={() => AstalBluetooth.get_default().adapter?.set_powered(false)}
|
onEnabled={() => AstalBluetooth.get_default().adapter?.set_powered(true)}
|
||||||
onClickMore={() => TilesPages?.toggle(BluetoothPage)}
|
onDisabled={() => AstalBluetooth.get_default().adapter?.set_powered(false)}
|
||||||
enableOnClickMore={true} iconSize={16}
|
onClicked={() => TilesPages?.toggle(BluetoothPage)}
|
||||||
toggleState={createBinding(AstalBluetooth.get_default(), "isPowered")}
|
enableOnClicked hasArrow
|
||||||
|
state={createBinding(AstalBluetooth.get_default(), "isPowered")}
|
||||||
icon={createComputed([
|
icon={createComputed([
|
||||||
createBinding(AstalBluetooth.get_default(), "isPowered"),
|
createBinding(AstalBluetooth.get_default(), "isPowered"),
|
||||||
createBinding(AstalBluetooth.get_default(), "isConnected")
|
createBinding(AstalBluetooth.get_default(), "isConnected")
|
||||||
@@ -24,5 +25,6 @@ export const TileBluetooth = () =>
|
|||||||
powered ? ( isConnected ?
|
powered ? ( isConnected ?
|
||||||
"bluetooth-active-symbolic"
|
"bluetooth-active-symbolic"
|
||||||
: "bluetooth-symbolic"
|
: "bluetooth-symbolic"
|
||||||
) : "bluetooth-disabled-symbolic")}
|
) : "bluetooth-disabled-symbolic")
|
||||||
|
}
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ export const TileDND = () =>
|
|||||||
<Tile title={tr("control_center.tiles.dnd.title")}
|
<Tile title={tr("control_center.tiles.dnd.title")}
|
||||||
description={createBinding(Notifications.getDefault().getNotifd(), "dontDisturb").as(
|
description={createBinding(Notifications.getDefault().getNotifd(), "dontDisturb").as(
|
||||||
(dnd: boolean) => dnd ? tr("control_center.tiles.enabled") : tr("control_center.tiles.disabled"))}
|
(dnd: boolean) => dnd ? tr("control_center.tiles.enabled") : tr("control_center.tiles.disabled"))}
|
||||||
onToggledOff={() => Notifications.getDefault().getNotifd().dontDisturb = false}
|
onDisabled={() => Notifications.getDefault().getNotifd().dontDisturb = false}
|
||||||
onToggledOn={() => Notifications.getDefault().getNotifd().dontDisturb = true}
|
onEnabled={() => Notifications.getDefault().getNotifd().dontDisturb = true}
|
||||||
icon={"minus-circle-filled-symbolic"}
|
icon={"minus-circle-filled-symbolic"}
|
||||||
iconSize={16}
|
state={Notifications.getDefault().getNotifd().dontDisturb}
|
||||||
toggleState={Notifications.getDefault().getNotifd().dontDisturb}
|
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
return tr("connecting") + "...";
|
return tr("connecting") + "...";
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
)} onToggledOn={() => wifi.set_enabled(true)}
|
)} onEnabled={() => wifi.set_enabled(true)}
|
||||||
onToggledOff={() => wifi.set_enabled(false)}
|
onDisabled={() => wifi.set_enabled(false)}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
hasArrow onClicked={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={"network-wireless-signal-excellent-symbolic"}
|
icon={"network-wireless-signal-excellent-symbolic"}
|
||||||
toggleState={createBinding(wifi, "enabled")}
|
state={createBinding(wifi, "enabled")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
} else if(primary === AstalNetwork.Primary.WIRED) {
|
} else if(primary === AstalNetwork.Primary.WIRED) {
|
||||||
@@ -48,9 +48,9 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
return tr("connecting") + "...";
|
return tr("connecting") + "...";
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
onToggledOn={() => execAsync("nmcli n on")}
|
hasArrow onEnabled={() => execAsync("nmcli n on")}
|
||||||
onToggledOff={() => execAsync("nmcli n off")}
|
onDisabled={() => execAsync("nmcli n off")}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
onClicked={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
icon={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
||||||
switch(internet) {
|
switch(internet) {
|
||||||
case AstalNetwork.Internet.CONNECTED:
|
case AstalNetwork.Internet.CONNECTED:
|
||||||
@@ -61,8 +61,7 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
|
|
||||||
return "network-wired-no-route-symbolic";
|
return "network-wired-no-route-symbolic";
|
||||||
})}
|
})}
|
||||||
iconSize={16}
|
state={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
||||||
toggleState={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
|
||||||
internet === AstalNetwork.Internet.CONNECTING
|
internet === AstalNetwork.Internet.CONNECTING
|
||||||
|| internet === AstalNetwork.Internet.CONNECTED
|
|| internet === AstalNetwork.Internet.CONNECTED
|
||||||
)}
|
)}
|
||||||
@@ -72,12 +71,11 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
return <Tile
|
return <Tile
|
||||||
title={tr("control_center.tiles.network.network")}
|
title={tr("control_center.tiles.network.network")}
|
||||||
description={tr("disconnected")}
|
description={tr("disconnected")}
|
||||||
onToggledOn={() => execAsync("nmcli n on")}
|
onEnabled={() => execAsync("nmcli n on")}
|
||||||
onToggledOff={() => execAsync("nmcli n off")}
|
onDisabled={() => execAsync("nmcli n off")}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
hasArrow onClicked={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={"network-wired-disconnected-symbolic"}
|
icon={"network-wired-disconnected-symbolic"}
|
||||||
iconSize={16}
|
state={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
||||||
toggleState={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
|
||||||
internet === AstalNetwork.Internet.CONNECTING || internet === AstalNetwork.Internet.CONNECTED)}
|
internet === AstalNetwork.Internet.CONNECTING || internet === AstalNetwork.Internet.CONNECTED)}
|
||||||
/>
|
/>
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ export const TileNightLight = () =>
|
|||||||
tr("control_center.tiles.night_light.default_desc") : `${temp}K`} ${
|
tr("control_center.tiles.night_light.default_desc") : `${temp}K`} ${
|
||||||
gamma < NightLight.getDefault().maxGamma ? `(${gamma}%)` : ""}`
|
gamma < NightLight.getDefault().maxGamma ? `(${gamma}%)` : ""}`
|
||||||
)}
|
)}
|
||||||
visible={isInstalled("hyprsunset")}
|
hasArrow visible={isInstalled("hyprsunset")}
|
||||||
onToggledOff={() => NightLight.getDefault().identity = true}
|
onDisabled={() => NightLight.getDefault().identity = true}
|
||||||
onToggledOn={() => NightLight.getDefault().identity = false}
|
onEnabled={() => NightLight.getDefault().identity = false}
|
||||||
enableOnClickMore={true}
|
enableOnClicked
|
||||||
onClickMore={() => TilesPages?.toggle(PageNightLight)}
|
onClicked={() => TilesPages?.toggle(PageNightLight)}
|
||||||
toggleState={createBinding(NightLight.getDefault(), "identity").as(identity => !identity)}
|
state={createBinding(NightLight.getDefault(), "identity").as(identity => !identity)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ export const TileRecording = () =>
|
|||||||
})}
|
})}
|
||||||
icon={"media-record-symbolic"}
|
icon={"media-record-symbolic"}
|
||||||
visible={isInstalled("wf-recorder")}
|
visible={isInstalled("wf-recorder")}
|
||||||
onToggledOff={() => Recording.getDefault().stopRecording()}
|
onDisabled={() => Recording.getDefault().stopRecording()}
|
||||||
onToggledOn={() => Recording.getDefault().startRecording()}
|
onEnabled={() => Recording.getDefault().startRecording()}
|
||||||
toggleState={createBinding(Recording.getDefault(), "recording")}
|
state={createBinding(Recording.getDefault(), "recording")}
|
||||||
iconSize={16}
|
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@@ -1,30 +1,13 @@
|
|||||||
import { Gtk } from "ags/gtk4";
|
import { Gtk } from "ags/gtk4";
|
||||||
import { tr } from "../../../i18n/intl";
|
import { createBinding } from "ags";
|
||||||
import { Accessor, createBinding, createComputed, createState, getScope, onCleanup } from "ags";
|
|
||||||
import { omitObjectKeys, variableToBoolean } from "../../../modules/utils";
|
import { omitObjectKeys, variableToBoolean } from "../../../modules/utils";
|
||||||
import GObject, { property, register, signal } from "ags/gobject";
|
import { property, register, signal } from "ags/gobject";
|
||||||
|
|
||||||
import Pango from "gi://Pango?version=1.0";
|
import Pango from "gi://Pango?version=1.0";
|
||||||
|
|
||||||
|
|
||||||
export { Tile, TileProps };
|
export { Tile };
|
||||||
|
|
||||||
type TileProps = {
|
|
||||||
class?: string | Accessor<string>;
|
|
||||||
icon?: string | Accessor<string>;
|
|
||||||
visible?: boolean | Accessor<boolean>;
|
|
||||||
iconSize?: number | Accessor<number>;
|
|
||||||
title: string | Accessor<string>;
|
|
||||||
description?: string | Accessor<string>;
|
|
||||||
toggleState?: boolean | Accessor<boolean>;
|
|
||||||
enableOnClickMore?: boolean | Accessor<boolean>;
|
|
||||||
onUnmap?: () => void;
|
|
||||||
onToggledOn: () => void;
|
|
||||||
onToggledOff: () => void;
|
|
||||||
onClickMore?: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TODO: finish the tile class
|
|
||||||
@register({ GTypeName: "Tile" })
|
@register({ GTypeName: "Tile" })
|
||||||
class Tile extends Gtk.Box {
|
class Tile extends Gtk.Box {
|
||||||
@signal(Boolean) toggled(_state: boolean) {}
|
@signal(Boolean) toggled(_state: boolean) {}
|
||||||
@@ -42,6 +25,8 @@ class Tile extends Gtk.Box {
|
|||||||
public enableOnClicked: boolean = true;
|
public enableOnClicked: boolean = true;
|
||||||
@property(Boolean)
|
@property(Boolean)
|
||||||
public state: boolean = false;
|
public state: boolean = false;
|
||||||
|
@property(Boolean)
|
||||||
|
public hasArrow: boolean = false;
|
||||||
|
|
||||||
declare $signals: Gtk.Box.SignalSignatures & {
|
declare $signals: Gtk.Box.SignalSignatures & {
|
||||||
"toggled": (_state: boolean) => void;
|
"toggled": (_state: boolean) => void;
|
||||||
@@ -53,25 +38,29 @@ class Tile extends Gtk.Box {
|
|||||||
public enable(): void {
|
public enable(): void {
|
||||||
if(this.state) return;
|
if(this.state) return;
|
||||||
|
|
||||||
|
this.state = true;
|
||||||
|
!this.has_css_class("enabled") &&
|
||||||
|
this.add_css_class("enabled");
|
||||||
this.emit("toggled", true);
|
this.emit("toggled", true);
|
||||||
this.emit("enabled");
|
this.emit("enabled");
|
||||||
this.state = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public disable(): void {
|
public disable(): void {
|
||||||
if(!this.state) return;
|
if(!this.state) return;
|
||||||
|
|
||||||
|
this.state = false;
|
||||||
|
this.remove_css_class("enabled");
|
||||||
this.emit("toggled", false);
|
this.emit("toggled", false);
|
||||||
this.emit("disabled");
|
this.emit("disabled");
|
||||||
this.state = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: Omit<Gtk.Box.ConstructorProps, "orientation"> & {
|
constructor(props: Partial<Omit<Gtk.Box.ConstructorProps, "orientation">> & {
|
||||||
icon: string;
|
icon: string;
|
||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
state?: boolean;
|
state?: boolean;
|
||||||
enableOnClicked?: boolean;
|
enableOnClicked?: boolean;
|
||||||
|
hasArrow?: boolean;
|
||||||
}) {
|
}) {
|
||||||
super(omitObjectKeys(props, [
|
super(omitObjectKeys(props, [
|
||||||
"icon",
|
"icon",
|
||||||
@@ -81,9 +70,14 @@ class Tile extends Gtk.Box {
|
|||||||
"enableOnClicked"
|
"enableOnClicked"
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
this.add_css_class("tile");
|
||||||
|
|
||||||
this.icon = props.icon;
|
this.icon = props.icon;
|
||||||
this.title = props.title;
|
this.title = props.title;
|
||||||
|
|
||||||
|
if(props.hasArrow != null)
|
||||||
|
this.hasArrow = props.hasArrow;
|
||||||
|
|
||||||
if(props.description != null)
|
if(props.description != null)
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
|
|
||||||
@@ -93,32 +87,52 @@ class Tile extends Gtk.Box {
|
|||||||
if(props.enableOnClicked != null)
|
if(props.enableOnClicked != null)
|
||||||
this.enableOnClicked = props.enableOnClicked;
|
this.enableOnClicked = props.enableOnClicked;
|
||||||
|
|
||||||
const connections = new Map<GObject.Object, number>();
|
if(this.state)
|
||||||
const gestureClick = Gtk.GestureClick.new();
|
this.add_css_class("enabled"); // fix no highlight with state = true on construct
|
||||||
|
|
||||||
this.add_controller(gestureClick);
|
|
||||||
|
|
||||||
connections.set(gestureClick, gestureClick.connect("released", () => {
|
|
||||||
this.emit("clicked");
|
|
||||||
if(this.enableOnClicked && !this.state)
|
|
||||||
this.enable();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.prepend(
|
this.prepend(
|
||||||
<Gtk.Box hexpand={false} vexpand>
|
<Gtk.Box hexpand={false} vexpand class={"icon"}>
|
||||||
<Gtk.Image iconName={createBinding(this, "icon")} />
|
<Gtk.Image iconName={createBinding(this, "icon")} halign={Gtk.Align.CENTER} />
|
||||||
|
<Gtk.GestureClick onReleased={() => {
|
||||||
|
this.state ? this.disable() : this.enable();
|
||||||
|
}} />
|
||||||
</Gtk.Box> as Gtk.Box
|
</Gtk.Box> as Gtk.Box
|
||||||
);
|
);
|
||||||
|
|
||||||
this.append(
|
this.append(
|
||||||
<Gtk.Box class={"content"} orientation={Gtk.Orientation.VERTICAL}>
|
<Gtk.Box class={"content"} orientation={Gtk.Orientation.VERTICAL} vexpand
|
||||||
<Gtk.Label class={"title"} label={createBinding(this, "title")} />
|
valign={Gtk.Align.CENTER} hexpand>
|
||||||
<Gtk.Label class={"description"} label={createBinding(this, "description")} />
|
|
||||||
|
<Gtk.Label class={"title"} label={createBinding(this, "title")}
|
||||||
|
xalign={0} ellipsize={Pango.EllipsizeMode.END} />
|
||||||
|
<Gtk.Label class={"description"} label={createBinding(this, "description")}
|
||||||
|
xalign={0} ellipsize={Pango.EllipsizeMode.END} visible={
|
||||||
|
variableToBoolean(createBinding(this, "description"))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Gtk.GestureClick onReleased={() => {
|
||||||
|
this.emit("clicked");
|
||||||
|
if(this.enableOnClicked && !this.state)
|
||||||
|
this.enable();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}} />
|
||||||
</Gtk.Box> as Gtk.Box
|
</Gtk.Box> as Gtk.Box
|
||||||
);
|
);
|
||||||
|
|
||||||
getScope()?.onCleanup(() => connections.forEach((id, obj) => obj.disconnect(id)));
|
if(this.hasArrow)
|
||||||
|
this.append(
|
||||||
|
<Gtk.Image class={"arrow"} iconName={"go-next-symbolic"}>
|
||||||
|
<Gtk.GestureClick onReleased={() => {
|
||||||
|
this.emit("clicked");
|
||||||
|
if(this.enableOnClicked && !this.state)
|
||||||
|
this.enable();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}} />
|
||||||
|
</Gtk.Image> as Gtk.Image
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit<Signal extends keyof typeof this.$signals>(
|
emit<Signal extends keyof typeof this.$signals>(
|
||||||
@@ -135,81 +149,3 @@ class Tile extends Gtk.Box {
|
|||||||
return super.connect(signal, callback);
|
return super.connect(signal, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
function Tile(props: TileProps): Gtk.Widget {
|
|
||||||
const subs: Array<() => void> = [];
|
|
||||||
const [toggled, setToggled] = createState(((props.toggleState instanceof Accessor) ?
|
|
||||||
props.toggleState.get()
|
|
||||||
: props.toggleState) ?? false);
|
|
||||||
|
|
||||||
|
|
||||||
(props.toggleState instanceof Accessor) && subs.push(
|
|
||||||
props.toggleState.subscribe(() =>
|
|
||||||
setToggled((props.toggleState as Accessor<boolean>).get() ?? false))
|
|
||||||
);
|
|
||||||
|
|
||||||
onCleanup(() => subs.forEach(s => s()));
|
|
||||||
|
|
||||||
return <Gtk.Box hexpand visible={props.visible} onUnmap={props.onUnmap}
|
|
||||||
canFocus focusable={false} class={
|
|
||||||
(props.class instanceof Accessor) ?
|
|
||||||
createComputed([props.class, toggled], (clss, isToggled) =>
|
|
||||||
`tile ${clss} ${isToggled ? "toggled" : ""} ${
|
|
||||||
props.onClickMore ? "has-more" : ""
|
|
||||||
}`
|
|
||||||
)
|
|
||||||
: toggled.as(isToggled =>
|
|
||||||
`tile ${props.class ? props.class : ""} ${isToggled ? "toggled" : ""} ${
|
|
||||||
props.onClickMore ? "has-more" : ""
|
|
||||||
}`
|
|
||||||
)
|
|
||||||
}>
|
|
||||||
<Gtk.Button class={"toggle-button"} onClicked={() => {
|
|
||||||
if(toggled.get()) {
|
|
||||||
setToggled(false);
|
|
||||||
props.onToggledOff?.();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setToggled(true);
|
|
||||||
props.onToggledOn?.();
|
|
||||||
}}>
|
|
||||||
|
|
||||||
<Gtk.Box class={"content"} hexpand={true} vexpand={true}>
|
|
||||||
{props.icon && <Gtk.Image class={"icon"} iconName={props.icon} css={
|
|
||||||
(props.iconSize instanceof Accessor) ?
|
|
||||||
props.iconSize.as(size => `font-size: ${size}px;`)
|
|
||||||
: (props.iconSize ?
|
|
||||||
`font-size: ${props.iconSize ?? 16}px;`
|
|
||||||
: undefined)
|
|
||||||
} />}
|
|
||||||
|
|
||||||
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} class={"text"} vexpand={true} hexpand={true}
|
|
||||||
valign={Gtk.Align.CENTER}>
|
|
||||||
|
|
||||||
<Gtk.Label class={"title"} xalign={0} halign={Gtk.Align.START} ellipsize={Pango.EllipsizeMode.END}
|
|
||||||
label={props.title} />
|
|
||||||
|
|
||||||
{props.description && <Gtk.Label class={"description"} ellipsize={Pango.EllipsizeMode.END}
|
|
||||||
visible={variableToBoolean(props.description)} xalign={0} label={
|
|
||||||
(props.description instanceof Accessor) ?
|
|
||||||
props.description.as(str => str ?? "")
|
|
||||||
: (props.description ?? "")
|
|
||||||
} halign={Gtk.Align.START}
|
|
||||||
/>}
|
|
||||||
|
|
||||||
</Gtk.Box>
|
|
||||||
</Gtk.Box>
|
|
||||||
</Gtk.Button>
|
|
||||||
|
|
||||||
<Gtk.Button class={"more icon"} iconName={"go-next-symbolic"} widthRequest={32}
|
|
||||||
visible={Boolean(props.onClickMore)} halign={Gtk.Align.END} onClicked={() => {
|
|
||||||
((props.enableOnClickMore instanceof Accessor) ?
|
|
||||||
props.enableOnClickMore.get()
|
|
||||||
: props.enableOnClickMore) && props.onToggledOn?.();
|
|
||||||
|
|
||||||
props.onClickMore?.();
|
|
||||||
}} tooltipText={tr("control_center.tiles.more")} />
|
|
||||||
</Gtk.Box> as Gtk.Widget;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user