## widget-unit-test.pkg
#
# For the big picture see the imp dataflow diagrams in
#
#
src/lib/x-kit/xclient/src/window/xclient-ximps.pkg#
# NB: We must compile this locally via
# xclient-internals.sublib
# instead of globally via
#
src/lib/test/unit-tests.lib# like most unit tests, in order to have
# access to required library internals.
# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublib# Run by:
#
src/lib/test/all-unit-tests.pkgstipulate
include package unit_test; # unit_test is from
src/lib/src/unit-test.pkg include package makelib::scripting_globals;
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package ap = client_to_atom; # client_to_atom is from
src/lib/x-kit/xclient/src/iccc/client-to-atom.pkg package au = authentication; # authentication is from
src/lib/x-kit/xclient/src/stuff/authentication.pkg package awx = guishim_imp_for_x; # guishim_imp_for_x is from
src/lib/x-kit/widget/xkit/app/guishim-imp-for-x.pkg package agx = app_to_guishim_xspecific; # app_to_guishim_xspecific is from
src/lib/x-kit/widget/theme/app-to-guishim-xspecific.pkg package cpm = cs_pixmap; # cs_pixmap is from
src/lib/x-kit/xclient/src/window/cs-pixmap.pkg package cpt = cs_pixmat; # cs_pixmat is from
src/lib/x-kit/xclient/src/window/cs-pixmat.pkg #
package gd = gui_displaylist; # gui_displaylist is from
src/lib/x-kit/widget/theme/gui-displaylist.pkg #
package dbx = sprite_theme_imp; # sprite_theme_imp is from
src/lib/x-kit/widget/xkit/theme/sprite/default/sprite-theme-imp.pkg package dcx = object_theme_imp; # object_theme_imp is from
src/lib/x-kit/widget/xkit/theme/object/default/object-theme-imp.pkg package dtx = widget_theme_imp; # widget_theme_imp is from
src/lib/x-kit/widget/xkit/theme/widget/default/widget-theme-imp.pkg #
package dy = display; # display is from
src/lib/x-kit/xclient/src/wire/display.pkg# package w2x = windowsystem_to_xserver; # windowsystem_to_xserver is from
src/lib/x-kit/xclient/src/window/windowsystem-to-xserver.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package fti = font_index; # font_index is from
src/lib/x-kit/xclient/src/window/font-index.pkg package gtg = guiboss_to_guishim; # guiboss_to_guishim is from
src/lib/x-kit/widget/theme/guiboss-to-guishim.pkg package gq = guiboss_imp; # guiboss_imp is from
src/lib/x-kit/widget/gui/guiboss-imp.pkg# package r2k = xevent_router_to_keymap; # xevent_router_to_keymap is from
src/lib/x-kit/xclient/src/window/xevent-router-to-keymap.pkg package mtx = rw_matrix; # rw_matrix is from
src/lib/std/src/rw-matrix.pkg package r8 = rgb8; # rgb8 is from
src/lib/x-kit/xclient/src/color/rgb8.pkg package rgb = rgb; # rgb is from
src/lib/x-kit/xclient/src/color/rgb.pkg package rop = ro_pixmap; # ro_pixmap is from
src/lib/x-kit/xclient/src/window/ro-pixmap.pkg package rw = root_window; # root_window is from
src/lib/x-kit/widget/lib/root-window.pkg package rwv = rw_vector; # rw_vector is from
src/lib/std/src/rw-vector.pkg package sep = client_to_selection; # client_to_selection is from
src/lib/x-kit/xclient/src/window/client-to-selection.pkg package shp = shade; # shade is from
src/lib/x-kit/widget/lib/shade.pkg package sj = socket_junk; # socket_junk is from
src/lib/internet/socket-junk.pkg# package x2s = xclient_to_sequencer; # xclient_to_sequencer is from
src/lib/x-kit/xclient/src/wire/xclient-to-sequencer.pkg package ti = template_imp; # template_imp is from
src/lib/x-kit/xclient/src/wire/template-imp.pkg package tem = template; # template is from
src/lib/x-kit/xclient/src/wire/template.pkg package tr = logger; # logger is from
src/lib/src/lib/thread-kit/src/lib/logger.pkg package tsr = thread_scheduler_is_running; # thread_scheduler_is_running is from
src/lib/src/lib/thread-kit/src/core-thread-kit/thread-scheduler-is-running.pkg package u1 = one_byte_unt; # one_byte_unt is from
src/lib/std/one-byte-unt.pkg package v1u = vector_of_one_byte_unts; # vector_of_one_byte_unts is from
src/lib/std/src/vector-of-one-byte-unts.pkg package v2w = value_to_wire; # value_to_wire is from
src/lib/x-kit/xclient/src/wire/value-to-wire.pkg package wg = widget; # widget is from
src/lib/x-kit/widget/old/basic/widget.pkg package wi = window; # window is from
src/lib/x-kit/xclient/src/window/window.pkg package wme = window_map_event_sink; # window_map_event_sink is from
src/lib/x-kit/xclient/src/window/window-map-event-sink.pkg package wpp = client_to_window_watcher; # client_to_window_watcher is from
src/lib/x-kit/xclient/src/window/client-to-window-watcher.pkg package wy = widget_style; # widget_style is from
src/lib/x-kit/widget/lib/widget-style.pkg package xc = xclient; # xclient is from
src/lib/x-kit/xclient/xclient.pkg package g2d = geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg package g2j = geometry2d_junk; # geometry2d_junk is from
src/lib/std/2d/geometry2d-junk.pkg package xj = xsession_junk; # xsession_junk is from
src/lib/x-kit/xclient/src/window/xsession-junk.pkg package xtr = xlogger; # xlogger is from
src/lib/x-kit/xclient/src/stuff/xlogger.pkg package gtj = guiboss_types_junk; # guiboss_types_junk is from
src/lib/x-kit/widget/gui/guiboss-types-junk.pkg package blk = blank; # blank is from
src/lib/x-kit/widget/leaf/blank.pkg package frm = frame; # frame is from
src/lib/x-kit/widget/leaf/frame.pkg package ab = arrowbutton; # arrowbutton is from
src/lib/x-kit/widget/leaf/arrowbutton.pkg package bb = button; # button is from
src/lib/x-kit/widget/leaf/button.pkg package cb = checkbox; # checkbox is from
src/lib/x-kit/widget/leaf/checkbox.pkg package db = diamondbutton; # diamondbutton is from
src/lib/x-kit/widget/leaf/diamondbutton.pkg package rb = roundbutton; # roundbutton is from
src/lib/x-kit/widget/leaf/roundbutton.pkg# package sl = screenline; # screenline is from
src/lib/x-kit/widget/edit/screenline.pkg package tpf = textpane; # textpane is from
src/lib/x-kit/widget/edit/textpane.pkg package his = horizontal_int_slider; # horizontal_int_slider is from
src/lib/x-kit/widget/leaf/horizontal-int-slider.pkg package hfs = horizontal_float_slider; # horizontal_float_slider is from
src/lib/x-kit/widget/leaf/horizontal-float-slider.pkg package vis = vertical_int_slider; # vertical_int_slider is from
src/lib/x-kit/widget/leaf/vertical-int-slider.pkg package vfs = vertical_float_slider; # vertical_float_slider is from
src/lib/x-kit/widget/leaf/vertical-float-slider.pkg package ten = textentry; # textentry is from
src/lib/x-kit/widget/leaf/textentry.pkg package ted = texteditor; # texteditor is from
src/lib/x-kit/widget/edit/texteditor.pkg# package xet = xevent_types; # xevent_types is from
src/lib/x-kit/xclient/src/wire/xevent-types.pkg# package e2s = xevent_to_string; # xevent_to_string is from
src/lib/x-kit/xclient/src/to-string/xevent-to-string.pkg# package xt = xtypes; # xtypes is from
src/lib/x-kit/xclient/src/wire/xtypes.pkg #
# The above three are the X-specific versions of the
# below two platform-independent packages. X events
# come to windowsystem-imp-for-x in xet:: encoding. It # For the big dataflow diagram see
src/lib/x-kit/xclient/src/window/xclient-ximps.pkg # translates them to evt:: encoding and forward them to
# guiboss_imp, which forwards them to appropriate imps. # guiboss_imp is from
src/lib/x-kit/widget/gui/guiboss-imp.pkg #
package gt = guiboss_types; # guiboss_types is from
src/lib/x-kit/widget/gui/guiboss-types.pkg package wt = widget_theme; # widget_theme is from
src/lib/x-kit/widget/theme/widget/widget-theme.pkg package evt = gui_event_types; # gui_event_types is from
src/lib/x-kit/widget/gui/gui-event-types.pkg# package gts = gui_event_to_string; # gui_event_to_string is from
src/lib/x-kit/widget/gui/gui-event-to-string.pkg #
# This one translates from the X to Gui versions:
# package x2g = xevent_to_gui_event; # xevent_to_gui_event is from
src/lib/x-kit/widget/xkit/app/xevent-to-gui-event.pkg# package g2x = gui_event_to_xevent; # gui_event_to_xevent is from
src/lib/x-kit/widget/xkit/app/gui-event-to-xevent.pkg package oim = object_imp; # object_imp is from
src/lib/x-kit/widget/xkit/theme/widget/default/look/object-imp.pkg package sim = sprite_imp; # sprite_imp is from
src/lib/x-kit/widget/xkit/theme/widget/default/look/sprite-imp.pkg package wim = widget_imp; # widget_imp is from
src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg package hslider = horizontal_int_slider; # horizontal_int_slider is from
src/lib/x-kit/widget/leaf/horizontal-int-slider.pkg package hflider = horizontal_float_slider; # horizontal_float_slider is from
src/lib/x-kit/widget/leaf/horizontal-float-slider.pkg package vslider = vertical_int_slider; # vertical_int_slider is from
src/lib/x-kit/widget/leaf/vertical-int-slider.pkg package vflider = vertical_float_slider; # vertical_float_slider is from
src/lib/x-kit/widget/leaf/vertical-float-slider.pkg tracefile = "widget-unit-test.trace.log";
# id = iui::issue_unique_id;
nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkg# These are crude hacks to force these to compile:
#
Dummy1 = wim::Widget;
Dummy2 = oim::Object;
Dummy3 = sim::Sprite;
dummy4 = ab::with;
dummy6 = blk::with;
dummy7 = ten::with;
dummy8 = ted::with;
sample_text
=
"=====================================\t# This is a poem by\n\
\#\t\t\t\t\t# Samuel Taylor Coleridge\n\
\In Xanadu did Kubla Khan\n\
\A stately pleasure-dome decree:\n\
\Where Alph, the sacred river, ran\n\
\Through caverns measureless to man\n\
\\tDown to a sunless sea.\n\
\So twice five miles of fertile ground\n\
\With walls and towers were girdled round;\n\
\And there were gardens bright with sinuous rills,\n\
\Where blossomed many an incense-bearing tree;\n\
\And here were forests ancient as the hills,\n\
\Enfolding sunny spots of greenery.\n\
\\n\
\But oh! that deep romantic chasm which slanted\n\
\Down the green hill athwart a cedarn cover!\n\
\A savage place! as holy and enchanted\n\
\As e'er beneath a waning moon was haunted\n\
\By woman wailing for her demon-lover!\n\
\And from this chasm, with ceaseless turmoil seething,\n\
\As if this earth in fast thick pants were breathing,\n\
\A mighty fountain momently was forced:\n\
\Amid whose swift half-intermitted burst\n\
\Huge fragments vaulted like rebounding hail,\n\
\Or chaffy grain beneath the thresher's flail:\n\
\And 'mid these dancing rocks at once and ever\n\
\It flung up momently the sacred river.\n\
\Five miles meandering with a mazy motion\n\
\Through wood and dale the sacred river ran,\n\
\Then reached the caverns measureless to man,\n\
\And sank in tumult to a lifeless ocean;\n\
\And 'mid this tumult Kubla heard from far\n\
\Ancestral voices prophesying war!\n\
\ The shadow of the dome of pleasure\n\
\ Floated midway on the waves;\n\
\ Where was heard the mingled measure\n\
\ From the fountain and the caves.\n\
\It was a miracle of rare device,\n\
\A sunny pleasure-dome with caves of ice!\n\
\\n\
\ A damsel with a dulcimer\n\
\ In a vision once I saw:\n\
\ It was an Abyssinian maid\n\
\ And on her dulcimer she played,\n\
\ Singing of Mount Abora.\n\
\ Could I revive within me\n\
\ Her symphony and song,\n\
\ To such a deep delight 'twould win me,\n\
\That with music loud and long,\n\
\I would build that dome in air,\n\
\That sunny dome! those caves of ice!\n\
\And all who heard should see them there,\n\
\And all should cry, Beware! Beware!\n\
\His flashing eyes, his floating hair!\n\
\Weave a circle round him thrice,\n\
\And close your eyes with holy dread\n\
\For he on honey-dew hath fed,\n\
\And drunk the milk of Paradise.\n\
\\^A\^B\^C\^I\^K\n\
\And now for something completely different -- some test 16-bit UTF8 chars.\n\
\Depending on your font, you may see mostly boxes:\n\
\ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſ\n\
\ƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀǁǂǃDŽDždžLJLjljNJNjnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏ\n\
\ɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯ\n\
\ʰʱʲʳʴʵʶʷʸʹʺʻʼʽʾʿˀˁ˂˃˄˅ˆˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˜˝˞˟ˠˡˢˣˤ˥˦˧˨˩˪˫ˬ˭ˮ˯˰˱˲˳˴˵˶˷˸˹˺˻˼˽˾˿\n\
\ͰͱͲͳʹ͵Ͷͷͺͻͼͽ;Ϳ΄΅Ά·ΈΉΊΌΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώϏϐϑϒϓϔϕϖϗϘϙϚϛϜϝϞϟϠϡϢϣϤϥϦϧϨϩϪϫϬϭϮϯϰϱϲϳϴϵ϶ϷϸϹϺϻϼϽϾϿ\n\
\ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁ҂҃҄҅҆҇҈҉ҊҋҌҍҎҏҐґҒғҔҕҖҗҘҙҚқҜҝҞҟҠҡҢңҤҥҦҧҨҩҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽҾҿӀӁӂӃӄӅӆӇӈӉӊӋӌӍӎӏӐӑӒӓӔӕӖӗӘәӚӛӜӝӞӟӠӡӢӣӤӥӦӧӨөӪӫӬӭӮӯӰӱӲӳӴӵӶӷӸӹӺӻӼӽӾӿ\\n\
\ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖՙ՚՛՜՝՞ ՟աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆև։֊֍֎֏\n\
\ֿ׀ׁׂ׃ׅׄ׆ׇאבגדהוזחטיךכלםמןנסעףפץצקרשתװױײ׳״\n\
\℀℁ℂ℃℄℅℆ℇ℈℉ℊℋℌℍℎℏℐℑℒℓ℔ℕ№℗℘ℙℚℛℜℝ℞℟℠℡™℣ℤ℥Ω℧ℨ℩KÅℬℭ℮ℯℰℱℲℳℴℵℶℷℸℹ℺℻ℼℽℾℿ⅀⅁⅂⅃⅄ⅅⅆⅇⅈⅉ⅊⅋⅌⅍ⅎ⅏\n\
\⟰⟱⟲⟳⟴⟵⟶⟷⟸⟹⟺⟻⟼⟽⟾⟿⤀⤁⤂⤃⤄⤅⤆⤇⤈⤉⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓⤔⤕⤖⤗⤘⤙⤚⤛⤜⤝⤞⤟⤠⤡⤢⤣⤤⤥⤦⤧⤨⤩⤪⤫⤬⤭⤮⤯⤰⤱⤲⤳⤴⤵⤶⤷⤸⤹⤺⤻⤼⤽⤾⤿⥀⥁⥂⥃⥄⥅⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑⥒⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩⥪⥫⥬⥭⥮⥯⥰⥱⥲⥳⥴⥵⥶⥷⥸⥹⥺⥻⥼⥽⥾⥿\n\
\✁✂✃✄✅✆✇✈✉✊✋✌✍✎✏✐✑✒✓✔✕✖✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✨✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❌❍❎❏❐❑❒❓❔❕❖❗❘❙❚❛❜❝❞❟❠❡❢❣❤❥❦❧❨❩❪❫❬❭❮❯❰❱❲❳❴❵❶❷❸❹❺❻❼❽❾❿➀➁➂➃➄➅➆➇➈➉➊➋➌➍➎➏➐➑➒➓➔➕➖➗➘➙➚➛➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➰➱➲➳➴➵➶➷➸➹➺➻➼➽➾➿\n\
\∑−∓∔∕∖∗∘∙√∛∜∝∞∟\n\
\";
herein
package widget_unit_test {
#
name = "src/lib/x-kit/widget/widget-unit-test.pkg";
trace = xtr::log_if xtr::io_logging 0; # Conditionally write strings to tracing.log or whatever.
fun exercise_convex_hull () # Probably should be in a separate geometry2d-unit-text.pkg, but at the moment I'm too lazy to take time to establish one.
=
{
points1 = [ { col => 100, row => 100 }, { col => 400, row => 100 }, { col => 400, row => 400 }, { col => 100, row => 400 } ];
points2 = [ { col => 200, row => 200 }, { col => 300, row => 200 }, { col => 300, row => 300 }, { col => 200, row => 300 } ];
points3 = points1 @ points2;
#
points1' = g2d::convex_hull points1;
points2' = g2d::convex_hull points2;
points4 = g2d::convex_hull points3;
#
assert (points1' == points1);
assert (points2' == points2);
assert (points4 == points1);
#
points1' = g2d::convex_hull (reverse points1);
points2' = g2d::convex_hull (reverse points2);
points4 = g2d::convex_hull (reverse points3);
#
assert (points1' == points1);
assert (points2' == points2);
assert (points4 == points1);
};
fun exercise_point_in_polygon () # Probably should be in a separate geometry2d-unit-text.pkg, but at the moment I'm too lazy to take time to establish one.
=
{
# Basic square, as above
#
points = [ { col => 100, row => 100 }, { col => 200, row => 100 }, { col => 200, row => 200 }, { col => 100, row => 200 } ];
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == TRUE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
points = [ { col => 100, row => 200 }, { col => 200, row => 200 }, { col => 200, row => 100 }, { col => 100, row => 100 } ]; # Does vertex order matter?
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == TRUE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
points = [ { col => 100, row => 100 }, { col => 100, row => 100 }, # Do duplicate vertices matter?
{ col => 200, row => 100 }, { col => 200, row => 100 },
{ col => 200, row => 200 }, { col => 200, row => 200 },
{ col => 100, row => 200 }, { col => 100, row => 200 }
];
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == TRUE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
# Diamond instead of square:
#
points = [ { col => 100, row => 150 }, { col => 150, row => 200 }, { col => 200, row => 150 }, { col => 150, row => 100 } ];
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == TRUE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
# Chevron shape concave down:
#
points = [ { col => 100, row => 150 }, { col => 150, row => 200 }, { col => 200, row => 150 }, { col => 150, row => 190 } ];
#
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
# Chevron shape concave up:
#
points = [ { col => 100, row => 150 }, { col => 150, row => 110 }, { col => 200, row => 150 }, { col => 150, row => 100 } ];
#
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
# Chevron shape concave left:
#
points = [ { col => 190, row => 150 }, { col => 150, row => 200 }, { col => 200, row => 150 }, { col => 150, row => 100 } ];
#
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
# Chevron shape concave right:
#
points = [ { col => 100, row => 150 }, { col => 150, row => 200 }, { col => 110, row => 150 }, { col => 150, row => 100 } ];
#
#
p1 = { col => 0, row => 0 }; p4 = { col => 0, row => 150 }; p7 = { col => 0, row => 250 }; # Middles of the 9 squares of a tic-tac-toe pattern.
p2 = { col => 150, row => 0 }; p5 = { col => 150, row => 150 }; p8 = { col => 150, row => 250 };
p3 = { col => 250, row => 0 }; p6 = { col => 250, row => 150 }; p9 = { col => 250, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
assert (g2d::point_in_polygon(p9,points) == FALSE);
p1 = { col => 0, row => 100 }; # On the horizontal lines of the tic-tac-toe pattern.
p2 = { col => 250, row => 100 };
p3 = { col => 0, row => 200 };
p4 = { col => 250, row => 200 };
p5 = { col => 100, row => 0 }; # On the vertical lines of the tic-tac-toe pattern.
p7 = { col => 100, row => 250 };
p7 = { col => 200, row => 0 };
p8 = { col => 200, row => 250 };
assert (g2d::point_in_polygon(p1,points) == FALSE);
assert (g2d::point_in_polygon(p2,points) == FALSE);
assert (g2d::point_in_polygon(p3,points) == FALSE);
assert (g2d::point_in_polygon(p4,points) == FALSE);
assert (g2d::point_in_polygon(p5,points) == FALSE);
assert (g2d::point_in_polygon(p6,points) == FALSE);
assert (g2d::point_in_polygon(p7,points) == FALSE);
assert (g2d::point_in_polygon(p8,points) == FALSE);
};
fun next_relief wt::FLAT => wt::RAISED;
next_relief wt::RAISED => wt::SUNKEN;
next_relief wt::SUNKEN => wt::GROOVE;
next_relief wt::GROOVE => wt::RIDGE;
next_relief wt::RIDGE => wt::FLAT;
end;
fun relief_to_string wt::FLAT => "FLAT";
relief_to_string wt::RAISED => "RAISED";
relief_to_string wt::SUNKEN => "SUNKEN";
relief_to_string wt::GROOVE => "GROOVE";
relief_to_string wt::RIDGE => "RIDGE";
end;
fun make_three_row_guiplan
(
scrollable_view_size: g2d::Size,
popup_info: Null_Or( Void -> { requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
),
popup_info3: Null_Or( Void -> { requested_popup_site: g2d::Box, #
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
),
popup_info1c: Null_Or( Void -> { requested_popup_site: g2d::Box, #
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
),
popup_info2c: Null_Or( Void -> { requested_popup_site: g2d::Box, #
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
),
popup_info3c: Null_Or( Void -> { requested_popup_site: g2d::Box, #
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
),
popup_info4c: Null_Or( Void -> { requested_popup_site: g2d::Box, #
popup_plan: gt::Guiplan, #
read_sites_and_ports: Void -> Void
}
)
)
: { guiplan: gt::Guiplan,
# Here we return globals which wind up containing the window sites
# assigned to our various widgets. Normal application code never
# needs to know this, but our test code needs this information in
# order to synthesize fake mouseclicks etc on the buttons.
#
scrollport_scroller: Ref( Null_Or( gt::Scroller ) ),
scroll_state: Ref( g2d::Point ),
widget_sites: { site1a: Ref (Null_Or((Id,g2d::Box))), # Row one, button one.
site2a: Ref (Null_Or((Id,g2d::Box))), # Row one, button two.
site3a: Ref (Null_Or((Id,g2d::Box))), # Row one, button three.
site4a: Ref (Null_Or((Id,g2d::Box))), # Row one, button four.
#
site1b: Ref (Null_Or((Id,g2d::Box))), # Row two, button one.
site2b: Ref (Null_Or((Id,g2d::Box))), # Row two, button two.
site3b: Ref (Null_Or((Id,g2d::Box))), # Row two, button three.
site4b: Ref (Null_Or((Id,g2d::Box))), # Row two, button four.
#
site1c: Ref (Null_Or((Id,g2d::Box))), # Row three, button one.
site2c: Ref (Null_Or((Id,g2d::Box))), # Row three, button two.
site3c: Ref (Null_Or((Id,g2d::Box))), # Row three, button three.
site4c: Ref (Null_Or((Id,g2d::Box))) # Row three, button four.
},
read_back_sites_and_ports_of_guiplan_widgets: Void -> Void # Fills in values of widget_sites
}
=
{
scrollport_scroller = REF (NULL: Null_Or(gt::Scroller)); # This global tracks the scrollport scroller which will be handed to use by guiboss-imp at GUI startup -- see SCROLLABLE_VIEW below in guiplan.
scroll_state = REF { row => 0, col => 0 }; # Not currently in use. This global tracks where the middle roll is current scrolled to. We only need this when doing autoscrolling in conjunction with autoscroll_distance above.
stipulate
site1a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, first button, site notification mailqueue.
site2a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, second button, site notification mailqueue.
site3a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, third button, site notification mailqueue.
site4a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, fourth button, site notification mailqueue.
#
site1b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, first button, site notification mailqueue.
site2b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, second button, site notification mailqueue.
site3b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, third button, site notification mailqueue.
site4b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, fourth button, site notification mailqueue.
#
site1c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, first button, site notification mailqueue.
site2c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, second button, site notification mailqueue.
site3c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, third button, site notification mailqueue.
site4c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, fourth button, site notification mailqueue.
port1a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row one, first button, port notification mailqueue.
port2a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row one, seond button, port notification mailqueue.
port3a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row one, third button, port notification mailqueue.
port4a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row one, fourth button, port notification mailqueue.
#
port1b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row two, first button, port notification mailqueue.
port2b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row two, second button, port notification mailqueue.
port3b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row two, third button, port notification mailqueue.
port4b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row two, fourth button, port notification mailqueue.
#
port1c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row three, first button, port notification mailqueue.
port2c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row three, second button, port notification mailqueue.
port3c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row three, third button, port notification mailqueue.
port4c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or(ab::App_To_Arrowbutton) ); # Row three, fourth button, port notification mailqueue.
herein
# These globals hold the values read from the above
# mailops by the later do_one_mailop() calls.
# They hold the sites (window locations) assigned to
# our twelve pushbuttons. (We need this information
# to generate fake mouseclicks on them for test
# purposes. A normal GUI app wouldn't do this.)
#
site1a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button one.
site2a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button two.
site3a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button three.
site4a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button four.
#
site1b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button one.
site2b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button two.
site3b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button three.
site4b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button four.
#
site1c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button one.
site2c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button two.
site3c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button three.
site4c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button four.
port1a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button one.
port2a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button two.
port3a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button three.
port4a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button four.
# #
port1b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button one.
port2b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button two.
port3b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button three.
port4b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button four.
# #
port1c = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row three, button one.
port2c = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row three, button two.
port3c = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row three, button three.
port4c = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row three, button four.
# These are the site-watcher callbacks we pass to the
# guiboss layer to find out where our buttons are on
# the window:
#
fun sitewatcher1a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
fun sitewatcher2a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
fun sitewatcher3a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3a', site); # Row one, third button, site notification callback.
fun sitewatcher4a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4a', site); # Row one, fourth button, site notification callback.
# #
fun sitewatcher1b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
fun sitewatcher2b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
fun sitewatcher3b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3b', site); # Row two, third button, site notification callback.
fun sitewatcher4b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4b', site); # Row two, fourth button, site notification callback.
# #
fun sitewatcher1c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1c', site); # Row three, first button, site notification callback.
fun sitewatcher2c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2c', site); # Row three, second button, site notification callback.
fun sitewatcher3c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3c', site); # Row three, third button, site notification callback.
fun sitewatcher4c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4c', site); # Row three, fourth button, site notification callback.
fun portwatcher1a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port1a', port); # Row one, first button, port notification callback.
fun portwatcher2a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port2a', port); # Row one, second button, port notification callback.
fun portwatcher3a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port3a', port); # Row one, third button, port notification callback.
fun portwatcher4a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port4a', port); # Row one, fourth button, port notification callback.
# #
fun portwatcher1b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port1b', port); # Row two, first button, port notification callback.
fun portwatcher2b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port2b', port); # Row two, second button, port notification callback.
fun portwatcher3b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port3b', port); # Row two, third button, port notification callback.
fun portwatcher4b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port4b', port); # Row two, fourth button, port notification callback.
# #
fun portwatcher1c (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port1c', port); # Row three, first button, port notification callback.
fun portwatcher2c (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port2c', port); # Row three, second button, port notification callback.
fun portwatcher3c (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port3c', port); # Row three, third button, port notification callback.
fun portwatcher4c (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port4c', port); # Row three, fourth button, port notification callback.
fun read_back_sites_and_ports_of_guiplan_widgets () # Fill in the above globals via blocking reads.
= # We use timeouts (only) to recover gracefully if things are
{ # somehow so broken that guiboss-imp never calls our callbacks.
# The order shouldn't matter; here we go left-to-right top-to-bottom:
# XXX SUCKO FIXME all of these 'take' operations really should be done
# in a microthread that loops, rather than just once here, otherwise
# dynamic re-layout ops will not result in our 'site*' values getting
# properly updated here. (This logic predates dynamic re-layouts.)
do_one_mailop [ take_from_mailqueue' site1a' ==> {. site1a := #site; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no site1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2a' ==> {. site2a := #site; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no site2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3a' ==> {. site3a := #site; assert(TRUE); }, # Row one, button three.
timeout_in' 1.0 ==> {. printf "no site3a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4a' ==> {. site4a := #site; assert(TRUE); }, # Row one, button four.
timeout_in' 1.0 ==> {. printf "no site4a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1b' ==> {. site1b := #site; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no site1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2b' ==> {. site2b := #site; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no site2bin 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3b' ==> {. site3b := #site; assert(TRUE); }, # Row two, button three.
timeout_in' 1.0 ==> {. printf "no site3b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4b' ==> {. site4b := #site; assert(TRUE); }, # Row two, button four.
timeout_in' 1.0 ==> {. printf "no site4b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1c' ==> {. site1c := #site; assert(TRUE); }, # Row three, button one.
timeout_in' 1.0 ==> {. printf "no site1c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2c' ==> {. site2c := #site; assert(TRUE); }, # Row three, button two.
timeout_in' 1.0 ==> {. printf "no site2c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3c' ==> {. site3c := #site; assert(TRUE); }, # Row three, button three.
timeout_in' 1.0 ==> {. printf "no site3c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4c' ==> {. site4c := #site; assert(TRUE); }, # Row three, button four.
timeout_in' 1.0 ==> {. printf "no site4c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port1a' ==> {. port1a := #port; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no port1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port2a' ==> {. port2a := #port; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no port2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port3a' ==> {. port3a := #port; assert(TRUE); }, # Row one, button three.
timeout_in' 1.0 ==> {. printf "no port3a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port4a' ==> {. port4a := #port; assert(TRUE); }, # Row one, button four.
timeout_in' 1.0 ==> {. printf "no port4a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port1b' ==> {. port1b := #port; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no port1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port2b' ==> {. port2b := #port; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no port2b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port3b' ==> {. port3b := #port; assert(TRUE); }, # Row two, button three.
timeout_in' 1.0 ==> {. printf "no port3b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port4b' ==> {. port4b := #port; assert(TRUE); }, # Row two, button four.
timeout_in' 1.0 ==> {. printf "no port4b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port1c' ==> {. port1c := #port; assert(TRUE); }, # Row three, button one.
timeout_in' 1.0 ==> {. printf "no port1c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port2c' ==> {. port2c := #port; assert(TRUE); }, # Row three, button two.
timeout_in' 1.0 ==> {. printf "no port2c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port3c' ==> {. port3c := #port; assert(TRUE); }, # Row three, button three.
timeout_in' 1.0 ==> {. printf "no port3c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port4c' ==> {. port4c := #port; assert(TRUE); }, # Row three, button four.
timeout_in' 1.0 ==> {. printf "no port4c in 1 sec!\n"; assert(FALSE); }
];
};
end; # stipulate
# fun mouse_drag_fn # This mouse-drag callback fn is used by all twelve buttons.
# {
# id: Id, # Unique id.
# doc: String,
# event_point: g2d::Point,
# start_point: g2d::Point,
# last_point: g2d::Point,
# widget_layout_hint: gt::Widget_Layout_Hint,
# site: g2d::Box, # Widget's assigned area in window coordinates.
# phase: gt::Drag_Phase,
# button: evt::Mousebutton,
# modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
# mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
# widget_to_guiboss: gt::Widget_To_Guiboss,
# theme: wt::Widget_Theme,
# do: (Void -> Void) -> Void,
# to: Replyqueue # Used to call 'pass_*' methods in other imps.
# }
# =
# if (phase == gt::DRAG) # Ignore the OPEN and DONE events because OPEN won't have a good last_point and
# # # DONE's event_point may be dubious, e.g. if drag ended outside of drag widget.
# motion = event_point - last_point;
# #
# scroll_state := *scroll_state + motion;
#
# case *scrollport_scroller
# #
# NULL => ();
# THE s => s.set_scrollport_upperleft *scroll_state;
# esac;
# fi;
fun arrowbutton_mouse_drag_fn #
#
(port: Ref( Null_Or( ab::App_To_Arrowbutton ))) # Curried.
#
( ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request:Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
if (mousebuttons_state == evt::only_mouse_button_1_was_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
# Handle drag stuff:
#
if (phase == gt::DRAG) # Ignore the OPEN and DONE events because OPEN won't have a good last_point and
# # DONE's event_point may be dubious, e.g. if drag ended outside of drag widget.
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
if (phase == gt::DONE)
#
case *port
#
NULL =>
{
();
};
THE app_to_arrowbutton
=>
{
relief = app_to_arrowbutton.get_button_relief ();
old_relief = relief;
relief = next_relief relief;
nb {. sprintf "make_three_row_guiplan.arrowbutton_mouse_drag_fn: relief was %s, now %s" (relief_to_string old_relief) (relief_to_string relief); };
app_to_arrowbutton.set_state_to FALSE; # Widget appearance depends on both 'state' and 'relief' settings; keep state FALSE for simplicity.
app_to_arrowbutton.set_button_relief_to relief;
};
esac;
fi;
fi;
stipulate
client_to_guiwindow_ref_1a = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
client_to_guiwindow_ref_4a = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
client_to_guiwindow_ref_1c = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
client_to_guiwindow_ref_2c = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
client_to_guiwindow_ref_3c = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
client_to_guiwindow_ref_4c = REF (NULL: Null_Or( gt::Client_To_Guiwindow ) ); # This is NULL when our popup_plan sub-gui is not running; when popup_plan gui is running it contains (THE client_to_guiwindow), which interface contains the call to shut down the popup gui.
herein
fun mouse_drag_and_popup_fn_1a # This mouse-drag callback fn is used by only row-1, button-4 on guiplan gui, which button pops up a popup gui based on popup_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_1a
#
THE client_to_guiwindow # popup_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_1a := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # popup_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info3
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{
(popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_1a := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
fun mouse_drag_and_popup_fn_4a # This mouse-drag callback fn is used by only row-1, button-4 on guiplan gui, which button pops up a popup gui based on popup_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_4a
#
THE client_to_guiwindow # popup_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_4a := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # popup_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{ (popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_4a := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
fun mouse_drag_and_popup_fn_1c # This mouse-drag callback fn is used by only row-3, button-1 on guiplan gui, which button pops up a popup gui based on hsliders_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_1c
#
THE client_to_guiwindow # hsliders_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_1c := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # hsliders_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info1c
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{
(popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_1c := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
fun mouse_drag_and_popup_fn_2c # This mouse-drag callback fn is used by only row-3, button-2 on guiplan gui, which button pops up a popup gui based on hsliders_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_2c
#
THE client_to_guiwindow # hsliders_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_2c := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # hsliders_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info2c
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{
(popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_2c := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
fun mouse_drag_and_popup_fn_3c # This mouse-drag callback fn is used by only row-3, button-3 on guiplan gui, which button pops up a popup gui based on hsliders_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_3c
#
THE client_to_guiwindow # hsliders_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_3c := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # hsliders_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info3c
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{
(popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_3c := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
fun mouse_drag_and_popup_fn_4c # This mouse-drag callback fn is used by only row-3, button-4 on guiplan gui, which button pops up a popup gui based on hsliders_plan.
(
ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
case phase
#
gt::DONE => (); # Ignore the DONE event.
gt::OPEN
=>
if (button == evt::button1)
#
case *client_to_guiwindow_ref_4c
#
THE client_to_guiwindow # hsliders_plan is running, so we'll interpret the mouse downclick as a request to kill it.
=>
{
client_to_guiwindow.kill_gui (); # Tell guiboss_imp to shut down the popup_plan gui.
#
client_to_guiwindow_ref_4c := NULL; # Trust that guiboss_imp did so and record the popup_plan as being dead.
};
NULL => # hsliders_plan is not currently running, so we'll interpret the mouse downclick as a request try starting it.
case popup_info4c
#
NULL => (); # This gui doesn't pop up a sub-gui.
THE popup_info_fn
=>
{
(popup_info_fn ())
->
{ requested_popup_site: g2d::Box, # For popup_plan this was: { row => 200, col => 200, wide => 1200, high => 900 };
popup_plan: gt::Guiplan, #
read_sites_and_ports
};
(widget_to_guiboss.g.make_popup (requested_popup_site, popup_plan))
->
(actual_site, client_to_guiwindow);
client_to_guiwindow_ref_4c := (THE client_to_guiwindow);
read_sites_and_ports ();
};
esac;
esac;
fi;
gt::DRAG # For drag purposes (sliding the scrollport contents) we ignore the OPEN
=> # and DONE events because OPEN won't have a good last_point and DONE's
if (mousebuttons_state == evt::only_mouse_button_1_was_down # event_point may be dubious, e.g. if drag ended outside of drag widget.
and modifier_keys_state == evt::no_modifier_keys_were_down)
motion = event_point - last_point;
#
scroll_state := *scroll_state + motion;
case *scrollport_scroller
#
NULL => ();
THE s => s.set_scrollport_upperleft *scroll_state;
esac;
fi;
esac;
end;
font = [ "-*-courier-bold-r-*-*-20-*-*-*-*-*-*-*" ];
label_1c = case popup_info1c NULL => ab::TEXT "xyz"; _ => ab::TEXT "HSLIDERS"; esac;
label_2c = case popup_info2c NULL => ab::TEXT "xyz"; _ => ab::TEXT "VSLIDERS"; esac;
label_3c = case popup_info3c NULL => ab::TEXT "xyz"; _ => ab::TEXT "TEXT ENTRIES"; esac;
label_4c = case popup_info4c NULL => ab::TEXT "xyz"; _ => ab::TEXT "TEXT EDITOR"; esac;
guiplan
=
gt::FRAME
( [ gt::FRAME_WIDGET (popupframe::with []) ],
gt::COL
[
( gt::FRAME
# ( [ gt::FRAME_WIDGET (frame::with [ frm::FRAME_INDENT_HINT { pixels_for_top_of_frame => 50, pixels_for_bottom_of_frame => 5, pixels_for_left_of_frame => 3, pixels_for_right_of_frame => 3 }]) ],
( [ gt::FRAME_WIDGET (frame::with [ frm::FRAME_INDENT_HINT { pixels_for_top_of_frame => 0, pixels_for_bottom_of_frame => 0, pixels_for_left_of_frame => 0, pixels_for_right_of_frame => 0 }]) ],
# ( [],
gt::ROW [
arrowbutton::with [ ab::PORTWATCHER portwatcher1a, ab::LEFT , ab::TEXT "BUTTONS", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher1a, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_1a ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher2a, ab::UP , ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher2a, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port2a) ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher3a, ab::DOWN , ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher3a, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port3a) ],
arrowbutton::with [ ab::PORTWATCHER portwatcher4a, ab::RIGHT, ab::TEXT "SUB", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher4a, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_4a ]
]
)
),
( gt::SCROLLPORT
{
scroller_callback => (\\ scroller = scrollport_scroller := scroller): gt::Scroller_Callback,
#
pixmap_size => scrollable_view_size,
widget => gt::FRAME
( [],
gt::ROW [
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher1b, ab::LEFT , ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher1b, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port1b) ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher2b, ab::UP , ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher2b, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port2b) ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher3b, ab::DOWN , ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher3b, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port3b) ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher4b, ab::RIGHT, ab::TEXT "xyz", ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher4b, ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn port4b) ]
]
)
}
),
( gt::FRAME
( [],
gt::ROW [
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher1c, ab::LEFT , label_1c, ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher1c, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_1c ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher2c, ab::UP , label_2c, ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher2c, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_2c ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher3c, ab::DOWN , label_3c, ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher3c, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_3c ],
arrowbutton::with [ ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher4c, ab::RIGHT, label_4c, ab::THICK 20, ab::FONTS font, ab::MARGIN 40, ab::SITEWATCHER sitewatcher4c, ab::MOUSE_DRAG_FN mouse_drag_and_popup_fn_4c ]
]
)
)
]
);
{ guiplan,
scrollport_scroller,
scroll_state,
widget_sites => { site1a, site2a, site3a, site4a,
site1b, site2b, site3b, site4b,
site1c, site2c, site3c, site4c
},
read_back_sites_and_ports_of_guiplan_widgets
};
}; # fun make_three_row_guiplan
fun make_grid_2x2_guiplan ()
#
: { guiplan: gt::Guiplan,
# Here we return globals which wind up containing the window sites
# assigned to our various widgets. Normal application code never
# needs to know this, but our test code needs this information in
# order to synthesize fake mouseclicks etc on the buttons.
#
widget_sites: { site1a: Ref (Null_Or((Id,g2d::Box))), # Row one, button one.
site2a: Ref (Null_Or((Id,g2d::Box))), # Row one, button two.
#
site1b: Ref (Null_Or((Id,g2d::Box))), # Row two, button one.
site2b: Ref (Null_Or((Id,g2d::Box))) # Row two, button two.
},
read_back_sites_and_ports_of_grid_guiplan_widgets: Void -> Void # Fills in values of widget_sites
}
=
{
stipulate
site1a' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or((Id,g2d::Box))); # Row one, first button, site notification mailqueue.
site2a' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or((Id,g2d::Box))); # Row one, second button, site notification mailqueue.
# #
site1b' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or((Id,g2d::Box))); # Row two, first button, site notification mailqueue.
site2b' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or((Id,g2d::Box))); # Row two, second button, site notification mailqueue.
port1a' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or(ab::App_To_Arrowbutton)); # Row one, first button, port notification mailqueue.
port2a' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or(ab::App_To_Arrowbutton)); # Row one, seond button, port notification mailqueue.
#
port1b' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or(ab::App_To_Arrowbutton)); # Row two, first button, port notification mailqueue.
port2b' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or(ab::App_To_Arrowbutton)); # Row two, second button, port notification mailqueue.
port1aa' = make_mailqueue (get_current_microthread()): Mailqueue(Null_Or(rb::App_To_Roundbutton)); # Row one, first button, port notification mailqueue.
herein
# These globals hold the values read from the above
# mailops by the later do_one_mailop() calls.
# They hold the sites (window locations) assigned to
# our twelve pushbuttons. (We need this information
# to generate fake mouseclicks on them for test
# purposes. A normal GUI app wouldn't do this.)
#
site1a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button one.
site2a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button two.
# #
site1b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button one.
site2b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button two.
port1a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button one.
port2a = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row one, button two.
# #
port1b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button one.
port2b = REF (NULL: Null_Or( ab::App_To_Arrowbutton )); # Row two, button two.
port1aa = REF (NULL: Null_Or( rb::App_To_Roundbutton )); # Row one, button one, alternate version (roundbutton vs arrowbutton).
# These are the site-watcher callbacks we pass to the
# guiboss layer to find out where our buttons are on
# the window:
#
# fun sitewatcher1a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
# fun sitewatcher2a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
# # #
# fun sitewatcher1b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
# fun sitewatcher2b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
fun sitewatcher1a (site: Null_Or((Id,g2d::Box)))
=
{
put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
};
fun sitewatcher2a (site: Null_Or((Id,g2d::Box)))
=
{
put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
};
# #
fun sitewatcher1b (site: Null_Or((Id,g2d::Box)))
=
{
put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
};
fun sitewatcher2b (site: Null_Or((Id,g2d::Box)))
=
{
put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
};
fun portwatcher1a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port1a', port); # Row one, first button, port notification callback.
fun portwatcher2a (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port2a', port); # Row one, second button, port notification callback.
# #
fun portwatcher1b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port1b', port); # Row two, first button, port notification callback.
fun portwatcher2b (port: Null_Or(ab::App_To_Arrowbutton)) = put_in_mailqueue (port2b', port); # Row two, second button, port notification callback.
fun portwatcher1aa(port: Null_Or(rb::App_To_Roundbutton)) = put_in_mailqueue (port1aa',port); # Row one, first button, port notification callback, alternate version (roundbutton instead of arrowbutton).
fun read_back_sites_and_ports_of_grid_guiplan_widgets () # Fill in the above globals via blocking reads.
= # We use timeouts (only) to recover gracefully if things are
{ # somehow so broken that guiboss-imp never calls our callbacks.
# The order shouldn't matter; here we go left-to-right top-to-bottom:
do_one_mailop [ take_from_mailqueue' site1a' ==> {. site1a := #site; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no site1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2a' ==> {. site2a := #site; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no site2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1b' ==> {. site1b := #site; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no site1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2b' ==> {. site2b := #site; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no site2b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port1a' ==> {. port1a := #port; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no port1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port2a' ==> {. port2a := #port; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no port2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port1b' ==> {. port1b := #port; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no port1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' port2b' ==> {. port2b := #port; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no port2b in 1 sec!\n"; assert(FALSE); }
];
};
end;
# fun mouse_drag_fn #
# {
# id: Id, # Unique id.
# doc: String,
# event_point: g2d::Point,
# start_point: g2d::Point,
# last_point: g2d::Point,
# widget_layout_hint: gt::Widget_Layout_Hint,
# frame_indent_hint: gt::Frame_Indent_Hint,
# site: g2d::Box, # Widget's assigned area in window coordinates.
# phase: gt::Drag_Phase,
# button: evt::Mousebutton,
# modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
# mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
# widget_to_guiboss: gt::Widget_To_Guiboss,
# theme: wt::Widget_Theme,
# do: (Void -> Void) -> Void,
# to: Replyqueue # Used to call 'pass_*' methods in other imps.
# }
# =
# if (phase == gt::DRAG) # Ignore the OPEN and DONE events because OPEN won't have a good last_point and
# # # DONE's event_point may be dubious, e.g. if drag ended outside of drag widget.
# motion = event_point - last_point;
# #
# fi;
grid_2x2 = issue_unique_id ();
#
bigarrowbtn = issue_unique_id ();
bigroundbtn = issue_unique_id ();
verticalbtn = issue_unique_id ();
horizontalbtn = issue_unique_id ();
cornerbtn = issue_unique_id ();
fun arrowbutton_mouse_drag_fn #
#
(which: Int) # 1,2,3,4.
(port: Ref( Null_Or( ab::App_To_Arrowbutton ))) # Curried.
#
=
{ big = REF FALSE; # Issue each button its own boolean state value.
#
\\ ( ab::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: ab::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_direction: Ref(ab::d::Button_Direction), # Which way does the arrow on the button point?
button_type: ab::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
# Handle drag stuff:
#
case phase
#
gt::OPEN => if (button == evt::button1
and mousebuttons_state == evt::no_mouse_buttons_were_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
if (which == 1)
#
do_while_not {.
#
(widget_to_guiboss.g.get_guipiths ())
->
(gui_version, guipiths);
guipiths = gtj::guipith_map
(
guipiths,
[ gtj::XI_GRID_MAP_FN do_grid
]
)
where
fun do_grid (xi_grid: gt::Xi_Grid)
=
{ xi_grid -> { id: Id, # A grid of widgets.
widgets: List( List( gt::Xi_Widget_Type ) )
};
if (same_id (id, grid_2x2))
#
case xi_grid
#
{ id, widgets => [ [ w1 as gt::XI_WIDGET w1', w2 ], [ w3, w4 ] ] }
=>
{ id, widgets => [ [ w4,
w3
],
[ w2,
gt::XI_GUIPLAN (roundbutton::with [ rb::ID bigroundbtn,
rb::MOMENTARY_CONTACT,
rb::PORTWATCHER portwatcher1aa,
rb::SITEWATCHER sitewatcher1a,
rb::MOUSE_DRAG_FN (roundbutton_mouse_drag_fn 1 port1aa),
rb::PIXELS_HIGH_MIN 0,
rb::PIXELS_WIDE_MIN 0,
rb::PIXELS_HIGH_CUT 1.0,
rb::PIXELS_WIDE_CUT 1.0,
rb::MARGIN 40,
rb::THICK 20
]
)
]
]
};
_ => { log::note_on_stderr {. "widgets grid not 2x2 as expected?! -- arrowbutton_mouse_drag_fn in widget-unit-test.pkg"; };
xi_grid;
};
esac;
else
xi_grid;
fi;
};
end;
widget_to_guiboss.g.install_updated_guipiths # If this returns FALSE we'll repeat.
#
(gui_version, guipiths);
}; # do_while_not
else
big := not *big;
widget_layout_hint
->
{ pixels_high_min,
pixels_wide_min,
pixels_high_cut,
pixels_wide_cut
};
my (pixels_high_min, pixels_wide_min)
=
*big ?? (pixels_high_min + 10, pixels_wide_min + 10)
:: (pixels_high_min - 10, pixels_wide_min - 10);
widget_layout_hint
=
{ pixels_high_min,
pixels_wide_min,
pixels_high_cut,
pixels_wide_cut
};
widget_to_guiboss.note_widget_layout_hint { id, widget_layout_hint };
fi;
();
fi;
gt::DRAG => if (mousebuttons_state == evt::only_mouse_button_1_was_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
fi;
gt::DONE => if (mousebuttons_state == evt::only_mouse_button_1_was_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
case *port
#
NULL =>
{
();
};
THE app_to_arrowbutton
=>
{
relief = app_to_arrowbutton.get_button_relief ();
old_relief = relief;
relief = next_relief relief;
nb {. sprintf "make_grid_2x2_guiplan.arrowbutton_mouse_drag_fn: relief was %s, now %s" (relief_to_string old_relief) (relief_to_string relief); };
app_to_arrowbutton.set_state_to FALSE; # Widget appearance depends on both 'state' and 'relief' settings; keep state FALSE for simplicity.
app_to_arrowbutton.set_button_relief_to relief;
};
esac;
fi;
esac;
}
also
fun roundbutton_mouse_drag_fn #
#
(which: Int) # 1,2,3,4.
(port: Ref( Null_Or( rb::App_To_Roundbutton ))) # Curried.
#
=
{ big = REF FALSE; # Issue each button its own boolean state value.
#
\\ ( rb::MOUSE_DRAG_FN_ARG
{
id: Id, # Unique id.
doc: String,
event_point: g2d::Point,
start_point: g2d::Point,
last_point: g2d::Point,
widget_layout_hint: gt::Widget_Layout_Hint,
frame_indent_hint: gt::Frame_Indent_Hint,
site: g2d::Box, # Widget's assigned area in window coordinates.
phase: gt::Drag_Phase,
button: evt::Mousebutton,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
widget_to_guiboss: gt::Widget_To_Guiboss,
theme: wt::Widget_Theme,
do: (Void -> Void) -> Void, # Used by widget subthreads to execute code in main widget microthread.
to: Replyqueue, # Used to call 'pass_*' methods in other imps.
#
default_mouse_drag_fn: rb::Mouse_Drag_Fn,
#
button_state: Bool, # Is the button ON or OFF?
button_type: rb::t::Button_Type, # Is the button push-on-push-off or momentary-contact?
button_relief: Ref(wt::Relief), # Is the button outline a slope, a ridge, or a flat band?
#
initial_state: Bool, # Original state of button.
note_state: Bool -> Void, # Change state of button. This takes care of notifying our state-watchers.
needs_redraw_gadget_request: Void -> Void # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
}
)
=
# Handle drag stuff:
#
case phase
#
gt::OPEN => if (button == evt::button1
and mousebuttons_state == evt::no_mouse_buttons_were_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
if (which == 1)
#
do_while_not {.
#
(widget_to_guiboss.g.get_guipiths ())
->
(gui_version, guipiths);
guipiths = gtj::guipith_map
(
guipiths,
[ gtj::XI_GRID_MAP_FN do_grid
]
)
where
fun do_grid (xi_grid: gt::Xi_Grid)
=
{ xi_grid -> { id: Id, # A grid of widgets.
widgets: List( List( gt::Xi_Widget_Type ) )
};
if (same_id (id, grid_2x2))
#
case xi_grid
#
{ id, widgets => [ [ w1 as gt::XI_WIDGET w1', w2 ], [ w3, w4 ] ] }
=>
{ id, widgets => [ [ gt::XI_GUIPLAN (arrowbutton::with [ ab::ID bigarrowbtn,
ab::MOMENTARY_CONTACT,
ab::PORTWATCHER portwatcher1a,
ab::SITEWATCHER sitewatcher1a,
ab::LEFT,
ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn 1 port1a),
ab::PIXELS_HIGH_MIN 0,
ab::PIXELS_WIDE_MIN 0,
ab::PIXELS_HIGH_CUT 1.0,
ab::PIXELS_WIDE_CUT 1.0,
ab::MARGIN 40,
ab::THICK 20
]
),
w3
],
[ w2,
w1
]
]
};
_ => { log::note_on_stderr {. "widgets grid not 2x2 as expected?! -- roundbutton_mouse_drag_fn in widget-unit-test.pkg"; };
xi_grid;
};
esac;
else
xi_grid;
fi;
};
end;
widget_to_guiboss.g.install_updated_guipiths # If this returns FALSE, we'll loop back and retry.
#
(gui_version, guipiths);
}; # do_while_not
else
big := not *big;
widget_layout_hint
->
{ pixels_high_min,
pixels_wide_min,
pixels_high_cut,
pixels_wide_cut
};
my (pixels_high_min, pixels_wide_min)
=
*big ?? (pixels_high_min + 10, pixels_wide_min + 10)
:: (pixels_high_min - 10, pixels_wide_min - 10);
widget_layout_hint
=
{ pixels_high_min,
pixels_wide_min,
pixels_high_cut,
pixels_wide_cut
};
widget_to_guiboss.note_widget_layout_hint { id, widget_layout_hint };
fi;
();
fi;
gt::DRAG => if (mousebuttons_state == evt::only_mouse_button_1_was_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
motion = event_point - last_point;
fi;
gt::DONE => if (mousebuttons_state == evt::only_mouse_button_1_was_down
and modifier_keys_state == evt::no_modifier_keys_were_down)
#
case *port
#
NULL =>
{
();
};
THE app_to_roundbutton
=>
{
relief = app_to_roundbutton.get_button_relief ();
old_relief = relief;
relief = next_relief relief;
nb {. sprintf "make_grid_2x2_guiplan.roundbutton_mouse_drag_fn: relief was %s, now %s" (relief_to_string old_relief) (relief_to_string relief); };
app_to_roundbutton.set_state_to FALSE; # Widget appearance depends on both 'state' and 'relief' settings; keep state FALSE for simplicity.
app_to_roundbutton.set_button_relief_to relief;
};
esac;
fi;
esac;
};
guiplan
=
gt::FRAME
( [ gt::FRAME_WIDGET (gt::MARK (popupframe::with [])) ],
( gt::MARK # These two MARKs serve no purpose beyond exercising MARK support code in src/lib/x-kit/widget/gui/translate-guiplan-to-guipane.pkg,
src/lib/x-kit/widget/gui/translate-guipane-to-guipith.pkg and
src/lib/x-kit/widget/gui/guiboss-types.pkg (gt::GRID'
( grid_2x2,
[
[ arrowbutton::with [ ab::ID bigarrowbtn, ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher1a, ab::SITEWATCHER sitewatcher1a, ab::LEFT , ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn 1 port1a), ab::PIXELS_HIGH_MIN 0, ab::PIXELS_WIDE_MIN 0, ab::PIXELS_HIGH_CUT 1.0, ab::PIXELS_WIDE_CUT 1.0, ab::MARGIN 40, ab::THICK 20 ],
arrowbutton::with [ ab::ID verticalbtn, ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher2a, ab::SITEWATCHER sitewatcher2a, ab::UP , ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn 2 port2a), ab::PIXELS_HIGH_MIN 0, ab::PIXELS_WIDE_MIN 40, ab::PIXELS_HIGH_CUT 1.0, ab::PIXELS_WIDE_CUT 0.0 ]
],
[ arrowbutton::with [ ab::ID horizontalbtn, ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher1b, ab::SITEWATCHER sitewatcher1b, ab::LEFT , ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn 3 port1b), ab::PIXELS_HIGH_MIN 40, ab::PIXELS_WIDE_MIN 0, ab::PIXELS_HIGH_CUT 0.0, ab::PIXELS_WIDE_CUT 1.0 ],
arrowbutton::with [ ab::ID cornerbtn, ab::MOMENTARY_CONTACT, ab::PORTWATCHER portwatcher2b, ab::SITEWATCHER sitewatcher2b, ab::UP , ab::MOUSE_DRAG_FN (arrowbutton_mouse_drag_fn 4 port2b), ab::PIXELS_HIGH_MIN 40, ab::PIXELS_WIDE_MIN 40, ab::PIXELS_HIGH_CUT 0.0, ab::PIXELS_WIDE_CUT 0.0 ]
]
]
)
)
)
);
{ guiplan,
widget_sites => { site1a, site2a,
site1b, site2b
},
read_back_sites_and_ports_of_grid_guiplan_widgets
};
}; # fun make_grid_2x2_guiplan
fun make_buttons_guiplan ()
#
: { guiplan: gt::Guiplan,
# Here we return globals which wind up containing the window sites
# assigned to our various widgets. Normal application code never
# needs to know this, but our test code needs this information in
# order to synthesize fake mouseclicks etc on the buttons.
#
widget_sites: { site1a: Ref (Null_Or((Id,g2d::Box))), # Row one, button one.
site2a: Ref (Null_Or((Id,g2d::Box))), # Row one, button two.
site3a: Ref (Null_Or((Id,g2d::Box))), # Row one, button three.
site4a: Ref (Null_Or((Id,g2d::Box))), # Row one, button four.
#
site1b: Ref (Null_Or((Id,g2d::Box))), # Row two, button one.
site2b: Ref (Null_Or((Id,g2d::Box))), # Row two, button two.
site3b: Ref (Null_Or((Id,g2d::Box))), # Row two, button three.
site4b: Ref (Null_Or((Id,g2d::Box))), # Row two, button four.
#
site1c: Ref (Null_Or((Id,g2d::Box))), # Row three, button one.
site2c: Ref (Null_Or((Id,g2d::Box))), # Row three, button two.
site3c: Ref (Null_Or((Id,g2d::Box))), # Row three, button three.
site4c: Ref (Null_Or((Id,g2d::Box))), # Row three, button four.
#
site1d: Ref (Null_Or((Id,g2d::Box))), # Row four, button one.
site2d: Ref (Null_Or((Id,g2d::Box))), # Row four, button two.
site3d: Ref (Null_Or((Id,g2d::Box))), # Row four, button three.
site4d: Ref (Null_Or((Id,g2d::Box))) # Row four, button four.
},
read_back_sites_and_ports_of_buttons_guiplan_widgets: Void -> Void # Fills in values of widget_sites
}
=
{
stipulate
site1a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row one, first button, site notification mailqueue.
site2a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row one, second button, site notification mailqueue.
site3a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row one, third button, site notification mailqueue.
site4a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row one, fourth button, site notification mailqueue.
# #
site1b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row two, first button, site notification mailqueue.
site2b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row two, second button, site notification mailqueue.
site3b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row two, third button, site notification mailqueue.
site4b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row two, fourth button, site notification mailqueue.
# #
site1c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row three, first button, site notification mailqueue.
site2c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row three, second button, site notification mailqueue.
site3c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row three, third button, site notification mailqueue.
site4c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row three, fourth button, site notification mailqueue.
# #
site1d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row four, first button, site notification mailqueue.
site2d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row four, second button, site notification mailqueue.
site3d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row four, third button, site notification mailqueue.
site4d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box))); # Row four, fourth button, site notification mailqueue.
herein
# These globals hold the values read from the above
# mailops by the later do_one_mailop() calls.
# They hold the sites (window locations) assigned to
# our twelve pushbuttons. (We need this information
# to generate fake mouseclicks on them for test
# purposes. A normal GUI app wouldn't do this.)
#
site1a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button one.
site2a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button two.
site3a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button three.
site4a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button four.
# #
site1b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button one.
site2b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button two.
site3b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button three.
site4b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button four.
# #
site1c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button one.
site2c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button two.
site3c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button three.
site4c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button four.
# #
site1d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button one.
site2d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button two.
site3d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button three.
site4d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button four.
# These are the site-watcher callbacks we pass to the
# guiboss layer to find out where our buttons are on
# the window:
#
fun sitewatcher1a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
fun sitewatcher2a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
fun sitewatcher3a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3a', site); # Row one, third button, site notification callback.
fun sitewatcher4a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4a', site); # Row one, fourth button, site notification callback.
# #
fun sitewatcher1b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
fun sitewatcher2b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
fun sitewatcher3b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3b', site); # Row two, third button, site notification callback.
fun sitewatcher4b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4b', site); # Row two, fourth button, site notification callback.
# #
fun sitewatcher1c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1c', site); # Row three, first button, site notification callback.
fun sitewatcher2c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2c', site); # Row three, second button, site notification callback.
fun sitewatcher3c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3c', site); # Row three, third button, site notification callback.
fun sitewatcher4c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4c', site); # Row three, fourth button, site notification callback.
# #
fun sitewatcher1d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1d', site); # Row four, first button, site notification callback.
fun sitewatcher2d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2d', site); # Row four, second button, site notification callback.
fun sitewatcher3d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site3d', site); # Row four, third button, site notification callback.
fun sitewatcher4d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site4d', site); # Row four, fourth button, site notification callback.
fun read_back_sites_and_ports_of_buttons_guiplan_widgets () # Fill in the above globals via blocking reads.
= # We use timeouts (only) to recover gracefully if things are
{ # somehow so broken that guiboss-imp never calls our callbacks.
# The order shouldn't matter; here we go left-to-right top-to-bottom:
do_one_mailop [ take_from_mailqueue' site1a' ==> {. site1a := #site; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no site1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2a' ==> {. site2a := #site; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no site2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3a' ==> {. site3a := #site; assert(TRUE); }, # Row one, button three.
timeout_in' 1.0 ==> {. printf "no site3a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4a' ==> {. site4a := #site; assert(TRUE); }, # Row one, button four.
timeout_in' 1.0 ==> {. printf "no site4a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1b' ==> {. site1b := #site; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no site1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2b' ==> {. site2b := #site; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no site2b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3b' ==> {. site3b := #site; assert(TRUE); }, # Row two, button three.
timeout_in' 1.0 ==> {. printf "no site3b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4b' ==> {. site4b := #site; assert(TRUE); }, # Row two, button four.
timeout_in' 1.0 ==> {. printf "no site4b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1c' ==> {. site1c := #site; assert(TRUE); }, # Row three, button one.
timeout_in' 1.0 ==> {. printf "no site1c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2c' ==> {. site2c := #site; assert(TRUE); }, # Row three, button two.
timeout_in' 1.0 ==> {. printf "no site2c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3c' ==> {. site3c := #site; assert(TRUE); }, # Row three, button three.
timeout_in' 1.0 ==> {. printf "no site3c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4c' ==> {. site4c := #site; assert(TRUE); }, # Row three, button four.
timeout_in' 1.0 ==> {. printf "no site4c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1d' ==> {. site1d := #site; assert(TRUE); }, # Row four, button one.
timeout_in' 1.0 ==> {. printf "no site1d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2d' ==> {. site2d := #site; assert(TRUE); }, # Row four, button two.
timeout_in' 1.0 ==> {. printf "no site2d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site3d' ==> {. site3d := #site; assert(TRUE); }, # Row four, button three.
timeout_in' 1.0 ==> {. printf "no site3d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site4d' ==> {. site4d := #site; assert(TRUE); }, # Row four, button four.
timeout_in' 1.0 ==> {. printf "no site4d in 1 sec!\n"; assert(FALSE); }
];
};
end;
on_image
=
mtx::make_rw_matrix ((rows, cols), yellow)
where
rows = 30;
cols = 30;
yellow = r8::rgb8_yellow;
end;
off_image
=
mtx::make_rw_matrix ((rows, cols), green)
where
rows = 30;
cols = 30;
green = r8::rgb8_green;
end;
guiplan
=
gt::FRAME
( [ gt::FRAME_WIDGET (popupframe::with []) ],
( gt::GRID
[
[ arrowbutton::with [ ab::SITEWATCHER sitewatcher1a, ab::LEFT , ab::PIXELS_HIGH_MIN 0, ab::PIXELS_WIDE_MIN 0, ab::PIXELS_HIGH_CUT 1.0, ab::PIXELS_WIDE_CUT 1.0 ],
button::with [ bb::SITEWATCHER sitewatcher2a, bb::PIXELS_HIGH_MIN 0, bb::PIXELS_WIDE_MIN 0, bb::PIXELS_HIGH_CUT 1.0, bb::PIXELS_WIDE_CUT 1.0 ],
checkbox::with [ cb::SITEWATCHER sitewatcher3a, cb::PIXELS_HIGH_MIN 0, cb::PIXELS_WIDE_MIN 0, cb::PIXELS_HIGH_CUT 1.0, cb::PIXELS_WIDE_CUT 1.0 ],
checkbox::with [ cb::SITEWATCHER sitewatcher4a, cb::TEXT "fee", cb::ON_TEXT "FEE", cb::PIXELS_HIGH_MIN 0, cb::PIXELS_WIDE_MIN 0, cb::PIXELS_HIGH_CUT 1.0, cb::PIXELS_WIDE_CUT 1.0 ]
],
[ diamondbutton::with [ db::SITEWATCHER sitewatcher1b, db::TEXT "bff", db::ON_TEXT "BFF", db::PIXELS_HIGH_MIN 0, db::PIXELS_WIDE_MIN 0, db::PIXELS_HIGH_CUT 1.0, db::PIXELS_WIDE_CUT 1.0 ],
roundbutton::with [ rb::SITEWATCHER sitewatcher2b, rb::TEXT "xyz", rb::PIXELS_HIGH_MIN 0, rb::PIXELS_WIDE_MIN 0, rb::PIXELS_HIGH_CUT 1.0, rb::PIXELS_WIDE_CUT 1.0 ],
blank::with [ blk::SITEWATCHER sitewatcher3b, blk::PIXELS_HIGH_MIN 0, blk::PIXELS_WIDE_MIN 0, blk::PIXELS_HIGH_CUT 1.0, blk::PIXELS_WIDE_CUT 1.0 ],
checkbox::with [ cb::SITEWATCHER sitewatcher4b, cb::TEXT "fie", cb::ON_TEXT "FIE", cb::PIXELS_HIGH_MIN 0, cb::PIXELS_WIDE_MIN 0, cb::PIXELS_HIGH_CUT 1.0, cb::PIXELS_WIDE_CUT 1.0 ]
],
[ button::with [ bb::SITEWATCHER sitewatcher1c, bb::ON_IMAGE on_image, bb::OFF_IMAGE off_image, bb::PIXELS_HIGH_MIN 0, bb::PIXELS_WIDE_MIN 0, bb::PIXELS_HIGH_CUT 1.0, bb::PIXELS_WIDE_CUT 1.0 ],
button::with [ bb::SITEWATCHER sitewatcher2c, bb::ON_IMAGE on_image, bb::OFF_IMAGE off_image, bb::ITALIC, bb::ON_TEXT "ON", bb::OFF_TEXT "OFF", bb::PIXELS_HIGH_MIN 0, bb::PIXELS_WIDE_MIN 0, bb::PIXELS_HIGH_CUT 1.0, bb::PIXELS_WIDE_CUT 1.0 ],
button::with [ bb::SITEWATCHER sitewatcher3c, bb::ITALIC, bb::ON_TEXT "ON", bb::OFF_TEXT "OFF", bb::PIXELS_HIGH_MIN 0, bb::PIXELS_WIDE_MIN 0, bb::PIXELS_HIGH_CUT 1.0, bb::PIXELS_WIDE_CUT 1.0 ],
checkbox::with [ cb::SITEWATCHER sitewatcher4c, cb::TEXT "foe", cb::ON_TEXT "FOE", cb::PIXELS_HIGH_MIN 0, cb::PIXELS_WIDE_MIN 0, cb::PIXELS_HIGH_CUT 1.0, cb::PIXELS_WIDE_CUT 1.0 ]
],
[ blank::with [ blk::SITEWATCHER sitewatcher1d, blk::PIXELS_HIGH_MIN 0, blk::PIXELS_WIDE_MIN 0, blk::PIXELS_HIGH_CUT 1.0, blk::PIXELS_WIDE_CUT 1.0 ],
his::with [ his::SITEWATCHER sitewatcher2d, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ],
blank::with [ blk::SITEWATCHER sitewatcher3d, blk::PIXELS_HIGH_MIN 0, blk::PIXELS_WIDE_MIN 0, blk::PIXELS_HIGH_CUT 1.0, blk::PIXELS_WIDE_CUT 1.0 ],
checkbox::with [ cb::SITEWATCHER sitewatcher4d, cb::TEXT "fum", cb::ON_TEXT "FUM", cb::PIXELS_HIGH_MIN 0, cb::PIXELS_WIDE_MIN 0, cb::PIXELS_HIGH_CUT 1.0, cb::PIXELS_WIDE_CUT 1.0 ]
]
]
)
);
{ guiplan,
widget_sites => { site1a, site2a, site3a, site4a,
site1b, site2b, site3b, site4b,
site1c, site2c, site3c, site4c,
site1d, site2d, site3d, site4d
},
read_back_sites_and_ports_of_buttons_guiplan_widgets
};
}; # fun make_buttons_guiplan
fun make_hsliders_guiplan ()
#
: { guiplan: gt::Guiplan,
# Here we return globals which wind up containing the window sites
# assigned to our various widgets. Normal application code never
# needs to know this, but our test code needs this information in
# order to synthesize fake mouseclicks etc on the buttons.
#
widget_sites: { site1a: Ref (Null_Or((Id,g2d::Box))), # Row one, button one.
site2a: Ref (Null_Or((Id,g2d::Box))), # Row one, button two.
#
site1b: Ref (Null_Or((Id,g2d::Box))), # Row two, button one.
site2b: Ref (Null_Or((Id,g2d::Box))), # Row two, button two.
#
site1c: Ref (Null_Or((Id,g2d::Box))), # Row three, button one.
site2c: Ref (Null_Or((Id,g2d::Box))), # Row three, button two.
#
site1d: Ref (Null_Or((Id,g2d::Box))), # Row four, button one.
site2d: Ref (Null_Or((Id,g2d::Box))), # Row four, button two.
#
site1e: Ref (Null_Or((Id,g2d::Box))), # Row five, button one.
site2e: Ref (Null_Or((Id,g2d::Box))), # Row five, button two.
#
site1f: Ref (Null_Or((Id,g2d::Box))), # Row six, button one.
site2f: Ref (Null_Or((Id,g2d::Box))), # Row six, button two.
#
site1g: Ref (Null_Or((Id,g2d::Box))), # Row seven, button one.
site2g: Ref (Null_Or((Id,g2d::Box))), # Row seven, button two.
#
site1h: Ref (Null_Or((Id,g2d::Box))), # Row eight, button one.
site2h: Ref (Null_Or((Id,g2d::Box))) # Row eight, button two.
},
read_back_sites_and_ports_of_hsliders: Void -> Void # Fills in values of widget_sites
}
=
{
stipulate
site1a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, first button, site notification mailqueue.
site2a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, second button, site notification mailqueue.
# #
site1b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, first button, site notification mailqueue.
site2b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, second button, site notification mailqueue.
# #
site1c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, first button, site notification mailqueue.
site2c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, second button, site notification mailqueue.
# #
site1d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row four, first button, site notification mailqueue.
site2d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row four, second button, site notification mailqueue.
# #
site1e' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row five, first button, site notification mailqueue.
site2e' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row five, second button, site notification mailqueue.
# #
site1f' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row six, first button, site notification mailqueue.
site2f' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row six, second button, site notification mailqueue.
# #
site1g' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row seven, first button, site notification mailqueue.
site2g' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row seven, second button, site notification mailqueue.
# #
site1h' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row eight, first button, site notification mailqueue.
site2h' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row eight, second button, site notification mailqueue.
herein
# These globals hold the values read from the above
# mailops by the later do_one_mailop() calls.
# They hold the sites (window locations) assigned to
# our twelve pushbuttons. (We need this information
# to generate fake mouseclicks on them for test
# purposes. A normal GUI app wouldn't do this.)
#
site1a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button one.
site2a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button two.
# #
site1b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button one.
site2b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button two.
# #
site1c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button one.
site2c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button two.
# #
site1d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button one.
site2d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button two.
# #
site1e = REF (NULL: Null_Or((Id,g2d::Box))); # Row five, button one.
site2e = REF (NULL: Null_Or((Id,g2d::Box))); # Row five, button two.
# #
site1f = REF (NULL: Null_Or((Id,g2d::Box))); # Row six, button one.
site2f = REF (NULL: Null_Or((Id,g2d::Box))); # Row six, button two.
# #
site1g = REF (NULL: Null_Or((Id,g2d::Box))); # Row seven, button one.
site2g = REF (NULL: Null_Or((Id,g2d::Box))); # Row seven, button two.
# #
site1h = REF (NULL: Null_Or((Id,g2d::Box))); # Row eight, button one.
site2h = REF (NULL: Null_Or((Id,g2d::Box))); # Row eight, button two.
# These are the site-watcher callbacks we pass to the
# guiboss layer to find out where our buttons are on
# the window:
#
fun sitewatcher1a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
fun sitewatcher2a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
# #
fun sitewatcher1b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
fun sitewatcher2b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
# #
fun sitewatcher1c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1c', site); # Row three, first button, site notification callback.
fun sitewatcher2c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2c', site); # Row three, second button, site notification callback.
# #
fun sitewatcher1d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1d', site); # Row four, first button, site notification callback.
fun sitewatcher2d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2d', site); # Row four, second button, site notification callback.
# #
fun sitewatcher1e (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1e', site); # Row five, first button, site notification callback.
fun sitewatcher2e (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2e', site); # Row five, second button, site notification callback.
# #
fun sitewatcher1f (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1f', site); # Row six, first button, site notification callback.
fun sitewatcher2f (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2f', site); # Row six, second button, site notification callback.
# #
fun sitewatcher1g (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1g', site); # Row seven, first button, site notification callback.
fun sitewatcher2g (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2g', site); # Row seven, second button, site notification callback.
# #
fun sitewatcher1h (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1h', site); # Row eight, first button, site notification callback.
fun sitewatcher2h (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2h', site); # Row eight, second button, site notification callback.
fun read_back_sites_and_ports_of_hsliders () # Fill in the above globals via blocking reads.
= # We use timeouts (only) to recover gracefully if things are
{ # somehow so broken that guiboss-imp never calls our callbacks.
# The order shouldn't matter; here we go left-to-right top-to-bottom:
do_one_mailop [ take_from_mailqueue' site1a' ==> {. site1a := #site; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no site1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2a' ==> {. site2a := #site; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no site2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1b' ==> {. site1b := #site; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no site1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2b' ==> {. site2b := #site; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no site2b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1c' ==> {. site1c := #site; assert(TRUE); }, # Row three, button one.
timeout_in' 1.0 ==> {. printf "no site1c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2c' ==> {. site2c := #site; assert(TRUE); }, # Row three, button two.
timeout_in' 1.0 ==> {. printf "no site2c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1d' ==> {. site1d := #site; assert(TRUE); }, # Row four, button one.
timeout_in' 1.0 ==> {. printf "no site1d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2d' ==> {. site2d := #site; assert(TRUE); }, # Row four, button two.
timeout_in' 1.0 ==> {. printf "no site2d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1e' ==> {. site1e := #site; assert(TRUE); }, # Row five, button one.
timeout_in' 1.0 ==> {. printf "no site1e in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2e' ==> {. site2e := #site; assert(TRUE); }, # Row five, button two.
timeout_in' 1.0 ==> {. printf "no site2e in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1f' ==> {. site1f := #site; assert(TRUE); }, # Row six, button one.
timeout_in' 1.0 ==> {. printf "no site1f in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2f' ==> {. site2f := #site; assert(TRUE); }, # Row six, button two.
timeout_in' 1.0 ==> {. printf "no site2f in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1g' ==> {. site1g := #site; assert(TRUE); }, # Row seven, button one.
timeout_in' 1.0 ==> {. printf "no site1g in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2g' ==> {. site2g := #site; assert(TRUE); }, # Row seven, button two.
timeout_in' 1.0 ==> {. printf "no site2g in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1h' ==> {. site1h := #site; assert(TRUE); }, # Row eight, button one.
timeout_in' 1.0 ==> {. printf "no site1h in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2h' ==> {. site2h := #site; assert(TRUE); }, # Row eight, button two.
timeout_in' 1.0 ==> {. printf "no site2h in 1 sec!\n"; assert(FALSE); }
];
};
end;
on_image
=
mtx::make_rw_matrix ((rows, cols), yellow)
where
rows = 30;
cols = 30;
yellow = r8::rgb8_yellow;
end;
off_image
=
mtx::make_rw_matrix ((rows, cols), green)
where
rows = 30;
cols = 30;
green = r8::rgb8_green;
end;
guiplan
=
gt::FRAME
( [ gt::FRAME_WIDGET (popupframe::with []) ],
( gt::GRID
[
[ hflider::with [ hfs::SITEWATCHER sitewatcher1a, hfs::TEXT "red", hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ],
hflider::with [ hfs::SITEWATCHER sitewatcher2a, hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ]
],
[ hflider::with [ hfs::SITEWATCHER sitewatcher1b, hfs::TEXT "green", hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0, hfs::SHOW_LIMITS FALSE, hfs::SHOW_VALUE FALSE, hfs::COVERAGE 0.3 ],
hflider::with [ hfs::SITEWATCHER sitewatcher2b, hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0, hfs::SHOW_LIMITS FALSE, hfs::SHOW_VALUE FALSE, hfs::COVERAGE 0.3 ]
],
[ hflider::with [ hfs::SITEWATCHER sitewatcher1c, hfs::TEXT "blue", hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ],
hflider::with [ hfs::SITEWATCHER sitewatcher2c, hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ]
],
[ hflider::with [ hfs::SITEWATCHER sitewatcher1d, hfs::TEXT "alpha", hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ],
hflider::with [ hfs::SITEWATCHER sitewatcher2d, hfs::LOWER_LIMIT 0.0, hfs::UPPER_LIMIT 1.0, hfs::INITIAL_VALUE 0.5, hfs::PIXELS_HIGH_MIN 0, hfs::PIXELS_WIDE_MIN 0, hfs::PIXELS_HIGH_CUT 1.0, hfs::PIXELS_WIDE_CUT 1.0 ]
],
[ hslider::with [ his::SITEWATCHER sitewatcher1e, his::TEXT "red", his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ],
hslider::with [ his::SITEWATCHER sitewatcher2e, his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ]
],
[ hslider::with [ his::SITEWATCHER sitewatcher1f, his::TEXT "green", his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0, his::SHOW_LIMITS FALSE, his::SHOW_VALUE FALSE, his::COVERAGE 0.3 ],
hslider::with [ his::SITEWATCHER sitewatcher2f, his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0, his::SHOW_LIMITS FALSE, his::SHOW_VALUE FALSE, his::COVERAGE 0.3 ]
],
[ hslider::with [ his::SITEWATCHER sitewatcher1g, his::TEXT "blue", his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ],
hslider::with [ his::SITEWATCHER sitewatcher2g, his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ]
],
[ hslider::with [ his::SITEWATCHER sitewatcher1h, his::TEXT "alpha", his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ],
hslider::with [ his::SITEWATCHER sitewatcher2h, his::LOWER_LIMIT 0, his::UPPER_LIMIT 1000, his::INITIAL_VALUE 500, his::PIXELS_HIGH_MIN 0, his::PIXELS_WIDE_MIN 0, his::PIXELS_HIGH_CUT 1.0, his::PIXELS_WIDE_CUT 1.0 ]
]
]
)
);
{ guiplan,
widget_sites => { site1a, site2a,
site1b, site2b,
site1c, site2c,
site1d, site2d,
site1e, site2e,
site1f, site2f,
site1g, site2g,
site1h, site2h
},
read_back_sites_and_ports_of_hsliders
};
}; # fun make_hsliders_guiplan
fun make_vsliders_guiplan ()
#
: { guiplan: gt::Guiplan,
# Here we return globals which wind up containing the window sites
# assigned to our various widgets. Normal application code never
# needs to know this, but our test code needs this information in
# order to synthesize fake mouseclicks etc on the buttons.
#
widget_sites: { site1a: Ref (Null_Or((Id,g2d::Box))), # Row one, button one.
site2a: Ref (Null_Or((Id,g2d::Box))), # Row one, button two.
#
site1b: Ref (Null_Or((Id,g2d::Box))), # Row two, button one.
site2b: Ref (Null_Or((Id,g2d::Box))), # Row two, button two.
#
site1c: Ref (Null_Or((Id,g2d::Box))), # Row three, button one.
site2c: Ref (Null_Or((Id,g2d::Box))), # Row three, button two.
#
site1d: Ref (Null_Or((Id,g2d::Box))), # Row four, button one.
site2d: Ref (Null_Or((Id,g2d::Box))), # Row four, button two.
#
site1e: Ref (Null_Or((Id,g2d::Box))), # Row five, button one.
site2e: Ref (Null_Or((Id,g2d::Box))), # Row five, button two.
#
site1f: Ref (Null_Or((Id,g2d::Box))), # Row six, button one.
site2f: Ref (Null_Or((Id,g2d::Box))), # Row six, button two.
#
site1g: Ref (Null_Or((Id,g2d::Box))), # Row seven, button one.
site2g: Ref (Null_Or((Id,g2d::Box))), # Row seven, button two.
#
site1h: Ref (Null_Or((Id,g2d::Box))), # Row eight, button one.
site2h: Ref (Null_Or((Id,g2d::Box))) # Row eight, button two.
},
read_back_sites_and_ports_of_vsliders: Void -> Void # Fills in values of widget_sites
}
=
{
stipulate
site1a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, first button, site notification mailqueue.
site2a' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row one, second button, site notification mailqueue.
# #
site1b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, first button, site notification mailqueue.
site2b' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row two, second button, site notification mailqueue.
# #
site1c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, first button, site notification mailqueue.
site2c' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row three, second button, site notification mailqueue.
# #
site1d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row four, first button, site notification mailqueue.
site2d' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row four, second button, site notification mailqueue.
# #
site1e' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row five, first button, site notification mailqueue.
site2e' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row five, second button, site notification mailqueue.
# #
site1f' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row six, first button, site notification mailqueue.
site2f' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row six, second button, site notification mailqueue.
# #
site1g' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row seven, first button, site notification mailqueue.
site2g' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row seven, second button, site notification mailqueue.
# #
site1h' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row eight, first button, site notification mailqueue.
site2h' = make_mailqueue (get_current_microthread()): Mailqueue( Null_Or((Id,g2d::Box)) ); # Row eight, second button, site notification mailqueue.
herein
# These globals hold the values read from the above
# mailops by the later do_one_mailop() calls.
# They hold the sites (window locations) assigned to
# our twelve pushbuttons. (We need this information
# to generate fake mouseclicks on them for test
# purposes. A normal GUI app wouldn't do this.)
#
site1a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button one.
site2a = REF (NULL: Null_Or((Id,g2d::Box))); # Row one, button two.
# #
site1b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button one.
site2b = REF (NULL: Null_Or((Id,g2d::Box))); # Row two, button two.
# #
site1c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button one.
site2c = REF (NULL: Null_Or((Id,g2d::Box))); # Row three, button two.
# #
site1d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button one.
site2d = REF (NULL: Null_Or((Id,g2d::Box))); # Row four, button two.
# #
site1e = REF (NULL: Null_Or((Id,g2d::Box))); # Row five, button one.
site2e = REF (NULL: Null_Or((Id,g2d::Box))); # Row five, button two.
# #
site1f = REF (NULL: Null_Or((Id,g2d::Box))); # Row six, button one.
site2f = REF (NULL: Null_Or((Id,g2d::Box))); # Row six, button two.
# #
site1g = REF (NULL: Null_Or((Id,g2d::Box))); # Row seven, button one.
site2g = REF (NULL: Null_Or((Id,g2d::Box))); # Row seven, button two.
# #
site1h = REF (NULL: Null_Or((Id,g2d::Box))); # Row eight, button one.
site2h = REF (NULL: Null_Or((Id,g2d::Box))); # Row eight, button two.
# These are the site-watcher callbacks we pass to the
# guiboss layer to find out where our buttons are on
# the window:
#
fun sitewatcher1a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1a', site); # Row one, first button, site notification callback.
fun sitewatcher2a (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2a', site); # Row one, second button, site notification callback.
# #
fun sitewatcher1b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1b', site); # Row two, first button, site notification callback.
fun sitewatcher2b (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2b', site); # Row two, second button, site notification callback.
# #
fun sitewatcher1c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1c', site); # Row three, first button, site notification callback.
fun sitewatcher2c (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2c', site); # Row three, second button, site notification callback.
# #
fun sitewatcher1d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1d', site); # Row four, first button, site notification callback.
fun sitewatcher2d (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2d', site); # Row four, second button, site notification callback.
# #
fun sitewatcher1e (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1e', site); # Row five, first button, site notification callback.
fun sitewatcher2e (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2e', site); # Row five, second button, site notification callback.
# #
fun sitewatcher1f (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1f', site); # Row six, first button, site notification callback.
fun sitewatcher2f (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2f', site); # Row six, second button, site notification callback.
# #
fun sitewatcher1g (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1g', site); # Row seven, first button, site notification callback.
fun sitewatcher2g (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2g', site); # Row seven, second button, site notification callback.
# #
fun sitewatcher1h (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site1h', site); # Row eight, first button, site notification callback.
fun sitewatcher2h (site: Null_Or((Id,g2d::Box))) = put_in_mailqueue (site2h', site); # Row eight, second button, site notification callback.
fun read_back_sites_and_ports_of_vsliders () # Fill in the above globals via blocking reads.
= # We use timeouts (only) to recover gracefully if things are
{ # somehow so broken that guiboss-imp never calls our callbacks.
# The order shouldn't matter; here we go left-to-right top-to-bottom:
do_one_mailop [ take_from_mailqueue' site1a' ==> {. site1a := #site; assert(TRUE); }, # Row one, button one.
timeout_in' 1.0 ==> {. printf "no site1a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2a' ==> {. site2a := #site; assert(TRUE); }, # Row one, button two.
timeout_in' 1.0 ==> {. printf "no site2a in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1b' ==> {. site1b := #site; assert(TRUE); }, # Row two, button one.
timeout_in' 1.0 ==> {. printf "no site1b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2b' ==> {. site2b := #site; assert(TRUE); }, # Row two, button two.
timeout_in' 1.0 ==> {. printf "no site2b in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1c' ==> {. site1c := #site; assert(TRUE); }, # Row three, button one.
timeout_in' 1.0 ==> {. printf "no site1c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2c' ==> {. site2c := #site; assert(TRUE); }, # Row three, button two.
timeout_in' 1.0 ==> {. printf "no site2c in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1d' ==> {. site1d := #site; assert(TRUE); }, # Row four, button one.
timeout_in' 1.0 ==> {. printf "no site1d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2d' ==> {. site2d := #site; assert(TRUE); }, # Row four, button two.
timeout_in' 1.0 ==> {. printf "no site2d in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1e' ==> {. site1e := #site; assert(TRUE); }, # Row five, button one.
timeout_in' 1.0 ==> {. printf "no site1e in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2e' ==> {. site2e := #site; assert(TRUE); }, # Row five, button two.
timeout_in' 1.0 ==> {. printf "no site2e in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1f' ==> {. site1f := #site; assert(TRUE); }, # Row six, button one.
timeout_in' 1.0 ==> {. printf "no site1f in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2f' ==> {. site2f := #site; assert(TRUE); }, # Row six, button two.
timeout_in' 1.0 ==> {. printf "no site2f in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site1g' ==> {. site1g := #site; assert(TRUE); }, # Row seven, button one.
timeout_in' 1.0 ==> {. printf "no site1g in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [ take_from_mailqueue' site2g' ==> {. site2g := #site; assert(TRUE); }, # Row seven, button two.
timeout_in' 1.0 ==> {. printf "no site2g in 1 sec!\n"; assert(FALSE); }
];
do_one_mailop [&n