Branch: Tag:

2016-04-28

2016-04-28 15:15:58 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Variable.MultipleChoice: Added multiselect mode.

If the default value for Variable.MultipleChoice is an array
it switches operating mode to allow selection of multiple
items from the list of choices.

Also updates ModuleChoice accordingly.

1136:   // =====================================================================      class MultipleChoice - //! Base class for multiple-choice (one of many) variables. + //! Base class for multiple-choice (one or many of many) variables.   {    inherit Variable;    protected array _list = ({});    protected mapping _table = ([]);    -  +  protected int(0..1) multiselect; +     string diff( int render )    { -  if(!render) +  if(!render) { +  if (multiselect) +  return "(" + map(default_value(), _title) * ", " + ")";    return "("+_title( default_value() )+")";    } -  +  }       void set_choice_list( array to )    //! Set the list of choices.
1174:    return _table;    }    +  int(0..1) set_from_form(RequestID id, void|int(0..1) force) +  { +  if (!multiselect) return ::set_from_form(id); +  if (!id->real_variables[path()]) return 0; +  set_warning(0); +  mapping(string:string) m = get_form_vars(id); +  array(mixed) values = ({}); +  foreach(id->real_variables[path()] || ({}), string form_val) { +  mixed val = transform_from_form(form_val, m); +  array b = ({ 0, val }); +  mixed err = catch { b = verify_set_from_form(val); }; +  if (err) { +  add_warning(err); +  return 0; +  } else if (sizeof(b) != 2) { +  add_warning("Internal error: Illegal sized array " +  "from verify_set_from_form\n"); +  return 0; +  } +  if (b[0]) { +  add_warning(b[0]); +  } +  values += ({ b[1] }); +  } +  set(values); +  return 1; +  } +     protected string _name( mixed what )    //! Get the name used as value for an element gotten from the    //! get_choice_list() function.
1195:    string autosubmit = "";    if(additional_args && additional_args->autosubmit)    autosubmit = " autosubmit='autosubmit' onChange='javascript:submit();'"; -  string res = "<select name='"+path()+"'"+autosubmit+">\n"; +  if (multiselect) { +  array(string) current = map(query(), _name); +  string res = "<table>\n"; +  foreach( get_choice_list(), mixed elem ) +  { +  mapping m = ([ +  "type": "checkbox", +  "name": path(), +  "value": _name(elem), +  ]); +  if(has_value(current, m->value)) { +  m->checked="checked"; +  current -= ({ m->value }); +  } +  res += sprintf("<tr><td>%s</td><td>%s</td></tr>\n", +  Roxen.make_tag( "input", m), +  Roxen.html_encode_string(_title(elem))); +  } +  // Make an entry for the current values if they're not in the list, +  // to ensure that the value doesn't change as a side-effect by +  // another change. +  foreach(current, mixed elem ) +  { +  mapping m = ([ +  "type": "checkbox", +  "name": path(), +  "value": _name(elem), +  "checked": "checked", +  ]); +  string title = sprintf(LOCALE(332,"(keep stale value %s)"), current); +  res += sprintf("<tr><td>%s</td><td>%s</td></tr>\n", +  Roxen.make_tag( "input", m), +  Roxen.html_encode_string(title)); +  } +  return res + "</table>"; +  } else {    string current = _name (query());    int selected = 0; -  +  string res = "<select name='"+path()+"'"+autosubmit+">\n";    foreach( get_choice_list(), mixed elem )    {    mapping m = ([]);
1217:    sprintf(LOCALE(332,"(keep stale value %s)"),current));    return res + "</select>";    } +  }       protected void create( mixed default_value, array|mapping choices,    void|int _flags, void|LocaleString std_name,
1237:    //! for the default locale (always english)    {    ::create( default_value, _flags, std_name, std_doc ); +  multiselect = arrayp(default_value);    if( mappingp( choices ) ) {    set_translation_table( choices );    set_choice_list( sort(indices(choices)) );
1437:    inherit StringChoice;    constant type = "ModuleChoice";    protected Configuration conf; -  protected string module_id; -  protected string default_id; +  protected string|array(string) module_id; +  protected string|array(string) default_id;    protected int automatic_dependency;       int low_set(RoxenModule to)    { -  RoxenModule old = changed_values[_id]; +  array(RoxenModule)|RoxenModule old = changed_values[_id];    if (!old) {    if (module_id) { -  +  if (multiselect) { +  old = map(module_id, transform_from_form); +  } else {    old = transform_from_form(module_id); -  +  }    } else {    old = default_value();    if (old) {
1467:    }       // NOTE: Will be called with a string at module init! -  int set(string|RoxenModule to) +  int set(string|array(string)|RoxenModule|array(RoxenModule) to)    { -  if (stringp(to)) { +  if (multiselect && arrayp(to) && sizeof(to) && stringp(to[0])) {    module_id = to; -  +  array(RoxenModule) mods = map(to, transform_from_form); +  if (automatic_dependency) { +  foreach(mods; int i; RoxenModule mod) { +  if (!mod && conf->enabled_modules[to[i]]) { +  conf->add_modules(({to[i]}), 1); +  mod = transform_from_form(to[i]); +  } +  if (!mod && conf->enabled_modules[to[i]]) +  // The module exists but isn't started yet. Don't call set() +  // in this case since that will cause a bogus warning. +  return 0; +  mods[i] = mod; +  } +  } +  to = mods; +  } else if (stringp(to)) { +  module_id = to;    RoxenModule mod = transform_from_form (to);    if (!mod && automatic_dependency && conf->enabled_modules[to]) {    conf->add_modules (({to}), 1);
1485:    return ::set(to);    }    -  RoxenModule query() +  RoxenModule|array(RoxenModule) query()    { -  RoxenModule res = changed_values[_id]; +  array(RoxenModule)|RoxenModule res = changed_values[_id];    if (!res) {    if (module_id) {    // The module might have been reloaded.    // Try locating it again. -  +  if (multiselect) { +  res = map(module_id, transform_from_form); +  } else {    res = transform_from_form(module_id); -  if (res) low_set(res); +  }    } else {    res = default_value(); -  +  }    if (res) low_set(res);    } -  } +     return res;    }   
1538:    return conf->find_module(module_id);    }    -  RoxenModule default_value() +  RoxenModule|array(RoxenModule) default_value()    {    if (default_id) { -  +  if (multiselect) return map(default_id, transform_from_form);    return transform_from_form(default_id);    }    array(RoxenModule) modules = get_choice_list();
1567:    //! it already exists in the configuration then it will be loaded    //! before @expr{start@} in this module is called. Setting this    //! flag disables that. -  protected void create(string default_id, int flags, +  protected void create(string|array(string) default_id, int flags,    string std_name, string std_doc,    Configuration conf,    void|int no_automatic_dependency)
1576:    this_program::conf = conf;    automatic_dependency = !no_automatic_dependency;    ::create(0, ({}), flags, std_name, std_doc); +  multiselect = arrayp(default_id);    }   }