]> git.sur5r.net Git - i3/i3/commitdiff
i3bar: add min_width and align keys to blocks
authorAntoine Millet <antoine@inaps.org>
Sun, 2 Dec 2012 12:20:06 +0000 (13:20 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Thu, 6 Dec 2012 08:48:27 +0000 (09:48 +0100)
docs/i3bar-protocol
i3bar/include/common.h
i3bar/src/child.c
i3bar/src/xcb.c

index e3e42d10d4f3566388b2e820d29f8630bc0db788..2cf6dd0a18ebb263552e263a080e83887ee89913 100644 (file)
@@ -134,6 +134,16 @@ color::
        when it is associated.
        Colors are specified in hex (like in HTML), starting with a leading
        hash sign. For example, +#ff0000+ means red.
+min_width::
+       The minimum width (in pixels) of the block. If the content of the
+       +full_text+ key take less space than the specified min_width, the block
+       will be padded to the left and/or the right side, according to the +align+
+       key. This is useful when you want to prevent the whole status line to shift
+       when value take more or less space between each iteration.
+align::
+       Align text on the +center+ (default), +right+ or +left+ of the block, when
+       the minimum width of the latter, specified by the +min_width+ key, is not
+       reached.
 name and instance::
        Every block should have a unique +name+ (string) entry so that it can
        be easily identified in scripts which process the output. i3bar
@@ -166,6 +176,8 @@ An example of a block which uses all possible entries follows:
  "full_text": "E: 10.0.0.1 (1000 Mbit/s)",
  "short_text": "10.0.0.1",
  "color": "#00ff00",
+ "min_width": 300,
+ "align": "right",
  "urgent": false,
  "name": "ethernet",
  "instance": "eth0"
index 870e6dbeea3cf9944cbd636042aa8bea5e8d1413..05fb5aa1151f0cac88f29d6593ab4c5fc05f6704 100644 (file)
@@ -27,18 +27,28 @@ struct rect_t {
     int h;
 };
 
+typedef enum {
+    ALIGN_LEFT,
+    ALIGN_CENTER,
+    ALIGN_RIGHT
+} blockalign_t;
+
 /* This data structure represents one JSON dictionary, multiple of these make
  * up one status line. */
 struct status_block {
     i3String *full_text;
 
     char *color;
+    uint32_t min_width;
+    blockalign_t align;
 
     bool urgent;
 
-    /* The amount of pixels necessary to render this block. This variable is
+    /* The amount of pixels necessary to render this block. These variables are
      * only temporarily used in refresh_statusline(). */
     uint32_t width;
+    uint32_t x_offset;
+    uint32_t x_append;
 
     TAILQ_ENTRY(status_block) blocks;
 };
index 9a89d3c63eb608bf977138c04ecef25813d5b58d..bea1d58e43bb677f6fe25192f450f461ae396587 100644 (file)
@@ -132,6 +132,27 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le
     if (strcasecmp(ctx->last_map_key, "color") == 0) {
         sasprintf(&(ctx->block.color), "%.*s", len, val);
     }
+    if (strcasecmp(ctx->last_map_key, "align") == 0) {
+        if (len == strlen("left") && !strncmp((const char*)val, "left", strlen("left"))) {
+            ctx->block.align = ALIGN_LEFT;
+        } else if (len == strlen("right") && !strncmp((const char*)val, "right", strlen("right"))) {
+            ctx->block.align = ALIGN_RIGHT;
+        } else {
+            ctx->block.align = ALIGN_CENTER;
+        }
+    }
+    return 1;
+}
+
+#if YAJL_MAJOR >= 2
+static int stdin_integer(void *context, long long val) {
+#else
+static int stdin_integer(void *context, long val) {
+#endif
+    parser_ctx *ctx = context;
+    if (strcasecmp(ctx->last_map_key, "min_width") == 0) {
+        ctx->block.min_width = (uint32_t)val;
+    }
     return 1;
 }
 
@@ -313,6 +334,7 @@ void start_child(char *command) {
     callbacks.yajl_map_key = stdin_map_key;
     callbacks.yajl_boolean = stdin_boolean;
     callbacks.yajl_string = stdin_string;
+    callbacks.yajl_integer = stdin_integer;
     callbacks.yajl_start_array = stdin_start_array;
     callbacks.yajl_end_array = stdin_end_array;
     callbacks.yajl_start_map = stdin_start_map;
index 5ae8023af7dbc973a506b553e3be9bfff2567298..6bd8039b26289b7c6ced3e075bdb9d0eb588991f 100644 (file)
@@ -123,10 +123,31 @@ void refresh_statusline(void) {
             continue;
 
         block->width = predict_text_width(block->full_text);
+
+        /* Compute offset and append for text aligment in min_width. */
+        if (block->min_width <= block->width) {
+            block->x_offset = 0;
+            block->x_append = 0;
+        } else {
+            uint32_t padding_width = block->min_width - block->width;
+            switch (block->align) {
+                case ALIGN_LEFT:
+                    block->x_append = padding_width;
+                    break;
+                case ALIGN_RIGHT:
+                    block->x_offset = padding_width;
+                    break;
+                case ALIGN_CENTER:
+                    block->x_offset = padding_width / 2;
+                    block->x_append = padding_width / 2 + padding_width % 2;
+                    break;
+            }
+        }
+
         /* If this is not the last block, add some pixels for a separator. */
         if (TAILQ_NEXT(block, blocks) != NULL)
             block->width += 9;
-        statusline_width += block->width;
+        statusline_width += block->width + block->x_offset + block->x_append;
     }
 
     /* If the statusline is bigger than our screen we need to make sure that
@@ -147,8 +168,8 @@ void refresh_statusline(void) {
 
         uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg);
         set_font_colors(statusline_ctx, colorpixel, colors.bar_bg);
-        draw_text(block->full_text, statusline_pm, statusline_ctx, x, 0, block->width);
-        x += block->width;
+        draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, 0, block->width);
+        x += block->width + block->x_offset + block->x_append;
 
         if (TAILQ_NEXT(block, blocks) != NULL) {
             /* This is not the last block, draw a separator. */