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 */
 
        .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.
        /*
         * 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.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
 
 .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);
                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);
 }
 
        XrmDestroyDatabase(xdb);
 }
@@ -583,29 +591,26 @@ static void
 setupitems(struct Menu *menu)
 {
        struct Item *item;
 setupitems(struct Menu *menu)
 {
        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 */
                        item->h = config.separator_pixels;
                else
                        item->h = config.height_pixels;
                menu->h += item->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)
                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
                 * is equal to the width of the largest item).
                 *
                 * 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.
                 */
                 * 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);
                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)
 {
 static void
 drawitems(struct Menu *menu)
 {
+       XftDraw *dsel, *dunsel;
        struct Item *item;
        struct Item *item;
+       int textx;
+       int x, y;
 
        for (item = menu->list; item != NULL; item = item->next) {
 
        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));
 
                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 = 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 */
                        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);
                        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);
                        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);
 
                        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 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))
 /* 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 triangle_height;
        int iconpadding;
        int horzpadding;
+       int alignment;
 
        /* the values below are set by options */
        int monitor;
 
        /* 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 */
        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 */
        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 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 */
 };
        unsigned level;         /* menu level relative to root */
        Window win;             /* menu window to map on the screen */
 };