fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

fl_ask.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: fl_ask.cxx 8136 2010-12-29 11:51:29Z manolo $"
00003 //
00004 // Standard dialog functions for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // Implementation of fl_message, fl_ask, fl_choice, fl_input
00029 // The three-message fl_show_x functions are for forms compatibility
00030 // mostly.  In most cases it is easier to get a multi-line message
00031 // by putting newlines in the message.
00032 
00033 #include <stdio.h>
00034 #include <stdarg.h>
00035 #include "flstring.h"
00036 
00037 #include <FL/Fl.H>
00038 
00039 #include <FL/fl_ask.H>
00040 
00041 #include <FL/Fl_Box.H>
00042 #include <FL/Fl_Button.H>
00043 #include <FL/Fl_Return_Button.H>
00044 #include <FL/Fl_Window.H>
00045 #include <FL/Fl_Input.H>
00046 #include <FL/Fl_Secret_Input.H>
00047 #include <FL/x.H>
00048 #include <FL/fl_draw.H>
00049 
00050 static Fl_Window *message_form;
00051 static Fl_Box *message;
00052 static Fl_Box *icon;
00053 static Fl_Button *button[3];
00054 static Fl_Input *input;
00055 static int ret_val;
00056 static const char *iconlabel = "?";
00057 Fl_Font fl_message_font_ = FL_HELVETICA;
00058 Fl_Fontsize fl_message_size_ = 14;
00059 #ifdef __APPLE__
00060 extern "C" void NSBeep(void);
00061 #endif
00062 
00063 static char avoidRecursion = 0;
00064 
00065 // Sets the global return value (ret_val) and closes the window.
00066 // Note: this is used for the button callbacks and the window
00067 // callback (closing the window with the close button or menu).
00068 // The first argument (Fl_Widget *) can either be an Fl_Button*
00069 // pointer to one of the buttons or an Fl_Window* pointer to the
00070 // message window (message_form).
00071 static void button_cb(Fl_Widget *, void *val) {
00072   ret_val = (fl_intptr_t)val;
00073   message_form->hide();
00074 }
00075 
00076 static Fl_Window *makeform() {
00077  if (message_form) {
00078    message_form->size(410,103);
00079    return message_form;
00080  }
00081  // make sure that the dialog does not become the child of some 
00082  // current group
00083  Fl_Group *previously_current_group = Fl_Group::current();
00084  Fl_Group::current(0);
00085  // create a new top level window
00086  Fl_Window *w = message_form = new Fl_Window(410,103,"");
00087  message_form->callback(button_cb,(void *)0);
00088  // w->clear_border();
00089  // w->box(FL_UP_BOX);
00090  (message = new Fl_Box(60, 25, 340, 20))
00091    ->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
00092  (input = new Fl_Input(60, 37, 340, 23))->hide();
00093  {Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50);
00094   o->box(FL_THIN_UP_BOX);
00095   o->labelfont(FL_TIMES_BOLD);
00096   o->labelsize(34);
00097   o->color(FL_WHITE);
00098   o->labelcolor(FL_BLUE);
00099  }
00100  // create the buttons (right to left)
00101  for (int b=0, x=310; b<3; b++, x -= 100) {
00102    if (b==1)
00103      button[b] = new Fl_Return_Button(x, 70, 90, 23);
00104    else
00105      button[b] = new Fl_Button(x, 70, 90, 23);
00106    button[b]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
00107    button[b]->callback(button_cb,(void *)b);
00108  }
00109  button[0]->shortcut(FL_Escape);
00110  w->resizable(new Fl_Box(60,10,110-60,27));
00111  w->end();
00112  w->set_modal();
00113  Fl_Group::current(previously_current_group);
00114  return w;
00115 }
00116 
00117 /*
00118  * 'resizeform()' - Resize the form and widgets so that they hold everything
00119  *                  that is asked of them...
00120  */
00121 
00122 void resizeform() {
00123   int   i;
00124   int   message_w, message_h;
00125   int   text_height;
00126   int   button_w[3], button_h[3];
00127   int   x, w, h, max_w, max_h;
00128         const int icon_size = 50;
00129 
00130   fl_font(fl_message_font_, fl_message_size_);
00131   message_w = message_h = 0;
00132   fl_measure(message->label(), message_w, message_h);
00133 
00134   message_w += 10;
00135   message_h += 10;
00136   if (message_w < 340)
00137     message_w = 340;
00138   if (message_h < 30)
00139     message_h = 30;
00140 
00141   fl_font(button[0]->labelfont(), button[0]->labelsize());
00142 
00143   memset(button_w, 0, sizeof(button_w));
00144   memset(button_h, 0, sizeof(button_h));
00145 
00146   for (max_h = 25, i = 0; i < 3; i ++)
00147     if (button[i]->visible())
00148     {
00149       fl_measure(button[i]->label(), button_w[i], button_h[i]);
00150 
00151       if (i == 1)
00152         button_w[1] += 20;
00153 
00154       button_w[i] += 30;
00155       button_h[i] += 10;
00156 
00157       if (button_h[i] > max_h)
00158         max_h = button_h[i];
00159     }
00160 
00161   if (input->visible()) text_height = message_h + 25;
00162   else text_height = message_h;
00163 
00164   max_w = message_w + 10 + icon_size;
00165   w     = button_w[0] + button_w[1] + button_w[2] - 10;
00166 
00167   if (w > max_w)
00168     max_w = w;
00169 
00170   message_w = max_w - 10 - icon_size;
00171 
00172   w = max_w + 20;
00173   h = max_h + 30 + text_height;
00174 
00175   message_form->size(w, h);
00176   message_form->size_range(w, h, w, h);
00177 
00178   message->resize(20 + icon_size, 10, message_w, message_h);
00179   icon->resize(10, 10, icon_size, icon_size);
00180   icon->labelsize(icon_size - 10);
00181   input->resize(20 + icon_size, 10 + message_h, message_w, 25);
00182 
00183   for (x = w, i = 0; i < 3; i ++)
00184     if (button_w[i])
00185     {
00186       x -= button_w[i];
00187       button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h);
00188 
00189 //      printf("button %d (%s) is %dx%d+%d,%d\n", i, button[i]->label(),
00190 //             button[i]->w(), button[i]->h(),
00191 //           button[i]->x(), button[i]->y());
00192     }
00193 }
00194 
00195 static int innards(const char* fmt, va_list ap,
00196   const char *b0,
00197   const char *b1,
00198   const char *b2)
00199 {
00200   Fl::pushed(0); // stop dragging (STR #2159)
00201 
00202   avoidRecursion = 1;
00203 
00204   makeform();
00205   char buffer[1024];
00206   if (!strcmp(fmt,"%s")) {
00207     message->label(va_arg(ap, const char*));
00208   } else {
00209     ::vsnprintf(buffer, 1024, fmt, ap);
00210     message->label(buffer);
00211   }
00212 
00213   message->labelfont(fl_message_font_);
00214   message->labelsize(fl_message_size_);
00215   if (b0) {button[0]->show(); button[0]->label(b0); button[1]->position(210,70);}
00216   else {button[0]->hide(); button[1]->position(310,70);}
00217   if (b1) {button[1]->show(); button[1]->label(b1);}
00218   else button[1]->hide();
00219   if (b2) {button[2]->show(); button[2]->label(b2);}
00220   else button[2]->hide();
00221   const char* prev_icon_label = icon->label();
00222   if (!prev_icon_label) icon->label(iconlabel);
00223 
00224   resizeform();
00225 
00226   if (button[1]->visible() && !input->visible()) 
00227     button[1]->take_focus();
00228   message_form->hotspot(button[0]);
00229   if (b0 && Fl_Widget::label_shortcut(b0))
00230     button[0]->shortcut(0);
00231   else
00232     button[0]->shortcut(FL_Escape);
00233 
00234   // deactivate Fl::grab(), because it is incompatible with modal windows
00235   Fl_Window* g = Fl::grab();
00236   if (g) Fl::grab(0);
00237   message_form->show();
00238   while (message_form->shown()) Fl::wait();
00239   if (g) // regrab the previous popup menu, if there was one
00240     Fl::grab(g);
00241   icon->label(prev_icon_label);
00242 
00243   avoidRecursion = 0;
00244   return ret_val;
00245 }
00246 
00250 // pointers you can use to change FLTK to a foreign language:
00251 const char* fl_no = "No";        
00252 const char* fl_yes= "Yes";       
00253 const char* fl_ok = "OK";        
00254 const char* fl_cancel= "Cancel"; 
00255 const char* fl_close= "Close";   
00256 
00257 // fltk functions:
00262 void fl_beep(int type) {
00263 #ifdef WIN32
00264   switch (type) {
00265     case FL_BEEP_QUESTION :
00266     case FL_BEEP_PASSWORD :
00267       MessageBeep(MB_ICONQUESTION);
00268       break;
00269     case FL_BEEP_MESSAGE :
00270       MessageBeep(MB_ICONASTERISK);
00271       break;
00272     case FL_BEEP_NOTIFICATION :
00273       MessageBeep(MB_ICONASTERISK);
00274       break;
00275     case FL_BEEP_ERROR :
00276       MessageBeep(MB_ICONERROR);
00277       break;
00278     default :
00279       MessageBeep(0xFFFFFFFF);
00280       break;
00281   }
00282 #elif defined(__APPLE__)
00283   switch (type) {
00284     case FL_BEEP_DEFAULT :
00285     case FL_BEEP_ERROR :
00286       NSBeep();
00287       break;
00288     default :
00289       break;
00290   }  
00291 #else
00292   switch (type) {
00293     case FL_BEEP_DEFAULT :
00294     case FL_BEEP_ERROR :
00295       if (!fl_display) fl_open_display();
00296 
00297       XBell(fl_display, 100);
00298       break;
00299     default :
00300       if (!fl_display) fl_open_display();
00301 
00302       XBell(fl_display, 50);
00303       break;
00304   }
00305 #endif // WIN32
00306 }
00307 
00317 void fl_message(const char *fmt, ...) {
00318 
00319   if (avoidRecursion) return;
00320 
00321   va_list ap;
00322 
00323   fl_beep(FL_BEEP_MESSAGE);
00324 
00325   va_start(ap, fmt);
00326   iconlabel = "i";
00327   innards(fmt, ap, 0, fl_close, 0);
00328   va_end(ap);
00329   iconlabel = "?";
00330 }
00331 
00340 void fl_alert(const char *fmt, ...) {
00341 
00342   if (avoidRecursion) return;
00343 
00344   va_list ap;
00345 
00346   fl_beep(FL_BEEP_ERROR);
00347 
00348   va_start(ap, fmt);
00349   iconlabel = "!";
00350   innards(fmt, ap, 0, fl_close, 0);
00351   va_end(ap);
00352   iconlabel = "?";
00353 }
00365 int fl_ask(const char *fmt, ...) {
00366 
00367   if (avoidRecursion) return 0;
00368 
00369   va_list ap;
00370 
00371   fl_beep(FL_BEEP_QUESTION);
00372 
00373   va_start(ap, fmt);
00374   int r = innards(fmt, ap, fl_no, fl_yes, 0);
00375   va_end(ap);
00376 
00377   return r;
00378 }
00379 
00395 int fl_choice(const char*fmt,const char *b0,const char *b1,const char *b2,...){
00396 
00397   if (avoidRecursion) return 0;
00398 
00399   va_list ap;
00400 
00401   fl_beep(FL_BEEP_QUESTION);
00402 
00403   va_start(ap, b2);
00404   int r = innards(fmt, ap, b0, b1, b2);
00405   va_end(ap);
00406   return r;
00407 }
00413 Fl_Widget *fl_message_icon() {makeform(); return icon;}
00414 
00415 static const char* input_innards(const char* fmt, va_list ap,
00416                                  const char* defstr, uchar type) {
00417   makeform();
00418   message->position(60,10);
00419   input->type(type);
00420   input->show();
00421   input->value(defstr);
00422   input->take_focus();
00423 
00424   int r = innards(fmt, ap, fl_cancel, fl_ok, 0);
00425   input->hide();
00426   message->position(60,25);
00427   return r ? input->value() : 0;
00428 }
00429 
00440 const char* fl_input(const char *fmt, const char *defstr, ...) {
00441 
00442   if (avoidRecursion) return 0;
00443 
00444   fl_beep(FL_BEEP_QUESTION);
00445 
00446   va_list ap;
00447   va_start(ap, defstr);
00448   const char* r = input_innards(fmt, ap, defstr, FL_NORMAL_INPUT);
00449   va_end(ap);
00450   return r;
00451 }
00452 
00466 const char *fl_password(const char *fmt, const char *defstr, ...) {
00467 
00468   if (avoidRecursion) return 0;
00469 
00470   fl_beep(FL_BEEP_PASSWORD);
00471 
00472   va_list ap;
00473   va_start(ap, defstr);
00474   const char* r = input_innards(fmt, ap, defstr, FL_SECRET_INPUT);
00475   va_end(ap);
00476   return r;
00477 }
00478 
00481 //
00482 // End of "$Id: fl_ask.cxx 8136 2010-12-29 11:51:29Z manolo $".
00483 //