Redesigning the menu interface to be modular

interrupts
key 3 years ago
parent 225871dba4
commit 2f515e26df

@ -0,0 +1,60 @@
#include "main.h"
#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, xMouse, yMouse= 0;
char pressed;
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", 0, 0, 'f', menu1, 4),
Menu("Edit", 1, 0, 'e', menu2, 3),
Menu("Options", 2, 0, 'o', menu3, 5),
};
Terminal terminal;
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");
terminal.endDraw();
menuBar.drawBox();
menuBar.drawMenus();
while(pressed != 'k')
{
pressed = menuBar.getKey();
menuBar.handleTrigger(pressed);
menuBar.drawMenus();
terminal.endDraw();
}
menuBar.~MenuBar();
terminal.draw(1,2,"Press any key to exit the application");
terminal.endDraw();
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.

@ -0,0 +1,194 @@
#include "main.h"
#ifndef _MENU_H_
#define _MENU_H_
class Menu
{
public:
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();
bool isBoxCreated();
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;
bool boxIsCreated = false;
};
Menu::Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int 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
boxIsCreated = false;
// Vertical Alignment
if(direction)
{
}
else // Horizontal Alignment -> The Deffault
{
}
}
Menu::~Menu()
{
werase(menuItemsWin);
wclear(menuItemsWin);
wrefresh(menuItemsWin);
boxIsCreated = false;
}
void Menu::eraseBox()
{
werase(menuItemsWin);
wclear(menuItemsWin);
wrefresh(menuItemsWin);
boxIsCreated = false;
}
void Menu::setPosX(int x)
{
this->posX = x;
}
void Menu::setPosY(int y)
{
this->posY = y;
}
int Menu::getPosX()
{
return posX;
}
int Menu::getPosY()
{
return posY;
}
void Menu::setMenuBarBegX(int x)
{
this->menuBarBegX = x;
}
void Menu::setMenuBarBegY(int y)
{
this->menuBarBegY = y;
}
void Menu::setMenuBarSizeX(int x)
{
this->menuBarSizeX = x;
}
std::string Menu::getName()
{
return name;
}
int Menu::getNameLenght()
{
return name.length();
}
int Menu::getLongestItemLenght()
{
return xSize;
}
char Menu::getTrigger()
{
return trigger;
}
int Menu::getBoxBegX()
{
// Vertical Alignment
if(direction)
{
return menuBarSizeX+posX+menuBarBegX-1;
}
else // Horizontal Alignment -> The Deffault
{
return menuBarSizeX+posX+menuBarBegX-1;
}
return -1;
}
int Menu::getBoxBegY()
{
// Vertical Alignment
if(direction)
{
return posY+menuBarBegY-1;
}
else // Horizontal Alignment -> The Deffault
{
return posY+menuBarBegY-1;
}
return -1;
}
bool Menu::isBoxCreated()
{
return boxIsCreated;
}
void Menu::drawBox()
{
// Creates a box with caclulated dimention xSize & ySize and user given position
/*menuItemsWin = newwin(20, 20, getBoxBegY(), getBoxBegX());
boxIsCreated = true;
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

@ -41,6 +41,7 @@ MenuBar::MenuBar(Menu *menus, int direction, int xBeg, int yBeg, int menuCount)
xSize = 0;
ySize = 0;
selected_menu = -1; // No menus are selected a the beggining
prevSelected_menu = - 1; // Deselect for the next itteration. (unless handleTrigger has a new trigger)
// Vertical Alignment
@ -112,14 +113,19 @@ void MenuBar::drawMenus()
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
//menus[i].drawBox(); // Draws the lesefted Menus Items
}
else // Otherwise do not hightlight
{
if(menus[i].isBoxCreated())
{
//menus[i].eraseBox(); // Draws the lesefted Menus Items
}
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)
prevSelected_menu = - 1; // Deselect for the next itteration. (unless handleTrigger has a new trigger)
wrefresh(menuBarWin); // so we can see it
}

@ -0,0 +1,194 @@
#include "main.h"
#ifndef _MENU_H_
#define _MENU_H_
class Menu
{
public:
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();
bool isBoxCreated();
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;
bool boxIsCreated = false;
};
Menu::Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int 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
boxIsCreated = false;
// Vertical Alignment
if(direction)
{
}
else // Horizontal Alignment -> The Deffault
{
}
}
Menu::~Menu()
{
werase(menuItemsWin);
wclear(menuItemsWin);
wrefresh(menuItemsWin);
boxIsCreated = false;
}
void Menu::eraseBox()
{
werase(menuItemsWin);
wclear(menuItemsWin);
wrefresh(menuItemsWin);
boxIsCreated = false;
}
void Menu::setPosX(int x)
{
this->posX = x;
}
void Menu::setPosY(int y)
{
this->posY = y;
}
int Menu::getPosX()
{
return posX;
}
int Menu::getPosY()
{
return posY;
}
void Menu::setMenuBarBegX(int x)
{
this->menuBarBegX = x;
}
void Menu::setMenuBarBegY(int y)
{
this->menuBarBegY = y;
}
void Menu::setMenuBarSizeX(int x)
{
this->menuBarSizeX = x;
}
std::string Menu::getName()
{
return name;
}
int Menu::getNameLenght()
{
return name.length();
}
int Menu::getLongestItemLenght()
{
return xSize;
}
char Menu::getTrigger()
{
return trigger;
}
int Menu::getBoxBegX()
{
// Vertical Alignment
if(direction)
{
return menuBarSizeX+posX+menuBarBegX-1;
}
else // Horizontal Alignment -> The Deffault
{
return menuBarSizeX+posX+menuBarBegX-1;
}
return -1;
}
int Menu::getBoxBegY()
{
// Vertical Alignment
if(direction)
{
return posY+menuBarBegY-1;
}
else // Horizontal Alignment -> The Deffault
{
return posY+menuBarBegY-1;
}
return -1;
}
bool Menu::isBoxCreated()
{
return boxIsCreated;
}
void Menu::drawBox()
{
// Creates a box with caclulated dimention xSize & ySize and user given position
/*menuItemsWin = newwin(20, 20, getBoxBegY(), getBoxBegX());
boxIsCreated = true;
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,76 @@
#include "main.h"
#ifndef _ITEM_H_
#define _ITEM_H_
#define BRD_SPC 1
class Item
{
public:
Item(std::string name, char trigger);
~Item();
//Getters
int getPosX();
int getPosY();
int getLength();
char getTrigger();
std::string getName();
//Setters
void setPosX(int x);
void setPosY(int y);
private:
std::string name; // Name of the item
int xPos, yPos = 0; // Coordinates of the item
int itemLength = 0; //Lenght of the item
char trigger; // trigger to select this item
};
Item::Item(std::string name, char trigger)
{
this->name = name;
this->trigger = trigger;
}
Item::~Item()
{
}
//Getters
int Item::getPosX()
{
return xPos;
}
int Item::getPosY()
{
return yPos;
}
int Item::getLength()
{
return name.length();
}
char Item::getTrigger()
{
return trigger;
}
std::string Item::getName()
{
return name;
}
//Setters
void Item::setPosX(int x)
{
this->xPos = x;
}
void Item::setPosY(int y)
{
this->yPos = y;
}
#endif

@ -1,59 +1,64 @@
#include "main.h"
#include "terminal.h"
#include "menuBar.h"
#include "menu.h"
#include <cstring>
// INFO: wgetch(win); or getch(); // getch will make a refresh for us.
#define HORIZONTAL 0
#define VERTICAL 1
#define LINK_MAIN 1
int main(int argv, char ** argc)
{
//Variables
int xMax, yMax, xMouse, yMouse= 0;
int xMax, yMax = 0;
char pressed;
std::string menu1[4]={"New","Open","Save","Exit"};
std::string menu2[3]={"Copy","Cut","Paste"};
std::string menu3[5]={"Terminal","Help","Info","Update","Manual"};
Item devices[3] = {
Item("Stm32f042",'q'),
Item("Stm32g441",'w'),
Item("Raspberry",'e'),
};
// Second stage declarations
Menu menus[3]={ // init the menus
Menu("File", 0, 0, 'f', menu1, 4),
Menu("Edit", 1, 0, 'e', menu2, 3),
Menu("Options", 2, 0, 'o', menu3, 5),
Item mainMenu[3] = {
Item("Devices",'d'),
Item("Configrations",'c'),
Item("Help",'h'),
};
Terminal terminal;
MenuBar menuBar = MenuBar(menus,1,5,5,3);
Terminal terminal = Terminal();
Menu menu = Menu("Main", mainMenu, 0, 0, LINK_MAIN, HORIZONTAL, 5,5,3);
Menu menuDevices = Menu("Devices", devices, 1, 1, LINK_MAIN, VERTICAL, 5,5,3);
init_pair(2, COLOR_CYAN, COLOR_BLACK);
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";
attron(COLOR_PAIR(2));
terminal.draw(1,yMax-2,"Press x to Exit");
attroff(COLOR_PAIR(2));
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");
terminal.endDraw();
refresh();
menuBar.drawBox();
menuBar.drawMenus();
while(pressed != 'k')
while(pressed != 'x')
{
menu.printMenu();
pressed = terminal.getKey();
menu.handleTrigger(pressed);
if(menu.isActive())
{
pressed = menuBar.getKey();
menuBar.handleTrigger(pressed);
menuBar.drawMenus();
terminal.draw(1,yMax-4,"Main Menu Is Active");
terminal.endDraw();
}
else
{
terminal.draw(1,yMax-4,"Main Menu is Inactive");
}
menuBar.~MenuBar();
refresh();
terminal.endDraw();
}
terminal.draw(1,2,"Press any key to exit the application");
terminal.getKey();
terminal.endDraw();
terminal.draw(1,yMax-3,"The window should be deleted");
terminal.tearDown();
return 0;

Binary file not shown.

@ -1,174 +1,305 @@
#include "main.h"
#include "item.h"
#ifndef _MENU_H_
#define _MENU_H_
#define BRD_SPC 1
class Menu
{
public:
Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int itemCount);
Menu( std::string name,
Item *items,
int level, int no, int link,
int orientation,
int xBeg, int yBeg,
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();
//Functions
void initBox(); // Inits the box dimentions and sets it up with basic parameters
void drawBox();
void drawItems();
int getBoxBegY();
int getBoxBegX();
void eraseBox();
void deleteMenu();
void startDraw();
void endDraw();
void update();
void printItems();
void selectItem();
void findTheLongestItem();
void printMenu();
void handleTrigger(char ch);
bool isActive();
//Getters
int getSizeX();
int getSizeY();
int getBegX();
int getBegY();
int getLongestItem();
int getSelectedItem();
int getOrientation();
char getKey();
//Setters
void setBegX(int x);
void setBegY(int y);
void setTopLine(char ch);
void setBottomLine(char ch);
void setLeftLine(char ch);
void setRightLine(char ch);
void setActive();
void setInactive();
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;
WINDOW *menuWin; // window fo this menu
std::string name; // Name of the menu
Item *items; // Items plresent for this menu
int orientation = 0; // 0 = Horizontal 1 = Vertical
int level = 0; // Hierarchical level of the menu 0 is the top one
int no = 0; // To be able to track echa menu indvidualy
int xBeg, yBeg = 0; // Beginning coordinates of the menu window
int xSize, ySize = 0; // Size of the menu window
int itemCount = 0; // Number of elents in this menu
int selectedItem = 0; // Currenlty selected Item on the menu
int link = 0; //If this menu is linked to anothar one // level 0 menus can not be linked
int longestItem = 0; //Lenght Of the Longest item
int i, pos = 0;
bool activeMenu = false;
};
Menu::Menu(std::string name, int menuNo, int direction, char trigger, std::string *items, int itemCount)
Menu::Menu( std::string name,
Item *items,
int level, int no, int link,
int orientation,
int xBeg, int yBeg,
int 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
this->name = name;
this->items = items;
this->level = level;
this->no = no;
this->link = link;
this->orientation = orientation;
this->xBeg = xBeg;
this->yBeg = yBeg;
this->itemCount = itemCount;
//To be sure
longestItem = 0;
xSize = 0;
ySize = 0;
selected_item = -1; // No menus are selected a the beggining
selectedItem = - 1;
activeMenu = false;
initBox();
}
// Vertical Alignment
if(direction)
//TODO: The correct way to end or erase s window is still unclear
Menu::~Menu()
{
deleteMenu();
werase(menuWin);
}
else // Horizontal Alignment -> The Deffault
void Menu::initBox()
{
pos = 1; // So that it doesn write over the border
findTheLongestItem();
// if Horizontal aligment else vertical
if(orientation)
{
xSize = longestItem + 2;
for(i = 0; i < itemCount ; i ++)
{
this->items[i].setPosY(pos);
this->items[i].setPosX(1); // So tha it write in the middle
pos ++;
}
ySize = itemCount + 2;
}
else
{
for(i = 0; i < itemCount ; i ++)
{
items[i].setPosX(pos);
items[i].setPosY(1);
pos += this->items[i].getLength() + 1;
}
xSize = pos;
ySize = 3;
}
// Creates a box with caclulated dimention xSize & ySize and user given position
menuWin = newwin(ySize, xSize, yBeg, xBeg);
}
Menu::~Menu()
//Functions
void Menu::drawBox()
{
//menuWin = newwin(5, 5, 5, 5);
box(menuWin,0,0); //Here we can define other cahr insterad of 0,0
wrefresh(menuWin); //Refresh so that we can see it
}
//TODO: The correct way to end or erase s window is still unclear
void Menu::deleteMenu()
{
werase(menuItemsWin);
wrefresh(menuItemsWin);
wclear(menuWin);
endDraw();
}
void Menu::eraseBox()
void Menu::startDraw()
{
werase(menuItemsWin);
wrefresh(menuItemsWin);
}
void Menu::setPosX(int x)
void Menu::endDraw()
{
this->posX = x;
wrefresh(menuWin); //Refresh so that we can see it
}
void Menu::setPosY(int y)
void Menu::update()
{
this->posY = y;
}
int Menu::getPosX()
void Menu::printItems()
{
for(i=0 ; i < itemCount; i++)
{
if(i == selectedItem)
{
wattron(menuWin, A_STANDOUT);
mvwprintw(menuWin, items[i].getPosY(),items[i].getPosX(), items[i].getName().c_str());
wattroff(menuWin, A_STANDOUT);
}
else
{
return posX;
mvwprintw(menuWin, items[i].getPosY(),items[i].getPosX(), items[i].getName().c_str());
}
}
selectedItem = -1; // Deselcting the item
}
int Menu::getPosY()
void Menu::selectItem()
{
return posY;
}
void Menu::setMenuBarBegX(int x)
void Menu::findTheLongestItem()
{
for(i=0; i < itemCount; i++)
{
if(longestItem < items[i].getLength())
{
this->menuBarBegX = x;
longestItem = items[i].getLength();
}
}
}
void Menu::setMenuBarBegY(int y)
void Menu::printMenu()
{
this->menuBarBegY = y;
drawBox();
printItems();
wrefresh(menuWin); //Refresh so that we can see it
}
void Menu::setMenuBarSizeX(int x)
// Handles user input but there shoud be a way to register the selection.
void Menu::handleTrigger(char ch)
{
for(i=0; i < itemCount; i++)
{
if(ch == items[i].getTrigger())
{
this->menuBarSizeX = x;
selectedItem = i;
activeMenu = true;
}
std::string Menu::getName()
else
{
return name;
activeMenu = false;
}
}
}
int Menu::getNameLenght()
bool Menu::isActive()
{
return name.length();
return activeMenu;
}
int Menu::getLongestItemLenght()
//Getters
int Menu::getSizeX()
{
return xSize;
}
char Menu::getTrigger()
int Menu::getSizeY()
{
return trigger;
return ySize;
}
int Menu::getBoxBegX()
int Menu::getBegX()
{
// Vertical Alignment
if(direction)
return xBeg;
}
int Menu::getBegY()
{
return yBeg;
}
else // Horizontal Alignment -> The Deffault
int Menu::getLongestItem()
{
return menuBarSizeX+posX+menuBarBegX-1;
return longestItem;
}
int Menu::getSelectedItem()
{
return selectedItem;
}
int Menu::getBoxBegY()
int Menu::getOrientation()
{
// Vertical Alignment
if(direction)
return orientation;
}
//Setters
void Menu::setBegX(int x)
{
this-> xBeg = x;
}
else // Horizontal Alignment -> The Deffault
void Menu::setBegY(int y)
{
return posY+menuBarBegY-1;
this-> yBeg = y;
}
void Menu::setTopLine(char ch)
{
}
void Menu::drawBox()
void Menu::setBottomLine(char ch)
{
// 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::setLeftLine(char ch)
{
}
void Menu::drawItems()
void Menu::setRightLine(char ch)
{
}
char Menu::getKey()
{
return wgetch(menuWin);
}
#endif

@ -2,6 +2,6 @@
rm ./menu
gcc main.c -o menu -lncurses
gcc main.c -o menu -lmenu -lncurses
./menu

@ -1,108 +1,100 @@
#include <ncurses.h>
#include <string.h>
#include <curses.h>
#include <menu.h>
#include <stdlib.h>
#define WIDTH 30
#define HEIGHT 10
#include <string.h>
int startx = 0;
int starty = 0;
char *choices[] = { "Choice 1",
"Choice 2",
"Choice 3",
"Choice 4",
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define CTRLD 4
char *choices[] = {
"Choice 1", "Choice 2", "Choice 3", "Choice 4", "Choice 5",
"Choice 6", "Choice 7", "Choice 8", "Choice 9", "Choice 10",
"Choice 11", "Choice 12", "Choice 13", "Choice 14", "Choice 15",
"Choice 16", "Choice 17", "Choice 18", "Choice 19", "Choice 20",
"Exit",
(char *)NULL,
};
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;
{ ITEM **my_items;
int c;
MENU *my_menu;
WINDOW *my_menu_win;
int n_choices, i;
/* Initialize curses */
initscr();
clear();
start_color();
cbreak();
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;
keypad(stdscr, TRUE);
init_pair(1, COLOR_RED, COLOR_BLACK);
init_pair(2, COLOR_CYAN, COLOR_BLACK);
attron(A_REVERSE);
mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
refresh();
attroff(A_REVERSE);
/* Create items */
n_choices = ARRAY_SIZE(choices);
my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
for(i = 0; i < n_choices; ++i)
my_items[i] = new_item(choices[i], choices[i]);
/* 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);
/* Crate menu */
my_menu = new_menu((ITEM **)my_items);
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;
}
/* Set menu option not to show the description */
menu_opts_off(my_menu, O_SHOWDESC);
/* Create the window to be associated with the menu */
my_menu_win = newwin(10, 70, 4, 4);
keypad(my_menu_win, TRUE);
void print_menu(WINDOW *menu_win, int highlight)
{
int x, y, i;
/* Set main window and sub window */
set_menu_win(my_menu, my_menu_win);
set_menu_sub(my_menu, derwin(my_menu_win, 6, 68, 3, 1));
set_menu_format(my_menu, 5, 3);
set_menu_mark(my_menu, " * ");
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);
}
/* Print a border around the main window and print a title */
box(my_menu_win, 0, 0);
/* Report the choice according to mouse position */
void report_choice(int mouse_x, int mouse_y, int *p_choice)
{ int i,j, choice;
attron(COLOR_PAIR(2));
mvprintw(LINES - 3, 0, "Use PageUp and PageDown to scroll");
mvprintw(LINES - 2, 0, "Use Arrow Keys to navigate (F1 to Exit)");
attroff(COLOR_PAIR(2));
refresh();
i = startx + 2;
j = starty + 3;
/* Post the menu */
post_menu(my_menu);
wrefresh(my_menu_win);
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;
while((c = wgetch(my_menu_win)) != KEY_F(1))
{ switch(c)
{ case KEY_DOWN:
menu_driver(my_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(my_menu, REQ_UP_ITEM);
break;
case KEY_LEFT:
menu_driver(my_menu, REQ_LEFT_ITEM);
break;
case KEY_RIGHT:
menu_driver(my_menu, REQ_RIGHT_ITEM);
break;
case KEY_NPAGE:
menu_driver(my_menu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(my_menu, REQ_SCR_UPAGE);
break;
}
wrefresh(my_menu_win);
}
/* Unpost and free all the memory taken up */
unpost_menu(my_menu);
free_menu(my_menu);
for(i = 0; i < n_choices; ++i)
free_item(my_items[i]);
endwin();
}

Binary file not shown.
Loading…
Cancel
Save