231 lines
5.9 KiB
C++
231 lines
5.9 KiB
C++
|
#include <FL/Fl.H>
|
||
|
#include <FL/Fl_Box.H>
|
||
|
#include <FL/Fl_Return_Button.H>
|
||
|
#include <FL/Fl_Window.H>
|
||
|
|
||
|
#include <FL/fl_draw.H>
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
class Tpt_Return_Button : public Fl_Return_Button {
|
||
|
public:
|
||
|
int handle(int event) {
|
||
|
if (event == FL_KEYBOARD
|
||
|
&& (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) {
|
||
|
simulate_key_action();
|
||
|
do_callback();
|
||
|
return 1;
|
||
|
} else
|
||
|
return Fl_Button::handle(event);
|
||
|
}
|
||
|
Tpt_Return_Button(int x, int y, int w, int h) : Fl_Return_Button(x, y, w, h)
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
static Fl_Window *message_form;
|
||
|
static Fl_Box *message;
|
||
|
static Fl_Box *icon;
|
||
|
static const int N_BUTTONS = 3;
|
||
|
static Fl_Button *button[N_BUTTONS];
|
||
|
static int ret_val;
|
||
|
static const char *iconlabel = "?";
|
||
|
static const char *message_title_default;
|
||
|
Fl_Font fl_message_font_ = FL_HELVETICA;
|
||
|
Fl_Fontsize fl_message_size_ = -1;
|
||
|
static int enableHotspot = 1;
|
||
|
|
||
|
static char avoidRecursion = 0;
|
||
|
|
||
|
|
||
|
// Sets the global return value (ret_val) and closes the window.
|
||
|
static void button_cb(Fl_Widget *, long val) {
|
||
|
ret_val = (int) val;
|
||
|
if (Fl::event_key() == FL_Escape) ret_val = -1;
|
||
|
message_form->hide();
|
||
|
}
|
||
|
|
||
|
// If the window is simply closed, that's the same as hitting escape
|
||
|
static void form_cb(Fl_Widget *, long val) {
|
||
|
ret_val = -1;
|
||
|
message_form->hide();
|
||
|
}
|
||
|
|
||
|
static Fl_Window *makeform() {
|
||
|
if (message_form) {
|
||
|
return message_form;
|
||
|
}
|
||
|
// make sure that the dialog does not become the child of some
|
||
|
// current group
|
||
|
Fl_Group *previously_current_group = Fl_Group::current();
|
||
|
Fl_Group::current(0);
|
||
|
// create a new top level window
|
||
|
Fl_Window *w = message_form = new Fl_Window(410,103);
|
||
|
message_form->callback(form_cb);
|
||
|
|
||
|
(message = new Fl_Box(60, 25, 340, 20))
|
||
|
->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
|
||
|
{Fl_Box* o = icon = new Fl_Box(10, 10, 50, 50);
|
||
|
o->box(FL_THIN_UP_BOX);
|
||
|
o->labelfont(FL_TIMES_BOLD);
|
||
|
o->labelsize(34);
|
||
|
o->color(FL_WHITE);
|
||
|
o->labelcolor(FL_BLUE);
|
||
|
}
|
||
|
w->end(); // don't add the buttons automatically
|
||
|
// create the buttons (right to left)
|
||
|
for (int b=0, x=100*N_BUTTONS+10; b<N_BUTTONS; b++, x -= 100) {
|
||
|
button[b] = new Tpt_Return_Button(x, 70, 90, 23);
|
||
|
button[b]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP);
|
||
|
button[b]->callback(button_cb, b);
|
||
|
}
|
||
|
button[0]->shortcut(FL_Escape);
|
||
|
// add the buttons (left to right so arrow keys work)
|
||
|
for (int b = N_BUTTONS-1; b >= 0; --b)
|
||
|
w->add(button[b]);
|
||
|
|
||
|
w->begin();
|
||
|
w->resizable(new Fl_Box(60,10,110-60,27));
|
||
|
w->end();
|
||
|
w->set_modal();
|
||
|
Fl_Group::current(previously_current_group);
|
||
|
return w;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 'resizeform()' - Resize the form and widgets so that they hold everything
|
||
|
* that is asked of them...
|
||
|
*/
|
||
|
|
||
|
static void resizeform() {
|
||
|
int i;
|
||
|
int message_w, message_h;
|
||
|
int text_height;
|
||
|
int button_w[N_BUTTONS], button_h[N_BUTTONS];
|
||
|
int x, w, h, max_w, max_h;
|
||
|
const int icon_size = 50;
|
||
|
|
||
|
message_form->size(410,103);
|
||
|
|
||
|
fl_font(message->labelfont(), message->labelsize());
|
||
|
message_w = message_h = 0;
|
||
|
fl_measure(message->label(), message_w, message_h);
|
||
|
|
||
|
message_w += 10;
|
||
|
message_h += 10;
|
||
|
if (message_w < 340)
|
||
|
message_w = 340;
|
||
|
if (message_h < 30)
|
||
|
message_h = 30;
|
||
|
|
||
|
fl_font(button[0]->labelfont(), button[0]->labelsize());
|
||
|
|
||
|
memset(button_w, 0, sizeof(button_w));
|
||
|
memset(button_h, 0, sizeof(button_h));
|
||
|
|
||
|
for (max_h = 25, i = 0; i < N_BUTTONS; i ++)
|
||
|
if (button[i]->visible())
|
||
|
{
|
||
|
fl_measure(button[i]->label(), button_w[i], button_h[i]);
|
||
|
|
||
|
if (i == 1)
|
||
|
button_w[1] += 20;
|
||
|
|
||
|
button_w[i] += 30;
|
||
|
button_h[i] += 10;
|
||
|
|
||
|
if (button_h[i] > max_h)
|
||
|
max_h = button_h[i];
|
||
|
}
|
||
|
|
||
|
text_height = message_h;
|
||
|
|
||
|
max_w = message_w + 10 + icon_size;
|
||
|
w = -10;
|
||
|
for (int i = 0; i < N_BUTTONS; ++i) w += button_w[i];
|
||
|
|
||
|
if (w > max_w)
|
||
|
max_w = w;
|
||
|
|
||
|
message_w = max_w - 10 - icon_size;
|
||
|
|
||
|
w = max_w + 20;
|
||
|
h = max_h + 30 + text_height;
|
||
|
|
||
|
message_form->size(w, h);
|
||
|
message_form->size_range(w, h, w, h);
|
||
|
|
||
|
message->resize(20 + icon_size, 10, message_w, message_h);
|
||
|
icon->resize(10, 10, icon_size, icon_size);
|
||
|
icon->labelsize(icon_size - 10);
|
||
|
|
||
|
for (x = w, i = 0; i < N_BUTTONS; i ++)
|
||
|
if (button_w[i])
|
||
|
{
|
||
|
x -= button_w[i];
|
||
|
button[i]->resize(x, h - 10 - max_h, button_w[i] - 10, max_h);
|
||
|
}
|
||
|
message_form->init_sizes();
|
||
|
}
|
||
|
|
||
|
int tpt_choose(const char* prompt, const char* op0, const char *op1,
|
||
|
const char* op2, int curx) {
|
||
|
|
||
|
if (avoidRecursion) return 0;
|
||
|
|
||
|
Fl::pushed(0); // stop dragging
|
||
|
|
||
|
avoidRecursion = 1;
|
||
|
|
||
|
makeform();
|
||
|
message_form->size(410,103);
|
||
|
message->label(prompt);
|
||
|
message->labelfont(fl_message_font_);
|
||
|
if (fl_message_size_ == -1) message->labelsize(FL_NORMAL_SIZE);
|
||
|
else message->labelsize(fl_message_size_);
|
||
|
if (op0) {
|
||
|
button[0]->show();
|
||
|
button[0]->label(op0);
|
||
|
button[1]->position(210,70);
|
||
|
}
|
||
|
else { button[0]->hide(); button[1]->position(310,70); }
|
||
|
if (op1) { button[1]->show(); button[1]->label(op1);}
|
||
|
else button[1]->hide();
|
||
|
if (op2) { button[2]->show(); button[2]->label(op2); }
|
||
|
else button[2]->hide();
|
||
|
|
||
|
button[curx]->take_focus();
|
||
|
|
||
|
const char* prev_icon_label = icon->label();
|
||
|
if (!prev_icon_label) icon->label(iconlabel);
|
||
|
|
||
|
resizeform();
|
||
|
|
||
|
if (enableHotspot)
|
||
|
message_form->hotspot(button[0]);
|
||
|
if (op0 && Fl_Widget::label_shortcut(op0))
|
||
|
button[0]->shortcut(0);
|
||
|
else
|
||
|
button[0]->shortcut(FL_Escape);
|
||
|
|
||
|
// set default window title, if defined and a specific title is not set
|
||
|
if (!message_form->label() && message_title_default)
|
||
|
message_form->label(message_title_default);
|
||
|
|
||
|
// deactivate Fl::grab(), because it is incompatible with modal windows
|
||
|
Fl_Window* g = Fl::grab();
|
||
|
if (g) Fl::grab(0);
|
||
|
Fl_Group *current_group = Fl_Group::current(); // make sure the dialog does not interfere with any active group
|
||
|
message_form->show();
|
||
|
Fl_Group::current(current_group);
|
||
|
while (message_form->shown()) Fl::wait();
|
||
|
if (g) // regrab the previous popup menu, if there was one
|
||
|
Fl::grab(g);
|
||
|
icon->label(prev_icon_label);
|
||
|
message_form->label(0); // reset window title
|
||
|
|
||
|
avoidRecursion = 0;
|
||
|
|
||
|
return ret_val;
|
||
|
}
|