parent
e51885a007
commit
225871dba4
@ -1,5 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
clear
|
||||
|
||||
rm menu
|
||||
|
||||
g++ main.cpp -o menu -lncurses
|
||||
|
||||
./menu
|
||||
|
@ -1,58 +1,60 @@
|
||||
#include <ncurses.h>
|
||||
#include "menu.h"
|
||||
#include "main.h"
|
||||
|
||||
#define ctrl(x) (x & 0x1F) // Detection of ctrl+x presses please do not forget that in unix ctrl+c and ctrl+z are special commands.
|
||||
#include "terminal.h"
|
||||
#include "menuBar.h"
|
||||
|
||||
// INFO: wgetch(win); or getch(); // getch will make a refresh for us.
|
||||
|
||||
int main(int argv, char ** argc)
|
||||
{
|
||||
//Variables
|
||||
int xMax, yMax = 0;
|
||||
int xMax, yMax, xMouse, yMouse= 0;
|
||||
char pressed;
|
||||
|
||||
|
||||
//Init Ncurses
|
||||
initscr();
|
||||
|
||||
if(has_colors() == false) // If the terminal does have colors
|
||||
{
|
||||
printf("This menu is not supported by terminals without colors\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
start_color();
|
||||
|
||||
noecho();
|
||||
curs_set(0); // Cursor won't show up
|
||||
getmaxyx(stdscr, yMax, xMax);
|
||||
// size y size x pos y pos x
|
||||
WINDOW *win = newwin(yMax/2, xMax/2, yMax/4, xMax/4);
|
||||
box(win,0,0);
|
||||
|
||||
//Setc colors
|
||||
init_pair(1, COLOR_WHITE, COLOR_BLUE);
|
||||
|
||||
|
||||
std::string menu1[4]={"New","Open","Save","Exit"};
|
||||
std::string menu2[3]={"Copy","Cut","Paste"};
|
||||
std::string menu3[5]={"Terminal","Help","Info","Update","Manual"};
|
||||
|
||||
// Second stage declarations
|
||||
Menu menus[3]={ // init the menus
|
||||
Menu("File", 'f', menu1, 4),
|
||||
Menu("Edit", 'e', menu2, 3),
|
||||
Menu("Options", 'o', menu3, 5),
|
||||
Menu("File", 0, 0, 'f', menu1, 4),
|
||||
Menu("Edit", 1, 0, 'e', menu2, 3),
|
||||
Menu("Options", 2, 0, 'o', menu3, 5),
|
||||
};
|
||||
|
||||
MenuBar menuBar = MenuBar(win, menus, 3); // init the menu bar
|
||||
menuBar.draw();
|
||||
Terminal terminal;
|
||||
MenuBar menuBar = MenuBar(menus,1,5,5,3);
|
||||
|
||||
while(pressed = wgetch(win))
|
||||
xMax = terminal.getXMax();
|
||||
yMax = terminal.getYMax();
|
||||
|
||||
std::string termToPrint = "Terminal with ";
|
||||
termToPrint += std::to_string(xMax);
|
||||
termToPrint += "x";
|
||||
termToPrint += std::to_string(yMax);
|
||||
termToPrint += " is drawn";
|
||||
|
||||
terminal.draw(1,1,termToPrint);
|
||||
terminal.draw(1,3,"Press f For Files e For Edit and o for Options");
|
||||
terminal.draw(1,2,"Press K to kill the menu");
|
||||
|
||||
refresh();
|
||||
menuBar.drawBox();
|
||||
menuBar.drawMenus();
|
||||
|
||||
while(pressed != 'k')
|
||||
{
|
||||
pressed = menuBar.getKey();
|
||||
menuBar.handleTrigger(pressed);
|
||||
menuBar.draw();
|
||||
menuBar.drawMenus();
|
||||
}
|
||||
menuBar.~MenuBar();
|
||||
|
||||
refresh();
|
||||
|
||||
endwin();
|
||||
terminal.draw(1,2,"Press any key to exit the application");
|
||||
terminal.getKey();
|
||||
terminal.tearDown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
#include <ncurses.h>
|
||||
#include <string>
|
||||
|
||||
#define ctrl(x) (x & 0x1F) // Detection of ctrl+x presses please do not forget that in unix ctrl+c and ctrl+z are special commands.
|
Binary file not shown.
@ -1,180 +1,174 @@
|
||||
#include <curses.h>
|
||||
#include <string>
|
||||
|
||||
#include "main.h"
|
||||
#ifndef _MENU_H_
|
||||
#define _MENU_H_
|
||||
|
||||
class Menu
|
||||
{
|
||||
public:
|
||||
Menu(std::string name, char trigger, std::string *items, int itemCount);
|
||||
void selectNextItem();
|
||||
void selectPrevItem();
|
||||
|
||||
int startX, startY;
|
||||
std::string name;
|
||||
char trigger;
|
||||
int selectedItem = 0; // alyas have the first one selected
|
||||
std::string *items;
|
||||
int itemCount=0;
|
||||
Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int itemCount);
|
||||
~Menu();
|
||||
void draw();
|
||||
void nextItem();
|
||||
void prevItem();
|
||||
int getSelectedItem();
|
||||
void setSelectedItem();
|
||||
void setPosX(int x);
|
||||
void setPosY(int y);
|
||||
int getPosX();
|
||||
int getPosY();
|
||||
void setMenuBarBegX(int x); // it must be indicated from menu bar so that we can print the box on the right place
|
||||
void setMenuBarBegY(int y); // it must be indicated from menu bar so that we can print the box on the right place
|
||||
void setMenuBarSizeX(int x); // it must be indicated from menu bar so that we can print the box on the right place
|
||||
std::string getName();
|
||||
int getNameLenght();
|
||||
int getLongestItemLenght();
|
||||
char getTrigger();
|
||||
void drawBox();
|
||||
void drawItems();
|
||||
int getBoxBegY();
|
||||
int getBoxBegX();
|
||||
void eraseBox();
|
||||
|
||||
private:
|
||||
WINDOW * menuItemsWin;
|
||||
std::string name;
|
||||
std::string *items;
|
||||
int menuNo, currPos, direction= 0;
|
||||
int posX, xSize, menuBarBegX = 0;
|
||||
int posY, ySize, menuBarBegY = 0;
|
||||
int menuBarSizeX = 0;
|
||||
int selected_item = 0;
|
||||
int itemCount = 0;
|
||||
int itemLenght = 0;
|
||||
char trigger;
|
||||
};
|
||||
|
||||
Menu::Menu(std::string name, char trigger, std::string *items, int itemCount)
|
||||
Menu::Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int itemCount)
|
||||
{
|
||||
this->name = name;
|
||||
this->trigger = trigger;
|
||||
this->items = items;
|
||||
this->itemCount = itemCount;
|
||||
this->name = name; //Name of the menu
|
||||
this->menuNo = menuNo; //No of the menu so that we can index it with the menuBar.handdleTrigger option.
|
||||
this->direction = direction; //Direction o the menu Bar Horizontal = 0, vertical = 1
|
||||
this->trigger = trigger; //The trigger for the given menu
|
||||
this->items = items; //Items present in thei menu
|
||||
this->itemCount = itemCount; //Nouber of item present in this menu
|
||||
|
||||
//To be sure
|
||||
xSize = 0;
|
||||
ySize = 0;
|
||||
selected_item = -1; // No menus are selected a the beggining
|
||||
|
||||
// Vertical Alignment
|
||||
if(direction)
|
||||
{
|
||||
}
|
||||
else // Horizontal Alignment -> The Deffault
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Menu::selectNextItem()
|
||||
Menu::~Menu()
|
||||
{
|
||||
selectedItem ++;
|
||||
if(selectedItem >= itemCount)
|
||||
{
|
||||
selectedItem = 0;
|
||||
}
|
||||
werase(menuItemsWin);
|
||||
wrefresh(menuItemsWin);
|
||||
}
|
||||
|
||||
void Menu::selectPrevItem()
|
||||
void Menu::eraseBox()
|
||||
{
|
||||
selectedItem--;
|
||||
if(selectedItem < 0)
|
||||
{
|
||||
selectedItem = itemCount-1;
|
||||
}
|
||||
werase(menuItemsWin);
|
||||
wrefresh(menuItemsWin);
|
||||
}
|
||||
|
||||
class MenuBar
|
||||
{
|
||||
public:
|
||||
MenuBar(WINDOW * win, Menu * menus, int menuCnt);
|
||||
void draw();
|
||||
void handleTrigger(char trigger);
|
||||
void reset();
|
||||
void drawMenu(Menu menu, int currIndex);
|
||||
void drawMenuItems(Menu menu);
|
||||
|
||||
WINDOW * win;
|
||||
WINDOW * menuwin;
|
||||
Menu * menus;
|
||||
int menuCnt;
|
||||
int i =0;
|
||||
int selected_menu = 90;
|
||||
int start_pos = 0;
|
||||
std::string name;
|
||||
};
|
||||
void Menu::setPosX(int x)
|
||||
{
|
||||
this->posX = x;
|
||||
}
|
||||
|
||||
void Menu::setPosY(int y)
|
||||
{
|
||||
this->posY = y;
|
||||
}
|
||||
|
||||
MenuBar::MenuBar(WINDOW * win, Menu * menus, int menuCnt)
|
||||
int Menu::getPosX()
|
||||
{
|
||||
this->win = win;
|
||||
this->menus = menus;
|
||||
this->menuCnt = menuCnt;
|
||||
int currPos = 2;
|
||||
return posX;
|
||||
}
|
||||
|
||||
int Menu::getPosY()
|
||||
{
|
||||
return posY;
|
||||
}
|
||||
|
||||
//Initialize the menu window
|
||||
int xMax, yMax, xBeg, yBeg = 0;
|
||||
getmaxyx(win, yMax, xMax);
|
||||
getbegyx(win, yBeg, xBeg);
|
||||
|
||||
menuwin = newwin(yMax-2, xMax-2, yBeg+1, xBeg+1);
|
||||
keypad(menuwin, true);
|
||||
wrefresh(menuwin);
|
||||
void Menu::setMenuBarBegX(int x)
|
||||
{
|
||||
this->menuBarBegX = x;
|
||||
}
|
||||
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
this->menus[i].startX = currPos;
|
||||
currPos += this->menus[i].name.length() + 1;
|
||||
}
|
||||
void Menu::setMenuBarBegY(int y)
|
||||
{
|
||||
this->menuBarBegY = y;
|
||||
}
|
||||
|
||||
void MenuBar::draw()
|
||||
void Menu::setMenuBarSizeX(int x)
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
drawMenu(menus[i], i);
|
||||
}
|
||||
selected_menu = -1;
|
||||
this->menuBarSizeX = x;
|
||||
}
|
||||
std::string Menu::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void MenuBar::drawMenu(Menu menu,int currIndex)
|
||||
int Menu::getNameLenght()
|
||||
{
|
||||
start_pos = menu.startX;
|
||||
name = menu.name;
|
||||
if(currIndex == selected_menu)
|
||||
{
|
||||
wattron(win, A_STANDOUT);
|
||||
}
|
||||
mvwprintw(win, 0, start_pos, name.c_str());
|
||||
wattroff(win, A_STANDOUT);
|
||||
wrefresh(win);
|
||||
return name.length();
|
||||
}
|
||||
|
||||
int ch = 0;
|
||||
|
||||
drawMenuItems(menu);
|
||||
|
||||
while(currIndex == selected_menu && (ch = wgetch(menuwin)))
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case KEY_UP:
|
||||
menu.selectPrevItem();
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
menu.selectNextItem();
|
||||
break;
|
||||
default:
|
||||
currIndex = -1;
|
||||
break;
|
||||
}
|
||||
drawMenuItems(menu);
|
||||
}
|
||||
werase(menuwin);
|
||||
wrefresh(menuwin);
|
||||
reset();
|
||||
int Menu::getLongestItemLenght()
|
||||
{
|
||||
return xSize;
|
||||
}
|
||||
|
||||
void MenuBar::drawMenuItems(Menu menu)
|
||||
char Menu::getTrigger()
|
||||
{
|
||||
int yMax, xMax;
|
||||
getmaxyx(menuwin, yMax, xMax);
|
||||
return trigger;
|
||||
}
|
||||
|
||||
for(i=0; i < menu.itemCount ; i ++)
|
||||
{
|
||||
mvwprintw(menuwin,i,0,menu.items[i].c_str());
|
||||
if(menu.selectedItem == i)
|
||||
{
|
||||
//if selected change to color pair 1
|
||||
mvwchgat(menuwin,i,0,xMax,A_NORMAL,1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not selected but we still want it to be reversed
|
||||
mvwchgat(menuwin,i,0,xMax,A_STANDOUT,0, NULL);
|
||||
}
|
||||
int Menu::getBoxBegX()
|
||||
{
|
||||
// Vertical Alignment
|
||||
if(direction)
|
||||
{
|
||||
}
|
||||
else // Horizontal Alignment -> The Deffault
|
||||
{
|
||||
return menuBarSizeX+posX+menuBarBegX-1;
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::reset()
|
||||
int Menu::getBoxBegY()
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
start_pos = this->menus[i].startX;
|
||||
name = this->menus[i].name;
|
||||
mvwprintw(win, 0, start_pos, name.c_str());
|
||||
// Vertical Alignment
|
||||
if(direction)
|
||||
{
|
||||
}
|
||||
wrefresh(win);
|
||||
else // Horizontal Alignment -> The Deffault
|
||||
{
|
||||
return posY+menuBarBegY-1;
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::handleTrigger(char trigger)
|
||||
void Menu::drawBox()
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
if(trigger == this->menus[i].trigger)
|
||||
{
|
||||
selected_menu = i;
|
||||
}
|
||||
}
|
||||
// Creates a box with caclulated dimention xSize & ySize and user given position
|
||||
menuItemsWin = newwin(20, 20, getBoxBegY(), getBoxBegX());
|
||||
box(menuItemsWin ,0,0); //Here we can define other cahr insterad of 0,0
|
||||
mvwprintw(menuItemsWin,1,1,"PosY:%d PosX:%d",getBoxBegY(), getBoxBegX());
|
||||
wrefresh(menuItemsWin); //Refresh so that we can see it
|
||||
}
|
||||
|
||||
void Menu::drawItems()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,174 @@
|
||||
#include "main.h"
|
||||
#include "menu.h"
|
||||
|
||||
#ifndef _MENU_BAR_H_
|
||||
#define _MENU_BAR_H_
|
||||
|
||||
class MenuBar
|
||||
{
|
||||
public:
|
||||
MenuBar(Menu *menus, int direction, int xBeg, int yBeg, int menuCount);
|
||||
~MenuBar();
|
||||
void drawBox();
|
||||
void drawMenus();
|
||||
void handleTrigger(char trig);
|
||||
char getKey();
|
||||
void reset();
|
||||
int getPosX();
|
||||
int getPosY();
|
||||
int getSizeX();
|
||||
int getSizeY();
|
||||
private:
|
||||
int i, xSize, ySize, xBeg, yBeg, menuCount, direction, currPos = 0;
|
||||
int selected_menu = -1;
|
||||
int prevSelected_menu = -1;
|
||||
char currIndex;
|
||||
Menu *menus;
|
||||
WINDOW *menuBarWin;
|
||||
};
|
||||
|
||||
MenuBar::MenuBar(Menu *menus, int direction, int xBeg, int yBeg, int menuCount)
|
||||
{
|
||||
this->menus = menus; // All the menu class
|
||||
this->direction = direction; // Direction o the menu Bar Horizontal = 0, vertical = 1
|
||||
this->xSize = xSize; // Size x of the menuBar box
|
||||
this->ySize = ySize; // Size y of the menuBar box
|
||||
this->xBeg = xBeg; // beginnin x Coordinate for the menuBar Box
|
||||
this->yBeg = yBeg; // beginnin y Coordinate for the menuBar Box
|
||||
this->menuCount = menuCount; // Total Menu class element count
|
||||
|
||||
// Jsut to be sure
|
||||
xSize = 0;
|
||||
ySize = 0;
|
||||
selected_menu = -1; // No menus are selected a the beggining
|
||||
|
||||
|
||||
// Vertical Alignment
|
||||
if(direction)
|
||||
{
|
||||
currPos = 1; // So that it doesn write the first item on the top border
|
||||
// Finding the longest word between the disponible menus
|
||||
for(i = 0; i < menuCount ; i ++)
|
||||
{
|
||||
if(xSize < this->menus[i].getNameLenght())
|
||||
{
|
||||
xSize = this->menus[i].getNameLenght()+2; // +1 for left +1 lor right = +2
|
||||
}
|
||||
}
|
||||
|
||||
// Defining vertical separations
|
||||
for(i = 0; i < menuCount ; i ++)
|
||||
{
|
||||
this->menus[i].setPosY(currPos);
|
||||
this->menus[i].setPosX(1); // So tha it write in the middle
|
||||
currPos ++;
|
||||
|
||||
this->menus[i].setMenuBarBegX(xBeg);
|
||||
this->menus[i].setMenuBarBegY(yBeg);
|
||||
this->menus[i].setMenuBarSizeX(xSize);
|
||||
}
|
||||
ySize = menuCount + 2;
|
||||
}
|
||||
else // Horizontal Alignment -> The Deffault
|
||||
{
|
||||
currPos = 1; // So that it doesn write the first item on the left border
|
||||
for(i = 0; i < menuCount ; i ++) // Defining horizontal distances
|
||||
{
|
||||
this->menus[i].setPosX(currPos);
|
||||
this->menus[i].setPosY(1); // So tha it write in the middle
|
||||
currPos += this->menus[i].getNameLenght() + 1;
|
||||
|
||||
this->menus[i].setMenuBarBegX(xBeg);
|
||||
this->menus[i].setMenuBarBegY(yBeg);
|
||||
this->menus[i].setMenuBarSizeX(xSize);
|
||||
}
|
||||
xSize = currPos;
|
||||
ySize = 3;
|
||||
}
|
||||
}
|
||||
|
||||
MenuBar::~MenuBar()
|
||||
{
|
||||
werase(menuBarWin);
|
||||
wrefresh(menuBarWin);
|
||||
}
|
||||
|
||||
void MenuBar::drawBox()
|
||||
{
|
||||
// Creates a box with caclulated dimention xSize & ySize and user given position
|
||||
menuBarWin = newwin(ySize, xSize, yBeg, xBeg);
|
||||
box(menuBarWin,0,0); //Here we can define other cahr insterad of 0,0
|
||||
wrefresh(menuBarWin); //Refresh so that we can see it
|
||||
}
|
||||
|
||||
// Draws menus and highlight the selected one selection in made on the handdleTrigger() Function
|
||||
void MenuBar::drawMenus()
|
||||
{
|
||||
for(i = 0; i < menuCount ; i ++)
|
||||
{
|
||||
if(i == selected_menu) // If the iterration come to the selected menu than it will highlight it
|
||||
{
|
||||
prevSelected_menu = i;
|
||||
wattron(menuBarWin, A_STANDOUT);
|
||||
mvwprintw(menuBarWin, menus[i].getPosY(),menus[i].getPosX(), menus[i].getName().c_str());
|
||||
wattroff(menuBarWin, A_STANDOUT);
|
||||
menus[i].drawBox(); // Draws the lesefted Menus Items
|
||||
}
|
||||
else // Otherwise do not hightlight
|
||||
{
|
||||
mvwprintw(menuBarWin, menus[i].getPosY(),menus[i].getPosX(), menus[i].getName().c_str());
|
||||
}
|
||||
}
|
||||
selected_menu = - 1; // Deselect for the next itteration. (unless handleTrigger has a new trigger)
|
||||
wrefresh(menuBarWin); // so we can see it
|
||||
}
|
||||
|
||||
// recieves a char an checks it fo ot corrensponds to a Menu Trigger
|
||||
void MenuBar::handleTrigger(char trig)
|
||||
{
|
||||
for(i = 0; i < menuCount ; i ++)
|
||||
{
|
||||
if(trig == this->menus[i].getTrigger()) // If the recieved trigger matches the one from a menu
|
||||
{
|
||||
selected_menu = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char MenuBar::getKey()
|
||||
{
|
||||
return wgetch(menuBarWin);
|
||||
}
|
||||
|
||||
// Will draw the menu as for the first time
|
||||
void MenuBar::reset()
|
||||
{
|
||||
for(i = 0; i < menuCount ; i ++)
|
||||
{
|
||||
mvwprintw(menuBarWin, menus[i].getPosY(),menus[i].getPosX(), menus[i].getName().c_str());
|
||||
}
|
||||
selected_menu = - 1; // Deselect for the next itteration. (unless handleTrigger has a new trigger)
|
||||
wrefresh(menuBarWin); // so we can see it
|
||||
}
|
||||
|
||||
int MenuBar::getPosX()
|
||||
{
|
||||
return xBeg;
|
||||
}
|
||||
|
||||
int MenuBar::getPosY()
|
||||
{
|
||||
return yBeg;
|
||||
}
|
||||
|
||||
int MenuBar::getSizeX()
|
||||
{
|
||||
return xSize;
|
||||
}
|
||||
|
||||
int MenuBar::getSizeY()
|
||||
{
|
||||
return ySize;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,110 @@
|
||||
#include "main.h"
|
||||
|
||||
#ifndef _TEMINAL_H_
|
||||
#define _TEMINAL_H_
|
||||
|
||||
|
||||
// This calls is used to initilaize ncurses terminal the correct way depending of the terminalk
|
||||
class Terminal
|
||||
{
|
||||
public:
|
||||
// Constuctor & Destructor
|
||||
Terminal();
|
||||
~Terminal();
|
||||
|
||||
//Functions
|
||||
int setup();
|
||||
void tearDown();
|
||||
int getKey();
|
||||
int getXMax();
|
||||
int getYMax();
|
||||
void startDraw();
|
||||
void endDraw();
|
||||
bool isDone();
|
||||
void quit();
|
||||
void draw(int x, int y, const std::string& toDraw);
|
||||
|
||||
private:
|
||||
int xMax, yMax, mouseX, mouseY = 0;
|
||||
bool m_done = false;
|
||||
};
|
||||
|
||||
|
||||
Terminal::Terminal()
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
Terminal::~Terminal()
|
||||
{
|
||||
tearDown();
|
||||
}
|
||||
|
||||
int Terminal::setup()
|
||||
{
|
||||
initscr(); // Inits ncurses screen in memory
|
||||
raw(); // raw input sor ctrl-c and ctrl-z wont work
|
||||
noecho(); // don't show the user inputs
|
||||
curs_set(0); // Cursor won't show up
|
||||
getmaxyx(stdscr, yMax, xMax);
|
||||
box(stdscr,0,0);
|
||||
if(!has_colors()) // If the terminal doesn't have colors
|
||||
{
|
||||
tearDown(); // Destroys the mains window
|
||||
printf("This menu is not supported by terminals without colors\n");
|
||||
return -1; // Return an error.
|
||||
}
|
||||
|
||||
getyx(stdscr, mouseY, mouseX);
|
||||
start_color(); // Otherwise init colors
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Terminal::tearDown()
|
||||
{
|
||||
endwin();
|
||||
}
|
||||
|
||||
|
||||
int Terminal::getKey()
|
||||
{
|
||||
return getch();
|
||||
}
|
||||
|
||||
int Terminal::getXMax()
|
||||
{
|
||||
return xMax;
|
||||
}
|
||||
|
||||
int Terminal::getYMax()
|
||||
{
|
||||
return yMax;
|
||||
}
|
||||
|
||||
void Terminal::startDraw()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void Terminal::endDraw()
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
bool Terminal::isDone()
|
||||
{
|
||||
return m_done;
|
||||
}
|
||||
|
||||
void Terminal::quit()
|
||||
{
|
||||
m_done = true;
|
||||
}
|
||||
|
||||
void Terminal::draw(int x, int y, const std::string& toDraw)
|
||||
{
|
||||
mvprintw(y,x,toDraw.c_str());
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm menu
|
||||
|
||||
g++ main.cpp -o menu -lncurses
|
||||
|
||||
./menu
|
@ -0,0 +1,58 @@
|
||||
#include <ncurses.h>
|
||||
#include "menu.h"
|
||||
|
||||
#define ctrl(x) (x & 0x1F) // Detection of ctrl+x presses please do not forget that in unix ctrl+c and ctrl+z are special commands.
|
||||
|
||||
// INFO: wgetch(win); or getch(); // getch will make a refresh for us.
|
||||
|
||||
int main(int argv, char ** argc)
|
||||
{
|
||||
//Variables
|
||||
int xMax, yMax = 0;
|
||||
char pressed;
|
||||
|
||||
j
|
||||
//Init Ncurses
|
||||
initscr();
|
||||
|
||||
if(has_colors() == false) // If the terminal does have colors
|
||||
{
|
||||
printf("This menu is not supported by terminals without colors\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
start_color();
|
||||
|
||||
noecho();
|
||||
curs_set(0); // Cursor won't show up
|
||||
getmaxyx(stdscr, yMax, xMax);
|
||||
// size y size x pos y pos x
|
||||
WINDOW *win = newwin(yMax/2, xMax/2, yMax/4, xMax/4);
|
||||
box(win,0,0);
|
||||
|
||||
//Setc colors
|
||||
init_pair(1, COLOR_WHITE, COLOR_BLUE);
|
||||
|
||||
std::string menu1[4]={"New","Open","Save","Exit"};
|
||||
std::string menu2[3]={"Copy","Cut","Paste"};
|
||||
std::string menu3[5]={"Terminal","Help","Info","Update","Manual"};
|
||||
|
||||
// Second stage declarations
|
||||
Menu menus[3]={ // init the menus
|
||||
Menu("File", 'f', menu1, 4),
|
||||
Menu("Edit", 'e', menu2, 3),
|
||||
Menu("Options", 'o', menu3, 5),
|
||||
};
|
||||
|
||||
MenuBar menuBar = MenuBar(win, menus, 3); // init the menu bar
|
||||
menuBar.draw();
|
||||
|
||||
while(pressed = wgetch(win))
|
||||
{
|
||||
menuBar.handleTrigger(pressed);
|
||||
menuBar.draw();
|
||||
}
|
||||
|
||||
endwin();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
#include <curses.h>
|
||||
#include <string>
|
||||
|
||||
#ifndef _MENU_H_
|
||||
#define _MENU_H_
|
||||
|
||||
class Menu
|
||||
{
|
||||
public:
|
||||
Menu(std::string name, char trigger, std::string *items, int itemCount);
|
||||
void selectNextItem();
|
||||
void selectPrevItem();
|
||||
|
||||
int startX, startY;
|
||||
std::string name;
|
||||
char trigger;
|
||||
int selectedItem = 0; // alyas have the first one selected
|
||||
std::string *items;
|
||||
int itemCount=0;
|
||||
};
|
||||
|
||||
Menu::Menu(std::string name, char trigger, std::string *items, int itemCount)
|
||||
{
|
||||
this->name = name;
|
||||
this->trigger = trigger;
|
||||
this->items = items;
|
||||
this->itemCount = itemCount;
|
||||
}
|
||||
|
||||
void Menu::selectNextItem()
|
||||
{
|
||||
selectedItem ++;
|
||||
if(selectedItem >= itemCount)
|
||||
{
|
||||
selectedItem = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::selectPrevItem()
|
||||
{
|
||||
selectedItem--;
|
||||
if(selectedItem < 0)
|
||||
{
|
||||
selectedItem = itemCount-1;
|
||||
}
|
||||
}
|
||||
|
||||
class MenuBar
|
||||
{
|
||||
public:
|
||||
MenuBar(WINDOW * win, Menu * menus, int menuCnt);
|
||||
void draw();
|
||||
void handleTrigger(char trigger);
|
||||
void reset();
|
||||
void drawMenu(Menu menu, int currIndex);
|
||||
void drawMenuItems(Menu menu);
|
||||
|
||||
WINDOW * win;
|
||||
WINDOW * menuwin;
|
||||
Menu * menus;
|
||||
int menuCnt;
|
||||
int i =0;
|
||||
int selected_menu = 90;
|
||||
int start_pos = 0;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
MenuBar::MenuBar(WINDOW * win, Menu * menus, int menuCnt)
|
||||
{
|
||||
this->win = win;
|
||||
this->menus = menus;
|
||||
this->menuCnt = menuCnt;
|
||||
int currPos = 2;
|
||||
|
||||
//Initialize the menu window
|
||||
int xMax, yMax, xBeg, yBeg = 0;
|
||||
getmaxyx(win, yMax, xMax);
|
||||
getbegyx(win, yBeg, xBeg);
|
||||
|
||||
menuwin = newwin(yMax-2, xMax-2, yBeg+1, xBeg+1);
|
||||
keypad(menuwin, true);
|
||||
wrefresh(menuwin);
|
||||
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
this->menus[i].startX = currPos;
|
||||
currPos += this->menus[i].name.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::draw()
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
drawMenu(menus[i], i);
|
||||
}
|
||||
selected_menu = -1;
|
||||
}
|
||||
|
||||
void MenuBar::drawMenu(Menu menu,int currIndex)
|
||||
{
|
||||
start_pos = menu.startX;
|
||||
name = menu.name;
|
||||
if(currIndex == selected_menu)
|
||||
{
|
||||
wattron(win, A_STANDOUT);
|
||||
}
|
||||
mvwprintw(win, 0, start_pos, name.c_str());
|
||||
wattroff(win, A_STANDOUT);
|
||||
wrefresh(win);
|
||||
|
||||
int ch = 0;
|
||||
|
||||
drawMenuItems(menu);
|
||||
|
||||
while(currIndex == selected_menu && (ch = wgetch(menuwin)))
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case KEY_UP:
|
||||
menu.selectPrevItem();
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
menu.selectNextItem();
|
||||
break;
|
||||
default:
|
||||
currIndex = -1;
|
||||
break;
|
||||
}
|
||||
drawMenuItems(menu);
|
||||
}
|
||||
werase(menuwin);
|
||||
wrefresh(menuwin);
|
||||
reset();
|
||||
}
|
||||
|
||||
void MenuBar::drawMenuItems(Menu menu)
|
||||
{
|
||||
int yMax, xMax;
|
||||
getmaxyx(menuwin, yMax, xMax);
|
||||
|
||||
for(i=0; i < menu.itemCount ; i ++)
|
||||
{
|
||||
mvwprintw(menuwin,i,0,menu.items[i].c_str());
|
||||
if(menu.selectedItem == i)
|
||||
{
|
||||
//if selected change to color pair 1
|
||||
mvwchgat(menuwin,i,0,xMax,A_NORMAL,1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not selected but we still want it to be reversed
|
||||
mvwchgat(menuwin,i,0,xMax,A_STANDOUT,0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::reset()
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
start_pos = this->menus[i].startX;
|
||||
name = this->menus[i].name;
|
||||
mvwprintw(win, 0, start_pos, name.c_str());
|
||||
}
|
||||
wrefresh(win);
|
||||
}
|
||||
|
||||
void MenuBar::handleTrigger(char trigger)
|
||||
{
|
||||
for(i = 0; i < menuCnt ; i ++)
|
||||
{
|
||||
if(trigger == this->menus[i].trigger)
|
||||
{
|
||||
selected_menu = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm ./menu
|
||||
|
||||
gcc main.c -o menu -lncurses
|
||||
|
||||
./menu
|
@ -0,0 +1,108 @@
|
||||
#include <ncurses.h>
|
||||
#include <string.h>
|
||||
#include <menu.h>
|
||||
#include <stdlib.h>
|
||||
#define WIDTH 30
|
||||
#define HEIGHT 10
|
||||
|
||||
int startx = 0;
|
||||
int starty = 0;
|
||||
|
||||
char *choices[] = { "Choice 1",
|
||||
"Choice 2",
|
||||
"Choice 3",
|
||||
"Choice 4",
|
||||
"Exit",
|
||||
};
|
||||
|
||||
int n_choices = sizeof(choices) / sizeof(char *);
|
||||
|
||||
void print_menu(WINDOW *menu_win, int highlight);
|
||||
void report_choice(int mouse_x, int mouse_y, int *p_choice);
|
||||
|
||||
int main()
|
||||
{ int c, choice = 0;
|
||||
WINDOW *menu_win;
|
||||
MEVENT event;
|
||||
|
||||
/* Initialize curses */
|
||||
initscr();
|
||||
clear();
|
||||
noecho();
|
||||
cbreak(); //Line buffering disabled. pass on everything
|
||||
|
||||
/* Try to put the window in the middle of screen */
|
||||
startx = (80 - WIDTH) / 2;
|
||||
starty = (24 - HEIGHT) / 2;
|
||||
|
||||
attron(A_REVERSE);
|
||||
mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
|
||||
refresh();
|
||||
attroff(A_REVERSE);
|
||||
|
||||
/* Print the menu for the first time */
|
||||
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
|
||||
print_menu(menu_win, 1);
|
||||
/* Get all the mouse events */
|
||||
mousemask(ALL_MOUSE_EVENTS, NULL);
|
||||
|
||||
while(1)
|
||||
{ c = wgetch(menu_win);
|
||||
switch(c)
|
||||
{ case KEY_MOUSE:
|
||||
if(getmouse(&event) == OK)
|
||||
{ /* When the user clicks left mouse button */
|
||||
if(event.bstate & BUTTON1_PRESSED)
|
||||
{ report_choice(event.x + 1, event.y + 1, &choice);
|
||||
if(choice == -1) //Exit chosen
|
||||
goto end;
|
||||
mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
print_menu(menu_win, choice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
endwin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void print_menu(WINDOW *menu_win, int highlight)
|
||||
{
|
||||
int x, y, i;
|
||||
|
||||
x = 2;
|
||||
y = 2;
|
||||
box(menu_win, 0, 0);
|
||||
for(i = 0; i < n_choices; ++i)
|
||||
{ if(highlight == i + 1)
|
||||
{ wattron(menu_win, A_REVERSE);
|
||||
mvwprintw(menu_win, y, x, "%s", choices[i]);
|
||||
wattroff(menu_win, A_REVERSE);
|
||||
}
|
||||
else
|
||||
mvwprintw(menu_win, y, x, "%s", choices[i]);
|
||||
++y;
|
||||
}
|
||||
wrefresh(menu_win);
|
||||
}
|
||||
|
||||
/* Report the choice according to mouse position */
|
||||
void report_choice(int mouse_x, int mouse_y, int *p_choice)
|
||||
{ int i,j, choice;
|
||||
|
||||
i = startx + 2;
|
||||
j = starty + 3;
|
||||
|
||||
for(choice = 0; choice < n_choices; ++choice)
|
||||
if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice]))
|
||||
{ if(choice == n_choices - 1)
|
||||
*p_choice = -1;
|
||||
else
|
||||
*p_choice = choice + 1;
|
||||
break;
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,102 @@
|
||||
#ifndef _PLAYER_H_
|
||||
#define _PLAYER_H_
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
Player(WINDOW* win, int y, int x, char c);
|
||||
void mvUp();
|
||||
void mvDown();
|
||||
void mvLeft();
|
||||
void mvRight();
|
||||
int getMv();
|
||||
void display();
|
||||
|
||||
private:
|
||||
int xLoc, yLoc, xMax, yMax;
|
||||
char playerChar;
|
||||
WINDOW * curWin;
|
||||
};
|
||||
|
||||
|
||||
Player::Player(WINDOW* win, int y, int x, char c)
|
||||
{
|
||||
curWin = win;
|
||||
xLoc = x;
|
||||
yLoc = y;
|
||||
getmaxyx(curWin, yMax, xMax);
|
||||
keypad(curWin, true);
|
||||
playerChar = c;
|
||||
}
|
||||
|
||||
void Player::mvUp()
|
||||
{
|
||||
mvwaddch(curWin,yLoc, xLoc, '.');
|
||||
yLoc --;
|
||||
if(yLoc < 1)
|
||||
{
|
||||
yLoc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::mvDown()
|
||||
{
|
||||
mvwaddch(curWin,yLoc, xLoc, '.');
|
||||
yLoc ++;
|
||||
if(yLoc > yMax-2)
|
||||
{
|
||||
yLoc = yMax-2;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::mvLeft()
|
||||
{
|
||||
mvwaddch(curWin,yLoc, xLoc, '.');
|
||||
xLoc --;
|
||||
if(xLoc < 1)
|
||||
{
|
||||
xLoc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::mvRight()
|
||||
{
|
||||
mvwaddch(curWin,yLoc, xLoc, '.');
|
||||
xLoc ++;
|
||||
if(xLoc > xMax-2)
|
||||
{
|
||||
xLoc = xMax-2;
|
||||
}
|
||||
}
|
||||
|
||||
int Player::getMv()
|
||||
{
|
||||
int choice = wgetch(curWin);
|
||||
switch(choice)
|
||||
{
|
||||
case KEY_UP:
|
||||
mvUp();
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
mvDown();
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
mvLeft();
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
mvRight();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
void Player::display()
|
||||
{
|
||||
mvwaddch(curWin,yLoc, xLoc, playerChar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in new issue