private void indentHeading(AuthorElement heading) throws Exception { Matcher matcher = HEADING_PATTERN.matcher(heading.getLocalName()); matcher.matches(); int lvl = Integer.parseInt(matcher.group(1)); if (lvl == 6) throw new AuthorOperationException("Operation not permitted on h6."); AuthorElement level = (AuthorElement) heading.getParent(); assert (isDtbElement("level" + lvl, level)); controller.renameElement(heading, "h" + (lvl + 1)); AuthorElement nextSubLevel = xpath.getElement("following-sibling::level" + (lvl + 1), heading, controller); controller.surroundInFragment( dtbElement("level" + (lvl + 1)), heading.getStartOffset(), (nextSubLevel != null) ? nextSubLevel.getStartOffset() - 1 : level.getEndOffset() - 1); AuthorElement previousLevel = xpath.getElement( "preceding-sibling::*[not(normalize-space(string(.))='')][1][self::level" + lvl + "]", level, controller); if (previousLevel != null) { int insertAt = previousLevel.getEndOffset(); controller.insertFragment( insertAt, controller.createDocumentFragment(level.getStartOffset() + 1, level.getEndOffset() - 1)); controller.deleteNode(level); level = getElementAtOffset(insertAt + 1, controller); } editor.setCaretPosition( xpath.getElement("descendant::h" + (lvl + 1), level, controller).getStartOffset() + 1); }
protected void doOperation() throws Exception { AuthorElement element = getElementAtOffset(getSelectionStart(editor), controller); Matcher matcher = HEADING_PATTERN.matcher(element.getLocalName()); if (!isDtbElement(element) || !matcher.matches()) throw new AuthorOperationException("Operation only permitted on heading elements."); indentHeading(element); }