/*
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;
/**
* This is used by RankResponse for simple UI.
*/
class RankFoilgroup extends LCDBlock {
x.Element foilRef;
String simpleFoilNamePrefix = 'foil'; // can be changed to 'Foil'
RankFoilgroup.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
initRankFoilgroup();
}
RankFoilgroup.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
initRankFoilgroup();
if ((parent as RankResponse).simpleUI && simpleUIPossibleNoThrow())
simpleUI = true;
if (simpleUI)
setupSimpleUI();
}
void initRankFoilgroup() {
List<x.Element> foilRefs = doc.cfg.elementReferences('foil');
foilRef = doc.cfg.findSubElement(ref, foilRefs);
}
/**
* Returns the RankFoil children
*/
List<RankFoil> getFoils() {
List<RankFoil> list = new List<RankFoil>();
for (DaxeNode dn in childNodes) {
if (dn is RankFoil)
list.add(dn);
}
return list;
}
@override
bool simpleUIPossible() {
if (attributes.length != 0)
throw new SimpleUIException('foilgroup: ' + LCDStrings.get('no_attribute'));
List<int> values = new List<int>();
bool aFoilHasAValue = false;
bool aFoilHasNoValue = false;
for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
if (dn is RankFoil) {
if (!dn.simpleUIPossible())
return false;
// check values are unique integers
String value = dn.getAttribute('value');
if (value != null) {
aFoilHasAValue = true;
try {
int iv = int.parse(value);
if (values.contains(iv))
throw new SimpleUIException(LCDStrings.get('rank_foil_values_unique'));
values.add(iv);
} on FormatException {
throw new SimpleUIException(LCDStrings.get('rank_foil_values'));
}
} else
aFoilHasNoValue = true;
} 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 (aFoilHasAValue && aFoilHasNoValue)
throw new SimpleUIException(LCDStrings.get('rank_foil_values')); // reordering is not possible in this case
return true;
}
@override
void setupSimpleUI() {
// NOTE: changes here do not need to be undoable, because this is only called
// by initRankFoilgroup() and RankResponse.setupSimpleUI().
simpleUI = true;
setupRestrictions();
if (getFoils().length == 0) {
addFirstFoil();
} else {
prepareFoilsForSimpleUI();
}
}
void setupRestrictions() {
if (restrictedInserts == null)
restrictedInserts = ['foil'];
}
@override
h.Element html() {
simpleUI = parent is RankResponse && (parent as RankResponse).simpleUI;
if (!simpleUI)
return super.html();
setupRestrictions();
h.DivElement div = new h.DivElement();
div.id = id;
div.classes.add('rank-foilgroup');
h.TableElement table = new h.TableElement();
table.id = "contents-$id";
for (RankFoil foil in getFoils()) {
table.append(foil.html());
}
div.append(table);
h.ButtonElement bAdd = new h.ButtonElement();
bAdd.attributes['type'] = 'button';
bAdd.text = LCDStrings.get('add_foil');
bAdd.onClick.listen((h.MouseEvent event) => addUndoableFoil());
div.append(bAdd);
return div;
}
/* not called, and anyway we cannot know if it is simpleUI before it gets inserted
@override
void newNodeCreationUI(ActionFunction okfct) {
// called when a new element is inserted
// automatically add a foil in simple UI, never display an attribute dialog
if (simpleUI)
addFirstFoil();
okfct();
}
*/
@override
void updateHTMLAfterChildrenChange(List<DaxeNode> changed) {
updateHTML(); // because of renamed foils
}
/**
* Adds a foil (not using an UndoableEdit)
*/
void addFirstFoil() {
RankFoil foil = new RankFoil.fromRef(foilRef);
foil.state = 1;
foil.simpleUI = true;
appendChild(foil);
}
/**
* Adds a foil at the end (using an UndoableEdit)
*/
void addUndoableFoil() {
RankFoil foil = new RankFoil.fromRef(foilRef);
foil.state = 1;
foil.simpleUI = true;
Position pos = new Position(this, offsetLength);
doc.insertNode(foil, pos);
page.moveCursorTo(new Position(foil, 0));
page.updateAfterPathChange();
}
/**
* Removes the given foil (called when the user click on the button).
*/
void removeFoil(RankFoil foil) {
doc.doNewEdit(new UndoableEdit.removeNode(foil));
}
/**
* Reorders the foils based on their values, and removes the name and value attributes.
* It is assumed that simple UI is possible.
*/
void prepareFoilsForSimpleUI() {
List<RankFoil> foils = getFoils();
if (foils.length == 0)
return;
bool needOrdering = false;
for (int i=0; i<foils.length-1; i++) {
String value1 = foils[i].getAttribute('value');
String value2 = foils[i+1].getAttribute('value');
if (value1 == null || value2 == null)
break;
int cv1 = int.parse(value1);
int cv2 = int.parse(value2);
if (cv1 > cv2) {
needOrdering = true;
break;
}
}
if (needOrdering) {
// remove all child nodes, order the foils in the array, reinsert them with the right name/value
for (DaxeNode dn in childNodes)
removeChild(dn);
foils.sort((foil1, foil2) {
int cv1 = int.parse(foil1.getAttribute('value'));
int cv2 = int.parse(foil2.getAttribute('value'));
return cv1.compareTo(cv2);
});
for (RankFoil foil in foils)
appendChild(foil);
}
for (RankFoil foil in foils) {
if (foil.getAttribute('name') != null) {
if (foil.getAttribute('name').startsWith('Foil'))
simpleFoilNamePrefix = 'Foil';
foil.removeAttribute('name');
}
if (foil.getAttribute('value') != null)
foil.removeAttribute('value');
}
}
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>