diff --git a/darwin/progressbar.m b/darwin/progressbar.m index a26874f1..87a9c8d2 100644 --- a/darwin/progressbar.m +++ b/darwin/progressbar.m @@ -27,10 +27,31 @@ struct uiProgressBar { uiDarwinControlAllDefaults(uiProgressBar, pi) +int uiProgressBarValue(uiProgressBar *p) +{ + if ([p->pi getIndeterminate]) { + return -1; + } + + return (int) [p->pi getDoubleValue]; +} + void uiProgressBarSetValue(uiProgressBar *p, int value) { + if (value == -1) { + [p->pi setIndeterminate:YES]; + [p->pi startAnimation:p->pi]; + return; + } + + if ([p->pi getIndeterminate]) { + [p->pi setIndeterminate:NO]; + [p->pi stopAnimation:p->pi]; + } + if (value < 0 || value > 100) userbug("Value %d out of range for a uiProgressBar.", value); + // on 10.8 there's an animation when the progress bar increases, just like with Aero if (value == 100) { [p->pi setMaxValue:101]; diff --git a/test/page13.c b/test/page13.c index 0f3f358c..6eb19f29 100644 --- a/test/page13.c +++ b/test/page13.c @@ -75,6 +75,20 @@ static void showHide(uiButton *b, void *data) uiControlShow(c); } +static void setIndeterminate(uiButton *b, void *data) +{ + uiProgressBar *p = uiProgressBar(data); + + int value = uiProgressBarValue(p); + if (value == -1) { + value = 0; + } else { + value = -1; + } + + uiProgressBarSetValue(p, value); +} + static void deleteFirst(uiButton *b, void *data) { uiForm *f = uiForm(data); @@ -89,6 +103,7 @@ uiBox *makePage13(void) uiButton *b; uiForm *f; uiEntry *e; + uiProgressBar *p; page13 = newVerticalBox(); @@ -123,6 +138,12 @@ uiBox *makePage13(void) uiFormAppend(f, "MLE", uiControl(uiNewMultilineEntry()), 1); + p = uiNewProgressBar(); + uiBoxAppend(page13, uiControl(p), 0); + b = uiNewButton("Toggle indeterminate"); + uiButtonOnClicked(b, setIndeterminate, p); + uiBoxAppend(page13, uiControl(b), 0); + b = uiNewButton("Show/Hide"); uiButtonOnClicked(b, showHide, e); uiBoxAppend(page13, uiControl(b), 0); diff --git a/ui.h b/ui.h index 4fdd9e3e..82079371 100644 --- a/ui.h +++ b/ui.h @@ -199,7 +199,7 @@ _UI_EXTERN uiSlider *uiNewSlider(int min, int max); typedef struct uiProgressBar uiProgressBar; #define uiProgressBar(this) ((uiProgressBar *) (this)) -// TODO uiProgressBarValue() +_UI_EXTERN int uiProgressBarValue(uiProgressBar *p); _UI_EXTERN void uiProgressBarSetValue(uiProgressBar *p, int n); _UI_EXTERN uiProgressBar *uiNewProgressBar(void); diff --git a/unix/progressbar.c b/unix/progressbar.c index 40306e6c..9e3fd4a4 100644 --- a/unix/progressbar.c +++ b/unix/progressbar.c @@ -5,14 +5,44 @@ struct uiProgressBar { uiUnixControl c; GtkWidget *widget; GtkProgressBar *pbar; + int indeterminate; }; uiUnixControlAllDefaults(uiProgressBar) +int uiProgressBarValue(uiProgressBar *p) +{ + if (p->indeterminate) + return -1; + + return (int) (gtk_progress_bar_get_fraction(p->pbar) * 100); +} + +gboolean uiProgressBarPulse(void* data) +{ + uiProgressBar *p = (uiProgressBar*) data; + + if (!GTK_IS_WIDGET(p->pbar) || !p->indeterminate) + return 0; + + gtk_progress_bar_pulse(p->pbar); + return 1; +} + void uiProgressBarSetValue(uiProgressBar *p, int value) { + if (value == -1) { + if (!p->indeterminate) { + p->indeterminate = 1; + g_timeout_add(100, uiProgressBarPulse, p); + } + return; + } + if (value < 0 || value > 100) userbug("Value %d is out of range for a uiProgressBar.", value); + + p->indeterminate = 0; gtk_progress_bar_set_fraction(p->pbar, ((gdouble) value) / 100); } diff --git a/windows/progressbar.cpp b/windows/progressbar.cpp index d16569ad..2d155de1 100644 --- a/windows/progressbar.cpp +++ b/windows/progressbar.cpp @@ -26,14 +26,40 @@ static void uiProgressBarMinimumSize(uiWindowsControl *c, int *width, int *heigh *height = y; } +int uiProgressBarValue(uiProgressBar *p) +{ + LONG_PTR style = GetWindowLongPtr(p->hwnd, GWL_STYLE); + if ((style & PBS_MARQUEE) != 0) { + return -1; + } + + return (int) SendMessage(p->hwnd, PBM_GETPOS, 0, 0); +} + // unfortunately, as of Vista progress bars have a forced animation on increase // we have to set the progress bar to value + 1 and decrease it back to value if we want an "instant" change // see http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug // it's not ideal/perfect, but it will have to do void uiProgressBarSetValue(uiProgressBar *p, int value) { + LONG_PTR style = GetWindowLongPtr(p->hwnd, GWL_STYLE); + + if (value == -1) { + if ((style & PBS_MARQUEE) == 0) { + SetWindowLongPtr(p->hwnd, GWL_STYLE, style | PBS_MARQUEE); + SendMessage(p->hwnd, PBM_SETMARQUEE, 1, 0); + } + return; + } + + if ((style & PBS_MARQUEE) != 0) { + SetWindowLongPtr(p->hwnd, GWL_STYLE, style ^ PBS_MARQUEE); + SendMessage(p->hwnd, PBM_SETMARQUEE, 0, 0); + } + if (value < 0 || value > 100) userbug("Value %d is out of range for uiProgressBars.", value); + if (value == 100) { // because we can't 101 SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 101); SendMessageW(p->hwnd, PBM_SETPOS, 101, 0);