123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- {$MODE OBJFPC}
- program Menu_Example;
- uses
- ncurses, menu, panel, sysutils;
- function st_middle(scrlen, itemlen: Smallint): Smallint; inline;
- begin
- st_middle := (scrlen - itemlen) div 2;
- end;
- procedure print_in_middle(win: PWINDOW; starty, startx: Smallint;
- width: Longint; pair: Smallint;
- const fmt: AnsiString; args: array of const);
- var
- tstr: AnsiString;
- my, mx: Smallint;
- begin
- FmtStr(tstr, fmt, args);
- getmaxyx(win, my, mx);
- mx -= startx;
- if (width > length(tstr)) OR (width < 2) then
- width := length(tstr);
- if width > mx then
- width := mx;
- wattron(win,COLOR_PAIR(pair));
- mvwaddnstr(win,starty,startx + st_middle(mx,width),PChar(tstr),width);
- wattroff(win,COLOR_PAIR(pair));
- end;
- type
- PMinfo = ^TMinfo;
- TMinfo = record
- n, d: PChar;
- end;
- type
- TSubmenu = class
- private
- _win: PWINDOW;
- _pan: PPANEL;
- _items: ppITEM;
- _exit, _sitem: pITEM;
- _menu: pMENU;
- public
- function doevent: chtype;
- constructor create(szy,szx,nch: Smallint; choices: PMinfo;
- pair: Smallint;const name: AnsiString);
- destructor destroy; override;
- property menu: pMENU read _menu;
- property items: ppITEM read _items;
- property sitem: pITEM read _sitem write _sitem ;
- property win: PWINDOW read _win;
- property pan: PPANEL read _pan;
- end;
- function TSubmenu.doevent: chtype;
- function doenter(var ch: chtype): Boolean;
- begin
- if current_item(_menu) = _exit then
- begin
- doenter := false;
- ch := -1
- end
- else
- if current_item(_menu) = sitem then
- begin
- doenter := false;
- ch := 10
- end
- else
- doenter := true;
- end;
- var
- ch: chtype = 0;
- doiter: Boolean = true;
- begin
- while doiter do
- begin
- ch := wgetch(_win);
- case ch of
- KEY_DOWN: menu_driver(_menu, REQ_DOWN_ITEM);
- KEY_UP: menu_driver(_menu, REQ_UP_ITEM);
- KEY_LEFT: menu_driver(_menu, REQ_LEFT_ITEM);
- KEY_RIGHT: menu_driver(_menu, REQ_RIGHT_ITEM);
- KEY_NPAGE: menu_driver(_menu, REQ_SCR_DPAGE);
- KEY_PPAGE: menu_driver(_menu, REQ_SCR_UPAGE);
- chtype(' '): menu_driver(_menu, REQ_TOGGLE_ITEM);
- 10: doiter := doenter(ch); (* Enter *)
- else
- if menu_driver(_menu, ch) <> E_OK then
- begin
- doiter := false;
- if (ch <> chtype('q')) AND (ch <> KEY_F(10)) then
- ch := -1; (* Close menu *)
- end
- else
- if (ch = KEY_MOUSE) then
- doiter := doenter(ch);
- end;
- end;
- update_panels();
- doupdate();
- doevent := ch;
- end;
- constructor TSubmenu.create(szy,szx,nch: Smallint; choices: PMinfo;
- pair: Smallint;const name: AnsiString);
- var
- i: Longint = 0;
- begin
- GetMem(_items, (nch+1)*sizeof(pITEM));
- for i := 0 to nch - 1 do
- _items[i] := new_item(choices[i].n, choices[i].d);
- _items[nch] := nil;
- _exit := _items[i];
- sitem := nil;
- _menu := new_menu(_items);
- //scale_menu(_menu, @mrows, @mcols);
- _win := newwin(szy,szx,st_middle(LINES,szy),st_middle(COLS,szx));
- //_win := newwin(mrows + 2, mcols + 2, st_middle(LINES,mrows+2),st_middle(COLS,mcols+2));
- _pan := new_panel(_win);
- keypad(_win, TRUE);
- box(_win, ACS_VLINE, ACS_HLINE);
- wbkgd(_win, COLOR_PAIR(pair));
- set_menu_back(_menu, COLOR_PAIR(pair));
- print_in_middle(_win,0,0,szx-2,pair,name,[]);
- set_menu_win(_menu, _win);
- set_menu_sub(_menu, derwin(_win, szy-2, szx-2, 1, 1));
- //set_menu_sub(_menu, derwin(_win, mrows, mcols, 1, 1));
- set_menu_mark(_menu, '-');
- end;
- destructor TSubmenu.destroy;
- var
- i: Longint = 0;
- begin
- unpost_menu(_menu);
- free_menu(_menu);
- while _items[i] <> nil do
- begin
- free_item(_items[i]); Inc(i);
- end;
- FreeMem(_items, (i+1)*sizeof(pITEM));
- del_panel(_pan);
- delwin(_win);
- update_panels();
- doupdate();
- end;
- type
- Tmainptr = function: chtype;
- const
- EXIT_PROGRAM = KEY_MAX + 100;
- function confirm_menu: chtype;
- const
- choices: array[0..2] of TMinfo =
- (
- (n:' Yes ';d:nil),
- (n:'I dont know';d:nil),
- (n:' No ';d:nil)
- );
- var
- smenu: TSubmenu;
- begin
- smenu := TSubmenu.create(3, 41,3,choices,5,'Do you really want to quit?');
- menu_opts_off(smenu.menu, O_SHOWDESC);
- set_menu_format(smenu.menu, 1, 3);
- post_menu(smenu.menu);
- smenu.sitem := smenu.items[0];
- confirm_menu := smenu.doevent;
- if (confirm_menu = 10) OR (confirm_menu = chtype('q')) OR (confirm_menu = KEY_F(10)) then
- confirm_menu := EXIT_PROGRAM
- else
- confirm_menu := -1;
- smenu.destroy;
- end;
- (* Scrolling Menus example *)
- function scroll_menu: chtype;
- const
- choices: array[0..9] of TMinfo =
- (
- (n: '1_'; d: 'Choice'),
- (n: '2_'; d: 'Choice'),
- (n: '3_'; d: 'Choice'),
- (n: '4_'; d: 'Choice'),
- (n: '5_'; d: 'Choice'),
- (n: '6_'; d: 'Choice'),
- (n: '7_'; d: 'Choice'),
- (n: '8_'; d: 'Choice'),
- (n: '9_'; d: 'Choice'),
- (n: '..'; d: 'Close')
- );
- var
- smenu: TSubmenu;
- begin
- mvaddstr(LINES - 3, COLS - 30, '"PAGEUP" "PAGEDOWN" - scroll');
- refresh();
- smenu := TSubmenu.create(8, 13,10,choices,6,'Scrolling');
- set_menu_format(smenu.menu, 6, 1);
- post_menu(smenu.menu);
- scroll_menu := smenu.doevent;
- smenu.destroy;
- mvaddstr(LINES - 3, COLS - 30, ' ');
- refresh();
- end;
- (* Milt Columnar Menus Example *)
- function multicol_menu: chtype;
- const
- choices: array[0..24] of TMinfo =
- (
- (n:'1_';d:nil),(n:'2_';d:nil),(n:'3_';d:nil),(n:'4_';d:nil),(n:'5_';d:nil),
- (n:'6_';d:nil),(n:'7_';d:nil),(n:'8_';d:nil),(n:'9_';d:nil),(n:'10';d:nil),
- (n:'11';d:nil),(n:'12';d:nil),(n:'13';d:nil),(n:'14';d:nil),(n:'15';d:nil),
- (n:'16';d:nil),(n:'17';d:nil),(n:'18';d:nil),(n:'19';d:nil),(n:'20';d:nil),
- (n:'21';d:nil),(n:'22';d:nil),(n:'23';d:nil),(n:'24';d:nil),(n:'..';d:nil)
- );
- var
- smenu: TSubmenu;
- i: Longint;
- begin
- smenu := TSubmenu.create(7, 22,25,choices,5,'Multicol');
- (* Set menu option not to show the description *)
- menu_opts_off(smenu.menu, O_SHOWDESC);
- set_menu_format(smenu.menu, 5, 5);
- post_menu(smenu.menu);
- multicol_menu := smenu.doevent;
- smenu.destroy;
- end;
- (* Multi Valued Menus example *)
- function multival_menu: chtype;
- const
- choices: array[0..5] of TMinfo =
- (
- (n: '1_'; d: 'Choice'),
- (n: '2_'; d: 'Choice'),
- (n: '3_'; d: 'Choice'),
- (n: '4_'; d: 'Choice'),
- (n: '5_'; d: 'Choice'),
- (n: '..'; d: 'Close')
- );
- var
- smenu: TSubmenu;
- begin
- mvaddstr(LINES - 3, COLS - 30, '"SPACE" - toggle choice');
- refresh();
- smenu := TSubmenu.create(8, 13,6,choices,7,'Multival');
- menu_opts_off(smenu.menu, O_ONEVALUE);
- post_menu(smenu.menu);
- multival_menu := smenu.doevent;
- smenu.destroy;
- mvaddstr(LINES - 3, COLS - 30, ' ');
- refresh();
- end;
- const
- n_choices = 4;
- choices: array[0..3] of TMinfo =
- (
- (n: '1_'; d: 'Scrolling Menus'),
- (n: '2_'; d: 'Multi Columnar Menus'),
- (n: '3_'; d: 'Multi Valued Menus'),
- (n: '..'; d: 'Exit')
- );
- var
- main_menu_win: PWINDOW;
- main_menu_panel: PPANEL;
- function mgetch: chtype;
- begin
- mgetch := wgetch(main_menu_win);
- end;
- var
- my_bg: Smallint = COLOR_BLACK;
- main_items: ppITEM;
- cur_item: pITEM;
- main_menu: pMENU;
- ptr: Tmainptr = @mgetch;
- ch: chtype = -1;
- i: Longint;
- begin
- try
- (* Initialize curses *)
- initscr();
- noecho();
- cbreak();
- keypad(stdscr, TRUE);
- curs_set(0);
- clear();
- mousemask(ALL_MOUSE_EVENTS, nil);
- if has_colors() then
- begin
- start_color();
- if (use_default_colors() = OK) then
- my_bg := -1
- else
- my_bg := COLOR_BLACK;
- init_pair(1, COLOR_YELLOW, my_bg);
- init_pair(2, COLOR_RED, my_bg);
- init_pair(3, COLOR_MAGENTA, my_bg);
- init_pair(4, COLOR_CYAN, my_bg);
- init_pair(5, COLOR_WHITE, COLOR_RED);
- init_pair(6, COLOR_WHITE, COLOR_BLUE);
- init_pair(7, COLOR_WHITE, COLOR_GREEN);
- end;
- main_menu_win := newwin(8, 40, st_middle(LINES, 8) - 2, st_middle(COLS, 40) - 10);
- main_menu_panel := new_panel(main_menu_win);
- keypad(main_menu_win, TRUE);
- (* Create items *)
- GetMem(main_items, (n_choices+1)*sizeof(pITEM));
- for i := 0 to n_choices-1 do
- main_items[i] := new_item(choices[i].n, choices[i].d);
- main_items[n_choices] := nil;
- (* Set the user pointers *)
- set_item_userptr(main_items[0], @scroll_menu);
- set_item_userptr(main_items[1], @multicol_menu);
- set_item_userptr(main_items[2], @multival_menu);
- set_item_userptr(main_items[3], @confirm_menu);
- (* Crate menu *)
- main_menu := new_menu(main_items);
- (* Set main window and sub window *)
- set_menu_win(main_menu, main_menu_win);
- set_menu_sub(main_menu, derwin(main_menu_win, 4, 38, 3, 1));
- (* Set menu mark to the string "=>" *)
- set_menu_mark(main_menu, '=>');
- (* Print a border around the main window and print a title *)
- box(main_menu_win, 0, 0);
- wbkgd(main_menu_win, COLOR_PAIR(6));
- set_menu_back(main_menu, COLOR_PAIR(6));
- print_in_middle(main_menu_win, 1, 0, 40, COLOR_PAIR(6), 'Main Menu', []);
- mvwaddch(main_menu_win, 2, 0, ACS_LTEE);
- mvwhline(main_menu_win, 2, 1, ACS_HLINE, 38);
- mvwaddch(main_menu_win, 2, 39, ACS_RTEE);
- attron(COLOR_PAIR(4));
- mvaddstr(LINES - 1, COLS - 30, 'Press "F10" or "q" to exit ');
- attroff(COLOR_PAIR(4));
- refresh();
- (* Post the menu *)
- post_menu(main_menu);
- wrefresh(main_menu_win);
- while ch <> EXIT_PROGRAM do
- begin
- case ch of
- KEY_DOWN: menu_driver(main_menu, REQ_DOWN_ITEM);
- KEY_UP: menu_driver(main_menu, REQ_UP_ITEM);
- -1: ptr := @mgetch; (* Restore ptr *)
- 10: (* Enter *)
- begin
- cur_item := current_item(main_menu); (* get current item *)
- ptr := Tmainptr(item_userptr(cur_item)); (* set ptr to current item *)
- end;
- else
- (* Process mouse and others events *)
- if (menu_driver(main_menu, ch) = E_OK) AND (ch = KEY_MOUSE) then
- begin
- cur_item := current_item(main_menu);
- ptr := Tmainptr(item_userptr(cur_item));
- wrefresh(main_menu_win);
- end;
- end;
- ch := ptr(); (* Call ptr function *)
- if (ch = chtype('q')) OR (ch = KEY_F(10)) then
- ch := confirm_menu();
- end;
- finally
- unpost_menu(main_menu);
- free_menu(main_menu);
- for i := 0 to n_choices - 1 do
- free_item(main_items[i]);
- FreeMem(main_items, (n_choices+1)*sizeof(pITEM));
- del_panel(main_menu_panel);
- delwin(main_menu_win);
- curs_set(1);
- endwin();
- end;
- end.
|