File:  [LON-CAPA] / modules / damieng / graphical_editor / loncapa_daxe / web / nodes / radio_response.dart
Revision 1.9: download - view: text, annotated - select for diffs
Mon Mar 27 17:35:05 2017 UTC (7 years, 2 months ago) by damieng
Branches: MAIN
CVS tags: HEAD
avoid adding a missing textline to a response when opening a document missing it (using advanced response in that case); added more messages related to hintgroup, textline and textfield to explain why the switch to simple UI fails

/*
  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 radiobuttonresponse, with a possible simple UI.
 * Jaxe display type: 'radioresponse'.
 */
class RadioResponse extends LCDBlock {
  
  static List<String> simpleUIAttributes = ['max', 'randomize', 'id'];
  
  RadioResponse.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
    displaySimpleButton = true;
  }
  
  RadioResponse.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) &&
          (att.name != 'direction' || att.value != 'vertical')) {
        throw new SimpleUIException('radioresponse: ' + LCDStrings.get('attribute_problem') + ' ' + att.name);
      }
    }
    int nbHintgroup = 0;
    for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
      if (dn is RadioFoilgroup) {
        if (!dn.simpleUIPossible())
          return false;
      } 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) {
        String title = doc.cfg.elementTitle(dn.ref);
        throw new SimpleUIException(LCDStrings.get('element_prevents') + ' ' + dn.nodeName +
            (title != null ? " ($title)" : ''));
      } else if (dn.nodeType == DaxeNode.TEXT_NODE) {
        if (dn.nodeValue.trim() != '')
          return false;
      } else {
        return false;
      }
    }
    if (nbHintgroup > 1)
      throw new SimpleUIException(LCDStrings.get('one_hintgroup_max'));
    return true;
  }
  
  /*
  @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));
    RadioResponse newNode = new DaxeNode.clone(this);
    newNode.simpleUI = true;
    newNode.setupSimpleUI();
    edit.addSubEdit(new UndoableEdit.insertNode(pos, newNode));
    doc.doNewEdit(edit);
  }
  */
  
  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() {
    // NOTE: changes here do not need to be undoable, because a new node is created.
    simpleUI = true;
    setupRestrictions();
    if (getAttribute('direction') == 'vertical')
      removeAttribute('direction');
    fixChildrenForSimpleUI();
  }
  
  @override
  void newNodeCreationUI(ActionFunction okfct) {
    setupSimpleUI();
    okfct();
  }
  
  /**
   * Returns the first foilgroup.
   */
  RadioFoilgroup getFoilgroup() {
    for (DaxeNode dn in childNodes) {
      if (dn is RadioFoilgroup)
        return dn;
    }
    return null;
  }
  
  /**
   * Returns the first hintgroup.
   */
  Hintgroup getHintgroup() {
    for (DaxeNode dn in childNodes) {
      if (dn is Hintgroup)
        return dn;
    }
    return null;
  }
  
  RadioFoilgroup newFoilgroup() {
    List<x.Element> foilgroupRefs = doc.cfg.elementReferences('foilgroup');
    x.Element foilgroupRef = doc.cfg.findSubElement(ref, foilgroupRefs);
    RadioFoilgroup foilgroup = new RadioFoilgroup.fromRef(foilgroupRef);
    foilgroup.setupSimpleUI();
    return foilgroup;
  }
  
  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;
  }
  
  /**
   * Inserts a foilgroup and hintgroup if missing, fixes them otherwise.
   */
  void fixChildrenForSimpleUI() {
    RadioFoilgroup foilgroup = getFoilgroup();
    Hintgroup hintgroup = getHintgroup();
    if (foilgroup != null)
      foilgroup.setupSimpleUI();
    else {
      foilgroup = newFoilgroup();
      insertBefore(foilgroup, hintgroup);
    }
    foilgroup.userCannotRemove = true;
    if (hintgroup != null)
      hintgroup.setupSimpleUI();
    else {
      hintgroup = newHintgroup();
      appendChild(hintgroup);
    }
    hintgroup.userCannotRemove = true;
  }
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>