File:  [LON-CAPA] / modules / damieng / graphical_editor / loncapa_daxe / web / nodes / rank_foilgroup.dart
Revision 1.8: download - view: text, annotated - select for diffs
Wed Mar 8 20:31:22 2017 UTC (7 years, 3 months ago) by damieng
Branches: MAIN
CVS tags: HEAD
making sure that getHTMLContentsNode() returns something for foilgroups

/*
  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>