mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
menu: support titles
...defined by `<separator label="">`. Also add the theme option `menu.title.bg.color: #589bda` The following will be added in separate commits - menu.title.bg.border.color: #7cb6ec - menu.title.text.color: #ffffff - menu.title.text.justify: center
This commit is contained in:
parent
a368bbee6a
commit
0552c6b7f0
7 changed files with 106 additions and 26 deletions
|
|
@ -25,7 +25,7 @@ The menu file must be entirely enclosed within <openbox_menu> and
|
|||
<!-- A submenu defined elsewhere -->
|
||||
<menu id="" />
|
||||
|
||||
<!-- Horizontal line >
|
||||
<!-- Horizontal line -->
|
||||
<separator />
|
||||
|
||||
<!-- An inline submenu -->
|
||||
|
|
@ -33,6 +33,9 @@ The menu file must be entirely enclosed within <openbox_menu> and
|
|||
...some content...
|
||||
</menu>
|
||||
|
||||
<!-- Title -->
|
||||
<separator label=""/>
|
||||
|
||||
<!-- Pipemenu -->
|
||||
<menu id="" label="" execute="COMMAND"/>
|
||||
|
||||
|
|
@ -63,6 +66,11 @@ The menu file must be entirely enclosed within <openbox_menu> and
|
|||
*menu.separator*
|
||||
Horizontal line.
|
||||
|
||||
*menu.separator.label*
|
||||
In a "separator" element, the label attribute transforms the separator
|
||||
from a horizontal line to a menu title (heading) with the text specified
|
||||
by label in it.
|
||||
|
||||
*menu.execute*
|
||||
Command to execute for pipe menu. See details below.
|
||||
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ elements are not listed here, but are supported.
|
|||
*menu.separator.color*
|
||||
Menu separator color. Default #888888.
|
||||
|
||||
*menu.title.bg.color*
|
||||
Menu title color. Default #589bda.
|
||||
Note: A menu title is a separator with a label.
|
||||
|
||||
*osd.bg.color*
|
||||
Background color of on-screen-display. Inherits
|
||||
*window.active.title.bg.color* if not set.
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ menu.separator.width: 1
|
|||
menu.separator.padding.width: 6
|
||||
menu.separator.padding.height: 3
|
||||
menu.separator.color: #888888
|
||||
menu.title.bg.color: #589bda
|
||||
|
||||
# on screen display (window-cycle dialog)
|
||||
osd.bg.color: #e1dedb
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ struct menu_scene {
|
|||
struct scaled_font_buffer *buffer;
|
||||
};
|
||||
|
||||
enum menuitem_type {
|
||||
LAB_MENU_ITEM = 0,
|
||||
LAB_MENU_SEPARATOR_LINE,
|
||||
LAB_MENU_TITLE,
|
||||
};
|
||||
|
||||
struct menuitem {
|
||||
struct wl_list actions;
|
||||
char *execute;
|
||||
|
|
@ -34,6 +40,7 @@ struct menuitem {
|
|||
struct menu *parent;
|
||||
struct menu *submenu;
|
||||
bool selectable;
|
||||
enum menuitem_type type;
|
||||
int height;
|
||||
int native_width;
|
||||
struct wlr_scene_tree *tree;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ struct theme {
|
|||
int menu_separator_padding_height;
|
||||
float menu_separator_color[4];
|
||||
|
||||
float menu_title_bg_color[4];
|
||||
|
||||
int osd_border_width;
|
||||
|
||||
float osd_bg_color[4];
|
||||
|
|
|
|||
102
src/menu/menu.c
102
src/menu/menu.c
|
|
@ -118,26 +118,42 @@ menu_update_width(struct menu *menu)
|
|||
}
|
||||
menu->size.width = max_width + 2 * theme->menu_item_padding_x;
|
||||
|
||||
/*
|
||||
* TODO: This function is getting a bit unwieldy. Consider calculating
|
||||
* the menu-window width up-front to avoid this post_processing() and
|
||||
* second-bite-of-the-cherry stuff
|
||||
*/
|
||||
|
||||
/* Update all items for the new size */
|
||||
wl_list_for_each(item, &menu->menuitems, link) {
|
||||
wlr_scene_rect_set_size(
|
||||
wlr_scene_rect_from_node(item->normal.background),
|
||||
menu->size.width, item->height);
|
||||
|
||||
if (!item->selected.background) {
|
||||
/* This is a separator. They don't have a selected background. */
|
||||
/*
|
||||
* Separator lines are special because they change width with
|
||||
* the menu.
|
||||
*/
|
||||
if (item->type == LAB_MENU_SEPARATOR_LINE) {
|
||||
int width = menu->size.width
|
||||
- 2 * theme->menu_separator_padding_width
|
||||
- 2 * theme->menu_item_padding_x;
|
||||
wlr_scene_rect_set_size(
|
||||
wlr_scene_rect_from_node(item->normal.text),
|
||||
menu->size.width - 2 * theme->menu_separator_padding_width,
|
||||
theme->menu_separator_line_thickness);
|
||||
} else {
|
||||
/* Usual menu item */
|
||||
width, theme->menu_separator_line_thickness);
|
||||
}
|
||||
|
||||
if (item->selectable) {
|
||||
/* Only selectable items have item->selected.background */
|
||||
wlr_scene_rect_set_size(
|
||||
wlr_scene_rect_from_node(item->selected.background),
|
||||
menu->size.width, item->height);
|
||||
if (item->native_width > max_width || item->submenu || item->execute) {
|
||||
scaled_font_buffer_set_max_width(item->normal.buffer,
|
||||
max_width);
|
||||
}
|
||||
|
||||
if (item->native_width > max_width || item->submenu || item->execute) {
|
||||
scaled_font_buffer_set_max_width(item->normal.buffer,
|
||||
max_width);
|
||||
if (item->selectable) {
|
||||
scaled_font_buffer_set_max_width(item->selected.buffer,
|
||||
max_width);
|
||||
}
|
||||
|
|
@ -188,11 +204,13 @@ item_create(struct menu *menu, const char *text, bool show_arrow)
|
|||
struct menuitem *menuitem = znew(*menuitem);
|
||||
menuitem->parent = menu;
|
||||
menuitem->selectable = true;
|
||||
menuitem->type = LAB_MENU_ITEM;
|
||||
struct server *server = menu->server;
|
||||
struct theme *theme = server->theme;
|
||||
|
||||
const char *arrow = show_arrow ? "›" : NULL;
|
||||
|
||||
/* TODO: Consider setting this somewhere else */
|
||||
if (!menu->item_height) {
|
||||
menu->item_height = font_height(&rc.font_menuitem)
|
||||
+ 2 * theme->menu_item_padding_y;
|
||||
|
|
@ -275,34 +293,68 @@ separator_create(struct menu *menu, const char *label)
|
|||
struct menuitem *menuitem = znew(*menuitem);
|
||||
menuitem->parent = menu;
|
||||
menuitem->selectable = false;
|
||||
menuitem->type = string_null_or_empty(label) ? LAB_MENU_SEPARATOR_LINE
|
||||
: LAB_MENU_TITLE;
|
||||
struct server *server = menu->server;
|
||||
struct theme *theme = server->theme;
|
||||
menuitem->height = theme->menu_separator_line_thickness +
|
||||
2 * theme->menu_separator_padding_height;
|
||||
|
||||
if (menuitem->type == LAB_MENU_TITLE) {
|
||||
menuitem->height = menu->item_height;
|
||||
menuitem->native_width = font_width(&rc.font_menuitem, label);
|
||||
} else if (menuitem->type == LAB_MENU_SEPARATOR_LINE) {
|
||||
menuitem->height = theme->menu_separator_line_thickness +
|
||||
2 * theme->menu_separator_padding_height;
|
||||
}
|
||||
|
||||
/* Menu item root node */
|
||||
menuitem->tree = wlr_scene_tree_create(menu->scene_tree);
|
||||
node_descriptor_create(&menuitem->tree->node,
|
||||
LAB_NODE_DESC_MENUITEM, menuitem);
|
||||
|
||||
/* Tree to hold background and text/line buffer */
|
||||
menuitem->normal.tree = wlr_scene_tree_create(menuitem->tree);
|
||||
|
||||
/* Item background nodes */
|
||||
float *bg_color = menuitem->type == LAB_MENU_TITLE
|
||||
? theme->menu_title_bg_color : theme->menu_items_bg_color;
|
||||
menuitem->normal.background = &wlr_scene_rect_create(
|
||||
menuitem->normal.tree,
|
||||
menu->size.width, menuitem->height,
|
||||
theme->menu_items_bg_color)->node;
|
||||
|
||||
int width = menu->size.width - 2 * theme->menu_separator_padding_width;
|
||||
menuitem->normal.text = &wlr_scene_rect_create(
|
||||
menuitem->normal.tree,
|
||||
width > 0 ? width : 0,
|
||||
theme->menu_separator_line_thickness,
|
||||
theme->menu_separator_color)->node;
|
||||
menu->size.width, menuitem->height, bg_color)->node;
|
||||
|
||||
/* Draw separator line or title */
|
||||
if (menuitem->type == LAB_MENU_TITLE) {
|
||||
menuitem->normal.buffer = scaled_font_buffer_create(menuitem->normal.tree);
|
||||
if (!menuitem->normal.buffer) {
|
||||
wlr_log(WLR_ERROR, "Failed to create menu item '%s'", label);
|
||||
wlr_scene_node_destroy(&menuitem->tree->node);
|
||||
free(menuitem);
|
||||
return NULL;
|
||||
}
|
||||
menuitem->normal.text = &menuitem->normal.buffer->scene_buffer->node;
|
||||
/* Font buffer */
|
||||
scaled_font_buffer_update(menuitem->normal.buffer, label,
|
||||
menuitem->native_width, &rc.font_menuitem,
|
||||
theme->menu_items_text_color, bg_color, /* arrow */ NULL);
|
||||
/* Center font nodes */
|
||||
int x, y;
|
||||
x = theme->menu_item_padding_x;
|
||||
y = (menu->item_height - menuitem->normal.buffer->height) / 2;
|
||||
wlr_scene_node_set_position(menuitem->normal.text, x, y);
|
||||
} else {
|
||||
int nominal_width = theme->menu_min_width;
|
||||
menuitem->normal.text = &wlr_scene_rect_create(
|
||||
menuitem->normal.tree, nominal_width,
|
||||
theme->menu_separator_line_thickness,
|
||||
theme->menu_separator_color)->node;
|
||||
wlr_scene_node_set_position(&menuitem->tree->node, 0, menu->size.height);
|
||||
/* Vertically center-align separator line */
|
||||
wlr_scene_node_set_position(menuitem->normal.text,
|
||||
theme->menu_separator_padding_width
|
||||
+ theme->menu_item_padding_x,
|
||||
theme->menu_separator_padding_height);
|
||||
}
|
||||
wlr_scene_node_set_position(&menuitem->tree->node, 0, menu->size.height);
|
||||
|
||||
/* Vertically center-align separator line */
|
||||
wlr_scene_node_set_position(menuitem->normal.text,
|
||||
theme->menu_separator_padding_width,
|
||||
theme->menu_separator_padding_height);
|
||||
|
||||
menu->size.height += menuitem->height;
|
||||
wl_list_append(&menu->menuitems, &menuitem->link);
|
||||
wl_list_init(&menuitem->actions);
|
||||
|
|
|
|||
|
|
@ -528,6 +528,8 @@ theme_builtin(struct theme *theme, struct server *server)
|
|||
theme->menu_separator_padding_height = 3;
|
||||
parse_hexstr("#888888", theme->menu_separator_color);
|
||||
|
||||
parse_hexstr("#589bda", theme->menu_title_bg_color);
|
||||
|
||||
theme->osd_window_switcher_width = 600;
|
||||
theme->osd_window_switcher_width_is_percent = false;
|
||||
theme->osd_window_switcher_padding = 4;
|
||||
|
|
@ -766,6 +768,10 @@ entry(struct theme *theme, const char *key, const char *value)
|
|||
parse_hexstr(value, theme->menu_separator_color);
|
||||
}
|
||||
|
||||
if (match_glob(key, "menu.title.bg.color")) {
|
||||
parse_hexstr(value, theme->menu_title_bg_color);
|
||||
}
|
||||
|
||||
if (match_glob(key, "osd.bg.color")) {
|
||||
parse_hexstr(value, theme->osd_bg_color);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue