1 package org.argeo.docbook.ui;
3 import static org.argeo.cms.ui.util.CmsUiUtils.fillWidth;
5 import java.util.ArrayList;
6 import java.util.Iterator;
9 import java.util.Observer;
11 import javax.jcr.Item;
12 import javax.jcr.Node;
13 import javax.jcr.NodeIterator;
14 import javax.jcr.RepositoryException;
15 import javax.jcr.Session;
16 import javax.jcr.nodetype.NodeType;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.argeo.cms.text.Paragraph;
21 import org.argeo.cms.text.TextInterpreter;
22 import org.argeo.cms.text.TextSection;
23 import org.argeo.cms.ui.CmsEditable;
24 import org.argeo.cms.ui.CmsImageManager;
25 import org.argeo.cms.ui.CmsView;
26 import org.argeo.cms.ui.util.CmsUiUtils;
27 import org.argeo.cms.ui.viewers.AbstractPageViewer;
28 import org.argeo.cms.ui.viewers.EditablePart;
29 import org.argeo.cms.ui.viewers.NodePart;
30 import org.argeo.cms.ui.viewers.PropertyPart;
31 import org.argeo.cms.ui.viewers.Section;
32 import org.argeo.cms.ui.viewers.SectionPart;
33 import org.argeo.cms.ui.widgets.EditableImage;
34 import org.argeo.cms.ui.widgets.EditableText;
35 import org.argeo.cms.ui.widgets.Img;
36 import org.argeo.cms.ui.widgets.StyledControl;
37 import org.argeo.entity.EntityType;
38 import org.argeo.jcr.JcrException;
39 import org.argeo.jcr.JcrUtils;
40 import org.eclipse.rap.fileupload.FileDetails;
41 import org.eclipse.rap.fileupload.FileUploadEvent;
42 import org.eclipse.rap.fileupload.FileUploadHandler;
43 import org.eclipse.rap.fileupload.FileUploadListener;
44 import org.eclipse.rap.rwt.RWT;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.events.KeyEvent;
47 import org.eclipse.swt.events.KeyListener;
48 import org.eclipse.swt.events.MouseAdapter;
49 import org.eclipse.swt.events.MouseEvent;
50 import org.eclipse.swt.events.MouseListener;
51 import org.eclipse.swt.graphics.Point;
52 import org.eclipse.swt.widgets.Composite;
53 import org.eclipse.swt.widgets.Control;
54 import org.eclipse.swt.widgets.Text;
56 /** Base class for text viewers and editors. */
57 public abstract class AbstractDbkViewer extends AbstractPageViewer implements KeyListener, Observer {
58 private static final long serialVersionUID = -2401274679492339668L;
59 private final static Log log = LogFactory.getLog(AbstractDbkViewer.class);
61 private final Section mainSection;
63 private TextInterpreter textInterpreter = new DbkTextInterpreter();
64 private CmsImageManager imageManager;
66 private FileUploadListener fileUploadListener;
67 private DbkContextMenu styledTools;
69 private final boolean flat;
71 protected AbstractDbkViewer(Section parent, int style, CmsEditable cmsEditable) {
72 super(parent, style, cmsEditable);
73 CmsView cmsView = CmsView.getCmsView(parent);
74 // imageManager = cmsView.getImageManager();
75 imageManager = new DbkImageManager();
76 flat = SWT.FLAT == (style & SWT.FLAT);
78 if (getCmsEditable().canEdit()) {
79 fileUploadListener = new FUL();
80 styledTools = new DbkContextMenu(this, parent.getShell());
82 this.mainSection = parent;
83 initModelIfNeeded(mainSection.getNode());
84 // layout(this.mainSection);
88 public Control getControl() {
92 protected void refresh(Control control) throws RepositoryException {
93 if (!(control instanceof Section))
95 Section section = (Section) control;
96 if (section instanceof TextSection) {
97 CmsUiUtils.clear(section);
98 Node node = section.getNode();
99 TextSection textSection = (TextSection) section;
100 if (node.hasNode(DocBookTypes.TITLE)) {
101 if (section.getHeader() == null)
102 section.createHeader();
103 Node titleNode = node.getNode(DocBookTypes.TITLE);
104 DocBookSectionTitle title = newSectionTitle(textSection, titleNode);
105 title.setLayoutData(CmsUiUtils.fillWidth());
106 updateContent(title);
109 for (NodeIterator ni = node.getNodes(); ni.hasNext();) {
110 Node child = ni.nextNode();
111 SectionPart sectionPart = null;
112 if (child.isNodeType(DocBookTypes.MEDIAOBJECT)) {
113 if (child.hasNode(DocBookTypes.IMAGEOBJECT)) {
114 Node imageNode = child.getNode(DocBookTypes.IMAGEOBJECT).getNode(DocBookTypes.INFO)
115 .getNode(EntityType.box.get());
116 sectionPart = newImg(textSection, imageNode);
118 } else if (child.isNodeType(DocBookTypes.PARA)) {
119 sectionPart = newParagraph(textSection, child);
121 sectionPart = newSectionPart(textSection, child);
122 // if (sectionPart == null)
123 // throw new IllegalArgumentException("Unsupported node " + child);
124 // TODO list node types in exception
126 if (sectionPart != null && sectionPart instanceof Control)
127 ((Control) sectionPart).setLayoutData(CmsUiUtils.fillWidth());
131 for (NodeIterator ni = section.getNode().getNodes(DocBookNames.DBK_SECTION); ni.hasNext();) {
132 Node child = ni.nextNode();
133 if (child.isNodeType(DocBookTypes.SECTION)) {
134 TextSection newSection = new TextSection(section, SWT.NONE, child);
135 newSection.setLayoutData(CmsUiUtils.fillWidth());
140 for (Section s : section.getSubSections().values())
143 // section.layout(true, true);
146 /** To be overridden in order to provide additional SectionPart types */
147 protected SectionPart newSectionPart(TextSection textSection, Node node) {
152 protected Paragraph newParagraph(TextSection parent, Node node) throws RepositoryException {
153 Paragraph paragraph = new Paragraph(parent, parent.getStyle(), node);
154 updateContent(paragraph);
155 paragraph.setLayoutData(fillWidth());
156 paragraph.setMouseListener(getMouseListener());
160 protected Img newImg(TextSection parent, Node node) {
162 Img img = new Img(parent, parent.getStyle(), node, imageManager) {
163 private static final long serialVersionUID = 1297900641952417540L;
166 protected void setContainerLayoutData(Composite composite) {
167 composite.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
171 protected void setControlLayoutData(Control control) {
172 control.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
175 img.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
177 img.setMouseListener(getMouseListener());
179 } catch (RepositoryException e) {
180 throw new JcrException("Cannot add new image " + node, e);
184 protected DocBookSectionTitle newSectionTitle(TextSection parent, Node titleNode) throws RepositoryException {
185 int style = parent.getStyle();
186 Composite titleParent = newSectionHeader(parent);
187 if (parent.isTitleReadOnly())
188 style = style | SWT.READ_ONLY;
189 DocBookSectionTitle title = new DocBookSectionTitle(titleParent, style, titleNode);
190 updateContent(title);
191 title.setMouseListener(getMouseListener());
196 * To be overridden in order to provide additional processing at the section
199 * @return the parent to use for the {@link DocBookSectionTitle}, by default
200 * {@link Section#getHeader()}
202 protected Composite newSectionHeader(TextSection section) {
203 return section.getHeader();
206 protected DocBookSectionTitle prepareSectionTitle(Section newSection, String titleText) throws RepositoryException {
207 Node sectionNode = newSection.getNode();
209 if (!sectionNode.hasNode(DocBookTypes.TITLE)) {
210 titleNode = sectionNode.addNode(DocBookTypes.TITLE, DocBookTypes.TITLE);
212 titleNode = sectionNode.getNode(DocBookTypes.TITLE);
214 getTextInterpreter().write(titleNode, titleText);
215 if (newSection.getHeader() == null)
216 newSection.createHeader();
217 DocBookSectionTitle sectionTitle = newSectionTitle((TextSection) newSection, sectionNode);
221 protected void updateContent(EditablePart part) throws RepositoryException {
222 if (part instanceof SectionPart) {
223 SectionPart sectionPart = (SectionPart) part;
224 Node partNode = sectionPart.getNode();
226 if (part instanceof StyledControl && (sectionPart.getSection() instanceof TextSection)) {
227 TextSection section = (TextSection) sectionPart.getSection();
228 StyledControl styledControl = (StyledControl) part;
229 if (partNode.isNodeType(DocBookTypes.PARA)) {
230 String style = partNode.hasProperty(DocBookNames.DBK_ROLE)
231 ? partNode.getProperty(DocBookNames.DBK_ROLE).getString()
232 : section.getDefaultTextStyle();
233 styledControl.setStyle(style);
236 // use control AFTER setting style, since it may have been reset
238 if (part instanceof EditableText) {
239 EditableText paragraph = (EditableText) part;
240 if (paragraph == getEdited())
241 paragraph.setText(textInterpreter.raw(partNode));
243 paragraph.setText(textInterpreter.readSimpleHtml(partNode));
244 } else if (part instanceof EditableImage) {
245 EditableImage editableImage = (EditableImage) part;
246 imageManager.load(partNode, part.getControl(), editableImage.getPreferredImageSize());
248 } else if (part instanceof DocBookSectionTitle) {
249 DocBookSectionTitle title = (DocBookSectionTitle) part;
250 title.setStyle(title.getSection().getTitleStyle());
251 // use control AFTER setting style
252 if (title == getEdited())
253 title.setText(textInterpreter.read(title.getNode()));
255 title.setText(textInterpreter.raw(title.getNode()));
259 // OVERRIDDEN FROM PARENT VIEWER
261 protected void save(EditablePart part) throws RepositoryException {
262 if (part instanceof EditableText) {
263 EditableText et = (EditableText) part;
264 if (!et.getEditable())
266 String text = ((Text) et.getControl()).getText();
268 // String[] lines = text.split("[\r\n]+");
269 String[] lines = { text };
270 assert lines.length != 0;
271 saveLine(part, lines[0]);
272 if (lines.length > 1) {
273 ArrayList<Control> toLayout = new ArrayList<Control>();
274 if (part instanceof Paragraph) {
275 Paragraph currentParagraph = (Paragraph) et;
276 Section section = currentParagraph.getSection();
277 Node sectionNode = section.getNode();
278 Node currentParagraphN = currentParagraph.getNode();
279 for (int i = 1; i < lines.length; i++) {
280 Node newNode = sectionNode.addNode(DocBookNames.DBK_PARA, DocBookTypes.PARA);
281 // newNode.addMixin(CmsTypes.CMS_STYLED);
282 saveLine(newNode, lines[i]);
283 // second node was create as last, if it is not the next
285 // means there are some in between and we can take the
287 // index+1 for the re-order
288 if (newNode.getIndex() > currentParagraphN.getIndex() + 1) {
289 sectionNode.orderBefore(p(newNode.getIndex()), p(currentParagraphN.getIndex() + 1));
291 Paragraph newParagraph = newParagraph((TextSection) section, newNode);
292 newParagraph.moveBelow(currentParagraph);
293 toLayout.add(newParagraph);
295 currentParagraph = newParagraph;
296 currentParagraphN = newNode;
299 // TODO or rather return the created paragraphs?
300 layout(toLayout.toArray(new Control[toLayout.size()]));
302 persistChanges(et.getNode());
306 protected void saveLine(EditablePart part, String line) {
307 if (part instanceof NodePart) {
308 saveLine(((NodePart) part).getNode(), line);
309 } else if (part instanceof PropertyPart) {
310 saveLine(((PropertyPart) part).getProperty(), line);
312 throw new IllegalArgumentException("Unsupported part " + part);
316 protected void saveLine(Item item, String line) {
318 textInterpreter.write(item, line);
322 protected void prepare(EditablePart part, Object caretPosition) {
323 Control control = part.getControl();
324 if (control instanceof Text) {
325 Text text = (Text) control;
326 if (caretPosition != null)
327 if (caretPosition instanceof Integer)
328 text.setSelection((Integer) caretPosition);
329 else if (caretPosition instanceof Point) {
330 // TODO find a way to position the caret at the right place
332 text.setData(RWT.ACTIVE_KEYS, new String[] { "BACKSPACE", "ESC", "TAB", "SHIFT+TAB", "ALT+ARROW_LEFT",
333 "ALT+ARROW_RIGHT", "ALT+ARROW_UP", "ALT+ARROW_DOWN", "RETURN", "CTRL+RETURN", "ENTER", "DELETE" });
334 text.setData(RWT.CANCEL_KEYS, new String[] { "RETURN", "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT" });
335 text.addKeyListener(this);
336 } else if (part instanceof Img) {
337 ((Img) part).setFileUploadListener(fileUploadListener);
341 // REQUIRED BY CONTEXT MENU
342 void setParagraphStyle(Paragraph paragraph, String style) {
344 Node paragraphNode = paragraph.getNode();
345 if (style == null) {// default
346 if (paragraphNode.hasProperty(DocBookNames.DBK_ROLE))
347 paragraphNode.getProperty(DocBookNames.DBK_ROLE).remove();
349 paragraphNode.setProperty(DocBookNames.DBK_ROLE, style);
351 persistChanges(paragraphNode);
352 updateContent(paragraph);
354 } catch (RepositoryException e1) {
355 throw new JcrException("Cannot set style " + style + " on " + paragraph, e1);
359 void insertPart(Section section, Node node) {
363 } catch (RepositoryException e) {
364 throw new JcrException("Cannot insert part " + node + " in section " + section.getNode(), e);
368 void deletePart(SectionPart sectionPart) {
370 Node node = sectionPart.getNode();
371 Session session = node.getSession();
372 if (sectionPart instanceof Img) {
373 // FIXME make it more robust
374 node = node.getParent().getParent().getParent();
378 if (sectionPart instanceof Control)
379 ((Control) sectionPart).dispose();
381 } catch (RepositoryException e1) {
382 throw new JcrException("Cannot delete " + sectionPart, e1);
386 void deleteSection(Section section) {
388 Node node = section.getNode();
389 Session session = node.getSession();
394 } catch (RepositoryException e1) {
395 throw new JcrException("Cannot delete " + section, e1);
399 String getRawParagraphText(Paragraph paragraph) {
400 return textInterpreter.raw(paragraph.getNode());
404 protected void splitEdit() {
407 if (getEdited() instanceof Paragraph) {
408 Paragraph paragraph = (Paragraph) getEdited();
409 Text text = (Text) paragraph.getControl();
410 int caretPosition = text.getCaretPosition();
411 String txt = text.getText();
412 String first = txt.substring(0, caretPosition);
413 String second = txt.substring(caretPosition);
414 Node firstNode = paragraph.getNode();
415 Node sectionNode = firstNode.getParent();
417 // FIXME set content the DocBook way
418 // firstNode.setProperty(CMS_CONTENT, first);
419 Node secondNode = sectionNode.addNode(DocBookNames.DBK_PARA, DocBookTypes.PARA);
420 // secondNode.addMixin(CmsTypes.CMS_STYLED);
422 // second node was create as last, if it is not the next one, it
423 // means there are some in between and we can take the one at
424 // index+1 for the re-order
425 if (secondNode.getIndex() > firstNode.getIndex() + 1) {
426 sectionNode.orderBefore(p(secondNode.getIndex()), p(firstNode.getIndex() + 1));
429 // if we die in between, at least we still have the whole text
432 textInterpreter.write(secondNode, second);
433 textInterpreter.write(firstNode, first);
434 } catch (Exception e) {
435 // so that no additional nodes are created:
436 JcrUtils.discardUnderlyingSessionQuietly(firstNode);
440 persistChanges(firstNode);
442 Paragraph secondParagraph = paragraphSplitted(paragraph, secondNode);
443 edit(secondParagraph, 0);
444 } else if (getEdited() instanceof DocBookSectionTitle) {
445 DocBookSectionTitle sectionTitle = (DocBookSectionTitle) getEdited();
446 Text text = (Text) sectionTitle.getControl();
447 String txt = text.getText();
448 int caretPosition = text.getCaretPosition();
449 Section section = sectionTitle.getSection();
450 Node sectionNode = section.getNode();
451 Node paragraphNode = sectionNode.addNode(DocBookNames.DBK_PARA, DocBookTypes.PARA);
452 // paragraphNode.addMixin(CmsTypes.CMS_STYLED);
454 textInterpreter.write(paragraphNode, txt.substring(caretPosition));
455 textInterpreter.write(sectionNode.getNode(DocBookTypes.TITLE), txt.substring(0, caretPosition));
456 sectionNode.orderBefore(p(paragraphNode.getIndex()), p(1));
457 persistChanges(sectionNode);
459 Paragraph paragraph = sectionTitleSplitted(sectionTitle, paragraphNode);
463 } catch (RepositoryException e) {
464 throw new JcrException("Cannot split " + getEdited(), e);
468 protected void mergeWithPrevious() {
471 Paragraph paragraph = (Paragraph) getEdited();
472 Text text = (Text) paragraph.getControl();
473 String txt = text.getText();
474 Node paragraphNode = paragraph.getNode();
475 if (paragraphNode.getIndex() == 1)
477 Node sectionNode = paragraphNode.getParent();
478 Node previousNode = sectionNode.getNode(p(paragraphNode.getIndex() - 1));
479 String previousTxt = textInterpreter.read(previousNode);
480 textInterpreter.write(previousNode, previousTxt + txt);
481 paragraphNode.remove();
482 persistChanges(sectionNode);
484 Paragraph previousParagraph = paragraphMergedWithPrevious(paragraph, previousNode);
485 edit(previousParagraph, previousTxt.length());
486 } catch (RepositoryException e) {
487 throw new JcrException("Cannot stop editing", e);
491 protected void mergeWithNext() {
494 Paragraph paragraph = (Paragraph) getEdited();
495 Text text = (Text) paragraph.getControl();
496 String txt = text.getText();
497 Node paragraphNode = paragraph.getNode();
498 Node sectionNode = paragraphNode.getParent();
499 NodeIterator paragraphNodes = sectionNode.getNodes(DocBookNames.DBK_PARA);
500 long size = paragraphNodes.getSize();
501 if (paragraphNode.getIndex() == size)
503 Node nextNode = sectionNode.getNode(p(paragraphNode.getIndex() + 1));
504 String nextTxt = textInterpreter.read(nextNode);
505 textInterpreter.write(paragraphNode, txt + nextTxt);
507 Section section = paragraph.getSection();
508 Paragraph removed = (Paragraph) section.getSectionPart(nextNode.getIdentifier());
511 persistChanges(sectionNode);
513 paragraphMergedWithNext(paragraph, removed);
514 edit(paragraph, txt.length());
515 } catch (RepositoryException e) {
516 throw new JcrException("Cannot stop editing", e);
520 protected synchronized void upload(EditablePart part) {
522 if (part instanceof SectionPart) {
523 SectionPart sectionPart = (SectionPart) part;
524 Node partNode = sectionPart.getNode();
525 int partIndex = partNode.getIndex();
526 Section section = sectionPart.getSection();
527 Node sectionNode = section.getNode();
529 if (part instanceof Paragraph) {
530 // FIXME adapt to DocBook
531 Node newNode = sectionNode.addNode(DocBookNames.DBK_MEDIAOBJECT, NodeType.NT_FILE);
532 newNode.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
533 JcrUtils.copyBytesAsFile(sectionNode, p(newNode.getIndex()), new byte[0]);
534 if (partIndex < newNode.getIndex() - 1) {
536 sectionNode.orderBefore(p(newNode.getIndex()), p(partIndex - 1));
538 // sectionNode.orderBefore(p(partNode.getIndex()),
539 // p(newNode.getIndex()));
540 persistChanges(sectionNode);
541 Img img = newImg((TextSection) section, newNode);
543 layout(img.getControl());
544 } else if (part instanceof Img) {
545 if (getEdited() == part)
551 } catch (RepositoryException e) {
552 throw new JcrException("Cannot upload", e);
556 protected void deepen() {
561 if (getEdited() instanceof Paragraph) {
562 Paragraph paragraph = (Paragraph) getEdited();
563 Text text = (Text) paragraph.getControl();
564 String txt = text.getText();
565 Node paragraphNode = paragraph.getNode();
566 Section section = paragraph.getSection();
567 Node sectionNode = section.getNode();
569 if (section == mainSection && section instanceof TextSection && paragraphNode.getIndex() == 1
570 && !sectionNode.hasNode(DocBookTypes.TITLE)) {
571 DocBookSectionTitle sectionTitle = prepareSectionTitle(section, txt);
572 edit(sectionTitle, 0);
575 Node newSectionNode = sectionNode.addNode(DocBookNames.DBK_SECTION, DocBookTypes.SECTION);
576 // newSectionNode.addMixin(NodeType.MIX_TITLE);
577 sectionNode.orderBefore(h(newSectionNode.getIndex()), h(1));
579 int paragraphIndex = paragraphNode.getIndex();
580 String sectionPath = sectionNode.getPath();
581 String newSectionPath = newSectionNode.getPath();
582 while (sectionNode.hasNode(p(paragraphIndex + 1))) {
583 Node parag = sectionNode.getNode(p(paragraphIndex + 1));
584 sectionNode.getSession().move(sectionPath + '/' + p(paragraphIndex + 1),
585 newSectionPath + '/' + DocBookNames.DBK_PARA);
586 SectionPart sp = section.getSectionPart(parag.getIdentifier());
587 if (sp instanceof Control)
588 ((Control) sp).dispose();
591 Node titleNode = newSectionNode.addNode(DocBookTypes.TITLE, DocBookTypes.TITLE);
592 getTextInterpreter().write(titleNode, txt);
594 TextSection newSection = new TextSection(section, section.getStyle(), newSectionNode);
595 newSection.setLayoutData(CmsUiUtils.fillWidth());
596 newSection.moveBelow(paragraph);
599 paragraphNode.remove();
603 newSection.getParent().layout();
605 persistChanges(sectionNode);
606 } else if (getEdited() instanceof DocBookSectionTitle) {
607 DocBookSectionTitle sectionTitle = (DocBookSectionTitle) getEdited();
608 Section section = sectionTitle.getSection();
609 Section parentSection = section.getParentSection();
610 if (parentSection == null)
611 return;// cannot deepen main section
612 Node sectionN = section.getNode();
613 Node parentSectionN = parentSection.getNode();
614 if (sectionN.getIndex() == 1)
615 return;// cannot deepen first section
616 Node previousSectionN = parentSectionN.getNode(h(sectionN.getIndex() - 1));
617 NodeIterator subSections = previousSectionN.getNodes(DocBookNames.DBK_SECTION);
618 int subsectionsCount = (int) subSections.getSize();
619 previousSectionN.getSession().move(sectionN.getPath(),
620 previousSectionN.getPath() + "/" + h(subsectionsCount + 1));
622 TextSection newSection = new TextSection(section, section.getStyle(), sectionN);
624 persistChanges(previousSectionN);
626 } catch (RepositoryException e) {
627 throw new JcrException("Cannot deepen " + getEdited(), e);
631 protected void undeepen() {
636 if (getEdited() instanceof Paragraph) {
638 } else if (getEdited() instanceof DocBookSectionTitle) {
639 DocBookSectionTitle sectionTitle = (DocBookSectionTitle) getEdited();
640 Section section = sectionTitle.getSection();
641 Node sectionNode = section.getNode();
642 Section parentSection = section.getParentSection();
643 if (parentSection == null)
644 return;// cannot undeepen main section
646 // choose in which section to merge
647 Section mergedSection;
648 if (sectionNode.getIndex() == 1)
649 mergedSection = section.getParentSection();
651 Map<String, Section> parentSubsections = parentSection.getSubSections();
652 ArrayList<Section> lst = new ArrayList<Section>(parentSubsections.values());
653 mergedSection = lst.get(sectionNode.getIndex() - 1);
655 Node mergedNode = mergedSection.getNode();
656 boolean mergedHasSubSections = mergedNode.hasNode(DocBookNames.DBK_SECTION);
658 // title as paragraph
659 Node newParagrapheNode = mergedNode.addNode(DocBookNames.DBK_PARA, DocBookTypes.PARA);
660 // newParagrapheNode.addMixin(CmsTypes.CMS_STYLED);
661 if (mergedHasSubSections)
662 mergedNode.orderBefore(p(newParagrapheNode.getIndex()), h(1));
663 String txt = getTextInterpreter().read(sectionNode.getNode(DocBookTypes.TITLE));
664 getTextInterpreter().write(newParagrapheNode, txt);
666 NodeIterator paragraphs = sectionNode.getNodes(DocBookNames.DBK_PARA);
667 while (paragraphs.hasNext()) {
668 Node p = paragraphs.nextNode();
669 SectionPart sp = section.getSectionPart(p.getIdentifier());
670 if (sp instanceof Control)
671 ((Control) sp).dispose();
672 mergedNode.getSession().move(p.getPath(), mergedNode.getPath() + '/' + DocBookNames.DBK_PARA);
673 if (mergedHasSubSections)
674 mergedNode.orderBefore(p(p.getIndex()), h(1));
677 Iterator<Section> subsections = section.getSubSections().values().iterator();
678 // NodeIterator sections = sectionNode.getNodes(CMS_H);
679 while (subsections.hasNext()) {
680 Section subsection = subsections.next();
681 Node s = subsection.getNode();
682 mergedNode.getSession().move(s.getPath(), mergedNode.getPath() + '/' + DocBookNames.DBK_SECTION);
683 subsection.dispose();
687 section.getNode().remove();
690 refresh(mergedSection);
691 mergedSection.getParent().layout();
692 layout(mergedSection);
693 persistChanges(mergedNode);
695 } catch (RepositoryException e) {
696 throw new JcrException("Cannot undeepen " + getEdited(), e);
701 protected Paragraph paragraphSplitted(Paragraph paragraph, Node newNode) throws RepositoryException {
702 Section section = paragraph.getSection();
703 updateContent(paragraph);
704 Paragraph newParagraph = newParagraph((TextSection) section, newNode);
705 newParagraph.setLayoutData(CmsUiUtils.fillWidth());
706 newParagraph.moveBelow(paragraph);
707 layout(paragraph.getControl(), newParagraph.getControl());
711 protected Paragraph sectionTitleSplitted(DocBookSectionTitle sectionTitle, Node newNode)
712 throws RepositoryException {
713 updateContent(sectionTitle);
714 Paragraph newParagraph = newParagraph(sectionTitle.getSection(), newNode);
715 // we assume beforeFirst is not null since there was a sectionTitle
716 newParagraph.moveBelow(sectionTitle.getSection().getHeader());
717 layout(sectionTitle.getControl(), newParagraph.getControl());
721 protected Paragraph paragraphMergedWithPrevious(Paragraph removed, Node remaining) throws RepositoryException {
722 Section section = removed.getSection();
725 Paragraph paragraph = (Paragraph) section.getSectionPart(remaining.getIdentifier());
726 updateContent(paragraph);
727 layout(paragraph.getControl());
731 protected void paragraphMergedWithNext(Paragraph remaining, Paragraph removed) throws RepositoryException {
733 updateContent(remaining);
734 layout(remaining.getControl());
738 protected String p(Integer index) {
739 StringBuilder sb = new StringBuilder(6);
740 sb.append(DocBookNames.DBK_PARA).append('[').append(index).append(']');
741 return sb.toString();
744 protected String h(Integer index) {
745 StringBuilder sb = new StringBuilder(5);
746 sb.append(DocBookNames.DBK_SECTION).append('[').append(index).append(']');
747 return sb.toString();
751 public Section getMainSection() {
755 public boolean isFlat() {
759 public TextInterpreter getTextInterpreter() {
760 return textInterpreter;
765 public void keyPressed(KeyEvent ke) {
766 if (log.isTraceEnabled())
769 if (getEdited() == null)
771 boolean altPressed = (ke.stateMask & SWT.ALT) != 0;
772 boolean shiftPressed = (ke.stateMask & SWT.SHIFT) != 0;
773 boolean ctrlPressed = (ke.stateMask & SWT.CTRL) != 0;
777 if (ke.keyCode == SWT.ESC) {
780 } else if (ke.character == '\r') {
783 } else if (ke.character == 'z') {
786 } else if (ke.character == 'S') {
789 } else if (ke.character == '\t') {
792 } else if (shiftPressed) {
796 if (getEdited() instanceof Paragraph) {
797 Paragraph paragraph = (Paragraph) getEdited();
798 Section section = paragraph.getSection();
799 if (altPressed && ke.keyCode == SWT.ARROW_RIGHT) {
800 edit(section.nextSectionPart(paragraph), 0);
801 } else if (altPressed && ke.keyCode == SWT.ARROW_LEFT) {
802 edit(section.previousSectionPart(paragraph), 0);
803 } else if (ke.character == SWT.BS) {
804 Text text = (Text) paragraph.getControl();
805 int caretPosition = text.getCaretPosition();
806 if (caretPosition == 0) {
809 } else if (ke.character == SWT.DEL) {
810 Text text = (Text) paragraph.getControl();
811 int caretPosition = text.getCaretPosition();
812 int charcount = text.getCharCount();
813 if (caretPosition == charcount) {
819 } catch (Exception e) {
821 notifyEditionException(e);
826 public void keyReleased(KeyEvent e) {
831 protected MouseListener createMouseListener() {
835 private class ML extends MouseAdapter {
836 private static final long serialVersionUID = 8526890859876770905L;
839 public void mouseDoubleClick(MouseEvent e) {
841 Control source = (Control) e.getSource();
842 EditablePart composite = findDataParent(source);
843 Point point = new Point(e.x, e.y);
844 if (composite instanceof Img) {
845 if (getCmsEditable().canEdit()) {
846 if (getCmsEditable().isEditing() && !(getEdited() instanceof Img)) {
847 if (source == mainSection)
849 EditablePart part = findDataParent(source);
852 getCmsEditable().startEditing();
856 edit(composite, source.toDisplay(point));
861 public void mouseDown(MouseEvent e) {
862 if (getCmsEditable().isEditing()) {
864 EditablePart composite = findDataParent((Control) e.getSource());
865 if (styledTools != null) {
866 List<String> styles = getAvailableStyles(composite);
867 styledTools.show(composite, new Point(e.x, e.y), styles);
874 public void mouseUp(MouseEvent e) {
878 protected List<String> getAvailableStyles(EditablePart editablePart) {
879 return new ArrayList<>();
882 // FILE UPLOAD LISTENER
883 private class FUL implements FileUploadListener {
884 public void uploadProgress(FileUploadEvent event) {
885 // TODO Monitor upload progress
888 public void uploadFailed(FileUploadEvent event) {
889 throw new RuntimeException("Upload failed " + event, event.getException());
892 public void uploadFinished(FileUploadEvent event) {
893 for (FileDetails file : event.getFileDetails()) {
894 if (log.isDebugEnabled())
895 log.debug("Received: " + file.getFileName());
897 mainSection.getDisplay().syncExec(new Runnable() {
903 FileUploadHandler uploadHandler = (FileUploadHandler) event.getSource();
904 uploadHandler.dispose();