From 00f799e29859230fee5a9b63b152197c7d111cd2 Mon Sep 17 00:00:00 2001 From: denes Date: Fri, 13 Jan 2017 15:56:39 +0100 Subject: [PATCH] first working proto with 1 window --- CMakeLists.txt | 2 +- main.cpp | 279 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 255 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5444133..910ec5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,4 +9,4 @@ set (CMAKE_CXX_COMPILER "/usr/bin/g++-5.1.0") add_executable (graph_browser main.cpp) include_directories(graph/lib/) -#target_link_libraries(test_bin gcov) +target_link_libraries(graph_browser ncurses menu) diff --git a/main.cpp b/main.cpp index fbaf417..a25a36e 100644 --- a/main.cpp +++ b/main.cpp @@ -2,26 +2,30 @@ #include #include -#include +#include -// https://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c -std::string GenerateRandomString(size_t length) +#include + +#include +#include + +std::string generateRandomString(size_t length) { - auto GenerateRandomChar = []() -> char - { - const char charset[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const size_t max_index = (sizeof(charset) - 1); - return charset[ rand() % max_index ]; - }; - std::string str(length,0); - std::generate_n( str.begin(), length, GenerateRandomChar ); - return str; + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + + std::string str(length,0); + for (int i = 0; i < length; ++i) { + const size_t r = rand() % max_index; + str[i] = charset[r]; + } + return str; } -std::vector GenerateRandomStrings(size_t number_of_strings, +std::vector generateRandomStrings(size_t number_of_strings, size_t min_length, size_t max_length) { @@ -29,32 +33,257 @@ std::vector GenerateRandomStrings(size_t number_of_strings, v.resize(number_of_strings); for (int i = 0; i < number_of_strings; ++i) { const size_t l = min_length + rand()%(max_length - min_length); - v[i] = GenerateRandomString(l); + v[i] = generateRandomString(l); } - return v; } -Graph GenerateRandomGraph(size_t number_of_vertices, +Graph generateRandomGraph(size_t number_of_vertices, size_t number_of_edges, size_t vertex_text_min_length, size_t vertex_text_max_length) { Graph graph; - const std::vector v = GenerateRandomStrings(number_of_vertices, + const std::vector v = generateRandomStrings(number_of_vertices, vertex_text_min_length, vertex_text_max_length); - for (int i = 0; i < number_of_edges; ++i) - graph.addEdge(v[rand()%number_of_vertices], v[rand()%number_of_vertices]); - + for (int i = 0; i < number_of_edges; ++i) { + const std::string source = v[rand()%number_of_vertices]; + const std::string destination = v[rand()%number_of_vertices]; + graph.addEdge(source, destination); + } return graph; } +class NCursesInterface { +public: + + static constexpr size_t TERM_MAX_X = 80; + static constexpr size_t TERM_MAX_Y = 24; + static constexpr int KEY_ESC = 27; + + void static init() + { + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + //Needed to have ‘immediate’ ESC-Key behavior: + if (getenv ("ESCDELAY") == NULL) { + set_escdelay(25); + } + } + + void static destroy() + { + clrtoeol(); + refresh(); + endwin(); + } + + NCursesInterface(const Graph& g) + : menu_(0) + , current_win_(0) + , items_(0) + , number_of_choices_(0) + + , graph_(g) + + , current_() + , history_() + , history_string_() + { + /* Crate menu */ + menu_ = new_menu((ITEM **)items_); + + /* Create the window to be associated with the menu */ + current_win_ = newwin(10, 40, 1, 0); + keypad(current_win_, TRUE); + + /* Set main window and sub window */ + set_menu_win(menu_, current_win_); + set_menu_sub(menu_, derwin(current_win_, 6, 38, 3, 1)); + set_menu_format(menu_, 6, 1); + + /* Set menu mark to the string " * " */ + set_menu_mark(menu_, " "); + + /* Print a border around the main window and print a title */ + box(current_win_, 0, 0); + //wborder(current_win_, '|', '|', '-', '-', '+', '+', '+', '+'); + + printInTheMiddle(current_win_, 1, 0, 40, "Current"); + mvwaddch(current_win_, 2, 0, ACS_LTEE); + mvwhline(current_win_, 2, 1, ACS_HLINE, 38); + mvwaddch(current_win_, 2, 39, ACS_RTEE); + mvprintw(TERM_MAX_Y-1, 0, "ESC to exit, cursor keys to navigate"); + refresh(); + + /* Post the menu */ + post_menu(menu_); + wrefresh(current_win_); + } + + ~NCursesInterface() + { + unpost_menu(menu_); + free_menu(menu_); + for(int i = 0; i < number_of_choices_; ++i) + free_item(items_[i]); + } + + void mainLoop() + { + int c; + while((c = wgetch(current_win_)) != KEY_ESC) { + switch(c) { + case KEY_DOWN: + menu_driver(menu_, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(menu_, REQ_UP_ITEM); + break; + case KEY_LEFT: { + if (history_.empty()) + break; + + const std::string prev = history_.back(); + history_.pop_back(); + current_ = prev; + const std::vector& n = graph_.neighboursOf(prev); + printInTheMiddle(current_win_, 1, 0, 40-2, prev.c_str()); + addItems(n); + history_string_ = historyToString(); + mvprintw(0, 0, "%s", std::string(TERM_MAX_X,' ').c_str()); + mvprintw(0, 0, history_string_.c_str()); + refresh(); + break; + } + case KEY_RIGHT: { + std::string next = item_name(current_item(menu_)); + + const std::vector& n = graph_.neighboursOf(next); + history_.push_back(current_); + current_ = next; + printInTheMiddle(current_win_, 1, 0, 40-2, next.c_str()); + addItems(n); + + history_string_ = historyToString(); + while (history_string_.length() > TERM_MAX_X) { + history_.pop_front(); + history_string_ = historyToString(); + } + mvprintw(0, 0, "%s",std::string(TERM_MAX_X,' ').c_str()); + mvprintw(0, 0, history_string_.c_str()); + refresh(); + break; + } + case KEY_NPAGE: + menu_driver(menu_, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(menu_, REQ_SCR_UPAGE); + break; + + } + wrefresh(current_win_); + } + } + + void setCurrentVertex(const std::string& s) + { + current_ = s; + const std::vector& n = graph_.neighboursOf(current_); + printInTheMiddle(current_win_, 1, 0, 40-2, current_.c_str()); + addItems(n); + } + +private: + + void addItems(const std::vector& stringVector) + { + unpost_menu(menu_); + for(int i = 0; i < number_of_choices_; ++i) + free_item(items_[i]); + + number_of_choices_ = stringVector.size(); + items_ = (ITEM **)calloc(number_of_choices_+1, sizeof(ITEM *)); + for(size_t i = 0; i < number_of_choices_; ++i) + items_[i] = new_item(stringVector[i].c_str(), 0); + + items_[number_of_choices_] = new_item(0, 0); + set_menu_items(menu_, items_); + set_menu_format(menu_, 6, 1); + + /* Post the menu */ + post_menu(menu_); + wrefresh(current_win_); + } + + std::string historyToString() const { + if (history_.empty()) + return std::string(); + + std::string s; + for (size_t i = 0; i < history_.size()-1; ++i) { + s += history_[i]; + s += " | "; + } + s += history_[history_.size()-1]; + return s; + } + + void printInTheMiddle(WINDOW *win, int starty, int startx, int width, const std::string& s) + { + size_t x, y; + float temp; + + if(win == NULL) + win = stdscr; + getyx(win, y, x); + if(startx != 0) + x = startx; + if(starty != 0) + y = starty; + if(width == 0) + width = 80; + + temp = (width - s.length())/ 2; + x = startx + (int)temp; + + y = 1; + x = 1 + (int)temp; + + mvwprintw(win, 1, 1, "%s",std::string(width-2,' ').c_str()); + mvwprintw(win, y, x, "%s", s.c_str()); + refresh(); + } + + MENU *menu_; + WINDOW *current_win_; + ITEM **items_; + int number_of_choices_; + + const Graph& graph_; + + std::string current_; + std::deque history_; + std::string history_string_; +}; + + + int main(int argc, char* argv[]) { - const Graph g = GenerateRandomGraph(10, 200, 5, 20); + const Graph g = generateRandomGraph(10, 200, 5, 20); + NCursesInterface::init(); + NCursesInterface ni(g); + ni.setCurrentVertex(*g.begin()); + ni.mainLoop(); + NCursesInterface::destroy(); return EXIT_SUCCESS; -} \ No newline at end of file +}