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
"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"
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;
};
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;
}
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;
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
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. */