## widget_tree.pkg
## Author: Burkhart Wolff
## (C) 1996, Bremen Institute for Safe Systems, Universitaet Bremen
# Compiled by:
#
src/lib/tk/src/tk.sublib# **************************************************************************
# Functions related to Path-Management (and widgets).
# **************************************************************************
### "The grid is very peaceful.
### Nothing can go wrong.
### Everything is complete."
###
### -- Louise Bourgeois
package widget_tree
: (weak) Widget_Tree # Widget_Tree is from
src/lib/tk/src/widget_tree.api{
stipulate
include package basic_tk_types;
include package gui_state;
include package basic_utilities;
herein
# ***********************************************************************
# CHECKING the INTEGRITY of WIDGETS
# ***********************************************************************
# yet implememed checks: widget_id of widgets /
# traits of widgets, mitems and citems
# other checks may be added
fun check_widget w
=
{
t = get_widget_type w;
if (not (check_widget_id (get_widget_id w)))
print("WidId " + get_widget_id w + " is not O.K.!");
raise exception WIDGET("WidId " + get_widget_id w + " is not O.K.!");
fi;
if (check_widget_configure t (get_the_widget_traits w) ) ();
else print("Configures of Widget " + get_widget_id w +
" are not O.K.!");
raise exception WIDGET("Configures of Widget " + get_widget_id w +
" are not O.K.!"); fi;
if (check_widget_naming t (get_the_widget_event_callbacks w) ) ();# NOT YET IMPL.
else print("Namings of Widget " + get_widget_id w +
" are not O.K.!");
raise exception WIDGET("Namings of Widget " + get_widget_id w +
" are not O.K.!"); fi;
case w
MENU_BUTTON { mitems, ... } =>
if (list::all check_mitem mitems ) ();
else print("Menu_Items of MENU_BUTTON " + get_widget_id w +
" are not O.K.!");
raise exception WIDGET("Menu_Items of MENU_BUTTON " + get_widget_id w +
" are not O.K.!"); fi;
POPUP { mitems, ... } =>
if (list::all check_mitem mitems ) ();
else print("Menu_Items of POPUP " + get_widget_id w +
" are not O.K.!");
raise exception WIDGET("Menu_Items of POPUP " + get_widget_id w +
" are not O.K.!"); fi;
CANVAS { citems, ... } =>
if (list::all check_citem citems ) ();
else print("CItems of CANVAS " + get_widget_id w +
" are not O.K.!");
raise exception WIDGET("CItems of CANVAS " + get_widget_id w +
" are not O.K.!"); fi;
_ => (); esac;
}
# Check on the widget-id. Currently only widget-ids that begin with
# lowercase, and further consist of alphanumerical characters allowed.
# Tcl allows a wider range of strings.
also
fun check_widget_id s
=
if (size s == 0)
#
FALSE;
else
char::is_lower (string::get_byte_as_char (s, 0))
and
string_util::all char::is_alpha_num s;
fi
also
fun check_one_mconfigure CHECKBOX_MENU_ITEM_TYPE c
=>
(case c
ACCELERATOR _ => TRUE;
BACKGROUND _ => TRUE;
FOREGROUND _ => TRUE;
CALLBACK _ => TRUE;
TEXT _ => TRUE;
FONT _ => TRUE;
VARIABLE _ => TRUE;
VALUE _ => TRUE;
MENU_UNDERLINE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for MENU_CHECKBUTTON!\n");
FALSE;}; esac);
check_one_mconfigure RADIO_BUTTON_MENU_ITEM_TYPE c =>
(case c
ACCELERATOR _ => TRUE;
BACKGROUND _ => TRUE;
FOREGROUND _ => TRUE;
CALLBACK _ => TRUE;
TEXT _ => TRUE;
FONT _ => TRUE;
VARIABLE _ => TRUE;
VALUE _ => TRUE;
MENU_UNDERLINE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for MENU_RADIOBUTTON!\n");
FALSE;}; esac);
check_one_mconfigure COMMAND_MENU_ITEM_TYPE c =>
(case c
ACCELERATOR _ => TRUE;
BACKGROUND _ => TRUE;
FOREGROUND _ => TRUE;
CALLBACK _ => TRUE;
TEXT _ => TRUE;
FONT _ => TRUE;
MENU_UNDERLINE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for MENU_COMMAND!\n");
FALSE;}; esac);
check_one_mconfigure CASCADE_MENU_ITEM_TYPE c =>
(case c
CALLBACK _ => TRUE;
BACKGROUND _ => TRUE;
FOREGROUND _ => TRUE;
TEXT _ => TRUE;
FONT _ => TRUE;
MENU_UNDERLINE _ => TRUE;
TEAR_OFF _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for MENU_CASCADE!\n");
FALSE;}; esac); end
also
fun check_mitem MENU_SEPARATOR => TRUE;
check_mitem (MENU_CASCADE (ms, cs)) =>
config::no_dbl_p cs and list::all (check_one_mconfigure CASCADE_MENU_ITEM_TYPE) cs
and list::all check_mitem ms;
check_mitem mit =>
{
cs = get_menu_item_traits mit;
config::no_dbl_p cs and
list::all (check_one_mconfigure (get_the_menu_item_type mit)) cs;
}; end
also
fun check_one_cconfigure CANVAS_BOX_TYPE c =>
(case c
FILL_COLOR _ => TRUE;
OUTLINE _ => TRUE;
OUTLINE_WIDTH _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_BOX!\n");
FALSE;}; esac);
check_one_cconfigure CANVAS_OVAL_TYPE c =>
(case c
FILL_COLOR _ => TRUE;
OUTLINE _ => TRUE;
OUTLINE_WIDTH _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_OVAL!\n");
FALSE;}; esac);
check_one_cconfigure CANVAS_LINE_TYPE c =>
(case c
ARROW _ => TRUE;
CAP_STYLE _ => TRUE;
FILL_COLOR _ => TRUE;
JOIN_STYLE _ => TRUE;
SMOOTH _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_LINE!\n");
FALSE;}; esac);
check_one_cconfigure CANVAS_POLYGON_TYPE c =>
(case c
FILL_COLOR _ => TRUE;
OUTLINE _ => TRUE;
OUTLINE_WIDTH _ => TRUE;
SMOOTH _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_POLYGON!\n");
FALSE;}; esac);
check_one_cconfigure CANVAS_TEXT_TYPE c =>
(case c
ANCHOR _ => TRUE;
FILL_COLOR _ => TRUE;
FONT _ => TRUE;
JUSTIFY _ => TRUE;
TEXT _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_TEXT!\n");
FALSE;}; esac);
check_one_cconfigure CANVAS_WIDGET_TYPE c =>
(case c
ANCHOR _ => TRUE;
HEIGHT _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_WIDGET!\n");
FALSE;}; esac); end
also
fun check_one_cicon_configure TRUE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
FOREGROUND _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_ICON with NoIcon, TkBitmap or " +
"FileBitmap!\n");
FALSE;}; esac);
check_one_cicon_configure FALSE c =>
(case c
ANCHOR _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CANVAS_ICON with FileImage!\n");
FALSE;}; esac); end
also
fun check_citem (CANVAS_TAG _) => TRUE;
check_citem (CANVAS_ICON { icon_variety, traits, ... } ) =>
(if (config::no_dbl_p traits ) TRUE;
else { print "Double configure option in Widget definition!\n";
FALSE;}
and
case icon_variety
FILE_IMAGE _ => list::all (check_one_cicon_configure FALSE) traits;
_ => list::all (check_one_cicon_configure TRUE) traits; esac;fi);
check_citem cit =>
{
cs = canvas_item::sel_item_configure cit;
if (config::no_dbl_p cs ) TRUE;
else { print "Double configure option in Widget definition!";
FALSE;}
and
list::all (check_one_cconfigure (canvas_item::sel_item_type cit)) cs;fi;
}; end
also
fun check_one_widget_configure FRAME_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
COLOR_MAP _ => TRUE;
CURSOR _ => TRUE;
HEIGHT _ => TRUE;
RELIEF _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for FRAME!\n");
FALSE;}; esac);
check_one_widget_configure MESSAGE_TYPE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Message!\n");
FALSE;}; esac);
check_one_widget_configure LABEL_TYPE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
ICON _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
UNDERLINE => TRUE;
MENU_UNDERLINE _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for LABEL!\n");
FALSE;}; esac);
check_one_widget_configure LIST_BOX_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
RELIEF _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Listbox!\n");
FALSE;}; esac);
check_one_widget_configure BUTTON_TYPE c
=>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CALLBACK _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
ICON _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
ACTIVE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Button!\n");
FALSE;}; esac);
check_one_widget_configure RADIO_BUTTON_TYPE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CALLBACK _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
ICON _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
VARIABLE _ => TRUE;
VALUE _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
ACTIVE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Radiobutton!\n");
FALSE;}; esac);
check_one_widget_configure CHECK_BUTTON_TYPE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CALLBACK _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
ICON _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
VARIABLE _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
ACTIVE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for CHECK_BUTTON!\n");
FALSE;}; esac);
check_one_widget_configure MENU_BUTTON_TYPE c =>
(case c
ANCHOR _ => TRUE;
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CALLBACK _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
ICON _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
TEXT _ => TRUE;
WIDTH _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
ACTIVE _ => TRUE;
TEAR_OFF _ => TRUE;
MENU_UNDERLINE _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for MENU_BUTTON!\n");
FALSE;}; esac);
check_one_widget_configure SCALE_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BIG_INCREMENT _ => TRUE;
BORDER_THICKNESS _ => TRUE;
REAL_CALLBACK _ => TRUE;
CURSOR _ => TRUE;
DIGITS _ => TRUE;
FROM _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
SLIDER_LABEL _ => TRUE;
LENGTH _ => TRUE;
ORIENT _ => TRUE;
RELIEF _ => TRUE;
RESOLUTION _ => TRUE;
SHOW_VALUE _ => TRUE;
SLIDER_LENGTH _ => TRUE;
SLIDER_RELIEF _ => TRUE;
ACTIVE _ => TRUE;
TICK_INTERVAL _ => TRUE;
TO _ => TRUE;
VARIABLE _ => TRUE;
WIDTH _ => TRUE;
REPEAT_DELAY _ => TRUE;
REPEAT_INTERVAL _ => TRUE;
THROUGH_COLOR _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Scale!\n");
FALSE;}; esac);
check_one_widget_configure TEXT_ENTRY_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
TEXT _ => TRUE;
FOREGROUND _ => TRUE;
JUSTIFY _ => TRUE;
RELIEF _ => TRUE;
WIDTH _ => TRUE;
ACTIVE _ => TRUE;
SHOW _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for TEXT_ENTRY!\n");
FALSE;}; esac);
check_one_widget_configure CANVAS_TYPE c
=>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
HEIGHT _ => TRUE;
RELIEF _ => TRUE;
SCROLL_REGION _ => TRUE;
WIDTH _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for Canvas!\n");
FALSE;}; esac);
check_one_widget_configure TEXT_WIDGET_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
HEIGHT _ => TRUE;
RELIEF _ => TRUE;
ACTIVE _ => TRUE;
WIDTH _ => TRUE;
WRAP _ => TRUE;
INNER_PAD_X _ => TRUE;
INNER_PAD_Y _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for TEXT_WIDGET!\n");
FALSE;}; esac);
check_one_widget_configure POPUP_TYPE c =>
(case c
BACKGROUND _ => TRUE;
BORDER_THICKNESS _ => TRUE;
CURSOR _ => TRUE;
FONT _ => TRUE;
FOREGROUND _ => TRUE;
TEAR_OFF _ => TRUE;
_ =>
{ print("Wrong configure option:\n" + config::conf_name c +
" not allowed for POPUP!\n");
FALSE;}; esac); end
also
fun check_widget_configure wt cs =
(if (config::no_dbl_p cs ) TRUE;
else { print "Double configure option in Widget definition!";
FALSE;};fi)
and
list::all (check_one_widget_configure wt) cs
also
fun check_one_widget_naming _ _ = TRUE # NOT YET IMPLEMENTED
also
fun check_widget_naming wt bs
=
bind::no_dbl_p bs
and
list::all ((check_one_widget_naming wt) o bind::sel_event) bs;
# ***********************************************************************
# SELECTING WIDGETS from the internal GUI state
# ***********************************************************************
# on the toplevel, widgets must be FRAMEs
# getWidgetGUIPath is a variant that has the internal path as argument
# is needed for use with the event loop
fun get_widget_guipath (window, p)
=
{ # my selWid: Widget -> String -> Widget
fun sel_wid w ""
=>
w;
sel_wid (w as LIST_BOX _) p
=>
if (p==".box")
w;
else raise exception WIDGET "Error occurred in function selWid 1";fi;
sel_wid (w as CANVAS _) p
=>
if (p == ".cnv")
w;
elif (list_util::prefix
(explode ".cnv.cfr"
| reverse)
(explode p
| reverse))
raise exception WIDGET ("widget_tree::getWidgetGUIPath: \"cfr\" should not appear");
else
debug::print 2 ("selWid (Canv) " + (get_widget_id w) + " " + p);
my (wid, np) = paths::fst_wid_path p; # strip ".cnv"
my (wid', np') = paths::fst_wid_path np; # strip ".cfr"
my (wid'', np'') = paths::fst_wid_path np';
debug::print 2 ("selWid (Canv) " + wid'' + " " + np'');
sel_wids (canvas_item::get_canvas_widgets w) wid'' np'';
fi;
sel_wid (w as TEXT_WIDGET _) p
=>
if (p==".txt")
w;
else
if (list_util::prefix
(explode ".cnv.tfr"
| reverse)
(explode p
| reverse))
raise exception WIDGET ("widget_tree::getWidgetGUIPath: \"tfr\" should not appear");
else
debug::print 2 ("selWid (Canv) " + (get_widget_id w) + " " + p);
my (wid, np) = paths::fst_wid_path p; # strip ".txt"
my (wid', np') = paths::fst_wid_path np; # strip ".tfr"
my (wid'', np'') = paths::fst_wid_path np';
debug::print 2 ("selWid (Canv) " + wid'' + " " + np'');
sel_wids (text_item::get_text_wid_widgets w) wid'' np'';
fi;
fi;
sel_wid (FRAME { subwidgets, ... } ) p
=>
{ my (wid, np) = paths::fst_wid_path p;
sel_wids (get_raw_widgets subwidgets) wid np;
};
sel_wid _ s
=>
raise exception WIDGET ("Error occurred in function selWid 3 " + s);
end
# my selWids: Widget List -> Widget_ID -> Widget_Path -> Widget
also
fun sel_wids wids w p
=
sel_wid (list_util::getx ((\\ x = w == x) o get_widget_id) wids
(WIDGET ("selWids with widgetId \"" + w + "\""))) p;
my (w, np) = paths::fst_wid_path p; # <-- w hier ""
sel_wids (get_window_subwidgets (get_window_gui window)) w np;
};
fun get_widget_gui w_id
=
get_widget_guipath (paths::get_int_path_gui w_id);
# ***********************************************************************
# ADDING WIDGETS to the internal GUI state
# ***********************************************************************
# my addWidgetPathAssGUI: Window_ID -> Widget_Path -> Widget -> Void
fun add_widget_path_ass_gui window p wid
=
if (paths::occurs_widget_gui (get_widget_id wid))
raise exception WIDGET("Two identical widget names not allowed: " +
(get_widget_id wid));
else
np = p + ("." + (get_widget_id wid));
ass = get_path_ass_gui();
nass = paths::add_widget (get_widget_id wid) window np ass;
upd_path_ass_gui nass;
case wid
FRAME { widget_id, subwidgets, ... }
=>
add_widgets_path_ass_gui window np
(get_raw_widgets subwidgets);
CANVAS _
=>
{ fun add_one (cit, ws)
=
{ np' = np + ".cnv." + (canvas_item::get_canvas_item_id cit);
add_widgets_path_ass_gui window np' ws;
};
assl = canvas_item::get_canvas_citem_widget_ass_list wid;
apply add_one assl;
};
TEXT_WIDGET _
=>
{ fun add_one (an, ws)
=
{ np' = np + ".txt." + (text_item::get_text_item_id an);
add_widgets_path_ass_gui window np' ws;
};
my
assl = text_item::get_text_wid_annotation_widget_ass_list wid;
apply add_one assl;
};
_ => ();
esac;
fi
# my addWidgetsPathAssGUI: Window_ID -> Widget_Path -> List( Widget ) -> Void
also
fun add_widgets_path_ass_gui w p wids
=
apply (add_widget_path_ass_gui w p) wids;
# my addWidgetGUI: Window_ID -> Widget_Path -> Widget -> Void
fun add_widget_gui window p wid
=
{ # my addWids: List( Widget ) -> Widget -> Widget_Path -> WidgetList
fun add_wids widgs widg ""
=>
{ debug::print 2 ("addWids (final)");
widgs @ [widg];
};
add_wids widgs widg wp
=>
{ my (w_id, nwp)
=
paths::fst_wid_path wp;
nwidg = list_util::getx ((\\ x => x==w_id; end ) o get_widget_id) widgs
(WIDGET ("addWids with widgetId \"" + w_id + "\""));
newwidg = add_wid nwidg widg nwp;
list_util::update_val
((\\ x = x == w_id) o get_widget_id) newwidg widgs;
};
end
# my addWid: Widget -> Widget -> Widget_Path -> Widget
also
fun add_wid (FRAME { widget_id, subwidgets, packing_hints, traits, event_callbacks } ) widg wp
=>
FRAME {
widget_id,
packing_hints,
traits,
event_callbacks,
subwidgets => case subwidgets
PACKED widgets
=>
PACKED (add_wids widgets widg wp);
GRIDDED widgets
=>
GRIDDED (add_wids widgets widg wp);
esac
};
add_wid (w as (CANVAS _)) widg wp
=>
{ debug::print 2 ("addWid (canv) " + " " + (get_widget_id w) + " " +
(get_widget_id widg) + " " + wp);
canvas_item::add_canvas_widget add_wids w widg wp;};
add_wid (w as (TEXT_WIDGET _)) widg wp
=>
{ debug::print 2 ("addWid (textw) " + " " + (get_widget_id w) + " " +
(get_widget_id widg) + " " + wp);
text_item::add_text_wid_widget add_wids w widg wp;};
add_wid _ _ _
=>
raise exception WIDGET
"addWidgetGUI: attempt to add widget to non-container widget";
end;
check_widget wid;
window = get_window_gui window;
newwids = add_wids (get_window_subwidgets window) wid p;
newwindow
=
( window,
get_window_traits window,
if (window_is_gridded window ) GRIDDED newwids;
else PACKED newwids; fi,
get_window_event_callbacks window,
get_window_callback window
);
debug::print 2 ("addWidgetGUI: done");
add_widget_path_ass_gui window p wid;
upd_window_gui window newwindow;
}
also
fun add_widgets_gui w p wids
=
apply (add_widget_gui w p) wids;
# ***********************************************************************
# DELETING WIDGETS from the internal GUI state
# ***********************************************************************
fun delete_widget_gui w_id
=
{
# my deleteWidgetPathAss: (Widget * PathAssList) -> PathAssList
fun delete_widget_path_ass ((widg as FRAME { widget_id, subwidgets, ... } ), ass)
=>
{ nass = delete_widgets_path_ass (get_raw_widgets subwidgets, ass);
paths::delete_widget widget_id nass;
};
delete_widget_path_ass ((widg as CANVAS { widget_id, ... } ), ass)
=>
{ widgs = canvas_item::get_canvas_widgets widg;
nass = delete_widgets_path_ass (widgs, ass);
paths::delete_widget widget_id nass;
};
delete_widget_path_ass ((widg as TEXT_WIDGET { widget_id, ... } ), ass)
=>
{ widgs = text_item::get_text_wid_widgets widg;
nass = delete_widgets_path_ass (widgs, ass);
paths::delete_widget widget_id nass;
};
delete_widget_path_ass (widg, ass)
=>
paths::delete_widget (get_widget_id widg) ass; end
# my deleteWidgetPathAss: (List( Widget ) * PathAssList) -> PathAssList
also
fun delete_widgets_path_ass (widgs, ass)
=
fold_backward delete_widget_path_ass ass widgs;
# my delWid: Widget -> Widget_ID -> Widget_Path -> Widget
fun del_wid (FRAME { widget_id, subwidgets, packing_hints, traits, event_callbacks } ) w p
=>
FRAME {
widget_id,
subwidgets => case subwidgets
PACKED widgets => PACKED (del_wids widgets w p);
GRIDDED widgets => GRIDDED (del_wids widgets w p); esac,
packing_hints,
traits,
event_callbacks
};
del_wid (widg as (CANVAS _)) w p
=>
canvas_item::delete_canvas_widget del_wids widg w p;
del_wid (widg as (TEXT_WIDGET _)) w p
=>
text_item::delete_text_wid_widget del_wids widg w p;
del_wid _ _ _
=>
raise exception WIDGET "Error occurred in function delWid"; end
# my delWids: List( Widget ) -> Widget_ID -> Widget_Path -> List( Widget )
also
fun del_wids wids w ""
=>
list::filter ((\\ x=> not (w == x); end )o get_widget_id) wids;
del_wids wids w p
=>
{ debug::print 2 ("delWids (Canv) " + w + " " + p);
wid = list_util::getx ((\\ x => w==x; end )o get_widget_id) wids
(WIDGET ("delWids with widgetId \"" + w + "\""));
my (nw, np) = paths::fst_wid_path p;
newwid = del_wid wid nw np;
list_util::update_val ((\\ x => w==x; end ) o get_widget_id) newwid wids;
}; end;
debug::print 2 ("deleteWidgetGUI " + w_id);
widg = get_widget_gui w_id;
my (ip as (window, p)) = paths::get_int_path_gui w_id;
ass = get_path_ass_gui();
nass = delete_widget_path_ass (widg, ass);
debug::print 2 ("deleteWidgetGUI (after nass) " + w_id);
my (nw, np) = paths::fst_wid_path p;
window = get_window_gui window;
newwids = del_wids (get_window_subwidgets window) nw np;
newwindow
=
( window,
get_window_traits window,
if (window_is_gridded window ) GRIDDED newwids;
else PACKED newwids;fi,
get_window_event_callbacks window,
get_window_callback window
);
upd_window_gui window newwindow;
upd_path_ass_gui nass;
};
fun delete_widget_guipath ip
=
delete_widget_gui (get_widget_id (get_widget_guipath ip));
# ***********************************************************************
# 3F. UPDATING WIDGETS in the internal GUI state
# ***********************************************************************
# updWidgetPath . IntPath -> Widget s -> GUI s -> ((), GUI s)
fun upd_widget_guipath (window, p) w
=
{
debug::print 2 ("updWidgetGUIPath " + window + " " + p + " " + (get_widget_id w));
# my updWids: List( Widget ) -> Widget_ID -> Widget_Path -> Widget -> List( Widget )
fun upd_wids wids w "" neww
=>
list_util::update_val ((\\ x => w==x; end ) o get_widget_id) neww wids;
upd_wids wids w p neww
=>
{
debug::print 2 ("updWids " + w + " " + p); my
wid = list_util::getx ((\\ x => w==x; end ) o get_widget_id) wids
(WIDGET ("updWids with widgetId " + w));
my
(nw, np) = paths::fst_wid_path p; my
newwid = upd_wid wid nw np neww;
list_util::update_val ((\\ x => w==x; end ) o get_widget_id) newwid wids;
}; end
# my updWid: Widget -> Widget_ID -> Widget_Path -> Widget -> Widget
also
fun upd_wid (FRAME { widget_id, subwidgets, packing_hints, traits, event_callbacks } ) w p neww
=>
FRAME {
widget_id,
subwidgets => case subwidgets PACKED widgets => PACKED (upd_wids widgets w p neww);
GRIDDED widgets => GRIDDED (upd_wids widgets w p neww); esac,
packing_hints,
traits,
event_callbacks
};
upd_wid (widg as (CANVAS _)) w p neww
=>
{ debug::print 2 ("updWid (Canv) " + (get_widget_id widg) + " " + w + " " + p);
canvas_item::upd_canvas_widget upd_wids widg w p neww;};
upd_wid (widg as (TEXT_WIDGET _)) w p neww
=>
{ debug::print 2 ("updWid (TextWid) " + (get_widget_id widg) + " " + w + " " + p);
text_item::upd_text_wid_widget upd_wids widg w p neww;};
upd_wid _ _ _ _
=>
raise exception WIDGET "Error occurred in function updWid"; end;
my
(nw, np) = paths::fst_wid_path p; my
window = get_window_gui window; my
newwids = upd_wids (get_window_subwidgets window) nw np w; my
newwindow = (window, get_window_traits window,
if (window_is_gridded window)
GRIDDED newwids;
else
PACKED newwids;fi,
get_window_event_callbacks window,
get_window_callback window);
upd_window_gui window newwindow;
};
fun upd_widget_gui w
=
upd_widget_guipath (paths::get_int_path_gui (get_widget_id w)) w;
# ***********************************************************************
# ADDING WIDGETS to the "real" GUI
# ***********************************************************************
# -- i.e. sending pack commands to Tcl/Tk
fun is_grid_path (window, p)
=
if (p == "")
window_is_gridded (get_window_gui window);
else
case (get_widget_guipath (window, p))
FRAME { subwidgets, ... }
=>
case subwidgets
GRIDDED _ => TRUE;
_ => FALSE;
esac;
_ => FALSE;
esac;
fi
except
WIDGET _
=
is_grid_path (window, #1 (paths::last_wid_path p));
fun pack_widgets do_p tp ip gopt ws
=
cat (map (pack_widget do_p tp ip gopt) ws)
also
fun pack_widget do_p tp (window, p) gopt w
=
{ my
wid = get_widget_id w; my
nip = (window, p + "." + wid); my
ntp = tp + "." + wid;
my
grid
=
if (not_null gopt)
the gopt;
else
is_grid_path (window, p);fi;
check_widget w;
case w
FRAME { subwidgets, packing_hints, traits, event_callbacks, ... }
=>
(pack_wid do_p "frame" ntp nip wid packing_hints traits event_callbacks
grid +
pack_widgets TRUE ntp nip (THE (is_gridded subwidgets))
(get_raw_widgets subwidgets));
MESSAGE { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "message" ntp nip wid packing_hints traits event_callbacks
grid;
LIST_BOX { scrollbars, packing_hints, traits, event_callbacks, ... }
=>
pack_listbox do_p ntp nip wid scrollbars packing_hints traits
event_callbacks grid;
LABEL { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "label" ntp nip wid packing_hints traits event_callbacks grid;
BUTTON { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "button" ntp nip wid packing_hints traits event_callbacks grid;
RADIO_BUTTON { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "radiobutton" ntp nip wid packing_hints traits event_callbacks
grid;
CHECK_BUTTON { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "checkbutton" ntp nip wid packing_hints traits event_callbacks
grid;
MENU_BUTTON { mitems, packing_hints, traits, event_callbacks, ... }
=>
pack_menu do_p ntp nip wid mitems packing_hints traits event_callbacks grid;
TEXT_WIDGET { scrollbars, live_text, packing_hints, traits, event_callbacks, ... }
=>
pack_text_wid do_p ntp nip wid scrollbars
(live_text::get_livetext_text live_text)
(live_text::get_livetext_text_items live_text) packing_hints traits
event_callbacks grid;
CANVAS { scrollbars, citems, packing_hints, traits, event_callbacks, ... }
=>
pack_canvas do_p ntp nip wid scrollbars citems packing_hints traits
event_callbacks grid;
POPUP { mitems, traits, ... }
=>
pack_popup do_p ntp nip wid mitems traits;
TEXT_ENTRY { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "entry" ntp nip wid packing_hints traits event_callbacks grid;
SCALE_WIDGET { packing_hints, traits, event_callbacks, ... }
=>
pack_wid do_p "scale" ntp nip wid packing_hints traits event_callbacks grid; esac;
}
also
fun pack_wid0 do_p s tp ip w pack conf confstr binds grid
=
if do_p
((if grid
("grid [" + s + " " + tp + " " + config::pack ip conf +
confstr + "] " + (config::grid_info pack) + "\n");
else ("pack [" + s + " " + tp + " " + config::pack ip conf +
confstr + "] " + (config::pack_info pack) + "\n");fi) +
cat (bind::pack_widget tp ip binds));
else
(s + " " + tp + " " + config::pack ip conf + confstr + "\n" +
cat (bind::pack_widget tp ip binds));
fi
also
fun pack_wid do_p s tp ip w pack conf binds grid
=
pack_wid0 do_p s tp ip w pack conf "" binds grid
also
fun pack_menu do_p tp (ip as (window, p)) w ms pack conf binds grid
=
{ my
mip = (window, p + ".m"); my
mtp = tp + ".m"; my
conf' = list::filter
(not o (config::conf_eq (TEAR_OFF TRUE)))
conf;
my
to
=
case (list::find (config::conf_eq (TEAR_OFF TRUE)) conf)
NULL => TRUE;
THE (TEAR_OFF b) => b; esac;
((if do_p
((if grid
"grid [menubutton " + tp + " " +
config::pack ip conf' + " -menu " + mtp +
"] " + config::grid_info pack + "\n";
else
"pack [menubutton " + tp + " " +
config::pack ip conf' + " -menu " + mtp +
"] " + config::pack_info pack + "\n";fi) +
cat (bind::pack_widget tp ip binds));
else
("menubutton " + tp + " " +
config::pack ip conf' + " -menu " + mtp + "\n" +
cat (bind::pack_widget tp ip binds));fi) +
"menu " + mtp + " -tearoff " + (bool::to_string to) + "\n" +
pack_menu_items mtp mip w ms []);
}
also
fun pack_popup do_p tp (ip as (window, p)) w ms conf
=
{ my
mip = (window, p + ".pop"); my
mtp = tp + ".pop";
"menu " + tp + config::pack ip conf + "\n" + pack_menu_items tp ip w ms [];
}
also
fun pack_menu_items tp ip wid mis m_item_path
=
{ fun pmi tp ip w [] n => "";
pmi tp ip w (m . ms) n =>
(pack_menu_item tp ip w m (n . m_item_path) +
pmi tp ip w ms (n+1)); end;
pmi tp ip wid mis 0;
}
also
fun pack_menu_item tp ip w (MENU_SEPARATOR) n
=>
tp + " add separator" + "\n";
pack_menu_item tp ip w (MENU_CHECKBUTTON (cs)) n
=>
tp + " add checkbutton " + config::pack_m ip (reverse n) cs + "\n";
pack_menu_item tp ip w (MENU_RADIOBUTTON (cs)) n
=>
tp + " add radiobutton "+ config::pack_m ip (reverse n) cs + "\n";
pack_menu_item tp (ip as (window, p)) w (MENU_CASCADE (ms, cs)) (n . s)
=>
{ my
ntp = tp + ".m" + int::to_string n; my
n2 = reverse (n . s); my
cs' = list::filter
(not o (config::conf_eq (TEAR_OFF TRUE)))
cs;
my
to =
case (list::find (config::conf_eq (TEAR_OFF TRUE)) cs)
NULL => TRUE;
THE (TEAR_OFF b) => b; esac;
(tp + " add cascade " + config::pack_m ip n2 cs' + " -menu " + ntp + "\n" +
"menu " + ntp + " -tearoff " + (bool::to_string to) + "\n" +
pack_menu_items ntp ip w ms (n . s));
};
pack_menu_item tp ip w (MENU_COMMAND cs) n
=>
tp + " add command " + config::pack_m ip (reverse n) cs + "\n";
end
# Around Listboxes, there is always a FRAME. This has the advantage, that
# packing can treat "Listbox with scrollbar" as a unit. Commands address-
# ing the "Listbox" have to take into account this change of paths...
also
fun pack_listbox do_p tp (ip as (window, pt)) wid NOWHERE p c b grid
=>
{ my
bip = (window, pt + ".box"); my
btp = tp + ".box";
( pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "listbox" btp bip wid [FILL XY, EXPAND TRUE] c b FALSE
);
};
pack_listbox do_p tp (ip as (window, pt)) wid scb /* C */ p c b grid
=>
if (single scb)
bip = (window, pt + ".box");
btp = tp + ".box";
scip = (window, pt + ".screen");
sctp = tp + ".screen";
si = PACK_AT (scrolltype_to_horizontal_edge scb);
siquer = PACK_AT (scrolltype_to_opposite_horizontal_edge scb);
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "listbox" btp bip wid
[siquer, FILL XY, EXPAND TRUE] c b FALSE +
pack_wid TRUE "scrollbar" sctp scip wid [si, FILL ONLY_Y] [] []
FALSE +
btp + " configure -yscrollcommand \"" + sctp + " set \" " + "\n" +
sctp + " configure -command \"" + btp + " yview\"" + "\n");
else
bip = (window, pt + ".box");
btp = tp + ".box";
vscip = (window, pt + ".hscr");
hscip = (window, pt + ".vscr");
vsctp = tp + ".hscr";
hsctp = tp + ".vscr";
my (scb_hpack, scb_vpack, boxpack)
=
scrolltype_to_grid_coords scb;
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "scrollbar" hsctp hscip wid (scb_hpack @ [STICK TO_EW])
[] [] TRUE +
pack_wid TRUE "scrollbar" vsctp vscip wid (scb_vpack @ [STICK TO_NS])
[] [] TRUE +
pack_wid TRUE "listbox" btp bip wid (boxpack @ [STICK TO_NSEW]) c b
TRUE +
btp + " configure -xscrollcommand \"" + hsctp +
" set \" " + "\n" +
hsctp + " configure -command \"" + btp +
" xview\"" + " -orient horizontal" + "\n" +
btp + " configure -yscrollcommand \"" + vsctp +
" set \" " + "\n" +
vsctp + " configure -command \"" + btp +
" yview\"" + "\n");
fi;
end
# Around Canvases, there is always a FRAME. This has the advantage, that
# packing can treat "Canvas with scrollbar" as a unit. Commands address-
# ing the "Canvas" have to take into account this change of paths...
also
fun pack_canvas do_p tp (ip as (window, pt)) wid NOWHERE ci p c b grid
=>
{ my
cip = (window, pt + ".cnv"); my
ctp = tp + ".cnv";
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "canvas" ctp cip wid [FILL XY, EXPAND TRUE] c b FALSE +
cat (map (canvas_item::pack pack_widget ctp cip) ci));
};
pack_canvas do_p tp (ip as (window, pt)) wid scb ci p c b grid
=>
if (single scb)
if (orient scb)
{ my
cip = (window, pt + ".cnv"); my
ctp = tp + ".cnv"; my
vscip = (window, pt + ".hscr"); my
vsctp = tp + ".hscr"; my
vsi = PACK_AT (scrolltype_to_horizontal_edge scb); my
siquer = PACK_AT (scrolltype_to_opposite_horizontal_edge scb);
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "canvas" ctp cip wid
[siquer, FILL XY, EXPAND TRUE] c b FALSE +
pack_wid TRUE "scrollbar" vsctp vscip wid [vsi, FILL ONLY_Y] [] []
FALSE +
ctp + " configure -yscrollcommand \"" + vsctp +
" set \" " + "\n" +
vsctp + " configure -command \"" + ctp + " yview\"" + "\n" +
cat (map (canvas_item::pack pack_widget ctp cip) ci));
};
else
{ my
cip = (window, pt + ".cnv"); my
ctp = tp + ".cnv"; my
hscip = (window, pt + ".vscr"); my
hsctp = tp + ".vscr"; my
hsi = PACK_AT (scrolltype_to_vertical_edge scb); my
siquer = PACK_AT (scrolltype_to_opposite_vertical_edge scb);
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "canvas" ctp cip wid
[siquer, FILL XY, EXPAND TRUE] c b FALSE +
pack_wid TRUE "scrollbar" hsctp hscip wid [hsi, FILL ONLY_X] [] []
FALSE +
ctp + " configure -xscrollcommand \"" + hsctp +
" set \" " + "\n" +
hsctp + " configure -command \"" + ctp +
" xview\"" + " -orient horizontal" + "\n" +
cat (map (canvas_item::pack pack_widget ctp cip) ci));
};fi;
else # two scrollbars
{ my
cip = (window, pt + ".cnv"); my
ctp = tp + ".cnv"; my
vscip = (window, pt + ".hscr"); my
hscip = (window, pt + ".vscr"); my
vsctp = tp + ".hscr"; my
hsctp = tp + ".vscr"; my
(scb_hpack, scb_vpack, cnvpack)
=
scrolltype_to_grid_coords scb;
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "scrollbar" hsctp hscip wid (scb_hpack @ [STICK TO_EW])
[] [] TRUE +
pack_wid TRUE "scrollbar" vsctp vscip wid (scb_vpack @ [STICK TO_NS])
[] [] TRUE +
pack_wid TRUE "canvas" ctp cip wid
(cnvpack @ [STICK TO_NSEW]) c b TRUE +
ctp + " configure -xscrollcommand \"" + hsctp +
" set \" " + "\n" +
hsctp + " configure -command \"" + ctp +
" xview\"" + " -orient horizontal" + "\n" +
ctp + " configure -yscrollcommand \"" + vsctp +
" set \" " + "\n" +
vsctp + " configure -command \"" + ctp +
" yview\"" + "\n" +
cat (map (canvas_item::pack pack_widget ctp cip) ci));
};fi; end
# At the moment only empty taglists ...
also
fun pack_text_wid do_p tp (ip as (window, pt)) wid NOWHERE t ans p c b grid
=>
{ my
fdef = FONT (fonts::NORMAL_FONT [fonts::NORMAL_SIZE]);
my
bip = (window, pt + ".txt"); my
btp = tp + ".txt";
my
nc = list::filter
(not o (config::conf_eq (ACTIVE TRUE)))
c;
my
sc = list::filter
(config::conf_eq (ACTIVE TRUE))
c;
my
tt = btp + " insert end \"" + string_util::adapt_string t +
"\"" + "\n";
my
stt = btp + " configure " + (config::pack bip sc) + "\n";
my
nc' =
if (list::exists (config::conf_eq fdef) nc) nc; else fdef . nc;fi;
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "text" btp bip wid [FILL XY, EXPAND TRUE] nc' b FALSE +
tt + stt +
cat (map (text_item::pack pack_widget btp bip) ans));
};
pack_text_wid do_p tp (ip as (window, pt)) wid scb t ans p c b grid
=>
if (single scb)
# one scrollbar
{
fdef = FONT (fonts::NORMAL_FONT [fonts::NORMAL_SIZE]);
bip = (window, pt + ".txt");
btp = tp + ".txt";
scip = (window, pt + ".screen");
sctp = tp + ".screen";
si = PACK_AT (scrolltype_to_horizontal_edge scb);
siquer = PACK_AT (scrolltype_to_opposite_horizontal_edge scb);
nc = list::filter (not o (config::conf_eq (ACTIVE TRUE))) c;
sc = list::filter (config::conf_eq (ACTIVE TRUE)) c;
tt = btp + " insert end \"" + string_util::adapt_string t +
"\"" + "\n";
stt = btp + " configure " + config::pack bip sc + "\n";
nc' =
if (list::exists (config::conf_eq fdef) nc) nc; else fdef . nc;fi;
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "text" btp bip wid [siquer, FILL XY, EXPAND TRUE] nc'
b FALSE +
pack_wid TRUE "scrollbar" sctp scip wid [si, FILL ONLY_Y] [] [] FALSE +
btp + " configure -yscrollcommand \"" + sctp + " set \" " + "\n" +
sctp + " configure -command \"" + btp + " yview\"" + "\n" +
tt + stt +
cat (map (text_item::pack pack_widget btp bip) ans));
};
else # two scrollbars
{
fdef = FONT (fonts::NORMAL_FONT [fonts::NORMAL_SIZE]);
bip = (window, pt + ".txt");
btp = tp + ".txt";
vscip = (window, pt + ".hscr");
hscip = (window, pt + ".vscr");
vsctp = tp + ".hscr";
hsctp = tp + ".vscr";
my (scb_hpack, scb_vpack, txtpack) = scrolltype_to_grid_coords scb;
nc = list::filter (not o (config::conf_eq (ACTIVE TRUE))) c;
sc = list::filter (config::conf_eq (ACTIVE TRUE)) c;
tt = btp + " insert end \"" + string_util::adapt_string t +
"\"" + "\n";
stt = btp + " configure " + config::pack bip sc + "\n";
nc' =
if (list::exists (config::conf_eq fdef) nc) nc; else fdef . nc;fi;
(pack_wid do_p "frame" tp ip wid p [] [] grid +
pack_wid TRUE "scrollbar" hsctp hscip wid (scb_hpack @ [STICK TO_EW])
[] [] TRUE +
pack_wid TRUE "scrollbar" vsctp vscip wid (scb_vpack @ [STICK TO_NS])
[] [] TRUE +
pack_wid TRUE "text" btp bip wid (txtpack @ [STICK TO_NSEW]) nc'
b TRUE +
btp + " configure -xscrollcommand \"" + hsctp +
" set \" " + "\n" +
hsctp + " configure -command \"" + btp +
" xview\"" + " -orient horizontal" + "\n" +
btp + " configure -yscrollcommand \"" + vsctp +
" set \" " + "\n" +
vsctp + " configure -command \"" + btp +
" yview\"" + "\n" +
tt + stt +
cat (map (text_item::pack pack_widget btp bip) ans));
};fi; end;
# ***********************************************************************
# UPDATING WIDGETS in the "real" GUI
# ***********************************************************************
/* General Case
-- the widget and its younger brothers must be destroyed
-- and then newly packed.
*/
# my selWidgetsFrom: Widget -> Widget_ID -> List( Widget )
/*
# updPackWidgetPath . IntPath -> GIO s ()
fun updWidgetPackPath (window, p)
=
let
fun selWidgetsFrom (Frame(_, ws, _, _, _))w
=
dropWhile((\\ x => w/=x)o get_widget_ID) ws
| selWidgetsFrom _ _ =
raise exception WIDGET "Error occurred in selWidgetsFrom"
my (fp, w) = paths::lastWidPath p
ftp = paths::getTclPathGUI (window, fp)
in
if fp == "" then
let
wids = dropWhile ((\\ x=>w/=x)o get_widget_ID)
(get_window_subwidgets (getWindowGUI window))
in
packWidgets TRUE ftp (window, fp) wids
end
else
let
wids = selWidgetsFrom (getWidgetGUIPath (window, fp)) w
in
packWidgets TRUE ftp (window, fp) wids
end
end
fun update_widget_packing_hints w
=
updWidgetPackPath (paths::getIntPathGUI (get_widget_ID w))
/* Special Cases
-- here we only have to send the appropriate Tcl/Tk scripts.
*/
fun updConfigurePack wId cs
=
com::putTclCmd (config::pack (paths::getIntPathGUI wId) cs)
fun updNamingPack w bs
=
let ip = paths::getIntPathGUI w
tp = paths::getTclPathGUI ip
in
basic_utilities::apply com::putTclCmd (bind::packWidget tp ip bs)
end
*/
# ***********************************************************************
# 3H. EXPORTED FUNCTIONS
# ***********************************************************************
select_widget = get_widget_gui;
select_widget_path = get_widget_guipath;
fun delete_widget wid
=
{ debug::print 2 ("deleteWidget " + wid);
com::put_tcl_cmd ("destroy " +
(paths::get_tcl_path_gui (paths::get_int_path_gui wid)));
delete_widget_gui wid;};
fun add_widget window_id widget_id widg
=
{ my
wid_path = paths::get_wid_path_gui widget_id;
add_widget_gui window_id wid_path widg;
{ /* Kurzform: hoffentlich hab ich das mit den Pfanden
alles richtig verstanden
nip = (window_id, widPath)
ntclp = paths::getTclPathGUI nip
*/
w_id = get_widget_id widg;
my (window, wp) = paths::get_int_path_gui w_id;
my (nwp, l) = paths::last_wid_path wp;
nip = (window, nwp);
ntclp = paths::get_tcl_path_gui nip;
nwidg = get_widget_gui w_id;
debug::print 2 ("addWidget: " + ntclp + " (" + window + ", " + nwp + ") " + w_id);
com::put_tcl_cmd (pack_widget TRUE ntclp nip NULL nwidg);
};
};
/*
# -- not yet implemented (sigh...)
fun updateWidget w
=
(checkWidget w;
let
ip = paths::getIntPathGUI (get_widget_ID w)
in
updWidgetGUIPath ip w;
updWidgetPackPath ip
end)
*/
# ***********************************************************************
#
# IMPLEMENTATION: WIDGET CONTENTS
#
# ***********************************************************************
# EXPORTED FUNCTIONS
select = get_the_widget_traits o get_widget_gui;
select_command = config::sel_command o get_widget_gui;
select_command_path = config::sel_command o get_widget_guipath;
select_scommand_path = config::sel_scommand o get_widget_guipath;
# This function gets the path of the MENU_BUTTON:
fun select_mcommand_path ip n
=
{ w = get_widget_guipath ip;
fun sel_cascade ms [n]
=>
list::nth (ms, n);
sel_cascade ms (n . m . s)
=>
case (list::nth (ms, n))
MENU_CASCADE (mms, _) => sel_cascade mms (m . s); esac; end;
case w
MENU_BUTTON { mitems, ... }
=>
config::get_menu_item_callback (sel_cascade mitems n);
POPUP { mitems, ... }
=>
config::get_menu_item_callback (sel_cascade mitems n);
_
=>
\\ () => (); end ; esac;
};
# This function gets the menu path, i.e. a path with .m suffix:
fun select_mcommand_mpath (window, mp) n
=
{ my (p, m) = paths::last_wid_path mp;
if (m == "m") select_mcommand_path (window, p ) n;
else select_mcommand_path (window, mp) n;
fi;
};
fun select_mcommand w_id n
=
select_mcommand_path (paths::get_int_path_gui w_id) n;
select_namings = get_the_widget_event_callbacks o get_widget_gui;
fun select_bind_key w_id name
=
bind::get_action_by_name name (get_the_widget_event_callbacks (get_widget_gui w_id));
fun select_bind_key_path ip name
=
bind::get_action_by_name name (get_the_widget_event_callbacks (get_widget_guipath ip));
select_width = config::get_width o get_widget_gui;
select_height = config::get_height o get_widget_gui;
select_relief = config::sel_relief o get_widget_gui;
fun configure w cs
=
{ ip = paths::get_int_path_gui w;
wid = get_widget_guipath ip;
tp = paths::get_tcl_path_gui ip;
ntp =
case wid
TEXT_WIDGET _ => tp + ".txt";
CANVAS _ => tp + ".cnv";
_ => tp;
esac;
if (check_widget_configure (get_widget_type wid) cs)
oldcs = get_the_widget_traits wid;
newcs = config::add oldcs cs;
newwid = set_the_widget_traits wid newcs;
upd_widget_guipath ip newwid;
com::put_tcl_cmd (ntp + " configure " + config::pack ip cs);
else
raise exception CONFIG "Trying to reconfigure with wrong type of configures";
fi;
};
fun newconfigure w cs
=
{ ip = paths::get_int_path_gui w;
wid = get_widget_guipath ip;
wt = get_widget_type wid;
tp = paths::get_tcl_path_gui ip;
ntp =
case wid
TEXT_WIDGET _ => tp + ".txt";
CANVAS _ => tp + ".cnv";
_ => tp; esac;
if (check_widget_configure wt cs)
oldcs = get_the_widget_traits wid;
newcs = config::new wt oldcs cs;
newwid = set_the_widget_traits wid newcs;
upd_widget_guipath ip newwid;
com::put_tcl_cmd (ntp + " configure " + config::pack ip newcs);
else
raise exception CONFIG "Trying to reconfigure with wrong type of configures";
fi;
};
fun configure_command w c = configure w [CALLBACK c];
fun configure_width w n = configure w [WIDTH n];
fun configure_relief w r = configure w [RELIEF r];
fun configure_text w t = configure w [TEXT t];
fun add_namings w bs
=
{ ip = paths::get_int_path_gui w;
wid = get_widget_guipath ip;
tp = paths::get_tcl_path_gui ip;
ntp = case wid
TEXT_WIDGET _ => tp + ".txt";
CANVAS _ => tp + ".cnv";
_ => tp;
esac;
if (check_widget_naming (get_widget_type wid) bs)
oldbs = get_the_widget_event_callbacks wid;
newbs = bind::add oldbs bs;
newwid = set_the_widget_event_callbacks wid newbs;
upd_widget_guipath ip newwid;
com::put_tcl_cmd (cat (bind::pack_widget ntp ip bs));
else
raise exception CONFIG "Trying to add wrong event_callbacks";
fi;
};
fun new_namings w bs
=
{ ip = paths::get_int_path_gui w;
wid = get_widget_guipath ip;
wt = get_widget_type wid;
tp = paths::get_tcl_path_gui ip;
ntp = case wid
TEXT_WIDGET _ => tp + ".txt";
CANVAS _ => tp + ".cnv";
_ => tp;
esac;
if (check_widget_naming wt bs)
oldbs = get_the_widget_event_callbacks wid;
oldks = bind::delete oldbs bs;
newwid = set_the_widget_event_callbacks wid bs;
upd_widget_guipath ip newwid;
com::put_tcl_cmd
( cat (bind::unpack_widget ntp wt oldks)
+ cat (bind::pack_widget ntp ip bs)
);
else
raise exception CONFIG "Trying to newly set wrong event_callbacks";
fi;
};
fun insert_text wid str m
=
{ tp = paths::get_wid_path_gui wid;
ip = paths::get_int_path_gui wid;
w = get_widget_guipath ip;
my (m1, _)= string_util::break_at_dot (mark::show m);
case w
TEXT_WIDGET _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) +
".txt insert " + mark::show m + " \"" +
string_util::adapt_string str + "\"");
LIST_BOX _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) +
".box insert " + m1 +
" \"" + string_util::adapt_string str + "\" ");
TEXT_ENTRY _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) + " insert " + m1 +
" \"" + string_util::adapt_string str + "\" ");
_
=>
raise exception WIDGET "text insertion in illegal window"; esac;
};
fun insert_text_end wid str
=
insert_text wid str MARK_END;
fun delete_text wid (from, to)
=
{ tp = paths::get_wid_path_gui wid;
ip = paths::get_int_path_gui wid;
w = get_widget_guipath ip;
my (m1, _) = string_util::break_at_dot (mark::show from);
my (m2, _) = string_util::break_at_dot (mark::show to);
case w
TEXT_WIDGET _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) + ".txt delete " +
mark::show from + " " + mark::show to);
LIST_BOX _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) + ".box delete " + m1 +
" " + m2);
TEXT_ENTRY _
=>
com::put_tcl_cmd ((paths::get_tcl_path_gui ip) + " delete " + m1 +
" " + m2);
_
=>
raise exception WIDGET "text deletion in illegal window"; esac;
};
fun clear_text wid
=
delete_text wid (MARK (0, 0), MARK_END);
fun focus window
=
if (window == "main"
or window == "."
)
com::put_tcl_cmd "focus .";
else
com::put_tcl_cmd ("focus ." + window);
fi;
fun de_focus _
=
com::put_tcl_cmd "focus .";
/* somewhat buggy: XXX BUGGO FIXME
let
my (window, p) = paths::getIntPathGUI wid
in
if ( window == "main" ) then
com::putTclCmd ("focus .")
else
com::putTclCmd ("focus ." + window)
end
*/
fun grab window
=
if (window == "main" or window == ".")
com::put_tcl_cmd "grab set .";
else
com::put_tcl_cmd ("grab set ." + window);fi;
fun de_grab window
=
if (window == "main" or window == ".")
com::put_tcl_cmd "grab release .";
else com::put_tcl_cmd ("grab release ." + window);fi;
fun pop_up_menu wid index co
=
{ tp = paths::get_tcl_path_gui (paths::get_int_path_gui wid);
cot = coordinate::show [co];
fun pop_it_up (MENU_BUTTON _) (THE i)
=>
com::put_tcl_cmd ("tk_popup " + tp + ".m " + cot + " " +
int::to_string (i: Int));
pop_it_up (MENU_BUTTON _) NULL
=>
com::put_tcl_cmd ("tk_popup " + tp + ".m " + cot);
pop_it_up (POPUP _ ) (THE i)
=>
com::put_tcl_cmd ("tk_popup " + tp + " " + cot + " " +
int::to_string (i: Int));
pop_it_up (POPUP _ ) NULL
=>
com::put_tcl_cmd ("tk_popup " + tp + " " + cot);
pop_it_up _ _
=>
raise exception WIDGET "widget_tree::pop_up_menu: tried to pop up non-MenuWidget";
end;
widg = get_widget_gui wid;
pop_it_up widg index;
};
/* doesn't really work --- XXX BUGGO FIXME
fun make_and_pop_up_window widg index co
=
let
winid = paths::make_widget_id()
frmid = paths::make_widget_id()
frm = Frame (frmId, [widg], [], [], [])
wid = get_widget_ID widg
in
window::openW (winid, [], [frm], \\()=> ());
pop_up_menu wid frmid co
end
*/
end;
};