basic ui
This commit is contained in:
parent
282a0dbc34
commit
793f8a8370
|
@ -13,17 +13,18 @@ OUT_CLI = cli
|
||||||
OBJ_CLI = cli.o
|
OBJ_CLI = cli.o
|
||||||
CFLAGS = -std=c++14 -O3 -Wall -Wextra
|
CFLAGS = -std=c++14 -O3 -Wall -Wextra
|
||||||
LDFLAGS = -lcurses
|
LDFLAGS = -lcurses
|
||||||
OBJECTS = drv/usart.o drv/b15f.o drv/plottyfile.o drv/dot.o
|
OBJECTS_DRV = drv/usart.o drv/b15f.o drv/plottyfile.o drv/dot.o
|
||||||
|
OBJECTS_UI = ui/view.o ui/view_main.o ui/view_info.o
|
||||||
|
|
||||||
COMPILE = $(COMPILER_PATH) $(CFLAGS)
|
COMPILE = $(COMPILER_PATH) $(CFLAGS)
|
||||||
|
|
||||||
main: $(OBJECTS) $(OBJ_MAIN)
|
main: $(OBJECTS_DRV) $(OBJ_MAIN)
|
||||||
@echo "Linking..."
|
@echo "Linking..."
|
||||||
$(COMPILE) $(OBJ_MAIN) $(OBJECTS) -o $(OUT_MAIN) $(LDFLAGS)
|
$(COMPILE) $(OBJ_MAIN) $(OBJECTS_DRV) -o $(OUT_MAIN) $(LDFLAGS)
|
||||||
|
|
||||||
cli: $(OBJECTS) $(OBJ_CLI)
|
cli: $(OBJECTS_DRV) $(OBJECTS_UI) $(OBJ_CLI)
|
||||||
@echo "Linking..."
|
@echo "Linking..."
|
||||||
$(COMPILE) $(OBJ_CLI) $(OBJECTS) -o $(OUT_CLI) $(LDFLAGS)
|
$(COMPILE) $(OBJ_CLI) $(OBJECTS_DRV) $(OBJECTS_UI) -o $(OUT_CLI) $(LDFLAGS)
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "This Makefile has the following rules:"
|
@echo "This Makefile has the following rules:"
|
||||||
|
@ -33,7 +34,7 @@ help:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning..."
|
||||||
rm -f $(OBJECTS) $(OUTPUT)
|
rm -f $(OBJECTS_DRV) $(OBJECTS_UI) $(OUT_CLI) $(OUT_MAIN)
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
$(COMPILE) -c $< -o $@
|
$(COMPILE) -c $< -o $@
|
||||||
|
|
BIN
driver/cli
BIN
driver/cli
Binary file not shown.
172
driver/cli.cpp
172
driver/cli.cpp
|
@ -5,112 +5,92 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "ui/view_main.h"
|
||||||
#define width 30
|
#include "ui/view_info.h"
|
||||||
#define height 10
|
|
||||||
|
|
||||||
WINDOW *win_menu;
|
|
||||||
|
|
||||||
std::vector<std::string> choices = {
|
|
||||||
"Choice 1",
|
|
||||||
"Choice 2",
|
|
||||||
"Choice 3",
|
|
||||||
"Choice 4",
|
|
||||||
"Exit",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void init_win(WINDOW*& win)
|
std::vector<View*> win_stack;
|
||||||
|
ViewMain* view_main = nullptr;
|
||||||
|
ViewInfo* view_info = nullptr;
|
||||||
|
|
||||||
|
void init()
|
||||||
{
|
{
|
||||||
struct winsize size;
|
|
||||||
if (ioctl(0, TIOCGWINSZ, (char *) &size) < 0)
|
|
||||||
throw std::runtime_error("TIOCGWINSZ error");
|
|
||||||
|
|
||||||
int start_x = (size.ws_col - width);
|
|
||||||
int start_y = (size.ws_row - height);
|
|
||||||
if(start_x % 2)
|
|
||||||
start_x++;
|
|
||||||
if(start_y % 2)
|
|
||||||
start_y++;
|
|
||||||
start_x /= 2;
|
|
||||||
start_y /= 2;
|
|
||||||
|
|
||||||
win = newwin(height, width, start_y, start_x);
|
|
||||||
keypad(win, TRUE);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_menu(WINDOW *win_menu, int highlight)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int x, y, i;
|
|
||||||
|
|
||||||
x = 2;
|
|
||||||
y = 2;
|
|
||||||
box(win_menu, 0, 0);
|
|
||||||
for(i = 0; i < choices.size(); ++i)
|
|
||||||
{ if(highlight == i + 1) /* High light the present choice */
|
|
||||||
{ wattron(win_menu, A_REVERSE);
|
|
||||||
mvwprintw(win_menu, y, x, "%s", choices[i].c_str());
|
|
||||||
wattroff(win_menu, A_REVERSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mvwprintw(win_menu, y, x, "%s", choices[i].c_str());
|
|
||||||
++y;
|
|
||||||
}
|
|
||||||
wrefresh(win_menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int highlight = 1;
|
|
||||||
int choice = 0;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
initscr();
|
initscr();
|
||||||
start_color();
|
start_color();
|
||||||
curs_set(0); // 0: invisible, 1: normal, 2: very visible
|
curs_set(0); // 0: invisible, 1: normal, 2: very visible
|
||||||
clear();
|
clear();
|
||||||
noecho();
|
noecho();
|
||||||
cbreak(); /* Line buffering disabled. pass on everything */
|
cbreak(); // Line buffering disabled. pass on everything
|
||||||
|
mousemask(ALL_MOUSE_EVENTS, NULL);
|
||||||
init_win(win_menu);
|
|
||||||
mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
|
|
||||||
print_menu(win_menu, highlight);
|
|
||||||
refresh();
|
|
||||||
|
|
||||||
while(1)
|
View::setWinContext(newwin(32, 128, 0, 0));
|
||||||
{ c = wgetch(win_menu);
|
}
|
||||||
switch(c)
|
|
||||||
{ case KEY_UP:
|
void cleanup()
|
||||||
if(highlight == 1)
|
{
|
||||||
highlight = choices.size();
|
|
||||||
else
|
|
||||||
--highlight;
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
if(highlight == choices.size())
|
|
||||||
highlight = 1;
|
|
||||||
else
|
|
||||||
++highlight;
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
choice = highlight;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mvprintw(24, 0, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
|
|
||||||
refresh();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
print_menu(win_menu, highlight);
|
|
||||||
if(choice != 0) /* User did a choice come out of the infinite loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1].c_str());
|
|
||||||
clrtoeol();
|
clrtoeol();
|
||||||
refresh();
|
refresh();
|
||||||
endwin();
|
endwin();
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
void finish(int key)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void input(int prev_key)
|
||||||
|
{
|
||||||
|
std::function<void(int)> nextCall;
|
||||||
|
int key;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
key = wgetch(View::getWinContext());
|
||||||
|
nextCall = win_stack.back()->keypress(key);
|
||||||
|
|
||||||
|
if(key == -1)
|
||||||
|
{
|
||||||
|
win_stack.pop_back();
|
||||||
|
if(win_stack.size())
|
||||||
|
win_stack.back()->repaint();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nextCall)
|
||||||
|
nextCall(key);
|
||||||
|
}
|
||||||
|
while(!false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_info(int key)
|
||||||
|
{
|
||||||
|
View* view = new ViewInfo();
|
||||||
|
view->setTitle("Info");
|
||||||
|
view->repaint();
|
||||||
|
|
||||||
|
win_stack.push_back(view);
|
||||||
|
input(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_main(int key)
|
||||||
|
{
|
||||||
|
View* view = new ViewMain();
|
||||||
|
view->setTitle("B15F - Command Line Interface");
|
||||||
|
view->addCall(&show_info);
|
||||||
|
view->addCall(&finish);
|
||||||
|
view->repaint();
|
||||||
|
|
||||||
|
win_stack.push_back(view);
|
||||||
|
input(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
show_main(0);
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
BIN
driver/main
BIN
driver/main
Binary file not shown.
58
driver/ui/view.cpp
Normal file
58
driver/ui/view.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
WINDOW* View::win = nullptr;
|
||||||
|
|
||||||
|
View::View()
|
||||||
|
{
|
||||||
|
if(!win)
|
||||||
|
throw std::runtime_error("View::win not initialized, missing context!");
|
||||||
|
getmaxyx(win, height, width); // init width and height
|
||||||
|
keypad(win, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setWinContext(WINDOW* win)
|
||||||
|
{
|
||||||
|
View::win = win;
|
||||||
|
}
|
||||||
|
|
||||||
|
WINDOW* View::getWinContext()
|
||||||
|
{
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::addCall(std::function<void(int)> call)
|
||||||
|
{
|
||||||
|
calls.push_back(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::setTitle(std::string title)
|
||||||
|
{
|
||||||
|
this->title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::repaint()
|
||||||
|
{
|
||||||
|
// get screen size
|
||||||
|
struct winsize size;
|
||||||
|
if (ioctl(0, TIOCGWINSZ, (char *) &size) < 0)
|
||||||
|
throw std::runtime_error("TIOCGWINSZ error");
|
||||||
|
|
||||||
|
|
||||||
|
start_x = floor((size.ws_col - width) / 2.);
|
||||||
|
start_y = floor((size.ws_row - height) / 2.);
|
||||||
|
|
||||||
|
mvwin(win, start_y, start_x);
|
||||||
|
|
||||||
|
wclear(win);
|
||||||
|
|
||||||
|
// generic draw
|
||||||
|
box(win, 0, 0);
|
||||||
|
int offset_x = (width - title.length()) / 2;
|
||||||
|
mvwprintw(win, 1, offset_x, "%s", title.c_str());
|
||||||
|
|
||||||
|
// specific draw
|
||||||
|
draw();
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
wrefresh(win);
|
||||||
|
}
|
42
driver/ui/view.h
Normal file
42
driver/ui/view.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef VIEW_H
|
||||||
|
#define VIEW_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <ncurses.h> // sudo apt-get install libncurses5-dev
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
class View
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
View(void);
|
||||||
|
|
||||||
|
static void setWinContext(WINDOW* win);
|
||||||
|
static WINDOW* getWinContext(void);
|
||||||
|
|
||||||
|
virtual void addCall(std::function<void(int)> call);
|
||||||
|
|
||||||
|
void setSize(int width, int height);
|
||||||
|
void setTitle(std::string title);
|
||||||
|
|
||||||
|
virtual void repaint(void);
|
||||||
|
|
||||||
|
virtual void draw(void) = 0;
|
||||||
|
virtual std::function<void(int)> keypress(int& key) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int width, height;
|
||||||
|
int start_x = 0, start_y = 0;
|
||||||
|
std::string title;
|
||||||
|
std::vector<std::function<void(int)>> calls;
|
||||||
|
|
||||||
|
constexpr static int KEY_ENT = 10;
|
||||||
|
|
||||||
|
static WINDOW* win;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VIEW_H
|
33
driver/ui/view_info.cpp
Normal file
33
driver/ui/view_info.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include "view_info.h"
|
||||||
|
|
||||||
|
ViewInfo::ViewInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewInfo::draw()
|
||||||
|
{
|
||||||
|
mvwprintw(win, text_offset_y, text_offset_x, "%s", "hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<void(int)> ViewInfo::keypress(int& key)
|
||||||
|
{
|
||||||
|
std::function<void(int)> ret = nullptr;
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
|
||||||
|
case KEY_MOUSE:
|
||||||
|
{
|
||||||
|
// http://pronix.linuxdelta.de/C/Linuxprogrammierung/Linuxsystemprogrammieren_C_Kurs_Kapitel10b.shtml
|
||||||
|
MEVENT event;
|
||||||
|
if(getmouse(&event) == OK && event.bstate & BUTTON1_CLICKED)
|
||||||
|
key = -1; // do return from view
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KEY_ENT:
|
||||||
|
key = -1; // do return from view
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
18
driver/ui/view_info.h
Normal file
18
driver/ui/view_info.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef VIEW_INFO
|
||||||
|
#define VIEW_INFO
|
||||||
|
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
class ViewInfo : public View
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewInfo(void);
|
||||||
|
virtual void draw(void) override;
|
||||||
|
virtual std::function<void(int)> keypress(int& key) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr static int text_offset_x = 2;
|
||||||
|
constexpr static int text_offset_y = 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VIEW_INFO
|
62
driver/ui/view_main.cpp
Normal file
62
driver/ui/view_main.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "view_main.h"
|
||||||
|
|
||||||
|
void ViewMain::draw()
|
||||||
|
{
|
||||||
|
|
||||||
|
for(size_t i = 0; i < choices.size(); i++)
|
||||||
|
{
|
||||||
|
if(selection == i)
|
||||||
|
wattron(win, A_REVERSE);
|
||||||
|
mvwprintw(win, i + choice_offset_y, choice_offset_x, "%s", choices[i].c_str());
|
||||||
|
if(selection == i)
|
||||||
|
wattroff(win, A_REVERSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<void(int)> ViewMain::keypress(int& key)
|
||||||
|
{
|
||||||
|
std::function<void(int)> ret = nullptr;
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case KEY_UP:
|
||||||
|
selection = (selection - 1) % choices.size();
|
||||||
|
break;
|
||||||
|
case KEY_DOWN:
|
||||||
|
selection = (selection + 1) % choices.size();
|
||||||
|
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 + choice_offset_x;
|
||||||
|
size_t row_start = start_y + choice_offset_y;
|
||||||
|
size_t mouse_x = event.x, mouse_y = event.y;
|
||||||
|
for(size_t i = 0; i < choices.size(); i++)
|
||||||
|
if(mouse_y == row_start + i && mouse_x >= column_start && mouse_x < column_start + choices[i].length())
|
||||||
|
{
|
||||||
|
if(selection == i || event.bstate & BUTTON1_DOUBLE_CLICKED)
|
||||||
|
hit = true;
|
||||||
|
selection = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!hit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// fall through to next case
|
||||||
|
__attribute__ ((fallthrough));
|
||||||
|
}
|
||||||
|
case KEY_ENT:
|
||||||
|
if(selection == choices.size() - 1) // exit
|
||||||
|
key = -1; // do return from view
|
||||||
|
else
|
||||||
|
ret = calls[selection];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
repaint();
|
||||||
|
return ret;
|
||||||
|
}
|
24
driver/ui/view_main.h
Normal file
24
driver/ui/view_main.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef VIEW_MAIN_H
|
||||||
|
#define VIEW_MAIN_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
class ViewMain : public View
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void draw(void) override;
|
||||||
|
virtual std::function<void(int)> keypress(int& key) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr static int choice_offset_x = 2;
|
||||||
|
constexpr static int choice_offset_y = 3;
|
||||||
|
size_t selection = 0;
|
||||||
|
const std::vector<std::string> choices = {
|
||||||
|
"Beobachten",
|
||||||
|
"Exit"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VIEW_MAIN_H
|
Loading…
Reference in a new issue