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();