Author: dejan Date: 2007-11-13 14:56:23 -0800 (Tue, 13 Nov 2007) New Revision: 5968 Log: This commit solves problem(s) reported in STR#1672 by Mr. Davy Durham who has sent patches and was kind enough to come to our IRC channel (irc://irc.oftc.net/fltk) and have discussion with me. Mr. Durham, thank You.
Modified: trunk/CREDITS trunk/fltk/ask.h trunk/src/message.cxx Modified: trunk/CREDITS =================================================================== --- trunk/CREDITS 2007-11-13 14:58:42 UTC (rev 5967) +++ trunk/CREDITS 2007-11-13 22:56:23 UTC (rev 5968) @@ -55,3 +55,4 @@ Brian Kropf Jason Bryan Tobias Markmann + Davy Durham ([EMAIL PROTECTED]) Modified: trunk/fltk/ask.h =================================================================== --- trunk/fltk/ask.h 2007-11-13 14:58:42 UTC (rev 5967) +++ trunk/fltk/ask.h 2007-11-13 22:56:23 UTC (rev 5968) @@ -58,6 +58,11 @@ extern FL_API NamedStyle* icon_style; extern FL_API NamedStyle* message_style; +extern FL_API const char* message_window_label; +extern FL_API float message_window_timeout; + +extern FL_API bool message_window_scrollable; + // pointers you can use to change FLTK to a foreign language: extern FL_API const char* no; extern FL_API const char* yes; Modified: trunk/src/message.cxx =================================================================== --- trunk/src/message.cxx 2007-11-13 14:58:42 UTC (rev 5967) +++ trunk/src/message.cxx 2007-11-13 22:56:23 UTC (rev 5968) @@ -30,8 +30,10 @@ #include <fltk/x.h> #include <fltk/ask.h> +#include <fltk/run.h> #include <fltk/ReturnButton.h> #include <fltk/SecretInput.h> +#include <fltk/TextDisplay.h> #include <fltk/string.h> #ifdef WIN32 @@ -69,6 +71,12 @@ w->window()->make_exec_return(false); } +static int timed_out; +static void timeout_handler(void *w) { + timed_out = 1; + ((Window *)w)->make_exec_return(false); +} + #define ICON_W 50 #define ICON_H 50 #define BORDER_W 10 @@ -92,6 +100,10 @@ Group* saved_current_group = Group::current(); load_theme(); Window window(3*BORDER_W+ICON_W+INPUT_W, 3*BORDER_H+ICON_H+BUTTON_H); + if(message_window_label && message_window_label[0] != 0) + window.copy_label(message_window_label); + + // add message, icon and possibly text input control window.begin(); // This keeps the icon from resizing. @@ -100,52 +112,102 @@ Widget icon(0, 0, ICON_W, ICON_H); icon.style(icon_style); icon.label(iconlabel); + ig.resizable(0); // no, THIS keeps the icon from resizing (when a text input field is present) ig.end(); - Widget message(2*BORDER_W+ICON_W, 0, INPUT_W, 2*BORDER_H+ICON_H); - message.set_flag(ALIGN_LEFT|ALIGN_INSIDE|ALIGN_WRAP); - message.style(message_style); + Widget *shortMessage=NULL; + TextDisplay *longMessage=NULL; + Widget *eitherMessage=NULL; + // Determine the complete and formatted message to show to the user + char messageBuffer[100*1024]; // 100k max + messageBuffer[sizeof(messageBuffer)-1]=0; + if (!strcmp(fmt,"%s")) { + strncpy(messageBuffer,va_arg(ap, const char*),sizeof(messageBuffer)-1); + } else if (!strchr(fmt, '%')) { + strncpy(messageBuffer,fmt,sizeof(messageBuffer)-1); + } else { + vsnprintf(messageBuffer, sizeof(messageBuffer)-1, fmt, ap); + } + + // determine if we need to have a scrollable area or not + bool scrollable=false; + if(message_window_scrollable) { + // it's allowed to scroll, let's see if it needs to + int w=(INPUT_W+3*BORDER_W+ICON_W+10), h=0; + setfont(window.labelfont(), window.labelsize()); + measure(messageBuffer, w, h, ALIGN_INSIDE_TOPLEFT | ALIGN_WRAP); + scrollable = h>(480-(3*BORDER_H+BUTTON_H)); + } + + if(scrollable) { + // Show a scrollable text display for a long message + eitherMessage=longMessage=new TextDisplay(2*BORDER_W+ICON_W, BORDER_H, INPUT_W, ICON_H); + + longMessage->wrap_mode(true); + longMessage->text(messageBuffer); + + window.resizable(longMessage); + window.resize_align(ALIGN_TOP|ALIGN_RIGHT); + + } else { + // Show a simple label for a short message + eitherMessage=shortMessage=new Widget(2*BORDER_W+ICON_W, 0, INPUT_W, BORDER_H+ICON_H); + shortMessage->set_flag(ALIGN_LEFT|ALIGN_INSIDE|ALIGN_WRAP); + shortMessage->style(message_style); + + window.resizable(shortMessage); + window.resize_align(ALIGN_TOP|ALIGN_RIGHT); + //w->size_range(window.w(), window.h(), 0, window.h()); + + shortMessage->label(messageBuffer); + } + + // Add the text input field if there should be one if (istr) { if (textfield) window.add(textfield); else - textfield = new Input(2*BORDER_W+ICON_W, 0, INPUT_W, 0); - textfield->h(int(textfield->textsize())+10); - textfield->y(BORDER_H+ICON_H-textfield->h()); - textfield->w(INPUT_W); - message.h(textfield->y()); + textfield = new Input(2*BORDER_W+ICON_W, 0, 0, 0); + textfield->type(itype); textfield->text(istr); + + int h=(int)textfield->textsize()+10; + textfield->resize( + textfield->x(), + (eitherMessage->y()+eitherMessage->h())-(h), + INPUT_W, + h + ); + + eitherMessage->h(eitherMessage->h()-h-(shortMessage ? 0 : BORDER_H)); window.set_focus(textfield); } - window.resizable(message); - window.resize_align(ALIGN_TOP|ALIGN_RIGHT); -// w->size_range(window.w(), window.h(), 0, window.h()); + window.end(); - char buffer[2048]; - if (!strcmp(fmt,"%s")) { - message.label(va_arg(ap, const char*)); - } else if (!strchr(fmt, '%')) { - message.label(fmt); - } else { - vsnprintf(buffer, 2048, fmt, ap); - message.label(buffer); - } - - window.end(); + // calculate into (w,h) how much wider and taller the window should become window.layout(); - setfont(message.labelfont(), message.labelsize()); int w = 400; int h = 0; - measure(message.label(), w, h, message.flags()); - w+=6; h+=6; - w -= message.w(); if (w < 0) w = 0; - h -= message.h(); if (h < 0) h = 0; + if(shortMessage) { + setfont(eitherMessage->labelfont(), eitherMessage->labelsize()); + measure(shortMessage->label(), w, h, shortMessage->flags()); + w+=6; h+=2*BORDER_H; + w -= shortMessage->w(); if (w < 0) w = 0; + h -= shortMessage->h(); if (h < 0) h = 0; + + } else /*if(longMessage)*/ { + w = 640-window.w(); if (w < 0) w = 0; + h = 400-window.h(); if (h < 0) h = 0; + + } window.resize(window.x(),window.y(),window.w()+w, window.h()+h); window.layout(); + + // add buttons window.begin(); const char* blabels[3]; @@ -178,14 +240,38 @@ } window.end(); + + timed_out=0; + if(message_window_timeout>0) { + add_timeout(message_window_timeout,timeout_handler,&window); + } + button_number = 0; window.exec(); + + if(message_window_timeout>0) { + remove_timeout(timeout_handler,&window); + } + if (istr) window.remove(textfield); // don't destroy it yet Group::current(saved_current_group); - return button_number; + + delete shortMessage; + delete longMessage; + + return timed_out ? -1 : button_number; } +/*! Set this to change the title of message(), alert(), ask(), choice(), etc. windows. */ +const char* fltk::message_window_label= NULL; + +/*! Set this to a positive value to cause the message(), alert(), ask(), choice(), etc. windows to close automatically after this timeout. If the timeout expires, -1 will be returned by the functions that return int. The timeout value is in seconds. */ +float fltk::message_window_timeout= 0; + +/*! When this is set to true, then (all) message windows will use scrollbars if the given message is too long. */ +bool fltk::message_window_scrollable = 0; + /*! You can change this string to convert fltk to a foreign language. */ const char* fltk::no = "&No"; /*! You can change this string to convert fltk to a foreign language. */ @@ -242,6 +328,9 @@ "No" button and waits for the user to hit a button. The return value is 1 if the user hits Yes, 0 if they pick No. The enter key is a shortcut for Yes and ESC is a shortcut for No. + + If message_window_timeout is used, then -1 will be returned if the + timeout expires. */ int fltk::ask(const char *fmt, ...) { if (fltk::beep_on_dialog()) (fltk::beep(BEEP_QUESTION)); @@ -259,6 +348,9 @@ is hit. If one of the strings begins with the special character '*' then the associated button will be the default which is selected when the enter key is pressed. ESC is a shortcut for b2. + + If message_window_timeout is used, then -1 will be returned if the + timeout expires. */ int fltk::choice(const char*fmt,const char *b0,const char *b1,const char *b2,...){ if (fltk::beep_on_dialog()) (fltk::beep(fltk::BEEP_QUESTION)); @@ -266,6 +358,8 @@ va_start(ap, b2); int r = innards("?", 0, 0, fmt, ap, b2, b1, b0); va_end(ap); + if(r<0) + return r; return 2-r; } @@ -276,6 +370,8 @@ va_start(ap, b2); int r = innards("!", 0, 0, fmt, ap, b2, b1, b0); va_end(ap); + if(r<0) + return r; return 2-r; } @@ -283,7 +379,7 @@ const char* defstr, uchar type) { int r = innards("?", defstr ? defstr : "", type, fmt, ap, fltk::cancel, fltk::ok, 0); - return r ? textfield->text() : 0; + return r>=0 ? textfield->text() : 0; } /*! @@ -293,6 +389,9 @@ pointer is only valid until the next time fltk::input() is called. Due to back-compatability, the arguments to any printf commands in the label are after the default value. + + If message_window_timeout is used, then 0 will be returned if the + timeout expires. */ const char* fltk::input(const char *fmt, const char *defstr, ...) { if (fltk::beep_on_dialog()) (fltk::beep(fltk::BEEP_QUESTION)); _______________________________________________ fltk-commit mailing list fltk-commit@easysw.com http://lists.easysw.com/mailman/listinfo/fltk-commit