## widgetspace-imp.pkg
#
# For background see comments at top of
#
src/lib/x-kit/widget/gui/guiboss-imp.pkg#
# For the big picture see the imp dataflow diagrams in
#
#
src/lib/x-kit/xclient/src/window/xclient-ximps.pkg#
# At present this imp does nothing. It was intended to maintain
# per-running-gui state, but later widgets became highly mobile
# between running guis which made it better to maintain state
# globally in guiboss-imp rather than locally here. I'm leaving
# this imp and its associated infrastructure in place because
# I suspect that the week after I rip all this stuff out, I'll
# discover a pressing need for it. -- 2015-02-07 CrT
# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublibstipulate
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 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 dy = display; # display is from
src/lib/x-kit/xclient/src/wire/display.pkg# package xet = xevent_types; # xevent_types is from
src/lib/x-kit/xclient/src/wire/xevent-types.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 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 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 e2s = xevent_to_string; # xevent_to_string is from
src/lib/x-kit/xclient/src/to-string/xevent-to-string.pkg# package xc = xclient; # xclient is from
src/lib/x-kit/xclient/xclient.pkg# package xj = xsession_junk; # xsession_junk is from
src/lib/x-kit/xclient/src/window/xsession-junk.pkg# package xt = xtypes; # xtypes is from
src/lib/x-kit/xclient/src/wire/xtypes.pkg# package xtr = xlogger; # xlogger is from
src/lib/x-kit/xclient/src/stuff/xlogger.pkg package pl = paired_lists; # paired_lists is from
src/lib/std/src/paired-lists.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 b2s = spritespace_to_sprite; # spritespace_to_sprite is from
src/lib/x-kit/widget/space/sprite/spritespace-to-sprite.pkg package c2o = objectspace_to_object; # objectspace_to_object is from
src/lib/x-kit/widget/space/object/objectspace-to-object.pkg package g2p = gadget_to_pixmap; # gadget_to_pixmap is from
src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg package im = int_red_black_map; # int_red_black_map is from
src/lib/src/int-red-black-map.pkg package gt = guiboss_types; # guiboss_types is from
src/lib/x-kit/widget/gui/guiboss-types.pkg package blk = blank; # blank is from
src/lib/x-kit/widget/leaf/blank.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkg #
tracefile = "widget-unit-test.trace.log";
nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkgherein
package widgetspace_imp
: Widgetspace_Imp # Widgetspace_Imp is from
src/lib/x-kit/widget/space/widget/widgetspace-imp.api {
#
Widgetspace_State # Holds all nonephemeral mutable state maintained by shape.
=
{ id: Id,
state: Ref( Void )
};
Imports = { # Ports we use, provided by other imps.
int_sink: Int -> Void,
space_to_gui: gt::Space_To_Gui # Our channel to
src/lib/x-kit/widget/gui/guiboss-imp.pkg };
Exports = { # Ports we provide for use by other imps.
guiboss_to_widgetspace: gt::Guiboss_To_Widgetspace
};
Widgetspace_Egg = Void -> (Exports, (Imports, Run_Gun) -> Void);
Me_Slot = Mailslot ( { imports: Imports,
me: Widgetspace_State,
options: List(gt::Widgetspace_Option),
run_gun': Run_Gun,
shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void )), # When die() runs shutdown is signalled via this.
callback: Null_Or(gt::Guiboss_To_Widgetspace -> Void)
}
);
Runstate = { # These values will be statically globally visible throughout the code body for the imp.
me: Widgetspace_State, #
options: List(gt::Widgetspace_Option),
imports: Imports, # Imps to which we send requests.
to: Replyqueue, # The name makes foo::pass_something(imp) to {. ... } syntax read well.
shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void )) # When die() runs shutdown is signalled via this.
};
Widgetspace_Q = Mailqueue( Runstate -> Void );
fun shut_down_widgetspace_imp ({ shutdown_oneshot, options, ... }: Runstate)
=
{ case shutdown_oneshot # Pass our state back to guiboss to allow later impnet restart without state loss.
#
NULL => ();
THE oneshot => put_in_oneshot (oneshot, ()); #
esac;
thread_exit { success => TRUE }; # Will not return.
};
fun run ( widgetspace_q: Widgetspace_Q, #
#
runstate as
{ # These values will be statically globally visible throughout the code body for the imp.
me: Widgetspace_State, #
options: List(gt::Widgetspace_Option),
imports: Imports, # Imps to which we send requests.
to: Replyqueue, # The name makes foo::pass_something(imp) to {. ... } syntax read well.
shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void )) # When die() runs shutdown is signalled via this.
}
)
=
{
loop ();
}
loop ()
where
fun loop () # Outer loop for the imp.
=
{ do_one_mailop' to [
#
(take_from_mailqueue' widgetspace_q ==> do_label_plea)
];
loop ();
}
where
fun do_label_plea thunk
=
thunk runstate;
end;
end;
fun startup (id: Id, reply_oneshot: Oneshot_Maildrop( (Me_Slot, Exports) )) () # Root fn of imp microthread. Note currying.
=
{ me_slot = make_mailslot () : Me_Slot;
#
guiboss_to_widgetspace = { id, do_something, pass_something, die };
exports = { guiboss_to_widgetspace };
to = make_replyqueue();
#
put_in_oneshot (reply_oneshot, (me_slot, exports)); # Return value from widgetspace_egg'().
(take_from_mailslot me_slot) # Imports from widgetspace_egg'().
->
{ me, options, imports, run_gun', shutdown_oneshot, callback };
block_until_mailop_fires run_gun'; # Wait for the starting gun.
case callback THE callback => callback guiboss_to_widgetspace; # Tell application how to contact us.
NULL => ();
esac;
run (widgetspace_q, { me, options, imports, to, shutdown_oneshot }); # Will not return.
}
where
widgetspace_q = make_mailqueue (get_current_microthread()): Widgetspace_Q;
#######################################################################
# guiboss_to_widgetspace fns:
fun do_something (i: Int) # PUBLIC.
=
put_in_mailqueue (widgetspace_q,
#
\\ ({ me, imports, ... }: Runstate)
=
imports.int_sink i # Demonstrate use of imports.
);
fun pass_something (replyqueue: Replyqueue) (reply_handler: Int -> Void) # PUBLIC.
=
{ reply_oneshot = make_oneshot_maildrop(): Oneshot_Maildrop( Int );
#
put_in_mailqueue (widgetspace_q,
#
\\ ({ me, ... }: Runstate)
=
put_in_oneshot (reply_oneshot, 0)
);
put_in_replyqueue (replyqueue, (get_from_oneshot' reply_oneshot) ==> reply_handler);
};
fun die ()
=
put_in_mailqueue (widgetspace_q,
#
\\ (runstate: Runstate)
=
shut_down_widgetspace_imp runstate
);
end;
fun process_options
(
options: List(gt::Widgetspace_Option),
#
{ name,
id,
callback
}
)
=
{ my_name = REF name;
my_id = REF id;
my_callback = REF callback;
#
apply do_option options
where
fun do_option (gt::PS_MICROTHREAD_NAME n) => my_name := n;
do_option (gt::PS_ID i) => my_id := i;
do_option (gt::PS_CALLBACK c) => my_callback := THE c;
end;
end;
{ name => *my_name,
id => *my_id,
callback => *my_callback
};
};
##########################################################################################
# PUBLIC.
#
fun make_widgetspace_egg
(options: List(gt::Widgetspace_Option)) # PUBLIC. PHASE 1: Construct our state and initialize from 'options'.
(shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void ))) # When die() runs shutdown is signalled via this.
=
{ (process_options
( options,
#
{ name => "widgetspace",
id => id_zero,
callback => NULL
}
) )
->
{ name,
id,
callback
};
my (id, options)
=
if (id_to_int(id) == 0)
id = issue_unique_id(); # Allocate unique imp id.
(id, gt::PS_ID id ! options); # Make our id stable across stop/restart cycles.
else
(id, options);
fi;
me = { id, state => REF () };
\\ () = { reply_oneshot = make_oneshot_maildrop(): Oneshot_Maildrop( (Me_Slot, Exports) ); # PUBLIC. PHASE 2: Start our microthread and return our Exports to caller.
#
xlogger::make_thread name (startup (id, reply_oneshot)); # Note that startup() is curried.
(get_from_oneshot reply_oneshot) -> (me_slot, exports);
fun phase3 # PUBLIC. PHASE 3: Accept our Imports, then wait for Run_Gun to fire.
( imports: Imports,
run_gun': Run_Gun
)
=
{
put_in_mailslot (me_slot, { me, options, imports, run_gun', shutdown_oneshot, callback });
};
(exports, phase3);
};
};
};
end;