add alignment

This commit is contained in:
phillbush 2020-12-15 13:14:57 -03:00
parent 1146fd8114
commit 27c03246ca
4 changed files with 50 additions and 17 deletions

View File

@ -17,6 +17,9 @@ static struct Config config = {
.separator_pixels = 3, /* space around separator */
.gap_pixels = 0, /* gap between menus */
/* text alignment, set to LeftAlignment, CenterAlignment or RightAlignment */
.alignment = LeftAlignment,
/*
* The variables below cannot be set by X resources.
* Their values must be less than .height_pixels.

View File

@ -168,6 +168,15 @@ The size in pixels of the border around the menu.
.TP
.B xmenu.separatorWidth
The size in pixels of the item separator.
.TP
.B xmenu.alignment
If set to
.BR "\(dqleft\(dq" ,
.BR "\(dqcenter\(dq" ,
or
.BR "\(dqright\(dq" ,
text is aligned to the left, center, or right of the menu, respectively.
By default, text is aligned to the left.
.SH EXAMPLES
The following script illustrates the use of

49
xmenu.c
View File

@ -228,6 +228,14 @@ initresources(void)
config.border_color = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.font", "*", &type, &xval) == True)
config.font = strdup(xval.addr);
if (XrmGetResource(xdb, "xmenu.alignment", "*", &type, &xval) == True) {
if (strcasecmp(xval.addr, "center") == 0)
config.alignment = CenterAlignment;
else if (strcasecmp(xval.addr, "left") == 0)
config.alignment = LeftAlignment;
else if (strcasecmp(xval.addr, "right") == 0)
config.alignment = RightAlignment;
}
XrmDestroyDatabase(xdb);
}
@ -583,29 +591,26 @@ static void
setupitems(struct Menu *menu)
{
struct Item *item;
int itemwidth;
menu->w = config.width_pixels;
menu->maxtextw = 0;
for (item = menu->list; item != NULL; item = item->next) {
int itemwidth;
int textwidth;
item->y = menu->h;
if (item->label == NULL) /* height for separator item */
item->h = config.separator_pixels;
else
item->h = config.height_pixels;
menu->h += item->h;
if (item->label)
textwidth = drawtext(NULL, NULL, 0, 0, 0, item->label);
item->textw = drawtext(NULL, NULL, 0, 0, 0, item->label);
else
textwidth = 0;
item->textw = 0;
/*
* set menu width
*
* the item width depends on the size of its label (textwidth),
* the item width depends on the size of its label (item->textw),
* and it is only used to calculate the width of the menu (which
* is equal to the width of the largest item).
*
@ -614,9 +619,10 @@ setupitems(struct Menu *menu)
* if the iflag is set (icons are disabled) then the horizontal
* padding appears 3 times: before the label and around the triangle.
*/
itemwidth = textwidth + config.triangle_width + config.horzpadding * 3;
itemwidth = item->textw + config.triangle_width + config.horzpadding * 3;
itemwidth += (iflag || !menu->hasicon) ? 0 : config.iconsize + config.horzpadding;
menu->w = MAX(menu->w, itemwidth);
menu->maxtextw = MAX(menu->maxtextw, item->textw);
}
}
@ -811,12 +817,12 @@ loadicon(const char *file)
static void
drawitems(struct Menu *menu)
{
struct Item *item;
for (item = menu->list; item != NULL; item = item->next) {
XftDraw *dsel, *dunsel;
struct Item *item;
int textx;
int x, y;
for (item = menu->list; item != NULL; item = item->next) {
item->unsel = XCreatePixmap(dpy, menu->win, menu->w, item->h,
DefaultDepth(dpy, screen));
@ -831,21 +837,30 @@ drawitems(struct Menu *menu)
item->sel = item->unsel;
} else {
item->sel = XCreatePixmap(dpy, menu->win, menu->w, item->h,
DefaultDepth(dpy, screen));
XSetForeground(dpy, dc.gc, dc.selected[ColorBG].pixel);
XFillRectangle(dpy, item->sel, dc.gc, 0, 0, menu->w, item->h);
/* draw text */
x = config.horzpadding;
x += (iflag || !menu->hasicon) ? 0 : config.horzpadding + config.iconsize;
textx = config.horzpadding;
textx += (iflag || !menu->hasicon) ? 0 : config.horzpadding + config.iconsize;
switch (config.alignment) {
case CenterAlignment:
textx += (menu->maxtextw - item->textw) / 2;
break;
case RightAlignment:
textx += menu->maxtextw - item->textw;
break;
default:
break;
}
dsel = XftDrawCreate(dpy, item->sel, visual, colormap);
dunsel = XftDrawCreate(dpy, item->unsel, visual, colormap);
XSetForeground(dpy, dc.gc, dc.selected[ColorFG].pixel);
drawtext(dsel, &dc.selected[ColorFG], x, 0, item->h, item->label);
drawtext(dsel, &dc.selected[ColorFG], textx, 0, item->h, item->label);
XSetForeground(dpy, dc.gc, dc.normal[ColorFG].pixel);
drawtext(dunsel, &dc.normal[ColorFG], x, 0, item->h, item->label);
drawtext(dunsel, &dc.normal[ColorFG], textx, 0, item->h, item->label);
XftDrawDestroy(dsel);
XftDrawDestroy(dunsel);

View File

@ -3,6 +3,9 @@
/* enum for keyboard menu navigation */
enum { ITEMPREV, ITEMNEXT, ITEMFIRST, ITEMLAST };
/* enum for text alignment */
enum {LeftAlignment, CenterAlignment, RightAlignment};
/* macros */
#define LEN(x) (sizeof (x) / sizeof (x[0]))
#define MAX(x,y) ((x)>(y)?(x):(y))
@ -34,6 +37,7 @@ struct Config {
int triangle_height;
int iconpadding;
int horzpadding;
int alignment;
/* the values below are set by options */
int monitor;
@ -64,6 +68,7 @@ struct Item {
char *file; /* filename of the icon */
int y; /* item y position relative to menu */
int h; /* item height */
int textw; /* text width */
struct Item *prev; /* previous item */
struct Item *next; /* next item */
struct Menu *submenu; /* submenu spawned by clicking on item */
@ -85,6 +90,7 @@ struct Menu {
int x, y, w, h; /* menu geometry */
int hasicon; /* whether the menu has item with icons */
int drawn; /* whether the menu was already drawn */
int maxtextw; /* maximum text width */
unsigned level; /* menu level relative to root */
Window win; /* menu window to map on the screen */
};