Adds more window title options (#169)
* Adds options for windowtitle to toggle: custom title, icon and truncation * Implements window title toggles: showIcon and showCustomTitle; Adds a new default title function and truncates it if specified * incorporate new show label option into window title * fix window title spacing to work with new styles * allows truncation for custom window titles * allows custom window title icon with default window title * add option to show the window class name or title; refactor for consistency and easier readability * remove redundant custom window title check
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
const hyprland = await Service.import("hyprland");
|
const hyprland = await Service.import("hyprland");
|
||||||
import options from 'options';
|
import options from 'options';
|
||||||
import { ActiveClient } from 'types/service/hyprland'
|
import { ActiveClient } from 'types/service/hyprland'
|
||||||
|
import Label from "types/widgets/label";
|
||||||
|
|
||||||
const filterTitle = (windowtitle: ActiveClient) => {
|
const filterTitle = (windowtitle: ActiveClient) => {
|
||||||
const windowTitleMap = [
|
const windowTitleMap = [
|
||||||
@@ -127,15 +128,36 @@ const filterTitle = (windowtitle: ActiveClient) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
icon: foundMatch ? foundMatch[1] : windowTitleMap[windowTitleMap.length - 1][1],
|
icon: foundMatch[1],
|
||||||
label: foundMatch ? foundMatch[2] : windowTitleMap[windowTitleMap.length - 1][2]
|
label: foundMatch[2]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTitle = (client: ActiveClient, useCustomTitle: boolean, useClassName: boolean) => {
|
||||||
|
if (useCustomTitle) return filterTitle(client).label;
|
||||||
|
if (useClassName) return client.class;
|
||||||
|
|
||||||
|
let title = client.title;
|
||||||
|
// If the title is empty or only filled with spaces, fallback to the class name
|
||||||
|
if (title.length === 0 || title.match(/^ *$/)) {
|
||||||
|
return client.class;
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
};
|
||||||
|
|
||||||
|
const truncateTitle = (title: string, max_size: number) => {
|
||||||
|
if (max_size > 0 && title.length > max_size) {
|
||||||
|
return title.substring(0, max_size).trim() + "...";
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
};
|
||||||
|
|
||||||
const ClientTitle = () => {
|
const ClientTitle = () => {
|
||||||
|
const { custom_title, class_name, label, icon, truncation, truncation_size } = options.bar.windowtitle;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component: Widget.Box({
|
component: Widget.Box({
|
||||||
className: Utils.merge([options.theme.bar.buttons.style.bind("value"), options.bar.windowtitle.label.bind("value")], (style, showLabel) => {
|
className: Utils.merge([options.theme.bar.buttons.style.bind("value"), label.bind("value")], (style, showLabel) => {
|
||||||
const styleMap = {
|
const styleMap = {
|
||||||
default: "style1",
|
default: "style1",
|
||||||
split: "style2",
|
split: "style2",
|
||||||
@@ -144,17 +166,26 @@ const ClientTitle = () => {
|
|||||||
};
|
};
|
||||||
return `windowtitle ${styleMap[style]} ${!showLabel ? "no-label" : ""}`;
|
return `windowtitle ${styleMap[style]} ${!showLabel ? "no-label" : ""}`;
|
||||||
}),
|
}),
|
||||||
children: options.bar.windowtitle.label.bind("value").as((showLabel) => {
|
children:
|
||||||
const titleIcon = Widget.Label({
|
Utils.merge(
|
||||||
class_name: "bar-button-icon windowtitle txt-icon bar",
|
[hyprland.active.bind("client"), custom_title.bind("value"), class_name.bind("value"), label.bind("value"),
|
||||||
label: hyprland.active.bind("client").as((v) => filterTitle(v).icon),
|
icon.bind("value"), truncation.bind("value"), truncation_size.bind("value")],
|
||||||
});
|
(client, useCustomTitle, useClassName, showLabel, showIcon, truncate, truncationSize) => {
|
||||||
const titleLabel = Widget.Label({
|
const children: Label<any>[] = [];
|
||||||
class_name: "bar-button-label windowtitle",
|
if (showIcon) {
|
||||||
label: hyprland.active.bind("client").as((v) => filterTitle(v).label),
|
children.push(Widget.Label({
|
||||||
});
|
class_name: "bar-button-icon windowtitle txt-icon bar",
|
||||||
return showLabel ? [titleIcon, titleLabel] : [titleIcon];
|
label: filterTitle(client).icon,
|
||||||
}),
|
}));
|
||||||
|
}
|
||||||
|
if (showLabel) {
|
||||||
|
children.push(Widget.Label({
|
||||||
|
class_name: `bar-button-label windowtitle ${showIcon ? "" : "no-icon"}`,
|
||||||
|
label: truncateTitle(getTitle(client, useCustomTitle, useClassName), truncate ? truncationSize : -1),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
boxClass: "windowtitle",
|
boxClass: "windowtitle",
|
||||||
|
|||||||
@@ -814,8 +814,13 @@ const options = mkOptions(OPTIONS, {
|
|||||||
icon: opt(""),
|
icon: opt(""),
|
||||||
},
|
},
|
||||||
windowtitle: {
|
windowtitle: {
|
||||||
|
custom_title: opt(true),
|
||||||
title_map: opt([]),
|
title_map: opt([]),
|
||||||
|
class_name: opt(true),
|
||||||
label: opt(true),
|
label: opt(true),
|
||||||
|
icon: opt(true),
|
||||||
|
truncation: opt(true),
|
||||||
|
truncation_size: opt(50),
|
||||||
},
|
},
|
||||||
workspaces: {
|
workspaces: {
|
||||||
show_icons: opt(false),
|
show_icons: opt(false),
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
.bar-button-label.windowtitle {
|
.bar-button-label.windowtitle {
|
||||||
color: if($bar-buttons-monochrome, $bar-buttons-text, $bar-buttons-windowtitle-text);
|
color: if($bar-buttons-monochrome, $bar-buttons-text, $bar-buttons-windowtitle-text);
|
||||||
margin-left: $bar-buttons-windowtitle-spacing;
|
margin-left: $bar-buttons-windowtitle-spacing;
|
||||||
|
|
||||||
|
&.no-icon {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.style2 {
|
.style2 {
|
||||||
|
|||||||
@@ -220,22 +220,50 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
|
|||||||
*/
|
*/
|
||||||
Header("Window Titles"),
|
Header("Window Titles"),
|
||||||
Option({
|
Option({
|
||||||
opt: options.bar.windowtitle.label,
|
opt: options.bar.windowtitle.custom_title,
|
||||||
title: "Show Window Title Label",
|
title: 'Use Custom Title',
|
||||||
type: "boolean",
|
type: 'boolean'
|
||||||
}),
|
|
||||||
Option({
|
|
||||||
opt: options.theme.bar.buttons.windowtitle.spacing,
|
|
||||||
title: "Inner Spacing",
|
|
||||||
subtitle: "Spacing between the icon and the label inside the buttons.",
|
|
||||||
type: "string",
|
|
||||||
}),
|
}),
|
||||||
Option({
|
Option({
|
||||||
opt: options.bar.windowtitle.title_map,
|
opt: options.bar.windowtitle.title_map,
|
||||||
title: "Window Title Mappings",
|
title: 'Window Title Mappings',
|
||||||
subtitle: "Wiki Link: https://hyprpanel.com/configuration/panel.html#window-title-mappings",
|
subtitle: 'Only applicable if Show Custom Title is enabled\nWiki Link: https://hyprpanel.com/configuration/panel.html#window-title-mappings',
|
||||||
type: "object",
|
type: 'object',
|
||||||
subtitleLink: "https://hyprpanel.com/configuration/panel.html#window-title-mappings",
|
subtitleLink: 'https://hyprpanel.com/configuration/panel.html#window-title-mappings'
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.windowtitle.class_name,
|
||||||
|
title: 'Use Class Name',
|
||||||
|
subtitle: 'Only applicable if Show Custom Title is disabled\nDisplays the window\'s class name instead of its title.',
|
||||||
|
type: 'boolean'
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.windowtitle.label,
|
||||||
|
title: 'Show Window Title Label',
|
||||||
|
type: 'boolean'
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.windowtitle.icon,
|
||||||
|
title: 'Show Icon',
|
||||||
|
type: 'boolean'
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.windowtitle.truncation,
|
||||||
|
title: 'Truncate Window Title',
|
||||||
|
subtitle: 'Will truncate the window title to the specified size below.',
|
||||||
|
type: 'boolean'
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.windowtitle.truncation_size,
|
||||||
|
title: 'Truncation Size',
|
||||||
|
type: 'number',
|
||||||
|
min: 10
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.theme.bar.buttons.windowtitle.spacing,
|
||||||
|
title: 'Inner Spacing',
|
||||||
|
subtitle: 'Spacing between the icon and the label inside the buttons.',
|
||||||
|
type: 'string'
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user