Привет всем, если у кого-то имеется опыт разработки на FLTK, дайте совет пожалуйста!
Пытаюсь реализовать для «Fl_Input» функционал редактирования как в терминальной строке - стрелками вверх/вниз подгружать историю ввода. Но засада с обработкой клавиш стрелок - не получается подвесить отдельный обработчик события на «стрелки» - приходится только полностью все события клавиатуры обрабатывать в собственном цикле. Или например такой вариант:
Fl_Simple_Terminal *Tty = nullptr;
Fl_Input* Input = nullptr;
/// callback
void cb(Fl_Widget*, void*)
{
auto key = Fl::event_key();
if(key == FL_Up) Tty->printf( "%s\n", "UP-key" );
else if(key == FL_Down) Tty->printf( "%s\n", "Down-key" );
else Tty->printf( "%s\n", Input->value() );
Input->take_focus();
return;
}
/// MAIN
int main(int, char**)
{
...
Fl::option(Fl::OPTION_ARROW_FOCUS, true);
Tty = new Fl_Simple_Terminal(0, 0, width, tty_h);
...
Input = new Fl_Input(0, tty_h, width, input_h, nullptr);
Input->callback(cb);
...
В таком варианте корректно обрабатывается только одно нажатие на стрелку сразу после ввода/удаления символа в строке ввода. Два нажатия подряд не работают. Что-то надо переключить в состоянии, но что? Или может использовать другой класс для ввода строки?
Ответ (спасибо, rymis):
#include <functional>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Simple_Terminal.H>
Fl_Simple_Terminal *Tty = nullptr;
Fl_Input* Input = nullptr;
class History {
public:
void log (const char* msg){ Tty->printf( "%s\n", msg ); }
void up (void){ log("Up is pressed."); };
void down(void){ log("Down is pressed."); };
void add (const char* msg){ log(msg + 2); };
};
class MyInput : public Fl_Input {
History hist;
public:
template <typename...Args>
MyInput(Args&&...args) : Fl_Input(std::forward<Args>(args)...) { }
int handle(int ev) override {
if (ev != FL_KEYDOWN) return Fl_Input::handle(ev);
auto key = Fl::event_key();
if (key == FL_Up) {
hist.up();
return 1;
} else if (key == FL_Down) {
hist.down();
return 1;
} else if (key == FL_Enter) {
hist.add(value());
value("$ ");
return 1;
}
return Fl_Input::handle(ev);
}
};
int main(int, char**) {
int width = 500; int tty_h = 500; int inp_h = 24;
Fl_Window *Win = new Fl_Window(width, tty_h + inp_h, "App");
Win->begin();
Tty = new Fl_Simple_Terminal(0, 0, width, tty_h);
Input = new MyInput(0, tty_h - 3, width, inp_h, nullptr);
Input->insert("$ ");
Win->end();
Win->resizable(Tty);
Win->show();
Fl::focus(Input);
return Fl::run();
}
Такой вот бесполезный но наглядный рабочий примерчик - можно даже скомпилировать и запустить. Правда, надо отметить, что народ не слишком-то любит FLTK.