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

Reply via email to