File:  [LON-CAPA] / modules / damieng / graphical_editor / loncapa_daxe / web / nodes / section.dart
Revision 1.5: download - view: text, annotated - select for diffs
Tue Jan 31 18:02:44 2017 UTC (7 years, 9 months ago) by damieng
Branches: MAIN
CVS tags: HEAD
fixes for dart strong mode

/*
  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 HTML section, with a possible simple UI.
 * Jaxe display type: 'section'.
 */
class Section extends LCDBlock {
  
  Section.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
    displaySimpleButton = true;
  }
  
  Section.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) {
      bool advanced = false;
      if (att.name != 'class')
        advanced = true;
      if (!advanced) {
        if (!att.value.startsWith('role-'))
          advanced = true;
      }
      if (!advanced) {
        String role = att.value.substring(5);
        if (!knownSectionRoles.contains(role))
          advanced = true;
      }
      if (advanced)
        throw new SimpleUIException('section: ' + LCDStrings.get('attribute_problem') + ' ' + att.name);
    }
    if (firstChild != null && firstChild is! H1)
      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('section');
    setStyle(div);
    DaxeNode dn = firstChild;
    while (dn != null) {
      h.Element he = dn.html();
      if (dn is DNHiddenP && dn.firstChild == null && dn.previousSibling is H1 &&
          dn.previousSibling.previousSibling == null && dn.nextSibling == null) {
        he.style.position = 'relative';
        h.SpanElement span = new h.SpanElement();
        span.style.position = 'absolute';
        span.style.color = '#CCC';
        span.appendText(LCDStrings.get('section_contents'));
        he.append(span);
      }
      div.append(he);
      dn = dn.nextSibling;
    }
    if (lastChild == null || lastChild.nodeType == DaxeNode.TEXT_NODE)
      div.appendText('\n');
    return(div);
  }
  
  void setupRestrictions() {
    for (int i=0; i<attRefs.length; i++) {
      x.Element refAttr = attRefs[i];
      if (doc.cfg.attributeName(refAttr) != 'class') {
        attRefs.removeAt(i);
        i--;
      }
    }
  }
  
  @override
  void setupSimpleUI() {
    simpleUI = true;
    setupRestrictions();
    fixChildrenForSimpleUI();
    state = 0;
  }
  
  @override
  void newNodeCreationUI(ActionFunction okfct) {
    setupSimpleUI();
    okfct();
    page.cursor.moveTo(new Position(firstChild, 0));
  }
  
  @override
  h.Element getHTMLContentsNode() {
    if (!simpleUI)
      return super.getHTMLContentsNode();
    return getHTMLNode();
  }
  
  @override
  void attributeDialog([ActionFunction okfct]) {
    // this is called by the contextual menu
    if (simpleUI) {
      AttributeDialog dlg = new AttributeDialog(this, okfct);
      dlg.show();
    } else {
      super.attributeDialog(okfct);
    }
  }
  
  @override
  void updateAttributes() {
    if (!simpleUI)
      super.updateAttributes();
    else
      updateHTML();
  }
  
  H1 newH1() {
    List<x.Element> h1Refs = doc.cfg.elementReferences('h1');
    x.Element h1Ref = doc.cfg.findSubElement(ref, h1Refs);
    H1 h1 = NodeFactory.create(h1Ref);
    h1.state = 1;
    return h1;
  }
  
  /**
   * This inserts simpleUI children if missing.
   */
  void fixChildrenForSimpleUI() {
    bool foundH1 = (firstChild is H1 && firstChild.nodeName == 'h1');
    if (!foundH1) {
      if (firstChild == null)
        appendChild(newH1());
      else
        insertBefore(newH1(), firstChild);
    }
    if (firstChild.nextSibling == null) {
      x.Element hiddenp = doc.cfg.findSubElement(ref, doc.hiddenParaRefs);
      appendChild(new DNHiddenP.fromRef(hiddenp));
    }
  }
  
  void showRolesMenu(h.Point pt) {
    Menu popup = new Menu('');
    popup.add(new MenuItem(LCDStrings.get('no_specific_role'), () {
      doc.doNewEdit(new UndoableEdit.changeAttribute(this, new DaxeAttr('class', null)));
    }));
    for (String role in knownSectionRoles) {
      popup.add(new MenuItem(LCDStrings.get(role), () {
        doc.doNewEdit(new UndoableEdit.changeAttribute(this, new DaxeAttr('class', 'role-' + role)));
      }));
    }
    h.DivElement div = popup.htmlMenu();
    div.style.position = 'absolute';
    div.style.display = 'block';
    div.style.left = "${pt.x}px";
    div.style.top = "${pt.y}px";
    div.style.width = "12em";
    ((div.firstChild) as h.Element).style.width = "12em"; // for the table
    h.document.body.append(div);
    StreamSubscription<h.MouseEvent> subscription = h.document.onMouseUp.listen(null);
    subscription.onData((h.MouseEvent event) {
      subscription.cancel();
      div.remove();
      event.preventDefault();
    });
  }
  
  void fillSelectWithRoles(h.SelectElement select) {
    h.OptionElement option = new h.OptionElement();
    option.text = LCDStrings.get('no_specific_role');
    select.append(option);
    for (String role in knownSectionRoles) {
      h.OptionElement option = new h.OptionElement();
      option.text = LCDStrings.get(role);
      option.value = role;
      select.append(option);
    }
    select.onChange.listen((h.Event e) {
      String role = select.value;
      UndoableEdit edit;
      if (role != null && role.length > 0)
        edit = new UndoableEdit.changeAttribute(this, new DaxeAttr('class', 'role-' + role));
      else
        edit = new UndoableEdit.changeAttribute(this, new DaxeAttr('class', null));
      doc.doNewEdit(edit);
    });
  }
}

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