diff --git a/driver/Makefile b/driver/Makefile index 723f21f..b34ad06 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -14,7 +14,7 @@ OBJ_CLI = cli.o CFLAGS = -std=c++14 -O3 -Wall -Wextra LDFLAGS = -lcurses -lpthread OBJECTS_DRV = drv/usart.o drv/b15f.o drv/plottyfile.o drv/dot.o -OBJECTS_UI = ui/view.o ui/view_selection.o ui/view_info.o ui/view_monitor.o +OBJECTS_UI = ui/view.o ui/view_selection.o ui/view_promt.o ui/view_info.o ui/view_monitor.o COMPILE = $(COMPILER_PATH) $(CFLAGS) diff --git a/driver/cli b/driver/cli index 8b7669f..282399b 100755 Binary files a/driver/cli and b/driver/cli differ diff --git a/driver/cli.cpp b/driver/cli.cpp index 357946a..114efd6 100644 --- a/driver/cli.cpp +++ b/driver/cli.cpp @@ -17,6 +17,7 @@ #include "ui/view_selection.h" #include "ui/view_info.h" #include "ui/view_monitor.h" +#include "ui/view_promt.h" #include "drv/b15f.h" // global error message @@ -81,6 +82,13 @@ void finish(int) exit(EXIT_SUCCESS); } +void view_back(int) +{ + win_stack.pop_back(); + if(win_stack.size()) + win_stack.back()->repaint(); +} + void input(int) { std::function nextCall; @@ -88,20 +96,16 @@ void input(int) do { key = wgetch(View::getWinContext()); + win_stack.back()->repaint(); nextCall = win_stack.back()->keypress(key); if(key == -1) - { - win_stack.pop_back(); - if(win_stack.size()) - win_stack.back()->repaint(); - return; - } + view_back(key); if(nextCall) nextCall(key); } - while(!false); + while(win_stack.size()); } void show_info(int) @@ -128,13 +132,83 @@ void show_monitor(int) input(0); } +void show_invalid_port_input(int) +{ + ViewInfo* view = new ViewInfo(); + view->setTitle("Falsche Eingabe"); + view->setText("Bitte geben Sie einen Wert aus dem Intervall [00, FF] an."); + view->setLabelClose("[ Schliessen ]"); + view->repaint(); + + win_stack.push_back(view); + input(0); +} + +void write_digital_output0(int) +{ + try + { + uint8_t port = std::stoi(static_cast(win_stack.back())->getInput(), 0, 16); + + B15F& drv = B15F::getInstance(); + drv.digitalWrite0(port); + view_back(0); + } + catch(std::invalid_argument& ex) + { + show_invalid_port_input(0); + } +} + +void write_digital_output1(int) +{ + try + { + uint8_t port = std::stoi(static_cast(win_stack.back())->getInput(), 0, 16); + + B15F& drv = B15F::getInstance(); + drv.digitalWrite1(port); + view_back(0); + } + catch(std::invalid_argument& ex) + { + show_invalid_port_input(0); + } +} + +void show_digital_output0(int) +{ + ViewPromt* view = new ViewPromt(); + view->setTitle("Digitale Ausgabe BE0"); + view->setMessage("\nEingabe Port-Wert (hex): 0x"); + view->setCancel("[ Zurueck ]", true); + view->setConfirm("[ OK ]", &write_digital_output0); + view->repaint(); + + win_stack.push_back(view); + input(0); +} + +void show_digital_output1(int) +{ + ViewPromt* view = new ViewPromt(); + view->setTitle("Digitale Ausgabe BE1"); + view->setMessage("\nEingabe Port-Wert (hex): 0x"); + view->setCancel("[ Zurueck ]", true); + view->setConfirm("[ OK ]", &write_digital_output1); + view->repaint(); + + win_stack.push_back(view); + input(0); +} + void show_main(int) { ViewSelection* view = new ViewSelection(); view->setTitle("B15F - Command Line Interface"); view->addChoice("[ Monitor - Eingaben beobachten ]", &show_monitor); - view->addChoice("[ Digitale Ausgabe BE0 ]", &show_monitor); - view->addChoice("[ Digitale Ausgabe BE1 ]", &show_monitor); + view->addChoice("[ Digitale Ausgabe BE0 ]", &show_digital_output0); + view->addChoice("[ Digitale Ausgabe BE1 ]", &show_digital_output1); view->addChoice("[ Analoge Ausgabe AA0 ]", &show_monitor); view->addChoice("[ Analoge Ausgabe AA1 ]", &show_monitor); view->addChoice("[ Informationen ]", &show_info); diff --git a/driver/ui/view_info.cpp b/driver/ui/view_info.cpp index b94ff4e..0528d45 100644 --- a/driver/ui/view_info.cpp +++ b/driver/ui/view_info.cpp @@ -47,7 +47,8 @@ std::function ViewInfo::keypress(int& key) { size_t column = start_x + close_offset_x; size_t row = start_y + close_offset_y; - if(event.y == row && event.x >= column && event.x < column + label_close.length()) + size_t mouse_x = event.x, mouse_y = event.y; + if(mouse_y == row && mouse_x >= column && mouse_x < column + label_close.length()) key = -1; // do return from view } break; diff --git a/driver/ui/view_monitor.cpp b/driver/ui/view_monitor.cpp index 12880ca..8f32b61 100644 --- a/driver/ui/view_monitor.cpp +++ b/driver/ui/view_monitor.cpp @@ -18,7 +18,8 @@ std::function ViewMonitor::keypress(int& key) { size_t column = start_x + close_offset_x; size_t row = start_y + close_offset_y; - if(event.y == row && event.x >= column && event.x < column + label_close.length()) + size_t mouse_x = event.x, mouse_y = event.y; + if(mouse_y == row && mouse_x >= column && mouse_x < column + label_close.length()) hit = true; } if(!hit) diff --git a/driver/ui/view_promt.cpp b/driver/ui/view_promt.cpp new file mode 100644 index 0000000..80e2f24 --- /dev/null +++ b/driver/ui/view_promt.cpp @@ -0,0 +1,114 @@ +#include "view_promt.h" + +void ViewPromt::draw() +{ + int li = text_offset_y; + for(std::string line : str_split(message + input, "\n")) + mvwprintw(win, li++, text_offset_x, "%s", line.c_str()); + + button_offset_x = (width - label_cancel.length() - sep.length() - label_confirm.length()) / 2; + button_offset_y = height - text_offset_y + 1; + + if(selection == 0) + { + wattron(win, A_REVERSE); + mvwprintw(win, button_offset_y, button_offset_x, "%s", label_cancel.c_str()); + wattroff(win, A_REVERSE); + mvwprintw(win, button_offset_y, button_offset_x + label_cancel.length(), "%s", sep.c_str()); + mvwprintw(win, button_offset_y, button_offset_x + label_cancel.length() + sep.length(), "%s", label_confirm.c_str()); + } + else + { + mvwprintw(win, button_offset_y, button_offset_x, "%s", label_cancel.c_str()); + mvwprintw(win, button_offset_y, button_offset_x + label_cancel.length(), "%s", sep.c_str()); + wattron(win, A_REVERSE); + mvwprintw(win, button_offset_y, button_offset_x + label_cancel.length() + sep.length(), "%s", label_confirm.c_str()); + wattroff(win, A_REVERSE); + } +} + +void ViewPromt::setMessage(std::string message) +{ + this->message = message; +} + +void ViewPromt::setConfirm(std::string name, std::function call) +{ + label_confirm = name; + call_confirm = call; +} + +void ViewPromt::setCancel(std::string name, bool cancelable) +{ + label_cancel = name; + this->cancelable = cancelable; +} + +std::string ViewPromt::getInput() +{ + return input; +} + +std::function ViewPromt::keypress(int& key) +{ + std::function ret = nullptr; + switch(key) + { + case KEY_BACKSPACE: + if(input.length()) + input.pop_back(); + break; + case KEY_LEFT: + selection = (selection + 1 ) % 2; + break; + case KEY_RIGHT: + selection = (selection + 1 ) % 2; + break; + case KEY_MOUSE: + { + // http://pronix.linuxdelta.de/C/Linuxprogrammierung/Linuxsystemprogrammieren_C_Kurs_Kapitel10b.shtml + MEVENT event; + bool hit = false; + if(getmouse(&event) == OK && event.bstate & (BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED)) + { + size_t column_start = start_x + button_offset_x; + size_t row_start = start_y + button_offset_y; + size_t mouse_x = event.x, mouse_y = event.y; + if(mouse_y == row_start) + { + if(cancelable && mouse_x >= column_start && mouse_x < column_start + label_cancel.length()) + { + if(selection == 0 || event.bstate & BUTTON1_DOUBLE_CLICKED) + hit = true; + selection = 0; + } + if(mouse_x >= column_start + label_cancel.length() + sep.length() && mouse_x < column_start + label_cancel.length() + sep.length() + label_confirm.length()) + { + if(selection == 1 || event.bstate & BUTTON1_DOUBLE_CLICKED) + hit = true; + selection = 1; + } + } + } + if(!hit) + break; + + // fall through to next case + __attribute__ ((fallthrough)); + } + case KEY_ENT: + if(selection == 0) // exit + key = -1; // do return from view + else + ret = call_confirm; + break; + default: + break; + } + + if(key >= ' ' && key <= '~') + input += (char) key; + + repaint(); + return ret; +} diff --git a/driver/ui/view_promt.h b/driver/ui/view_promt.h new file mode 100644 index 0000000..d48be9c --- /dev/null +++ b/driver/ui/view_promt.h @@ -0,0 +1,32 @@ +#ifndef VIEW_PROMT_H +#define VIEW_PROMT_H + +#include +#include +#include "view.h" + +class ViewPromt : public View +{ +public: + virtual void draw(void) override; + virtual void setMessage(std::string message); + virtual void setConfirm(std::string name, std::function call); + virtual void setCancel(std::string name, bool cancelable); + virtual std::string getInput(void); + virtual std::function keypress(int& key) override; + +protected: + size_t selection = 1; + std::string input; + std::string message = "Input"; + std::string label_confirm = "[ OK ]"; + std::string sep = " "; + std::string label_cancel = "[ Cancel ]"; + std::function call_confirm = nullptr; + bool cancelable = true; + int button_offset_x = 0, button_offset_y = 0; + constexpr static int text_offset_x = 2; + constexpr static int text_offset_y = 3; +}; + +#endif // VIEW_PROMT_H