/*
This file is part of LONCAPA-Daxe.
LONCAPA-Daxe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LONCAPA-Daxe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Daxe. If not, see <http://www.gnu.org/licenses/>.
*/
part of loncapa_daxe;
/**
* Display for organicresponse, with a possible simple UI.
* Jaxe display type: 'organicresponse'.
*/
class OrganicResponse extends LCDBlock {
static List<String> simpleUIAttributes = ['options','molecule','answer','jmeanswer','width','id'];
OrganicResponse.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
displaySimpleButton = true;
}
OrganicResponse.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
displaySimpleButton = true;
if (simpleUIPossibleNoThrow()) {
bool node_simpleUI = node.getUserData('simpleUI');
if (node_simpleUI == null || node_simpleUI)
setupSimpleUI();
}
}
@override
bool simpleUIPossible() {
for (DaxeAttr att in attributes) {
if (!simpleUIAttributes.contains(att.name)) {
throw new SimpleUIException('organicresponse: ' + LCDStrings.get('attribute_problem') + ' ' + att.name);
}
}
int nbTextline = 0;
int nbHintgroup = 0;
for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
if (dn is Textline) {
if (!dn.simpleUIPossible())
return false;
nbTextline++;
} else if (dn is Hintgroup) {
//if (!dn.simpleUIPossible())
// return false;
// accept hintgroup even if simple UI is not possible for it
nbHintgroup++;
} else if (dn.nodeType != DaxeNode.TEXT_NODE) {
String title = doc.cfg.elementTitle(dn.ref);
throw new SimpleUIException(LCDStrings.get('element_prevents') + ' ' + dn.nodeName +
(title != null ? " ($title)" : ''));
} else if (dn.nodeValue.trim() != '') {
return false;
}
}
if (nbTextline != 1)
throw new SimpleUIException(LCDStrings.get('one_textline'));
if (nbHintgroup > 1)
throw new SimpleUIException(LCDStrings.get('one_hintgroup_max'));
return true;
}
@override
h.Element html() {
if (!simpleUI)
return super.html();
h.DivElement div = new h.DivElement();
div.id = "$id";
div.classes.add('dn');
if (!valid)
div.classes.add('invalid');
div.classes.add('dnblock');
h.DivElement headerDiv = createHeaderDiv();
div.append(headerDiv);
if (state != 2) {
// for hintgroup
h.DivElement contents = new h.DivElement();
contents.id = 'contents-' + id;
contents.classes.add('indent');
contents.classes.add('dnblock-content');
setStyle(contents);
DaxeNode dn = firstChild;
while (dn != null) {
if (dn.nodeType != DaxeNode.ELEMENT_NODE || dn.nodeName != 'textline')
contents.append(dn.html());
dn = dn.nextSibling;
}
if (lastChild == null || lastChild.nodeType == DaxeNode.TEXT_NODE)
contents.appendText('\n');
div.append(contents);
} else {
headerDiv.classes.add('without-content-afterwards');
}
return(div);
}
@override
h.Element createAttributesHTML() {
h.Element attHTML = super.createAttributesHTML();
if (!simpleUI || attHTML == null)
return attHTML;
// add the fake attribute (textline readonly)
if (state == 0) {
h.TableElement table = attHTML;
for (DaxeNode dn in childNodes) {
if (dn is Textline)
table.append(dn.html());
}
return table;
} else if (state == 1) {
h.DivElement attDiv = attHTML;
for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
if (dn is Textline && dn.getAttribute('readonly') != null) {
attDiv.append(new h.Text(" "));
h.Element att_name = new h.SpanElement();
att_name.attributes['class'] = 'attribute_name';
att_name.text = LCDStrings.get('readonly_field');
attDiv.append(att_name);
attDiv.append(new h.Text("="));
h.Element att_val = new h.SpanElement();
att_val.attributes['class'] = 'attribute_value';
att_val.text = dn.getAttribute('readonly');
attDiv.append(att_val);
}
}
return attDiv;
} else
return null;
}
@override
h.TableRowElement attributeHTML(x.Element refAttr) {
// add another column, use it to add an edit button for certain fields
h.TableRowElement tr = super.attributeHTML(refAttr);
String name = doc.cfg.attributeName(refAttr);
if (name == 'answer' || name == 'molecule') {
h.TableCellElement td = tr.lastChild;
if (name == 'answer')
td.rowSpan = 2;
h.ButtonElement bEdit = new h.ButtonElement();
bEdit.attributes['type'] = 'button';
bEdit.text = LCDStrings.get('edit_with_jsme');
bEdit.onClick.listen((h.MouseEvent event) {
String jmeString;
if (name == 'answer')
jmeString = attributeControls['jmeanswer'].getValue();
else if (name == 'molecule')
jmeString = attributeControls['molecule'].getValue();
if (jmeString == '')
jmeString = null;
JSMEDialog dlg;
dlg = new JSMEDialog(() {
if (name == 'answer') {
String smiles = dlg.getSMILES();
String jmeString = dlg.getJMEString();
LinkedHashMap<String, DaxeAttr> attmap = getAttributesMapCopy();
attmap['answer'] = new DaxeAttr('answer', smiles);
attmap['jmeanswer'] = new DaxeAttr('jmeanswer', jmeString);
doc.doNewEdit(new UndoableEdit.changeAttributes(this, new List.from(attmap.values)));
} else if (name == 'molecule') {
String jmeString = dlg.getJMEString();
doc.doNewEdit(new UndoableEdit.changeAttribute(this, new DaxeAttr('molecule', jmeString)));
}
}, jmeString:jmeString);
dlg.show();
});
td.append(bEdit);
tr.append(td);
} else if (name == 'jmeanswer') {
h.TableCellElement td = tr.lastChild;
td.remove();
} else if (name == 'options' && (getAttribute('options') == null || !getAttribute('options').contains('\$'))) {
h.TableCellElement td = tr.lastChild;
td.remove();
td = tr.lastChild;
td.remove();
td = new h.TableCellElement();
td.colSpan = 2;
td.classes.add('expand');
List<String> optionList = parseOptions();
List<String> optionNames = ['autoez', 'multipart', 'nostereo', 'reaction', 'number'];
for (String option in optionNames) {
h.LabelElement label = new h.LabelElement();
h.CheckboxInputElement cb = new h.CheckboxInputElement();
cb.checked = optionList.contains(option);
cb.onChange.listen((h.Event event) {
List<String> newList = new List.from(parseOptions());
if (newList.contains(option))
newList.remove(option);
else
newList.add(option);
doc.doNewEdit(new UndoableEdit.changeAttribute(this,
new DaxeAttr('options', newList.join(',')), updateDisplay:false));
});
label.append(cb);
label.appendText(' ');
label.appendText(LCDStrings.get("option_$option"));
td.append(label);
td.append(new h.BRElement());
}
tr.append(td);
}
return tr;
}
List<String> parseOptions() {
String options = getAttribute('options');
if (options == null || options.trim() == '')
return new List<String>();
List<String> list = options.split(',');
for (int i=0; i<list.length; i++) {
list[i] = list[i].trim();
}
return list;
}
@override
void updateHTMLAfterChildrenChange(List<DaxeNode> changed) {
updateHTML(); // because DaxeNode's update does not handle fake attributes
}
@override
void updateAttributes() {
updateHTML(); // TODO: optimize for speed
}
void setupRestrictions() {
for (int i=0; i<attRefs.length; i++) {
x.Element refAttr = attRefs[i];
if (!simpleUIAttributes.contains(doc.cfg.attributeName(refAttr))) {
attRefs.removeAt(i);
i--;
}
}
restrictedInserts = [];
}
@override
void setupSimpleUI() {
simpleUI = true;
setupRestrictions();
fixChildrenForSimpleUI();
state = 0;
}
@override
void newNodeCreationUI(ActionFunction okfct) {
setupSimpleUI();
okfct();
}
Textline newTextline() {
List<x.Element> textlineRefs = doc.cfg.elementReferences('textline');
x.Element textlineRef = doc.cfg.findSubElement(ref, textlineRefs);
Textline textline = NodeFactory.create(textlineRef);
textline.state = 1;
return textline;
}
Hintgroup newHintgroup() {
List<x.Element> hintgroupRefs = doc.cfg.elementReferences('hintgroup');
x.Element hintgroupRef = doc.cfg.findSubElement(ref, hintgroupRefs);
Hintgroup hintgroup = new Hintgroup.fromRef(hintgroupRef);
hintgroup.state = 1;
return hintgroup;
}
/**
* This inserts a textline, hintgroup if missing.
*/
void fixChildrenForSimpleUI() {
LCDBlock textline = null;
Hintgroup hintgroup = null;
for (DaxeNode dn in childNodes) {
if (dn.nodeType == DaxeNode.ELEMENT_NODE) {
if (dn.nodeName == 'textline')
textline = dn;
else if (dn.nodeName == 'hintgroup')
hintgroup = dn;
}
}
if (textline == null) {
textline = newTextline();
appendChild(textline);
}
textline.userCannotRemove = true;
if (hintgroup == null) {
hintgroup = newHintgroup();
appendChild(hintgroup);
} else
hintgroup.setupSimpleUI();
hintgroup.userCannotRemove = true;
}
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>