[LON-CAPA-cvs] cvs: modules /damieng/graphical_editor/loncapa_daxe/web/nodes lcd_block.dart rank_foil.dart rank_foilgroup.dart rank_response.dart
damieng
damieng at source.lon-capa.org
Fri Apr 17 17:42:30 EDT 2015
damieng Fri Apr 17 21:42:30 2015 EDT
Modified files:
/modules/damieng/graphical_editor/loncapa_daxe/web/nodes
lcd_block.dart
rank_foil.dart
rank_foilgroup.dart
rank_response.dart
Log:
changed rankresponse implementation to avoid problems with undo/redo, switch to/from simple UI, and cut/paste several foils
-------------- next part --------------
Index: modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lcd_block.dart
diff -u modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lcd_block.dart:1.1 modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lcd_block.dart:1.2
--- modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lcd_block.dart:1.1 Fri Apr 17 15:35:06 2015
+++ modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lcd_block.dart Fri Apr 17 21:42:29 2015
@@ -86,12 +86,25 @@
}
/**
- * Called when switching to simple UI.
- * This is replaced by subclasses.
+ * Called when the button is used.
+ * This can be replaced by subclasses.
+ */
+ void switchToSimpleUI() {
+ simpleUI = true;
+ setupSimpleUI();
+ updateHTML();
+ }
+
+ /**
+ * Called by default switchToSimpleUI() when switching to simple UI.
+ * This can be replaced by subclasses.
*/
void setupSimpleUI() {
}
+ /**
+ * Called when the button is used.
+ */
void switchToAdvancedUI() {
simpleUI = false;
init();
@@ -148,9 +161,7 @@
simple.appendText(LCDStrings.get('simple'));
simple.onClick.listen((h.MouseEvent event) {
if (simpleUIPossible()) {
- simpleUI = true;
- setupSimpleUI();
- updateHTML();
+ switchToSimpleUI();
page.updateAfterPathChange();
}
});
Index: modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foil.dart
diff -u modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foil.dart:1.1 modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foil.dart:1.2
--- modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foil.dart:1.1 Fri Apr 17 15:35:06 2015
+++ modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foil.dart Fri Apr 17 21:42:29 2015
@@ -38,14 +38,20 @@
List<String> possibleAttributes = ['value'];
final RegExp numberedFoil = new RegExp("^[fF]oil[0-9]+\$");
final RegExp positiveInteger = new RegExp("^[0-9]+\$");
- for (DaxeAttr att in attributes)
+ for (DaxeAttr att in attributes) {
if (!(att.name == 'value' && positiveInteger.hasMatch(att.value) ||
(att.name == 'name' && numberedFoil.hasMatch(att.value)) ||
(att.name == 'location' && att.value == 'random')))
return false;
+ }
return SimpleUIText.checkNodeContents(this);
}
+ int getRank() {
+ List<RankFoil> foils = (parent as RankFoilgroup).getFoils();
+ return foils.indexOf(this) + 1;
+ }
+
@override
h.Element html() {
simpleUI = parent is RankFoilgroup && (parent as RankFoilgroup).simpleUI;
@@ -108,12 +114,7 @@
td.append(grip);
h.SpanElement rankNumberSpan = new h.SpanElement();
rankNumberSpan.classes.add('rank-number');
- int nb = 1;
- for (DaxeNode dn=previousSibling; dn!=null; dn=dn.previousSibling) {
- if (dn is RankFoil)
- nb++;
- }
- rankNumberSpan.appendText("$nb");
+ rankNumberSpan.appendText("${getRank()}");
td.append(rankNumberSpan);
tr.append(td);
td = new h.TableCellElement();
@@ -152,12 +153,15 @@
updateHTML();
}
- @override void afterInsert() {
- (parent as RankFoilgroup).renameFoils(null);
- (parent as RankFoilgroup).updateHTML();
- }
-
- @override void beforeRemove() {
- (parent as RankFoilgroup).renameFoils(this);
+ @override
+ x.Node toDOMNode(x.Document domDocument) {
+ x.Node node = super.toDOMNode(domDocument);
+ if (!simpleUI || parent == null)
+ return node;
+ x.Element el = node as x.Element;
+ int nb = getRank();
+ el.setAttribute('name', "foil$nb");
+ el.setAttribute('value', "$nb");
+ return el;
}
}
Index: modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foilgroup.dart
diff -u modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foilgroup.dart:1.1 modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foilgroup.dart:1.2
--- modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foilgroup.dart:1.1 Fri Apr 17 15:35:06 2015
+++ modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_foilgroup.dart Fri Apr 17 21:42:29 2015
@@ -26,13 +26,25 @@
RankFoil draggedFoil;
RankFoilgroup.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
- initRankFoilgroup(null);
+ initRankFoilgroup(false);
}
RankFoilgroup.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
- if ((parent as RankResponse).simpleUI)
+ if ((parent as RankResponse).simpleUI && simpleUIPossible())
simpleUI = true;
- initRankFoilgroup(node);
+ initRankFoilgroup(true);
+ }
+
+ /**
+ * 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;
}
/**
@@ -41,23 +53,46 @@
bool simpleUIPossible() {
if (attributes.length != 0)
return false;
+ 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))
+ return false;
+ values.add(iv);
+ } on FormatException catch(ex) {
+ return false;
+ }
+ } else
+ aFoilHasNoValue = true;
} else if (dn.nodeType != DaxeNode.TEXT_NODE || dn.nodeValue.trim() != '') {
return false;
}
}
+ if (aFoilHasAValue && aFoilHasNoValue)
+ return false; // reordering is not possible in this case
return true;
}
- void initRankFoilgroup(x.Node domNode) {
+ void initRankFoilgroup(bool fromNode) {
List<x.Element> foilRefs = doc.cfg.elementReferences('foil');
foilRef = doc.cfg.findSubElement(ref, foilRefs);
- if (simpleUI && domNode != null && (domNode as x.Element).getElementsByTagName('foil').length == 0) {
- // new node from DOM in simpleUI: add a foil if there is none
- addFirstFoil();
+ if (simpleUI && fromNode) {
+ if (getFoils().length == 0) {
+ // new node from DOM in simpleUI: add a foil if there is none
+ addFirstFoil();
+ } else {
+ prepareFoilsForSimpleUI();
+ }
}
restrictedInserts = ['foil'];
}
@@ -71,10 +106,8 @@
div.id = id;
div.classes.add('rank-foilgroup');
h.TableElement table = new h.TableElement();
- for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
- if (dn is! RankFoil)
- continue;
- table.append(dn.html());
+ for (RankFoil foil in getFoils()) {
+ table.append(foil.html());
}
div.append(table);
h.ButtonElement bAdd = new h.ButtonElement();
@@ -104,8 +137,6 @@
*/
void addFirstFoil() {
RankFoil foil = new RankFoil.fromRef(foilRef);
- foil.setAttribute('name', 'foil1');
- foil.setAttribute('value', '1');
foil.state = 1;
appendChild(foil);
}
@@ -129,28 +160,59 @@
doc.doNewEdit(new UndoableEdit.removeNode(foil));
}
- void renameFoils(RankFoil removedFoil) {
- // rename foils automatically only when all names are [fF]oil[0-9]+
- // and values are [0-9]+
- final RegExp numberedFoil = new RegExp("^[fF]oil[0-9]+\$");
- final RegExp positiveInteger = new RegExp("^[0-9]+\$");
- for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
- String name = dn.getAttribute('name');
- if (name != null && !numberedFoil.hasMatch(name))
- return;
- String value = dn.getAttribute('value');
- if (value != null && !positiveInteger.hasMatch(value))
- return;
+ /**
+ * 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;
+ }
+ }
+ UndoableEdit edit = null;
+ 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);
+ });
+ int nb = 1;
+ for (RankFoil foil in foils)
+ appendChild(foil);
}
int nb = 1;
- for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
- if (dn is! RankFoil)
- continue;
- if (dn == removedFoil)
- continue;
- dn.setAttribute('name', "foil$nb");
- dn.setAttribute('value', "$nb");
- dn.updateValidity();
+ for (RankFoil foil in foils) {
+ if (foil.getAttribute('name') != null)
+ foil.removeAttribute('name');
+ if (foil.getAttribute('value') != null)
+ foil.removeAttribute('value');
+ nb++;
+ }
+ }
+
+ /**
+ * Adds the name and value attributes to the foils, when switching to advanced UI
+ */
+ void addNamesAndValue() {
+ int nb = 1;
+ for (RankFoil foil in getFoils()) {
+ foil.setAttribute('name', "foil$nb");
+ foil.setAttribute('value', "$nb");
nb++;
}
}
Index: modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_response.dart
diff -u modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_response.dart:1.1 modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_response.dart:1.2
--- modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_response.dart:1.1 Fri Apr 17 15:35:06 2015
+++ modules/damieng/graphical_editor/loncapa_daxe/web/nodes/rank_response.dart Fri Apr 17 21:42:29 2015
@@ -27,11 +27,11 @@
bool displaySimpleButton = true;
RankResponse.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
- initRankResponse(null);
+ initRankResponse(false);
}
RankResponse.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
- initRankResponse(node);
+ initRankResponse(true);
}
/**
@@ -58,13 +58,38 @@
return true;
}
- void initRankResponse(x.Node domNode) {
+ /**
+ * Returns the first foilgroup.
+ */
+ RankFoilgroup getFoilgroup() {
+ for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
+ if (dn is RankFoilgroup)
+ return dn;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first hintgroup.
+ */
+ Hintgroup getHintgroup() {
+ for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
+ if (dn is Hintgroup)
+ return dn;
+ }
+ return null;
+ }
+
+ void initRankResponse(bool fromNode) {
simpleUI = simpleUIPossible();
- if (simpleUI && domNode != null) {
+ if (simpleUI && fromNode) {
// new node from DOM: add a foilgroup and hintgroup if missing
- if ((domNode as x.Element).getElementsByTagName('foilgroup').length == 0)
+ RankFoilgroup foilgroup = getFoilgroup();
+ if (foilgroup != null)
+ foilgroup.prepareFoilsForSimpleUI();
+ else
appendChild(newFoilgroup());
- if ((domNode as x.Element).getElementsByTagName('hintgroup').length == 0)
+ if (getHintgroup() == null)
appendChild(newHintgroup());
}
if (simpleUI)
@@ -83,9 +108,46 @@
}
@override
+ void switchToSimpleUI() {
+ // Replace the whole node, to keep the simpleUI status in the edit history
+ // (to avoid problems when names and values have to be changed automatically)
+ UndoableEdit edit = new UndoableEdit.compound(LCDStrings.get('switch_to_simple_ui'));
+ Position pos = new Position(parent, parent.offsetOf(this));
+ edit.addSubEdit(new UndoableEdit.removeNode(this));
+ setAttribute('no-simpleui', 'true');
+ RankResponse newNode = new DaxeNode.clone(this);
+ removeAttribute('no-simpleui');
+ newNode.removeAttribute('no-simpleui');
+ newNode.simpleUI = true;
+ newNode.setupSimpleUI();
+ edit.addSubEdit(new UndoableEdit.insertNode(pos, newNode));
+ doc.doNewEdit(edit);
+ }
+
+ @override
void setupSimpleUI() {
+ // NOTE: changes here do not need to be undoable, because a new node is created.
setupRestrictions();
- autoInsertFoilgroupAndHintgroup();
+ RankFoilgroup foilgroup = getFoilgroup();
+ if (foilgroup != null)
+ foilgroup.prepareFoilsForSimpleUI();
+ insertFoilgroupAndHintgroup();
+ }
+
+ @override
+ void switchToAdvancedUI() {
+ UndoableEdit edit = new UndoableEdit.compound(LCDStrings.get('switch_to_advanced_ui'));
+ Position pos = new Position(parent, parent.offsetOf(this));
+ edit.addSubEdit(new UndoableEdit.removeNode(this));
+ RankResponse newNode = new DaxeNode.clone(this);
+ newNode.simpleUI = false;
+ newNode.restrictedInserts = null;
+ RankFoilgroup foilgroup = newNode.getFoilgroup();
+ if (foilgroup != null)
+ foilgroup.addNamesAndValue();
+ newNode.init();
+ edit.addSubEdit(new UndoableEdit.insertNode(pos, newNode));
+ doc.doNewEdit(edit);
}
@override
@@ -116,10 +178,9 @@
}
/**
- * This inserts a foilgroup and hintgroup if missing, as if the user had done it
- * (with undoable edits).
+ * Inserts a foilgroup and hintgroup if missing.
*/
- void autoInsertFoilgroupAndHintgroup() {
+ void insertFoilgroupAndHintgroup() {
bool foundFoilgroup = false;
bool foundHintgroup = false;
for (DaxeNode dn in childNodes) {
@@ -129,8 +190,8 @@
foundHintgroup = true;
}
if (!foundFoilgroup)
- doc.insertNode(newFoilgroup(), new Position(this, 0));
+ insertBefore(newFoilgroup(), null);
if (!foundHintgroup)
- doc.insertNode(newHintgroup(), new Position(this, offsetLength));
+ appendChild(newHintgroup());
}
}
More information about the LON-CAPA-cvs
mailing list