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 */ .separator_pixels = 3, /* space around separator */
.gap_pixels = 0, /* gap between menus */ .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. * The variables below cannot be set by X resources.
* Their values must be less than .height_pixels. * 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 .TP
.B xmenu.separatorWidth .B xmenu.separatorWidth
The size in pixels of the item separator. 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 .SH EXAMPLES
The following script illustrates the use of The following script illustrates the use of

49
xmenu.c
View File

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

View File

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