## answer-dialog-factory.pkg
#
# When the user enters an incorrect answer, the application
# uses this dialog to display the problem plus the correct answer.
# Compiled by:
#
src/lib/x-kit/tut/arithmetic-game/arithmetic-game-app.libstipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package g2d= geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg #
package xc = xclient; # xclient is from
src/lib/x-kit/xclient/xclient.pkg #
package cv = canvas; # canvas is from
src/lib/x-kit/widget/old/leaf/canvas.pkg package wg = widget; # widget is from
src/lib/x-kit/widget/old/basic/widget.pkg package lw = line_of_widgets; # line_of_widgets is from
src/lib/x-kit/widget/old/layout/line-of-widgets.pkg package sz = size_preference_wrapper; # size_preference_wrapper is from
src/lib/x-kit/widget/old/wrapper/size-preference-wrapper.pkg package pb = pushbuttons; # pushbuttons is from
src/lib/x-kit/widget/old/leaf/pushbuttons.pkg package tw = hostwindow; # hostwindow is from
src/lib/x-kit/widget/old/wrapper/size-preference-wrapper.pkgherein
package answer_dialog_factory: Answer_Dialog_Factory { # Answer_Dialog_Factory is from
src/lib/x-kit/tut/arithmetic-game/answer-dialog-factory.api debug_tracing = logger::make_logtree_leaf
{ parent => xlogger::xkit_logging,
name => "answer::debug_tracing",
default => FALSE # Change to TRUE or call (log::enable debug_tracing) to enable logging in this file.
};
log_if = logger::log_if;
Answer_Dialog_Factory
=
ANSWER_DIALOG_FACTORY
{
root_window: wg::Root_Window,
font: xc::Font,
lead: Int
};
fun make_answer_dialog_factory
( root_window: wg::Root_Window,
fontname: String
)
=
{ font = xc::find_else_open_font (wg::xsession_of root_window) fontname;
#
(xc::font_high font) -> { ascent, descent };
lead = ascent + descent;
ANSWER_DIALOG_FACTORY { root_window, font, lead };
};
fun make_answer_dialog_widget
( answer_dialog_factory,
operand1, # First value user is to add/subtract/multiply.
operand2, # Second value user is to add/subtract/multipy.
op_string, # Is user to add, subtract or multiply?
correct_answer # Answer user should have gotten from above.
)
=
{ answer_dialog_factory
->
ANSWER_DIALOG_FACTORY { root_window, font, lead }; # 'lead' is the font height (i.e., ascent + descent).
s1 = int::to_string operand1;
s2 = op_string + " " + (int::to_string operand2);
s3 = int::to_string correct_answer;
l1 = xc::text_width font s1;
l2 = xc::text_width font s2;
l3 = xc::text_width font s3;
wd = int::max (l1, int::max (l2, l3));
s1y = lead;
s2y = s1y + lead;
liney = s2y + 4;
s3y = liney + lead;
size_preferences
=
{ col_preference => wg::tight_preference wd,
row_preference => wg::tight_preference (s3y + 4)
};
(cv::make_canvas root_window size_preferences)
->
(canvas, size, kidplug);
(xc::ignore_mouse_and_keyboard kidplug)
->
xc::KIDPLUG { from_other', ... };
black = xc::black;
pen = xc::make_pen [ xc::p::FOREGROUND (xc::rgb8_from_rgb black) ];
fun main size
=
other_loop size
where
drawable = cv::drawable_of canvas;
draw_transparent_string = xc::draw_transparent_string drawable pen font;
draw_line = xc::draw_lines drawable pen;
fun draw ({ wide, high } )
=
{ log_if debug_tracing 0 {. "in draw"; };
xc::clear_drawable drawable;
draw_transparent_string ({ col=>wide-l1, row=>s1y }, s1);
draw_transparent_string ({ col=>wide-l2, row=>s2y }, s2);
draw_line
[ { col=>0, row=>liney },
{ col=>wide, row=>liney }
];
draw_transparent_string ({ col=>wide-l3, row=>s3y }, s3);
};
fun other_loop size
=
case (xc::get_contents_of_envelope (block_until_mailop_fires from_other'))
#
xc::ETC_REDRAW _
=>
{ draw size;
other_loop size;
};
xc::ETC_RESIZE ({ wide, high, ... } )
=>
other_loop ({ wide, high } );
_ =>
other_loop size;
esac;
end;
make_thread "answer dialogue redrawer" {. main size; };
cv::as_widget canvas;
};
# Display correct answer to
# user in a pop-up dialog window:
#
fun make_answer_dialog
( answer_dialog_factory,
window,
operand1, # First value user is to add/subtract/multiply.
operand2, # Second value user is to add/subtract/multipy.
op_string, # Is user to add, subtract or multiply?
correct_answer # Answer user should have gotten from above.
)
=
{ log_if debug_tracing 0 {. "in show_answer_dialog"; };
answer_dialog_factory
->
ANSWER_DIALOG_FACTORY { root_window, ... };
# We close our pop-up window when
# either of these gets set:
#
close_dialog_oneshot = make_oneshot_maildrop (); # calculation_pane will set this at start of new game.
cancel_button_oneshot = make_oneshot_maildrop (); # Our "Cancel" button will set this when clicked.
answer_dialog_widget
=
make_answer_dialog_widget (answer_dialog_factory, operand1, operand2, op_string, correct_answer);
log_if debug_tracing 0 {. "Created answer_dialog."; };
cancel_button
=
pb::make_text_pushbutton_with_click_callback root_window
{
click_callback => {. put_in_oneshot (cancel_button_oneshot, ()); },
rounded => TRUE,
label => "Cancel",
#
foreground => NULL,
background => NULL
};
pane_layout
=
lw::as_widget
(lw::make_line_of_widgets root_window
( lw::VT_CENTER
[
lw::HZ_CENTER
[
lw::SPACER { min_size=>3, best_size=>3, max_size=>NULL },
lw::WIDGET answer_dialog_widget,
lw::SPACER { min_size=>3, best_size=>3, max_size=>NULL }
],
lw::SPACER { min_size=>5, best_size=>5, max_size=>NULL },
lw::HZ_CENTER
[
lw::SPACER { min_size=>5, best_size=>5, max_size=>NULL },
lw::WIDGET (sz::make_tight_size_preference_wrapper (pb::as_widget cancel_button)),
lw::SPACER { min_size=>5, best_size=>5, max_size=>NULL }
],
lw::SPACER { min_size=>5, best_size=>5, max_size=>NULL }
]
) );
log_if debug_tracing 0 {. "Created layout."; };
hostwindow = tw::make_transient_hostwindow
window
( pane_layout,
NULL,
{ window_name => THE "Answer Dialog",
icon_name => THE "Answer Dialog"
}
);
log_if debug_tracing 0 {. "Created hostwindow."; };
# Close our window if user clicks our "Cancel" button
# or if calculation_pane tells us to (at start of new game):
#
fun close_window_on_command ()
=
{ log_if debug_tracing 0 {. "close_window_on_command await event"; };
#
do_one_mailop (map get_from_oneshot' [close_dialog_oneshot, cancel_button_oneshot]);
log_if debug_tracing 0 {. "close_window_on_command got event; destroy hostwindow"; };
tw::destroy hostwindow;
};
log_if debug_tracing 0 {. "spawn close_window_on_command"; };
make_thread "answer dialog closer" close_window_on_command;
log_if debug_tracing 0 {. "Initializing hostwindow..."; };
tw::start_widgettree_running_in_hostwindow hostwindow;
log_if debug_tracing 0 {. "return iv"; };
close_dialog_oneshot; # Caller can close our window by setting this to void.
};
};
end;