/*
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 numericalresponse, with a possible simple UI.
* Jaxe display type: 'numericalresponse'.
*/
class NumericalResponse extends LCDBlock {
static List<String> simpleUIAttributes = ['answer', 'unit', 'format', 'id'];
static Map<String,String> tolDef = {
'name': 'tol',
'type': 'tolerance',
'default': '0%',
'description': 'Numerical Tolerance'
};
static Map<String,String> sigDef = {
'name': 'sig',
'type': 'int_range',
'default': '0,15',
'description': 'Significant Digits'
};
NumericalResponse.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
displaySimpleButton = true;
}
NumericalResponse.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('numericalresponse: ' + LCDStrings.get('attribute_problem') + ' ' + att.name);
}
}
int nbTextline = 0;
int nbHintgroup = 0;
int nbTol = 0;
int nbSig = 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.ELEMENT_NODE && dn.nodeName == 'responseparam') {
if (dn.getAttribute('name') == 'tol' && dn.getAttribute('type') == 'tolerance')
nbTol++;
else if (dn.getAttribute('name') == 'sig' && (dn.getAttribute('type') == 'int_range' ||
dn.getAttribute('type') == 'int_range,0-16'))
nbSig++;
else
return throw new SimpleUIException(LCDStrings.get('advanced_response_param'));
} 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'));
if (nbTol > 1 || nbSig > 1)
return false;
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 != 'responseparam' && 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 attributes
if (state == 0) {
h.TableElement table = attHTML;
for (DaxeNode dn in childNodes) {
if (dn is LCDParameter || 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.nodeType == DaxeNode.ELEMENT_NODE && dn.nodeName == 'responseparam' &&
dn.getAttribute('default') != null) {
attDiv.append(new h.Text(" "));
h.Element att_name = new h.SpanElement();
att_name.attributes['class'] = 'attribute_name';
att_name.text = dn.getAttribute('name');
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('default');
attDiv.append(att_val);
} else if (dn is Textline && dn.getAttribute('size') != null) {
attDiv.append(new h.Text(" "));
h.Element att_name = new h.SpanElement();
att_name.attributes['class'] = 'attribute_name';
att_name.text = LCDStrings.get('field_size');
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('size');
attDiv.append(att_val);
}
}
return attDiv;
} else
return null;
}
@override
void updateHTMLAfterChildrenChange(List<DaxeNode> changed) {
updateHTML(); // because DaxeNode's update does not handle fake attributes
}
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();
}
@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;
}
LCDParameter newResponseParam(Map<String,String> def) {
List<x.Element> responseparamRefs = doc.cfg.elementReferences('responseparam');
x.Element responseparamRef = doc.cfg.findSubElement(ref, responseparamRefs);
LCDParameter responseparam = new LCDParameter.fromRef(responseparamRef);
responseparam.setAttribute('name', def['name']);
responseparam.setAttribute('type', def['type']);
responseparam.setAttribute('default', def['default']);
responseparam.setAttribute('description', def['description']);
responseparam.state = 1;
return responseparam;
}
/**
* This inserts a textline, hintgroup, tol and sig parameters if missing.
*/
void fixChildrenForSimpleUI() {
LCDBlock textline = null;
Hintgroup hintgroup = null;
LCDBlock tolParam = null;
LCDBlock sigParam = 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;
else if (dn.nodeName == 'responseparam' &&
dn.getAttribute('name') == 'tol' && dn.getAttribute('type') == 'tolerance')
tolParam = dn;
else if (dn.nodeName == 'responseparam' &&
dn.getAttribute('name') == 'sig' && (dn.getAttribute('type') == 'int_range' ||
dn.getAttribute('type') == 'int_range,0-16'))
sigParam = dn;
}
}
if (tolParam == null) {
tolParam = newResponseParam(tolDef);
appendChild(tolParam);
}
tolParam.userCannotRemove = true;
if (sigParam == null) {
sigParam = newResponseParam(sigDef);
appendChild(sigParam);
}
sigParam.userCannotRemove = true;
if (textline == null) {
textline = newTextline();
appendChild(textline);
}
textline.userCannotRemove = true;
if (hintgroup == null) {
hintgroup = newHintgroup();
appendChild(hintgroup);
} else
hintgroup.setupSimpleUI();
hintgroup.userCannotRemove = true;
}
@override
x.Node toDOMNode(x.Document domDocument) {
// remove tol and sig if not set or set to default
x.Element response = super.toDOMNode(domDocument);
List<x.Node> list = response.getElementsByTagName('responseparam');
for (x.Node n in list) {
x.Element p = n;
if (p.getAttribute('default') == '' ||
(p.getAttribute('name') == tolDef['name'] &&
p.getAttribute('type') == tolDef['type'] &&
p.getAttribute('default') == tolDef['default'] &&
p.getAttribute('description') == tolDef['description']) ||
(p.getAttribute('name') == sigDef['name'] &&
p.getAttribute('type') == sigDef['type'] &&
p.getAttribute('default') == sigDef['default'] &&
p.getAttribute('description') == sigDef['description'])) {
if (p.nextSibling is x.Text && p.nextSibling.nodeValue == '\n')
p.parentNode.removeChild(p.nextSibling);
p.parentNode.removeChild(p);
}
}
return(response);
}
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>