ACC SHELL
/**
* File:
* include/mail/wj.ycp
*
* Package:
* Configuration of mail
*
* Summary:
* Widget Juggler. One of the predecessors of CWM.
*
* Authors:
* Martin Vidner <mvidner@suse.cz>
*
* $Id: wj.ycp 24825 2005-08-11 15:01:22Z mvidner $
*
* <ol>
* <li> Widget functions to make moving widgets between dialogs easier.
* <li> Table editing helpers
* </ol>
*/
{
textdomain "mail"; // shoudn't be necessary
include "mail/widgets.ycp";
/* ---------------------------------------------------------------- */
/**
* @param data a list of structs
* @param keys which members to put in the table
* @return an item list
*/
define list<term> makeItems (list<map> data, list<string> keys) ``{
integer i = 0;
return maplist (map d, data, ``{
term t = `item (`id (i));
i = i + 1;
foreach (string k, keys, ``{
t = add (t, d[k]:"");
});
return t;
});
}
boolean edit_touched = false;
/**
* A generic handler for editing tables.
* The current item of table_widget
* makeItems (new_data, keys) is used to fill table_widget
* @param action `add, `edit or `delete
* @param data the data edited using the table
* @param keys keys of respective columns
* @param editEntry a function to edit an entry:
* gets the current entry and list of othe entries as parameters
* @param table_widget id of the table (usually a symbol)
* @return the edited data
*/
define list<map> EditTable (symbol action,
list<map> data,
list<string> keys,
map (map,list<map>) editEntryP,
any table_widget) ``{
list<map> new_data = nil;
integer entryno = (integer)UI::QueryWidget(`id (table_widget),`CurrentItem);
boolean touched = false;
map (map, list<map>) editEntry = editEntryP;//FIXME
if (action == `add)
{
map entry = editEntry ($[], data);
if (size (entry) > 0)
{
new_data = add (data, entry);
touched = true;
}
else
{
new_data = data;
}
}
else if (action == `edit)
{
// edit known fields, preserve unknown fields
map old_entry = data[entryno]:$[];
map entry = editEntry (old_entry, remove (data, entryno));
if (size (entry) > 0)
{
integer i = 0;
new_data = maplist (map e, data, ``{
i = i + 1;
return (i - 1 == entryno)? union (old_entry, entry): e;
});
touched = true;
}
else
{
new_data = data;
}
}
else if (action == `delete)
{
new_data = remove (data, entryno);
touched = true;
}
else
{
y2error ("Unknown EditTable action %1.", action);
new_data = data; // be nice
}
if (touched)
{
UI::ChangeWidget (`id (table_widget), `Items, makeItems (new_data, keys));
edit_touched = true;
}
return new_data;
}
/* ---------------------------------------------------------------- */
/**
* Evaluate a function pointer, working around interpreter limitations
* @param fp pointer to a functin without parameters returning
* boolean string symbol or list
* @return its return value as any
*/
any evaluate_fp (any fp) {
if (is (fp, boolean ()))
{
boolean () boolean_fp = (boolean ()) fp;
return boolean_fp ();
}
if (is (fp, list ()))
{
list () list_fp = (list ()) fp;
return list_fp ();
}
if (is (fp, string ()))
{
string () string_fp = (string ()) fp;
return string_fp ();
}
if (is (fp, symbol ()))
{
symbol () symbol_fp = (symbol ()) fp;
return symbol_fp ();
}
// report as the caller
y2error (1, "evaluate_fp: Unexpected function pointer: %1", fp);
return nil;
}
/**
* Constructs a widget term.
* Uses a global Widgets map.
* Keys are symbols (ids), values are
* @struct widget_def
* `foo: $[
* "widget": `TextEntry (),
* "opt": `opt (`notify), // optional
* "label": "&Foo",
* // if there are choices, they are used to construct the widget,
* // otherwise get is used
* "choices": Choices_foo // list ()
* "help": _("<p>Foo!</p>"), // used by WJ_MakeHelp, optional
* "get": Get_foo, // gets value from module to widget
* "set": Set_foo, // sets value from widget to module
* // popups an error and returns false if invalid
* "validate": ``(Validate_foo ()),// optional
* ],
* @param id which widget
* @return a widget term
*/
define term WJ_MakeWidget (symbol id) ``{
map w_def = Widgets[id]:$[];
term widget = w_def["widget"]:`CheckBox ();
if (widget == nil)
{
return nil;
}
widget = add (widget, `id (id));
if (haskey (w_def, "opt"))
{
widget = add (widget, w_def["opt"]:`Empty());
}
widget = add (widget, w_def["label"]:"LABEL");
// if choices are defined (combo boxes ...), use them
// otherwise set the value directly
// TODO: verified only for TextEntry. Password, CheckBox, ComboBox
// "choices" returns list, "get" returns string, symbol or boolean
any init = evaluate_fp (w_def["choices"]:w_def["get"]:nil);
if (init != nil)
{
return add (widget, init);
}
return widget;
}
/**
* Changes widget value using "get" (useful for widgets with choices).
* Uses a global Widgets map. @ref widget_def
* @param id which widget
*/
define void WJ_GetWidget (symbol id) ``{
// "get" returns string or boolean:
any e = evaluate_fp (Widgets[id, "get"]:nil);
UI::ChangeWidget (`id (id), `Value, e);
}
/**
* Make a help string by concatenating
* individual widget helps and other strings.
* Uses a global Widgets map. @ref widget_def
* @param items an item is<br>
* either a string - use it<br>
* or a symbol - lookup its help string in Widgets
* @return concatenated strings
*/
define string WJ_MakeHelp (list items) ``{
string ret = "";
foreach (any item, items, ``{
if (!is (item, string))
{
item = Widgets[item, "help"]:"";
}
ret = ret + (string) item;
});
return ret;
}
/**
* A helper for WJ_Validate.
* @param id a widget id
* @return always true
*/
define boolean WJ_Validate_True (symbol id) ``{
return true;
}
/**
* Call the validation functions for a list of widgets.
* Widgets with an unspecified function are assumed to be valid.
* Uses a global Widgets map. @ref widget_def
* @param widgets which widgets to validate
* @return true if all widgets are ok
*/
define boolean WJ_Validate (list widgets) ``{
boolean ok = true;
foreach (any id, widgets, ``{
if (ok)
{
if (is(id,symbol))
{
symbol id_sym = (symbol) id;
map w_def = (map) Widgets[id]:nil;
if (w_def== nil)
{
// report as the caller
y2error (1, "WJ: Missing widget definition for %1", id);
ok = false;
}
else
{
boolean (symbol) validate = w_def["validate"]:WJ_Validate_True;
ok = validate (id_sym);
}
}
else
{
ok = false;
}
}
else
{
return; //break
}
});
return ok;
}
/**
* Set a variable acording to widget value
* This is an error reporting fallback if the real function was not defined
* @param id widget id
*/
define void WJ_Set_Missing (symbol id) ``{
// report as the caller
y2error (1, "WJ: Missing Set definition for %1", id);
}
/**
* Call the "set" functions for a list of widgets
* to commit the UI values to a module.
* Uses a global Widgets map. @ref widget_def
* @param widgets which widgets to commit
*/
define void WJ_Set (list widgets) ``{
foreach (any id, widgets, ``{
if (is(id,symbol))
{
symbol id_sym = (symbol) id;
void (symbol) set_it = Widgets[id_sym, "set"]:WJ_Set_Missing;
set_it (id_sym);
}
});
}
/* ---------------------------------------------------------------- */
// Layout
// Helpers for frequently used layout idioms
/**
* Make a RadioButtonGroup containing Left aligned widgets
* in a VBox that has VSpacing (0.2) as top/bottom padding.
* @param g_id group id
* @param rbs a list of widgets, usually RadioButtons
* @return widget
*/
define term RadioButtonVBox (symbol g_id,
list<term> rbs) ``{
term spacing = `VSpacing (0.2);
term rb_vbox = `VBox (spacing);
foreach (term rb, rbs, ``{
term left_rb = `Left (rb);
rb_vbox = add (rb_vbox, left_rb);
});
rb_vbox = add (rb_vbox, spacing);
return `RadioButtonGroup (
`id (g_id),
rb_vbox
);
}
}
ACC SHELL 2018