Migrate loadable plugin "batt" to new plugins API.
[lxde/lxpanel.git] / src / plugins / batt / batt.c
CommitLineData
8f11d5f8
HJYP
1/*
2 * ACPI battery monitor plugin for LXPanel
3 *
4 * Copyright (C) 2007 by Greg McNew <gmcnew@gmail.com>
802d5540 5 * Copyright (C) 2008 by Hong Jen Yee <pcman.tw@gmail.com>
c887dfa0 6 * Copyright (C) 2009 by Juergen Hoetzel <juergen@archlinux.org>
8f11d5f8
HJYP
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 *
23 * This plugin monitors battery usage on ACPI-enabled systems by reading the
c887dfa0
JH
24 * battery information found in /sys/class/power_supply. The update interval is
25 * user-configurable and defaults to 3 second.
8f11d5f8
HJYP
26 *
27 * The battery's remaining life is estimated from its current charge and current
28 * rate of discharge. The user may configure an alarm command to be run when
29 * their estimated remaining battery life reaches a certain level.
30 */
31
e751fe05
HJYP
32/* FIXME:
33 * Here are somethings need to be improvec:
34 * 1. Replace pthread stuff with gthread counterparts for portability.
e751fe05
HJYP
35 * 3. Add an option to hide the plugin when AC power is used or there is no battery.
36 * 4. Handle failure gracefully under systems other than Linux.
37*/
38
39#include <glib.h>
8f11d5f8 40#include <glib/gi18n.h>
c0ed75bf 41#include <pthread.h> /* used by pthread_create() and alarmThread */
8f11d5f8
HJYP
42#include <semaphore.h> /* used by update() and alarmProcess() for alarms */
43#include <stdlib.h>
802d5540 44#include <string.h>
9c9d3a00 45#include <stdarg.h>
8f11d5f8
HJYP
46
47#include "dbg.h"
c887dfa0 48#include "batt_sys.h"
813c2d44
AG
49#include "misc.h" /* used for lxpanel_generic_config_dlg() */
50#include "plugin.h" /* all other APIs including panel configuration */
8f11d5f8 51
8f11d5f8
HJYP
52/* The last MAX_SAMPLES samples are averaged when charge rates are evaluated.
53 This helps prevent spikes in the "time left" values the user sees. */
54#define MAX_SAMPLES 10
55
802d5540 56typedef struct {
8f11d5f8
HJYP
57 char *alarmCommand,
58 *backgroundColor,
59 *chargingColor1,
60 *chargingColor2,
61 *dischargingColor1,
802d5540
HJYP
62 *dischargingColor2;
63 GdkColor background,
64 charging1,
65 charging2,
66 discharging1,
67 discharging2;
f176735a 68 cairo_surface_t *pixmap;
802d5540 69 GtkWidget *drawingArea;
8f11d5f8
HJYP
70 int orientation;
71 unsigned int alarmTime,
72 border,
73 height,
74 length,
75 numSamples,
76 requestedBorder,
77 *rateSamples,
78 rateSamplesSum,
79 thickness,
80 timer,
802d5540
HJYP
81 state_elapsed_time,
82 info_elapsed_time,
8f11d5f8 83 wasCharging,
04a2f050
HJYP
84 width,
85 hide_if_no_battery;
8f11d5f8 86 sem_t alarmProcessLock;
c887dfa0 87 battery* b;
3051b49c 88 gboolean has_ac_adapter;
5c0c599d 89 gboolean show_extended_information;
813c2d44
AG
90 Panel *panel;
91 config_setting_t *settings;
c887dfa0 92} lx_battery;
8f11d5f8
HJYP
93
94
95typedef struct {
96 char *command;
97 sem_t *lock;
4a974f26 98} Alarm;
8f11d5f8 99
813c2d44 100static void destructor(gpointer data);
c887dfa0 101static void update_display(lx_battery *lx_b, gboolean repaint);
3051b49c 102
8f11d5f8
HJYP
103/* alarmProcess takes the address of a dynamically allocated alarm struct (which
104 it must free). It ensures that alarm commands do not run concurrently. */
c0ed75bf 105static void * alarmProcess(void *arg) {
4a974f26 106 Alarm *a = (Alarm *) arg;
8f11d5f8
HJYP
107
108 sem_wait(a->lock);
c0ed75bf 109 system(a->command);
8f11d5f8
HJYP
110 sem_post(a->lock);
111
112 g_free(a);
c0ed75bf 113 return NULL;
8f11d5f8
HJYP
114}
115
9c9d3a00
HG
116
117static void append(gchar **tooltip, gchar *fmt, ...)
118{
119 gchar *old = *tooltip;
120 gchar *new;
121 va_list va;
122
123 va_start(va, fmt);
124 new = g_strdup_vprintf(fmt, va);
125 va_end(va);
126
127 *tooltip = g_strconcat(old, new, NULL);
128
129 g_free(old);
130 g_free(new);
131}
132
133
f855ac58
HG
134/* Make a tooltip string, and display remaining charge time if the battery
135 is charging or remaining life if it's discharging */
136static gchar* make_tooltip(lx_battery* lx_b, gboolean isCharging)
137{
138 gchar * tooltip;
9c9d3a00
HG
139 gchar * indent = " ";
140 battery *b = lx_b->b;
f855ac58 141
029d9f0c
HG
142 if (b == NULL)
143 return NULL;
144
f855ac58
HG
145 if (isCharging) {
146 int hours = lx_b->b->seconds / 3600;
147 int left_seconds = lx_b->b->seconds - 3600 * hours;
148 int minutes = left_seconds / 60;
149 tooltip = g_strdup_printf(
150 _("Battery: %d%% charged, %d:%02d until full"),
151 lx_b->b->percentage,
152 hours,
153 minutes );
154 } else {
155 /* if we have enough rate information for battery */
156 if (lx_b->b->percentage != 100) {
157 int hours = lx_b->b->seconds / 3600;
158 int left_seconds = lx_b->b->seconds - 3600 * hours;
159 int minutes = left_seconds / 60;
160 tooltip = g_strdup_printf(
161 _("Battery: %d%% charged, %d:%02d left"),
162 lx_b->b->percentage,
163 hours,
164 minutes );
165 } else {
166 tooltip = g_strdup_printf(
167 _("Battery: %d%% charged"),
168 100 );
169 }
170 }
171
5c0c599d
HG
172 if (!lx_b->show_extended_information) {
173 return tooltip;
174 }
175
9c9d3a00
HG
176 if (b->energy_full_design != -1)
177 append(&tooltip, _("\n%sEnergy full design:\t\t%5d mWh"), indent, b->energy_full_design);
178 if (b->energy_full != -1)
179 append(&tooltip, _("\n%sEnergy full:\t\t\t%5d mWh"), indent, b->energy_full);
180 if (b->energy_now != -1)
181 append(&tooltip, _("\n%sEnergy now:\t\t\t%5d mWh"), indent, b->energy_now);
182 if (b->power_now != -1)
183 append(&tooltip, _("\n%sPower now:\t\t\t%5d mW"), indent, b->power_now);
184
185 if (b->charge_full_design != -1)
186 append(&tooltip, _("\n%sCharge full design:\t%5d mAh"), indent, b->charge_full_design);
187 if (b->charge_full != -1)
188 append(&tooltip, _("\n%sCharge full:\t\t\t%5d mAh"), indent, b->charge_full);
189 if (b->charge_now != -1)
190 append(&tooltip, _("\n%sCharge now:\t\t\t%5d mAh"), indent, b->charge_now);
191 if (b->current_now != -1)
192 append(&tooltip, _("\n%sCurrent now:\t\t\t%5d mA"), indent, b->current_now);
193
194 if (b->voltage_now != -1)
195 append(&tooltip, _("\n%sCurrent Voltage:\t\t%.3lf V"), indent, b->voltage_now / 1000.0);
196
f855ac58
HG
197 return tooltip;
198}
199
5c0c599d
HG
200static void set_tooltip_text(lx_battery* lx_b)
201{
029d9f0c
HG
202 if (lx_b->b == NULL)
203 return;
5c0c599d
HG
204 gboolean isCharging = battery_is_charging(lx_b->b);
205 gchar *tooltip = make_tooltip(lx_b, isCharging);
206 gtk_widget_set_tooltip_text(lx_b->drawingArea, tooltip);
207 g_free(tooltip);
208}
8f11d5f8 209
802d5540
HJYP
210/* FIXME:
211 Don't repaint if percentage of remaining charge and remaining time aren't changed. */
c887dfa0 212void update_display(lx_battery *lx_b, gboolean repaint) {
f176735a 213 cairo_t *cr;
c887dfa0
JH
214 battery *b = lx_b->b;
215 /* unit: mW */
7f9ba86b 216 int rate;
eef7d6f6 217 gboolean isCharging;
8f11d5f8 218
c887dfa0 219 if (! lx_b->pixmap )
802d5540 220 return;
8f11d5f8 221
f176735a
RM
222 cr = cairo_create(lx_b->pixmap);
223 cairo_set_line_width (cr, 1.0);
224
dc9d3b94
HG
225 /* draw background */
226 gdk_cairo_set_source_color(cr, &lx_b->background);
227 cairo_rectangle(cr, 0, 0, lx_b->width, lx_b->height);
228 cairo_fill(cr);
229
c887dfa0
JH
230 /* no battery is found */
231 if( b == NULL )
802d5540 232 {
c887dfa0 233 gtk_widget_set_tooltip_text( lx_b->drawingArea, _("No batteries found") );
dc9d3b94 234 goto update_done;
c887dfa0
JH
235 }
236
c887dfa0 237 /* fixme: only one battery supported */
8f11d5f8 238
7f9ba86b 239 rate = lx_b->b->current_now;
c887dfa0
JH
240 isCharging = battery_is_charging ( b );
241
242 /* Consider running the alarm command */
b37f46a0 243 if ( !isCharging && rate > 0 &&
c887dfa0
JH
244 ( ( battery_get_remaining( b ) / 60 ) < lx_b->alarmTime ) )
245 {
246 /* Shrug this should be done using glibs process functions */
247 /* Alarms should not run concurrently; determine whether an alarm is
248 already running */
249 int alarmCanRun;
250 sem_getvalue(&(lx_b->alarmProcessLock), &alarmCanRun);
251
252 /* Run the alarm command if it isn't already running */
253 if (alarmCanRun) {
254
4a974f26 255 Alarm *a = (Alarm *) malloc(sizeof(Alarm));
c887dfa0
JH
256 a->command = lx_b->alarmCommand;
257 a->lock = &(lx_b->alarmProcessLock);
258
259 /* Manage the alarm process in a new thread, which which will be
260 responsible for freeing the alarm struct it's given */
261 pthread_t alarmThread;
262 pthread_create(&alarmThread, NULL, alarmProcess, a);
263
264 }
265 }
8f11d5f8 266
5c0c599d 267 set_tooltip_text(lx_b);
eef7d6f6
HG
268
269 int chargeLevel = lx_b->b->percentage * (lx_b->length - 2 * lx_b->border) / 100;
270
cfde283a 271 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
eef7d6f6
HG
272
273 /* Draw the battery bar vertically, using color 1 for the left half and
274 color 2 for the right half */
f176735a
RM
275 gdk_cairo_set_source_color(cr,
276 isCharging ? &lx_b->charging1 : &lx_b->discharging1);
277 cairo_rectangle(cr, lx_b->border,
278 lx_b->height - lx_b->border - chargeLevel, lx_b->width / 2
279 - lx_b->border, chargeLevel);
280 cairo_fill(cr);
281 gdk_cairo_set_source_color(cr,
282 isCharging ? &lx_b->charging2 : &lx_b->discharging2);
283 cairo_rectangle(cr, lx_b->width / 2,
284 lx_b->height - lx_b->border - chargeLevel, (lx_b->width + 1) / 2
285 - lx_b->border, chargeLevel);
286 cairo_fill(cr);
eef7d6f6
HG
287
288 }
289 else {
290
291 /* Draw the battery bar horizontally, using color 1 for the top half and
292 color 2 for the bottom half */
f176735a
RM
293 gdk_cairo_set_source_color(cr,
294 isCharging ? &lx_b->charging1 : &lx_b->discharging1);
295 cairo_rectangle(cr, lx_b->border,
296 lx_b->border, chargeLevel, lx_b->height / 2 - lx_b->border);
297 cairo_fill(cr);
298 gdk_cairo_set_source_color(cr,
299 isCharging ? &lx_b->charging2 : &lx_b->discharging2);
300 cairo_rectangle(cr, lx_b->border, (lx_b->height + 1)
301 / 2, chargeLevel, lx_b->height / 2 - lx_b->border);
302 cairo_fill(cr);
eef7d6f6
HG
303
304 }
dc9d3b94
HG
305
306update_done:
eef7d6f6
HG
307 if( repaint )
308 gtk_widget_queue_draw( lx_b->drawingArea );
e4f8b15f
HG
309
310 check_cairo_status(cr);
311 cairo_destroy(cr);
8f11d5f8
HJYP
312}
313
71671bf6 314/* This callback is called every 3 seconds */
c887dfa0 315static int update_timout(lx_battery *lx_b) {
dc9d3b94 316 battery *bat;
251cfd3e
AG
317 if (g_source_is_destroyed(g_main_current_source()))
318 return FALSE;
52cb5b58 319 GDK_THREADS_ENTER();
c887dfa0
JH
320 lx_b->state_elapsed_time++;
321 lx_b->info_elapsed_time++;
71671bf6 322
dc9d3b94
HG
323 bat = battery_update( lx_b->b );
324 if (bat == NULL)
325 {
326 battery_free(lx_b->b);
327
328 /* maybe in the mean time a battery has been inserted. */
329 lx_b->b = battery_get();
330 }
802d5540 331
c887dfa0 332 update_display( lx_b, TRUE );
802d5540 333
52cb5b58 334 GDK_THREADS_LEAVE();
7c2a8701 335 return TRUE;
52cb5b58 336}
8f11d5f8
HJYP
337
338/* An update will be performed whenever the user clicks on the charge bar */
813c2d44
AG
339static gboolean buttonPressEvent(GtkWidget *p, GdkEventButton *event,
340 Panel *panel)
341{
342 lx_battery *lx_b = lxpanel_plugin_get_data(p);
8f11d5f8 343
c887dfa0 344 update_display(lx_b, TRUE);
8f11d5f8 345
813c2d44 346 return lxpanel_plugin_button_press_event(p, event, panel);
8f11d5f8
HJYP
347}
348
349
350static gint configureEvent(GtkWidget *widget, GdkEventConfigure *event,
c887dfa0 351 lx_battery *lx_b) {
8f11d5f8
HJYP
352
353 ENTER;
354
c887dfa0 355 if (lx_b->pixmap)
f176735a 356 cairo_surface_destroy(lx_b->pixmap);
8f11d5f8
HJYP
357
358 /* Update the plugin's dimensions */
c887dfa0
JH
359 lx_b->width = widget->allocation.width;
360 lx_b->height = widget->allocation.height;
cfde283a 361 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
c887dfa0
JH
362 lx_b->length = lx_b->height;
363 lx_b->thickness = lx_b->width;
8f11d5f8
HJYP
364 }
365 else {
c887dfa0
JH
366 lx_b->length = lx_b->width;
367 lx_b->thickness = lx_b->height;
8f11d5f8
HJYP
368 }
369
f176735a
RM
370 lx_b->pixmap = cairo_image_surface_create (CAIRO_FORMAT_RGB24, widget->allocation.width,
371 widget->allocation.height);
e4f8b15f 372 check_cairo_surface_status(&lx_b->pixmap);
8f11d5f8
HJYP
373
374 /* Perform an update so the bar will look right in its new orientation */
c887dfa0 375 update_display(lx_b, FALSE);
8f11d5f8
HJYP
376
377 RET(TRUE);
378
379}
380
381
c887dfa0 382static gint exposeEvent(GtkWidget *widget, GdkEventExpose *event, lx_battery *lx_b) {
8f11d5f8 383
e4f8b15f 384 ENTER;
f176735a
RM
385 cairo_t *cr = gdk_cairo_create(widget->window);
386 gdk_cairo_region(cr, event->region);
387 cairo_clip(cr);
8f11d5f8 388
f176735a
RM
389 gdk_cairo_set_source_color(cr, &lx_b->drawingArea->style->black);
390 cairo_set_source_surface(cr, lx_b->pixmap, 0, 0);
391 cairo_paint(cr);
e4f8b15f
HG
392
393 check_cairo_status(cr);
f176735a 394 cairo_destroy(cr);
e751fe05 395
8f11d5f8 396 RET(FALSE);
8f11d5f8
HJYP
397}
398
399
813c2d44 400static GtkWidget * constructor(Panel *panel, config_setting_t *settings)
8f11d5f8 401{
8f11d5f8
HJYP
402 ENTER;
403
c887dfa0 404 lx_battery *lx_b;
813c2d44
AG
405 GtkWidget *p;
406 const char *str;
407 int tmp_int;
408
409 lx_b = g_new0(lx_battery, 1);
c887dfa0
JH
410
411 /* get available battery */
412 lx_b->b = battery_get ();
813c2d44
AG
413
414 p = gtk_event_box_new();
415 lxpanel_plugin_set_data(p, lx_b, destructor);
416 GTK_WIDGET_SET_FLAGS( p, GTK_NO_WINDOW );
417 gtk_container_set_border_width( GTK_CONTAINER(p), 1 );
4542c20d 418
c887dfa0
JH
419 lx_b->drawingArea = gtk_drawing_area_new();
420 gtk_widget_add_events( lx_b->drawingArea, GDK_BUTTON_PRESS_MASK );
8f11d5f8 421
813c2d44 422 gtk_container_add( (GtkContainer*)p, lx_b->drawingArea );
4542c20d 423
813c2d44
AG
424 lx_b->orientation = panel_get_orientation(panel);
425 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
c887dfa0
JH
426 lx_b->height = lx_b->length = 20;
427 lx_b->thickness = lx_b->width = 8;
8f11d5f8
HJYP
428 }
429 else {
c887dfa0
JH
430 lx_b->height = lx_b->thickness = 8;
431 lx_b->length = lx_b->width = 20;
8f11d5f8 432 }
c887dfa0 433 gtk_widget_set_size_request(lx_b->drawingArea, lx_b->width, lx_b->height);
8f11d5f8 434
c887dfa0 435 gtk_widget_show(lx_b->drawingArea);
8f11d5f8 436
8e05828e 437 g_signal_connect (G_OBJECT (lx_b->drawingArea),"configure-event",
c887dfa0 438 G_CALLBACK (configureEvent), (gpointer) lx_b);
8e05828e 439 g_signal_connect (G_OBJECT (lx_b->drawingArea), "expose-event",
c887dfa0 440 G_CALLBACK (exposeEvent), (gpointer) lx_b);
8f11d5f8 441
c887dfa0 442 sem_init(&(lx_b->alarmProcessLock), 0, 1);
8f11d5f8 443
c887dfa0
JH
444 lx_b->alarmCommand = lx_b->backgroundColor = lx_b->chargingColor1 = lx_b->chargingColor2
445 = lx_b->dischargingColor1 = lx_b->dischargingColor2 = NULL;
8f11d5f8
HJYP
446
447 /* Set default values for integers */
c887dfa0
JH
448 lx_b->alarmTime = 5;
449 lx_b->requestedBorder = 1;
8f11d5f8 450
813c2d44
AG
451 /* remember instance data */
452 lx_b->panel = panel;
453 lx_b->settings = settings;
8f11d5f8 454
5c0c599d
HG
455 lx_b->show_extended_information = false;
456
813c2d44
AG
457 config_setting_lookup_int(settings, "HideIfNoBattery", &lx_b->hide_if_no_battery);
458 if (config_setting_lookup_string(settings, "AlarmCommand", &str))
459 lx_b->alarmCommand = g_strdup(str);
460 if (config_setting_lookup_string(settings, "BackgroundColor", &str))
461 lx_b->backgroundColor = g_strdup(str);
462 if (config_setting_lookup_string(settings, "ChargingColor1", &str))
463 lx_b->chargingColor1 = g_strdup(str);
464 if (config_setting_lookup_string(settings, "ChargingColor2", &str))
465 lx_b->chargingColor2 = g_strdup(str);
466 if (config_setting_lookup_string(settings, "DischargingColor1", &str))
467 lx_b->dischargingColor1 = g_strdup(str);
468 if (config_setting_lookup_string(settings, "DischargingColor2", &str))
469 lx_b->dischargingColor2 = g_strdup(str);
470 config_setting_lookup_int(settings, "AlarmTime", &lx_b->alarmTime);
471 config_setting_lookup_int(settings, "BorderWidth", &lx_b->requestedBorder);
472 if (config_setting_lookup_int(settings, "Size", &tmp_int)) {
473 lx_b->thickness = MAX(1, tmp_int);
474 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL)
475 lx_b->width = lx_b->thickness;
476 else
477 lx_b->height = lx_b->thickness;
478 gtk_widget_set_size_request(lx_b->drawingArea, lx_b->width,
479 lx_b->height);
8f11d5f8 480 }
813c2d44
AG
481 if (config_setting_lookup_int(settings, "ShowExtendedInformation", &tmp_int))
482 lx_b->show_extended_information = (tmp_int != 0);
8f11d5f8
HJYP
483
484 /* Make sure the border value is acceptable */
c887dfa0
JH
485 lx_b->border = MIN(MAX(0, lx_b->requestedBorder),
486 (MIN(lx_b->length, lx_b->thickness) - 1) / 2);
8f11d5f8
HJYP
487
488 /* Apply more default options */
c887dfa0
JH
489 if (! lx_b->alarmCommand)
490 lx_b->alarmCommand = g_strdup("xmessage Battery low");
491 if (! lx_b->backgroundColor)
492 lx_b->backgroundColor = g_strdup("black");
493 if (! lx_b->chargingColor1)
494 lx_b->chargingColor1 = g_strdup("#28f200");
495 if (! lx_b->chargingColor2)
496 lx_b->chargingColor2 = g_strdup("#22cc00");
497 if (! lx_b->dischargingColor1)
498 lx_b->dischargingColor1 = g_strdup("#ffee00");
499 if (! lx_b->dischargingColor2)
500 lx_b->dischargingColor2 = g_strdup("#d9ca00");
501
502 gdk_color_parse(lx_b->backgroundColor, &lx_b->background);
503 gdk_color_parse(lx_b->chargingColor1, &lx_b->charging1);
504 gdk_color_parse(lx_b->chargingColor2, &lx_b->charging2);
505 gdk_color_parse(lx_b->dischargingColor1, &lx_b->discharging1);
506 gdk_color_parse(lx_b->dischargingColor2, &lx_b->discharging2);
8f11d5f8 507
c887dfa0 508
8f11d5f8 509 /* Start the update loop */
13d82f29 510 lx_b->timer = g_timeout_add_seconds( 9, (GSourceFunc) update_timout, (gpointer) lx_b);
c887dfa0 511
813c2d44 512 RET(p);
8f11d5f8
HJYP
513}
514
515
516static void
813c2d44 517destructor(gpointer data)
8f11d5f8 518{
8f11d5f8
HJYP
519 ENTER;
520
813c2d44 521 lx_battery *b = (lx_battery *)data;
52cb5b58 522
029d9f0c
HG
523 if (b->b != NULL)
524 battery_free(b->b);
525
52cb5b58 526 if (b->pixmap)
f176735a 527 cairo_surface_destroy(b->pixmap);
8f11d5f8 528
8f11d5f8
HJYP
529 g_free(b->alarmCommand);
530 g_free(b->backgroundColor);
531 g_free(b->chargingColor1);
532 g_free(b->chargingColor2);
533 g_free(b->dischargingColor1);
534 g_free(b->dischargingColor2);
802d5540 535
8f11d5f8 536 g_free(b->rateSamples);
8f11d5f8 537 sem_destroy(&(b->alarmProcessLock));
3396dfea 538 if (b->timer)
539 g_source_remove(b->timer);
8f11d5f8
HJYP
540 g_free(b);
541
542 RET();
543
544}
545
546
813c2d44 547static void orientation(Panel *panel, GtkWidget *p) {
8f11d5f8
HJYP
548
549 ENTER;
550
813c2d44 551 lx_battery *b = lxpanel_plugin_get_data(p);
8f11d5f8 552
813c2d44
AG
553 if (b->orientation != panel_get_orientation(panel)) {
554 b->orientation = panel_get_orientation(panel);
8f11d5f8
HJYP
555 unsigned int swap = b->height;
556 b->height = b->width;
557 b->width = swap;
558 gtk_widget_set_size_request(b->drawingArea, b->width, b->height);
559 }
560
561 RET();
562}
563
564
813c2d44 565static gboolean applyConfig(gpointer user_data)
8f11d5f8 566{
8f11d5f8
HJYP
567 ENTER;
568
813c2d44 569 lx_battery *b = lxpanel_plugin_get_data(user_data);
8f11d5f8
HJYP
570
571 /* Update colors */
572 if (b->backgroundColor &&
813c2d44
AG
573 gdk_color_parse(b->backgroundColor, &b->background))
574 config_group_set_string(b->settings, "BackgroundColor", b->backgroundColor);
575 if (b->chargingColor1 && gdk_color_parse(b->chargingColor1, &b->charging1))
576 config_group_set_string(b->settings, "ChargingColor1", b->chargingColor1);
577 if (b->chargingColor2 && gdk_color_parse(b->chargingColor2, &b->charging2))
578 config_group_set_string(b->settings, "ChargingColor2", b->chargingColor2);
8f11d5f8 579 if (b->dischargingColor1 &&
813c2d44
AG
580 gdk_color_parse(b->dischargingColor1, &b->discharging1))
581 config_group_set_string(b->settings, "DischargingColor1", b->dischargingColor1);
8f11d5f8 582 if (b->dischargingColor2 &&
813c2d44
AG
583 gdk_color_parse(b->dischargingColor2, &b->discharging2))
584 config_group_set_string(b->settings, "DischargingColor2", b->dischargingColor2);
8f11d5f8 585
e751fe05 586 /* Make sure the border value is acceptable */
8f11d5f8
HJYP
587 b->border = MIN(MAX(0, b->requestedBorder),
588 (MIN(b->length, b->thickness) - 1) / 2);
589
8f11d5f8 590 /* Resize the widget */
cfde283a 591 if (b->orientation == GTK_ORIENTATION_HORIZONTAL)
8f11d5f8
HJYP
592 b->width = b->thickness;
593 else
594 b->height = b->thickness;
595 gtk_widget_set_size_request(b->drawingArea, b->width, b->height);
596
5c0c599d
HG
597 /* update tooltip */
598 set_tooltip_text(b);
599
813c2d44
AG
600 /* update settings */
601#if 0
602 config_group_set_int(b->settings, "HideIfNoBattery", b->hide_if_no_battery);
603#endif
604 config_group_set_string(b->settings, "AlarmCommand", b->alarmCommand);
605 config_group_set_int(b->settings, "AlarmTime", b->alarmTime);
606 config_group_set_int(b->settings, "BorderWidth", b->requestedBorder);
607 config_group_set_int(b->settings, "Size", b->thickness);
608 config_group_set_int(b->settings, "ShowExtendedInformation",
609 b->show_extended_information);
610
8f11d5f8 611 RET();
8f11d5f8
HJYP
612}
613
614
813c2d44 615static void config(Panel *panel, GtkWidget *p, GtkWindow *parent) {
8f11d5f8
HJYP
616 ENTER;
617
618 GtkWidget *dialog;
813c2d44
AG
619 lx_battery *b = lxpanel_plugin_get_data(p);
620 dialog = lxpanel_generic_config_dlg(_("Battery Monitor"),
621 panel, applyConfig, p,
04a2f050 622#if 0
e2957bd2 623 _("Hide if there is no battery"), &b->hide_if_no_battery, CONF_TYPE_BOOL,
04a2f050 624#endif
e2957bd2
HJYP
625 _("Alarm command"), &b->alarmCommand, CONF_TYPE_STR,
626 _("Alarm time (minutes left)"), &b->alarmTime, CONF_TYPE_INT,
627 _("Background color"), &b->backgroundColor, CONF_TYPE_STR,
628 _("Charging color 1"), &b->chargingColor1, CONF_TYPE_STR,
629 _("Charging color 2"), &b->chargingColor2, CONF_TYPE_STR,
630 _("Discharging color 1"), &b->dischargingColor1, CONF_TYPE_STR,
631 _("Discharging color 2"), &b->dischargingColor2, CONF_TYPE_STR,
632 _("Border width"), &b->requestedBorder, CONF_TYPE_INT,
633 _("Size"), &b->thickness, CONF_TYPE_INT,
5c0c599d 634 _("Show Extended Information"), &b->show_extended_information, CONF_TYPE_BOOL,
8f11d5f8
HJYP
635 NULL);
636 gtk_window_present(GTK_WINDOW(dialog));
637
638 RET();
8f11d5f8
HJYP
639}
640
641
813c2d44 642FM_DEFINE_MODULE(lxpanel_gtk, batt)
8f11d5f8 643
813c2d44
AG
644/* Plugin descriptor. */
645LXPanelPluginInit fm_module_init_lxpanel_gtk = {
3c3e9c9e 646 .name = N_("Battery Monitor"),
3c3e9c9e
HG
647 .description = N_("Display battery status using ACPI"),
648
813c2d44 649 .new_instance = constructor,
3c3e9c9e 650 .config = config,
813c2d44
AG
651 .reconfigure = orientation,
652 .button_press_event = buttonPressEvent
8f11d5f8 653};
f855ac58
HG
654
655
656/* vim: set sw=4 sts=4 : */