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"); 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,16 +166,25 @@ 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(
[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", class_name: "bar-button-icon windowtitle txt-icon bar",
label: hyprland.active.bind("client").as((v) => filterTitle(v).icon), label: filterTitle(client).icon,
}); }));
const titleLabel = Widget.Label({ }
class_name: "bar-button-label windowtitle", if (showLabel) {
label: hyprland.active.bind("client").as((v) => filterTitle(v).label), children.push(Widget.Label({
}); class_name: `bar-button-label windowtitle ${showIcon ? "" : "no-icon"}`,
return showLabel ? [titleIcon, titleLabel] : [titleIcon]; label: truncateTitle(getTitle(client, useCustomTitle, useClassName), truncate ? truncationSize : -1),
}));
}
return children;
}), }),
}), }),
isVisible: true, isVisible: true,

View File

@@ -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),

View File

@@ -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 {

View File

@@ -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'
}), }),
/* /*