:- package(gui). :- package(guibuilder). :- dynamic([ui_window/1]). main(Applet, _) :- appletButtons(Applet), newCalculator. newCalculator :- frame_create(Frame), frame_setTitle(Frame, 'MINERVA: Calculator'), font_create('Helvetica', bold, 24, Font1), component_setFont(Frame, Font1), gui(Frame, border, [ 'North' / text_field(CalcResult), 'Center' / panel(_, grid(4,5), [ button(_,'off') ** action(calcAction(Frame,'off')), button(_,'7') ** action(calcAction(Frame,'7')), button(_,'8') ** action(calcAction(Frame,'8')), button(_,'9') ** action(calcAction(Frame,'9')), button(_,'/') ** action(calcAction(Frame,'/')), button(_,''), button(_,'4') ** action(calcAction(Frame,'4')), button(_,'5') ** action(calcAction(Frame,'5')), button(_,'6') ** action(calcAction(Frame,'6')), button(_,'*') ** action(calcAction(Frame,'*')), button(_,'C') ** action(calcAction(Frame,'C')), button(_,'1') ** action(calcAction(Frame,'1')), button(_,'2') ** action(calcAction(Frame,'2')), button(_,'3') ** action(calcAction(Frame,'3')), button(_,'-') ** action(calcAction(Frame,'-')), button(_,'AC') ** action(calcAction(Frame,'AC')), button(_,'0') ** action(calcAction(Frame,'0')), button(_,'.') ** action(calcAction(Frame,'.')), button(_,'=') ** action(calcAction(Frame,'=')), button(_,'+') ** action(calcAction(Frame,'+')) ]) ]), assertz(ui_window(Frame)), InitCalcState = cs([],'0','ok'), set_global(Frame, CalcResult/InitCalcState), textComponent_setEditable(CalcResult,false), calcShow(CalcResult, InitCalcState), frame_pack(Frame), component_setVisible(Frame, true), !. appletButtons(Applet) :- font_create('Helvetica',bold,20,Font1), component_setFont(Applet,Font1), gui(Applet, grid(1,2), [ button(_,'new calculator') ** action(newCalculator), button(_,'dismiss') ** action(dismissAll) ]). %%% Calculator Engine: implemented as automaton calcKey('1',digit). calcKey('2',digit). calcKey('3',digit). calcKey('4',digit). calcKey('5',digit). calcKey('6',digit). calcKey('7',digit). calcKey('8',digit). calcKey('9',digit). calcKey('0',digit). calcKey('.',digit). calcKey('+',bin_op). calcKey('*',bin_op). calcKey('/',bin_op). calcKey('-',bin_op). calcKey('=',other_op). calcKey('AC',other_op). calcKey('C',other_op). calcKey('off',other_op). calcAction(Frame,Key) :- get_global(Frame, Field/CalcState1), calcKey(Key,Kind), !, calcTrans(Key,Kind,Frame,CalcState1,CalcState2), calcShow(Field, CalcState2), set_global(Frame, Field/CalcState2). % State transition: calcTrans(Key,Kind,CalcState1,CalcState2) % Single state: CalcState = cs(Stack,Display,Status) calcTrans('=',_K,_,cs([Num2,Op,Num|S],_D,done),cs([Result|S],NewD,done)) :- !, calcApply(Num,Op,Num2,Result), calcDisplayNumber(NewD,Result). calcTrans('=',_Kind,_,cs([Op,Num|S],D,ok),cs([Result|S],NewD,done)) :- calcDisplayNumber(D,Num2), calcApply(Num,Op,Num2,Result), calcDisplayNumber(NewD,Result),!. calcTrans(Key,bin_op,_,cs([Op,Num|S],D,ok),cs([Key,Result|S],NewD,op)) :- calcDisplayNumber(D,Num2), calcApply(Num,Op,Num2,Result), calcDisplayNumber(NewD1,Result),atom_concat(NewD1,Key,NewD),!. calcTrans(Key,bin_op,_,cs(S,D,done),cs([Key,Number|S],NewD,op)) :- !, calcDisplayNumber(D,Number), atom_concat(D,Key,NewD),!. calcTrans(Key,Kind,F,cs(S,_D,done),cs(S,NewD,NewState)) :- calcTrans(Key,Kind,F,cs(S,'0',ok),cs(S,NewD,NewState)). calcTrans(Key,bin_op,_,cs(S,D,ok),cs([Key,Number|S],NewD,op)) :- calcDisplayNumber(D,Number), atom_concat(D,Key,NewD),!. calcTrans('.',digit,_,cs(S,'0',ok),cs(S,'0.',ok)) :- !. calcTrans('.',digit,_,cs(S,D,ok),cs(S,NewD,ok)) :- atom_chars(D,DisplayChars), \+ member('.',DisplayChars),!, atom_concat(D,'.',NewD). calcTrans('.',digit,_,cs(S,D,ok),cs(S,D,ok)) :- atom_chars(D,DisplayChars), member('.',DisplayChars),!. calcTrans(Key, digit,_,cs(S,'0',ok),cs(S,Key,ok)) :- !. calcTrans(Key, digit,_,cs(S,D,ok),cs(S,NewD,ok)) :- !, atom_concat(D,Key,NewD),!. calcTrans(Key,digit,_,cs(S,_D,op),cs(S,Key,ok)) :- !. calcTrans(' AC ',_Kind,_,cs(_S,_D,_Status),cs([],'0',ok)) :- !. calcTrans('C',_Kind,_,cs(S,_D,_Status),cs(S,'0','ok')) :- !. calcTrans('off',_Kind,F,cs(S,_D,_Status),cs(S,'0','ok')) :- retract(ui_window(F)), frame_dispose(F), !. calcTrans(Key,_Kind,CalcState,CalcState) :- writeq(ignored(Key,CalcState)),nl,flush_output. calcShow(Field, cs(_,Display,_)) :- % writeq(cs(Stack,Display,Status)), nl, flush_output, textComponent_setText(Field, Display). calcApply(Num,Op,Num2,Result) :- Formula =.. [Op,Num,Num2], Result is Formula. % calcDisplayNumber(Display,Number) :- calcDisplayNumber('',0) :- !. calcDisplayNumber(Display,Number) :- atom_number(Display,Number). %%% Calculator GUI dismissAll :- retract(ui_window(F)), frame_dispose(F), fail. dismissAll.