PreviousUpNext

15.4.1356  src/lib/x-kit/tut/arithmetic-game/answer-dialog-factory.pkg

## 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.lib

stipulate
    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.pkg
herein

    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;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext