add alignment
authorphillbush <phillbush@cock.li>
Tue, 15 Dec 2020 16:14:57 +0000 (13:14 -0300)
committerphillbush <phillbush@cock.li>
Tue, 15 Dec 2020 16:14:57 +0000 (13:14 -0300)
config.h
xmenu.1
xmenu.c
xmenu.h

index 0723fcd..6eb9b7c 100644 (file)
--- a/config.h
+++ b/config.h
@@ -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.
diff --git a/xmenu.1 b/xmenu.1
index f5d95e5..c2495a1 100644 (file)
--- a/xmenu.1
+++ b/xmenu.1
@@ -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
diff --git a/xmenu.c b/xmenu.c
index 4bea2da..888d8dc 100644 (file)
--- a/xmenu.c
+++ b/xmenu.c
@@ -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)
 {
+       XftDraw *dsel, *dunsel;
        struct Item *item;
+       int textx;
+       int x, y;
 
        for (item = menu->list; item != NULL; item = item->next) {
-               XftDraw *dsel, *dunsel;
-               int x, y;
-
                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);
 
diff --git a/xmenu.h b/xmenu.h
index e29df02..ecb0d14 100644 (file)
--- a/xmenu.h
+++ b/xmenu.h
@@ -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 */
 };