/*  LPA Prolog 4.1 "gfx-graphics-based text menus" 
-(c) George A. Stathis 2001/2002  */

:- dynamic tx/2.
:- dynamic prevw/2.

/* DESCRIPTION:
These menus are more flexible than "usual" Windows-menus, in the sense that they can be freely and easily mixed with any other graphics (gfx- or other), while both mouse buttons can control (user-specified) events and colours. The menu's options change colours every time the mouse-cursor enters their area, etc. - and all this with an astonishingly small number of code lines!  Note that this file is only a small, trivial example of the beauty and simplicity of gfx_grafics-based text menus. My commercial application "HyperLEX 2002" (a multi-language "intelligent software dictionary") uses advanced forms of such graphic menus that are full-blown hypertext browsers as well as menus at the same time. The source-code for advanced gfx-based text menus and hypertext browsers can be made available on special request, at a high price. But the simple code that follows in this page also does wonders, compared to existing techniques, and you can use it in your own programs freely, provided you acknowledge its source. */

test:- SL = [`first`,`second`,`third`,`fourth`,`fifth`,`sixth`,`end`],
 repeat, Row is int(rand(200)), Col=Row,
 gfxmenu(0,Col,Row,`VERTICAL gfx_menu`,SL,SELx,RESPx),
 write(selected(SELx,RESPx)), nl,
 gfxmenu(1,Col,Row,`HORIZONTAL gfx_menu`,SL,SELy,RESPy),
 writeq(selected(SELy,RESPy)), nl,nl,
 (RESPy=close;RESPx=close), !.

%% main predicate is gfxmenu/7, where 1st argument is "type"
%% (0=vertical, 1=horizontal), 2nd and 3rd arguments are column
%% and row of top-left-corner on the screen, 4th arg. is TITLE,
%% 5th argument is a list of strings for the menu-contents,
%% 6th arg. is the selected string, and 7th argument is the menu-
%% response ( one of [more,close,leftdown(choice_string)] ):

gfxmenu(TYPE,Col,Row,Title,SL,SELECTED,Resp):-
  _S1 = [dlg_ownedbyprolog,ws_sysmenu,ws_caption],
  _S2 = [ws_child,ws_border,ws_visible],
  get_size(VGAwid,VGAhei), retractall(tx(_,_)),
  wdcreate('X',Title,0,0,VGAwid,VGAhei,_S1),
  gfx_font_create(gfxfont,courier,20,bold),
  gfx_font_create(gfxfont2,courier,23,bold),
  gfx_brush_create(eraser,255,255,255,solid),
  gfx_brush_create(marker,170,170,170,solid),
  gfx_brush_create(bblue,0,0,255,solid),
  gfx_brush_create(bgreen,0,255,0,solid),
  gfx_brush_create(bblack,127,127,127,solid),
  gfx_back_create(whitebk,255,255,255),
  gfx_pen_create(whitef,255,255,255,solid),
  wfsizelist(gfxfont2,SL,0,0,WW,HH),
  window_handler('X',phandler), show_dialog('X'),
  len(SL,Max), initgfx_hbuttons(TYPE,1,Max,Col,Row,WW,HH),
  fillgfx_hbuttons(1,eraser,SL), retractall(prevw(_,_)),
  wait_dialog(Resp), prevw(_,SELECTED), xx, !.
 

% initgfx_hbuttons/6 initialises the menu's "virtual buttons" (rectangles):

initgfx_hbuttons(_,N,Max,_,_,_,_):- N > Max, !.
initgfx_hbuttons(TYP,N,Max,C,R,W,H):- Wn is 9000+N,
 wccreate(('X',Wn),grafix,``,C,R,W,H,
   [ws_child,ws_border,ws_visible]),
 (TYP=0 -> (R2 is R+H+3,C2=C);(R2 = R,C2 is C+W+3)),
 NN is N+1, !, initgfx_hbuttons(TYP,NN,Max,C2,R2,W,H).
 

% fillgfx_hbuttons/4 displays the captions in the menu's (gfx-based) rectangles

fillgfx_hbuttons(_,_,[]):- !.
fillgfx_hbuttons(N,Color,[Text|TL]):- Wn is 9000+N,
   retractall(tx(('X',Wn),_)),
   assert(tx(('X',Wn),Text)), showgfx_text(('X',Wn),Color,Text),
   NN is N+1, !, fillgfx_hbuttons(NN,Color,TL).
 

% showgfx_text/3 draws rectangles-with-text for the menu's "gfx_objects",
% and avoids the use of buttons. These rectangles are more efficient buttons!

showgfx_text(Win,Colour,Text):- wshow(Win,1),
  warea(Win,Ci,Ri,Wi,Hi), gfx_begin(Win),
  gfx(( back=whitebk,pen=whitef,brush=Colour
      -> rectangle(0,0,Wi,Hi) )),
  gfx(( brush=bblack,font=gfxfont -> text(0,0,Text) )),
  gfx_end(Win), !.
 

% get_size/2 finds the size of the current VGA screen:

get_size(Xw,Yw):- gfx_begin(0),gfx_resolution(Xw,Yw,_,_),gfx_end(0),!.
 

% wait_dialog/1 is a "classic" event-handler recommended by LPA's documentation:

wait_dialog(V):-  wait((1,V)).
 

% wfsizelist/6 is an "extension" of LPA-predicate wfsize/4 to lists of strings:

wfsizelist(_,[],WW,HH,WW,HH):- !.
wfsizelist(Font,[S|SL],W1,H1,WW,HH):- wfsize(Font,S,W,H),
 W2 is max(W1,W), H2 is max(H1,H),
 !, wfsizelist(Font,SL,W2,H2,WW,HH).
 

% phandler/4 is a "classic" window_handler predicate (consult LPA Prolog HELP)

phandler(WND,msg_close,_,close):- retractall(prevw(_,_)),
 assert(prevw(WND,``)), !.
phandler((WND,W9),msg_leftdown,_,leftdown(TX)):- tx((WND,W9),TX),
 showgfx_text((WND,W9),bgreen,TX), !.
phandler((WND,W9),msg_leftup,_,leftup(TX)):- tx((WND,W9),TX),
 showgfx_text((WND,W9),marker,TX),
 retractall(prevw(_,_)), assert(prevw((WND,W9),TX)), !.
phandler((WND,W9),msg_rightdown,_,rightdown(TX)):- tx((WND,W9),TX),
 showgfx_text((WND,W9),bgreen,TX), !.
phandler((WND,W9),msg_rightup,_,rightup(TX)):- tx((WND,W9),TX),
 showgfx_text((WND,W9),marker,TX), !.
phandler((WND,W9),msg_mousemove,_,more):- tx((WND,W9),TX),
 \+prevw((WND,W9),_),
 (prevw(W1,TX0) -> showgfx_text(W1,eraser,TX0); true),
 retractall(prevw(_,_)), assert(prevw((WND,W9),TX)),
 showgfx_text((WND,W9),marker,TX), !, fail.
 

% xx/0 shuts down the gfx objects used by this program -and windows created:

xx:- gfx_back_dict(WL), member(F,WL), gfx_back_close(F), fail.
xx:- gfx_pen_dict(WL), member(F,WL), gfx_pen_close(F), fail.
xx:- gfx_brush_dict(WL), member(F,WL), gfx_brush_close(F), fail.

%%% the following clause has some unpleasant side-effects when
%%% running within the LPA 4.1 development environment, but is free
%%% of such side-effects in a stand-alone appication:
%xx:- gfx_font_dict(WL), member(F,WL), gfx_font_close(F), fail.

xx:- wdict(WL), member('X',WL), wclose('X'), fail.
xx.

/* TERMS: This code can be used freely in your own (LPA Prolog-) applications, but requires
    acknowledgement of its source */
 


OTHER PAGES in this site:

"What's better than a good plate of spaghetti? Well... two good plates of spaghetti!"

-software advice from a TV ad of the Greek Spaghetti Industry