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:
painerp
2024-09-08 22:09:13 +02:00
committed by GitHub
parent 4f91bb8b8f
commit 1aed9f51f9
4 changed files with 95 additions and 27 deletions

View File

@@ -1,6 +1,7 @@
const hyprland = await Service.import("hyprland");
import options from 'options';
import { ActiveClient } from 'types/service/hyprland'
import Label from "types/widgets/label";
const filterTitle = (windowtitle: ActiveClient) => {
const windowTitleMap = [
@@ -127,15 +128,36 @@ const filterTitle = (windowtitle: ActiveClient) => {
}
return {
icon: foundMatch ? foundMatch[1] : windowTitleMap[windowTitleMap.length - 1][1],
label: foundMatch ? foundMatch[2] : windowTitleMap[windowTitleMap.length - 1][2]
icon: foundMatch[1],
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 { custom_title, class_name, label, icon, truncation, truncation_size } = options.bar.windowtitle;
return {
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 = {
default: "style1",
split: "style2",
@@ -144,16 +166,25 @@ const ClientTitle = () => {
};
return `windowtitle ${styleMap[style]} ${!showLabel ? "no-label" : ""}`;
}),
children: options.bar.windowtitle.label.bind("value").as((showLabel) => {
const titleIcon = Widget.Label({
children:
Utils.merge(
[hyprland.active.bind("client"), custom_title.bind("value"), class_name.bind("value"), label.bind("value"),
icon.bind("value"), truncation.bind("value"), truncation_size.bind("value")],
(client, useCustomTitle, useClassName, showLabel, showIcon, truncate, truncationSize) => {
const children: Label<any>[] = [];
if (showIcon) {
children.push(Widget.Label({
class_name: "bar-button-icon windowtitle txt-icon bar",
label: hyprland.active.bind("client").as((v) => filterTitle(v).icon),
});
const titleLabel = Widget.Label({
class_name: "bar-button-label windowtitle",
label: hyprland.active.bind("client").as((v) => filterTitle(v).label),
});
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,

View File

@@ -814,8 +814,13 @@ const options = mkOptions(OPTIONS, {
icon: opt("󰣇"),
},
windowtitle: {
custom_title: opt(true),
title_map: opt([]),
class_name: opt(true),
label: opt(true),
icon: opt(true),
truncation: opt(true),
truncation_size: opt(50),
},
workspaces: {
show_icons: opt(false),

View File

@@ -5,6 +5,10 @@
.bar-button-label.windowtitle {
color: if($bar-buttons-monochrome, $bar-buttons-text, $bar-buttons-windowtitle-text);
margin-left: $bar-buttons-windowtitle-spacing;
&.no-icon {
margin-left: 0;
}
}
.style2 {

View File

@@ -220,22 +220,50 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
*/
Header("Window Titles"),
Option({
opt: options.bar.windowtitle.label,
title: "Show Window Title Label",
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",
opt: options.bar.windowtitle.custom_title,
title: 'Use Custom Title',
type: 'boolean'
}),
Option({
opt: options.bar.windowtitle.title_map,
title: "Window Title Mappings",
subtitle: "Wiki Link: https://hyprpanel.com/configuration/panel.html#window-title-mappings",
type: "object",
subtitleLink: "https://hyprpanel.com/configuration/panel.html#window-title-mappings",
title: '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',
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'
}),
/*