parent
e51885a007
commit
225871dba4
@ -1,5 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
|
rm menu
|
||||||
|
|
||||||
g++ main.cpp -o menu -lncurses
|
g++ main.cpp -o menu -lncurses
|
||||||
|
|
||||||
./menu
|
./menu
|
||||||
|
@ -1,58 +1,60 @@
|
|||||||
#include <ncurses.h>
|
#include "main.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.
|
#include "terminal.h"
|
||||||
|
#include "menuBar.h"
|
||||||
|
|
||||||
// INFO: wgetch(win); or getch(); // getch will make a refresh for us.
|
// INFO: wgetch(win); or getch(); // getch will make a refresh for us.
|
||||||
|
|
||||||
int main(int argv, char ** argc)
|
int main(int argv, char ** argc)
|
||||||
{
|
{
|
||||||
//Variables
|
//Variables
|
||||||
int xMax, yMax = 0;
|
int xMax, yMax, xMouse, yMouse= 0;
|
||||||
char pressed;
|
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 menu1[4]={"New","Open","Save","Exit"};
|
||||||
std::string menu2[3]={"Copy","Cut","Paste"};
|
std::string menu2[3]={"Copy","Cut","Paste"};
|
||||||
std::string menu3[5]={"Terminal","Help","Info","Update","Manual"};
|
std::string menu3[5]={"Terminal","Help","Info","Update","Manual"};
|
||||||
|
|
||||||
// Second stage declarations
|
// Second stage declarations
|
||||||
Menu menus[3]={ // init the menus
|
Menu menus[3]={ // init the menus
|
||||||
Menu("File", 'f', menu1, 4),
|
Menu("File", 0, 0, 'f', menu1, 4),
|
||||||
Menu("Edit", 'e', menu2, 3),
|
Menu("Edit", 1, 0, 'e', menu2, 3),
|
||||||
Menu("Options", 'o', menu3, 5),
|
Menu("Options", 2, 0, 'o', menu3, 5),
|
||||||
};
|
};
|
||||||
|
|
||||||
MenuBar menuBar = MenuBar(win, menus, 3); // init the menu bar
|
Terminal terminal;
|
||||||
menuBar.draw();
|
MenuBar menuBar = MenuBar(menus,1,5,5,3);
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
while(pressed = wgetch(win))
|
refresh();
|
||||||
|
menuBar.drawBox();
|
||||||
|
menuBar.drawMenus();
|
||||||
|
|
||||||
|
while(pressed != 'k')
|
||||||
{
|
{
|
||||||
|
pressed = menuBar.getKey();
|
||||||
menuBar.handleTrigger(pressed);
|
menuBar.handleTrigger(pressed);
|
||||||
menuBar.draw();
|
menuBar.drawMenus();
|
||||||
}
|
}
|
||||||
|
menuBar.~MenuBar();
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
terminal.draw(1,2,"Press any key to exit the application");
|
||||||
|
terminal.getKey();
|
||||||
|
terminal.tearDown();
|
||||||
|
|
||||||
endwin();
|
|
||||||
return 0;
|
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 "main.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifndef _MENU_H_
|
#ifndef _MENU_H_
|
||||||
#define _MENU_H_
|
#define _MENU_H_
|
||||||
|
|
||||||
class Menu
|
class Menu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Menu(std::string name, char trigger, std::string *items, int itemCount);
|
Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int itemCount);
|
||||||
void selectNextItem();
|
~Menu();
|
||||||
void selectPrevItem();
|
void draw();
|
||||||
|
void nextItem();
|
||||||
int startX, startY;
|
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 name;
|
||||||
char trigger;
|
|
||||||
int selectedItem = 0; // alyas have the first one selected
|
|
||||||
std::string *items;
|
std::string *items;
|
||||||
int itemCount=0;
|
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->name = name; //Name of the menu
|
||||||
this->trigger = trigger;
|
this->menuNo = menuNo; //No of the menu so that we can index it with the menuBar.handdleTrigger option.
|
||||||
this->items = items;
|
this->direction = direction; //Direction o the menu Bar Horizontal = 0, vertical = 1
|
||||||
this->itemCount = itemCount;
|
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
|
||||||
void Menu::selectNextItem()
|
|
||||||
{
|
//To be sure
|
||||||
selectedItem ++;
|
xSize = 0;
|
||||||
if(selectedItem >= itemCount)
|
ySize = 0;
|
||||||
|
selected_item = -1; // No menus are selected a the beggining
|
||||||
|
|
||||||
|
// Vertical Alignment
|
||||||
|
if(direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else // Horizontal Alignment -> The Deffault
|
||||||
{
|
{
|
||||||
selectedItem = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::selectPrevItem()
|
Menu::~Menu()
|
||||||
{
|
{
|
||||||
selectedItem--;
|
werase(menuItemsWin);
|
||||||
if(selectedItem < 0)
|
wrefresh(menuItemsWin);
|
||||||
{
|
|
||||||
selectedItem = itemCount-1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuBar
|
void Menu::eraseBox()
|
||||||
{
|
{
|
||||||
public:
|
werase(menuItemsWin);
|
||||||
MenuBar(WINDOW * win, Menu * menus, int menuCnt);
|
wrefresh(menuItemsWin);
|
||||||
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)
|
void Menu::setPosX(int x)
|
||||||
{
|
{
|
||||||
this->win = win;
|
this->posX = x;
|
||||||
this->menus = menus;
|
}
|
||||||
this->menuCnt = menuCnt;
|
|
||||||
int currPos = 2;
|
|
||||||
|
|
||||||
//Initialize the menu window
|
void Menu::setPosY(int y)
|
||||||
int xMax, yMax, xBeg, yBeg = 0;
|
{
|
||||||
getmaxyx(win, yMax, xMax);
|
this->posY = y;
|
||||||
getbegyx(win, yBeg, xBeg);
|
}
|
||||||
|
|
||||||
menuwin = newwin(yMax-2, xMax-2, yBeg+1, xBeg+1);
|
int Menu::getPosX()
|
||||||
keypad(menuwin, true);
|
{
|
||||||
wrefresh(menuwin);
|
return posX;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < menuCnt ; i ++)
|
int Menu::getPosY()
|
||||||
{
|
{
|
||||||
this->menus[i].startX = currPos;
|
return posY;
|
||||||
currPos += this->menus[i].name.length() + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::draw()
|
void Menu::setMenuBarBegX(int x)
|
||||||
{
|
{
|
||||||
for(i = 0; i < menuCnt ; i ++)
|
this->menuBarBegX = x;
|
||||||
{
|
|
||||||
drawMenu(menus[i], i);
|
|
||||||
}
|
|
||||||
selected_menu = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::drawMenu(Menu menu,int currIndex)
|
void Menu::setMenuBarBegY(int y)
|
||||||
{
|
{
|
||||||
start_pos = menu.startX;
|
this->menuBarBegY = y;
|
||||||
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;
|
void Menu::setMenuBarSizeX(int x)
|
||||||
|
{
|
||||||
|
this->menuBarSizeX = x;
|
||||||
|
}
|
||||||
|
std::string Menu::getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
drawMenuItems(menu);
|
int Menu::getNameLenght()
|
||||||
|
{
|
||||||
|
return name.length();
|
||||||
|
}
|
||||||
|
|
||||||
while(currIndex == selected_menu && (ch = wgetch(menuwin)))
|
int Menu::getLongestItemLenght()
|
||||||
{
|
{
|
||||||
switch(ch)
|
return xSize;
|
||||||
{
|
|
||||||
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)
|
char Menu::getTrigger()
|
||||||
{
|
{
|
||||||
int yMax, xMax;
|
return trigger;
|
||||||
getmaxyx(menuwin, yMax, xMax);
|
}
|
||||||
|
|
||||||
for(i=0; i < menu.itemCount ; i ++)
|
int Menu::getBoxBegX()
|
||||||
|
{
|
||||||
|
// Vertical Alignment
|
||||||
|
if(direction)
|
||||||
{
|
{
|
||||||
mvwprintw(menuwin,i,0,menu.items[i].c_str());
|
}
|
||||||
if(menu.selectedItem == i)
|
else // Horizontal Alignment -> The Deffault
|
||||||
{
|
{
|
||||||
//if selected change to color pair 1
|
return menuBarSizeX+posX+menuBarBegX-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()
|
int Menu::getBoxBegY()
|
||||||
{
|
{
|
||||||
for(i = 0; i < menuCnt ; i ++)
|
// Vertical Alignment
|
||||||
|
if(direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else // Horizontal Alignment -> The Deffault
|
||||||
{
|
{
|
||||||
start_pos = this->menus[i].startX;
|
return posY+menuBarBegY-1;
|
||||||
name = this->menus[i].name;
|
|
||||||
mvwprintw(win, 0, start_pos, name.c_str());
|
|
||||||
}
|
}
|
||||||
wrefresh(win);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::handleTrigger(char trigger)
|
void Menu::drawBox()
|
||||||
{
|
{
|
||||||
for(i = 0; i < menuCnt ; i ++)
|
// Creates a box with caclulated dimention xSize & ySize and user given position
|
||||||
{
|
menuItemsWin = newwin(20, 20, getBoxBegY(), getBoxBegX());
|
||||||
if(trigger == this->menus[i].trigger)
|
box(menuItemsWin ,0,0); //Here we can define other cahr insterad of 0,0
|
||||||
{
|
mvwprintw(menuItemsWin,1,1,"PosY:%d PosX:%d",getBoxBegY(), getBoxBegX());
|
||||||
selected_menu = i;
|
wrefresh(menuItemsWin); //Refresh so that we can see it
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void Menu::drawItems()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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