2 * progressbar.c - progress bar widget
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "common/util.h"
27 extern AwesomeConf globalconf
;
31 /** Percent 0 to 100 */
33 /** data_title of the data */
35 /** Width of the data_items */
39 /** Pixel between data_items (bars) */
41 /** Number of data_items (bars) */
43 /** Height 0-1, where 1 is height of statusbar */
45 /** Foreground color */
47 /** Foreground color when bar is half-full */
49 /** Foreground color when bar is full */
51 /** Background color */
58 progressbar_draw(Widget
*widget
, DrawCtx
*ctx
, int offset
,
59 int used
__attribute__ ((unused
)))
61 int i
, width
, pwidth
, margin_top
, pb_height
, left_offset
;
64 Data
*d
= widget
->data
;
66 if (!(d
->data_items
) || (d
->width
- d
->padding
< 3))
69 width
= d
->width
- 2 * d
->padding
;
71 if(!widget
->user_supplied_x
)
72 widget
->area
.x
= widget_calculate_offset(widget
->statusbar
->width
,
77 if(!widget
->user_supplied_y
)
80 margin_top
= (int) (widget
->statusbar
->height
* (1 - d
->height
)) / 2 + 0.5 + widget
->area
.y
;
81 pb_height
= (int) ((widget
->statusbar
->height
* d
->height
- (d
->gap
* (d
->data_items
- 1))) / d
->data_items
+ 0.5);
82 left_offset
= widget
->area
.x
+ d
->padding
;
84 for(i
= 0; i
< d
->data_items
; i
++)
86 pwidth
= (int) d
->percent
[i
] ? ((width
- 2) * d
->percent
[i
]) / 100 : 0;
88 rectangle
.x
= left_offset
;
89 rectangle
.y
= margin_top
;
90 rectangle
.width
= width
;
91 rectangle
.height
= pb_height
;
93 draw_rectangle(ctx
, rectangle
, False
, d
->bordercolor
[i
]);
97 rectangle
.x
= left_offset
+ 1;
98 rectangle
.y
= margin_top
+ 1;
99 rectangle
.width
= pwidth
;
100 rectangle
.height
= pb_height
- 2;
101 draw_rectangle_gradient(ctx
, rectangle
, width
- 2, True
, d
->fg
[i
],
102 d
->pfg_center
[i
], d
->pfg_end
[i
]);
105 if(width
- 2 - pwidth
> 0) /* not filled area */
107 rectangle
.x
= left_offset
+ 1 + pwidth
;
108 rectangle
.y
= margin_top
+ 1;
109 rectangle
.width
= width
- 2 - pwidth
;
110 rectangle
.height
= pb_height
- 2;
111 draw_rectangle(ctx
, rectangle
, True
, d
->bg
[i
]);
114 margin_top
+= (pb_height
+ d
->gap
);
117 widget
->area
.width
= d
->width
;
118 widget
->area
.height
= widget
->statusbar
->height
;
119 return widget
->area
.width
;
122 static widget_tell_status_t
123 progressbar_tell(Widget
*widget
, char *property
, char *command
)
125 Data
*d
= widget
->data
;
128 char *title
, *setting
;
130 if(!property
|| !command
|| !d
->data_items
)
133 if(!a_strcmp(property
, "data"))
135 title
= strtok(command
, " ");
136 setting
= strtok(NULL
, " ");
137 for(i
= 0; i
< d
->data_items
; i
++)
138 if(!a_strcmp(title
, d
->data_title
[i
]))
140 percent
= atoi(setting
);
141 d
->percent
[i
] = (percent
< 0 ? 0 : (percent
> 100 ? 100 : percent
));
142 return WIDGET_NOERROR
;
144 return WIDGET_ERROR_FORMAT_SECTION
;
146 else if(!a_strcmp(property
, "fg"))
148 title
= strtok(command
, " ");
149 setting
= strtok(NULL
, " ");
150 for(i
= 0; i
< d
->data_items
; i
++)
151 if(!a_strcmp(title
, d
->data_title
[i
]))
153 draw_color_new(globalconf
.display
, get_phys_screen(widget
->statusbar
->screen
),
155 return WIDGET_NOERROR
;
157 return WIDGET_ERROR_FORMAT_SECTION
;
159 else if(!a_strcmp(property
, "bg"))
161 title
= strtok(command
, " ");
162 setting
= strtok(NULL
, " ");
163 for(i
= 0; i
< d
->data_items
; i
++)
164 if(!a_strcmp(title
, d
->data_title
[i
]))
166 draw_color_new(globalconf
.display
, get_phys_screen(widget
->statusbar
->screen
),
168 return WIDGET_NOERROR
;
170 return WIDGET_ERROR_FORMAT_SECTION
;
172 else if(!a_strcmp(property
, "fg_center"))
174 title
= strtok(command
, " ");
175 setting
= strtok(NULL
, " ");
176 for(i
= 0; i
< d
->data_items
; i
++)
177 if(!a_strcmp(title
, d
->data_title
[i
]))
180 if(!d
->pfg_center
[i
])
182 flag
= True
; /* restore to NULL & p_delete */
183 d
->pfg_center
[i
] = p_new(XColor
, 1);
185 if(!(draw_color_new(globalconf
.display
, get_phys_screen(widget
->statusbar
->screen
),
186 setting
, d
->pfg_center
[i
])))
187 if(flag
) /* restore */
189 p_delete(&d
->pfg_center
[i
]);
190 d
->pfg_center
[i
] = NULL
;
192 return WIDGET_NOERROR
;
194 return WIDGET_ERROR_FORMAT_SECTION
;
196 else if(!a_strcmp(property
, "fg_end"))
198 title
= strtok(command
, " ");
199 setting
= strtok(NULL
, " ");
200 for(i
= 0; i
< d
->data_items
; i
++)
201 if(!a_strcmp(title
, d
->data_title
[i
]))
206 flag
= True
; /* restore to NULL & p_delete */
207 d
->pfg_end
[i
] = p_new(XColor
, 1);
209 if(!(draw_color_new(globalconf
.display
, get_phys_screen(widget
->statusbar
->screen
),
210 setting
, d
->pfg_end
[i
])))
211 if(flag
) /* restore */
213 p_delete(&d
->pfg_end
[i
]);
214 d
->pfg_end
[i
] = NULL
;
216 return WIDGET_NOERROR
;
219 else if(!a_strcmp(property
, "bordercolor"))
221 title
= strtok(command
, " ");
222 setting
= strtok(NULL
, " ");
223 for(i
= 0; i
< d
->data_items
; i
++)
224 if(!a_strcmp(title
, d
->data_title
[i
]))
226 draw_color_new(globalconf
.display
, get_phys_screen(widget
->statusbar
->screen
),
227 setting
, &d
->bordercolor
[i
]);
228 return WIDGET_NOERROR
;
230 return WIDGET_ERROR_FORMAT_SECTION
;
232 else if(!a_strcmp(property
, "gap"))
233 d
->gap
= atoi(command
);
234 else if(!a_strcmp(property
, "width"))
236 d
->width
= atoi(command
);
237 if(d
->width
- d
->padding
< 3)
238 warn("progressbar widget needs: (width - padding) >= 3\n");
239 return WIDGET_ERROR_CUSTOM
;
241 else if(!a_strcmp(property
, "height"))
242 d
->height
= atof(command
);
243 else if(!a_strcmp(property
, "padding"))
244 d
->padding
= atoi(command
);
248 return WIDGET_NOERROR
;
252 progressbar_new(Statusbar
*statusbar
, cfg_t
*config
)
257 int i
, phys_screen
= get_phys_screen(statusbar
->screen
);
260 w
= p_new(Widget
, 1);
261 widget_common_new(w
, statusbar
, config
);
262 w
->draw
= progressbar_draw
;
263 w
->tell
= progressbar_tell
;
264 d
= w
->data
= p_new(Data
, 1);
265 d
->width
= cfg_getint(config
, "width");
266 d
->height
= cfg_getfloat(config
, "height");
267 d
->gap
= cfg_getint(config
, "gap");
268 d
->padding
= cfg_getint(config
, "padding");
270 w
->alignment
= draw_get_align(cfg_getstr(config
, "align"));
273 if(!(d
->data_items
= cfg_size(config
, "data")))
275 warn("progressbar widget needs at least one bar section\n");
279 d
->fg
= p_new(XColor
, d
->data_items
);
280 d
->pfg_end
= p_new(XColor
*, d
->data_items
);
281 d
->pfg_center
= p_new(XColor
*, d
->data_items
);
282 d
->bg
= p_new(XColor
, d
->data_items
);
283 d
->bordercolor
= p_new(XColor
, d
->data_items
);
284 d
->percent
= p_new(int, d
->data_items
);
285 d
->data_title
= p_new(char *, d
->data_items
);
287 for(i
= 0; i
< d
->data_items
; i
++)
289 cfg
= cfg_getnsec(config
, "data", i
);
291 d
->data_title
[i
] = a_strdup(cfg_title(cfg
));
293 if((color
= cfg_getstr(cfg
, "fg")))
294 draw_color_new(globalconf
.display
, phys_screen
, color
, &d
->fg
[i
]);
296 d
->fg
[i
] = globalconf
.screens
[statusbar
->screen
].colors_normal
[ColFG
];
298 if((color
= cfg_getstr(cfg
, "fg_center")))
300 d
->pfg_center
[i
] = p_new(XColor
, 1);
301 draw_color_new(globalconf
.display
, phys_screen
, color
, d
->pfg_center
[i
]);
304 if((color
= cfg_getstr(cfg
, "fg_end")))
306 d
->pfg_end
[i
] = p_new(XColor
, 1);
307 draw_color_new(globalconf
.display
, phys_screen
, color
, d
->pfg_end
[i
]);
310 if((color
= cfg_getstr(cfg
, "bg")))
311 draw_color_new(globalconf
.display
, phys_screen
, color
, &d
->bg
[i
]);
313 d
->bg
[i
] = globalconf
.screens
[statusbar
->screen
].colors_normal
[ColBG
];
315 if((color
= cfg_getstr(cfg
, "bordercolor")))
316 draw_color_new(globalconf
.display
, phys_screen
, color
, &d
->bordercolor
[i
]);
318 d
->bordercolor
[i
] = d
->fg
[i
];
321 /* complete setup, since someone might 'enable' it with increasing the width with widget_tell */
322 if(d
->width
- d
->padding
< 3)
324 warn("progressbar widget needs: (width - padding) >= 3\n");
330 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80