#include #include /********************************************************************* * paramters */ name choicemode = /Exclusive; persist(choicemode); name placemode = /left2right; /********************************************************************* * admin */ void initmember(drawable m) { m.softpromote(/value,(choicemode == /Exclusive) && (length(members) == 1)); super.initmember(m); } void addmember(drawable m) { if (m.descendantof(/setting)) super.addmember(m); else m.destroy(); } float place_h() { return (choicemode == /NonExclusive) ? 10 : 0; } float place_v() { return (choicemode == /NonExclusive) ? 10 : 0; } void Paint() { } int *selected_settings() { int *list = (int *)[], n; for (n = 0 ; n < length(members) ; n++) if (members[n].value()) list = (int *)append(list,[n]); return list; } char **selected_strings() { char **list = (char **)[]; setting m; forall (; m ; members) if (m.value()) list = (char **)append(list,[DIString(m.str())]); return list; } /********************************************************************* * selection */ void setselection(int *list) { int *oldsel = selected_settings(); int *newsel = (int *)[]; int i; forall (; i ; list) if ((i >= 0) && (i < length(members))) newsel = (int *)append(newsel,[i]); if (length(members) && (choicemode != /NonExclusive)) { if (length(newsel) > 1) newsel = [newsel[0]]; if ((choicemode == /Exclusive) && (length(newsel) == 0)) newsel = [0]; } forall (; i ; oldsel) if (!arraycontains(newsel,i)) members[i].setvalue(false); forall (; i ; newsel) if (!arraycontains(oldsel,i)) members[i].setvalue(true); } /********************************************************************* * action */ void action() { Send Action(selected_strings()); } /********************************************************************* * hit detection */ setting hit_member(eventtype e) { drawable d; if (d = super.hit(e)) if (arraycontains(members,d)) return (setting)d; return null; } drawable hit(eventtype e) { drawable d = super.hit(e); if (d == self) return null; if (d && arraycontains(members,d)) return (drawable)self; return d; } /********************************************************************* * tracking */ setting trackcurrent = null; int *tracksel = (int *)[]; void track_setting() { setting d = hit_member(track_event); int i; if (d == trackcurrent) return; if ((i = arrayindex(members,trackcurrent = d)) < 0) { setselection(tracksel); return; } switch (choicemode) { case /Exclusive: setselection([i]); break; case /ExclusiveVariation: if (arraycontains(tracksel,i)) setselection((int *)[]); else setselection([i]); break; default: if (arraycontains(tracksel,i)) setselection((int *)arraydelete(tracksel, arrayindex(tracksel,i))); else setselection((int *)append(tracksel,[i])); } } void OnSelect() { tracksel = selected_settings(); track(/track_setting); if (!cmp(tracksel,selected_settings())) action(); unpromote(/tracksel); unpromote(/trackcurrent); } /********************************************************************* * */ void setchoicemode(name mode) { if (choicemode != mode) { softpromote(/choicemode,mode); invalidate(); setselection((int *)[]); } }