1 package org
.argeo
.cms
.text
;
3 import static javax
.jcr
.Property
.JCR_TITLE
;
4 import static org
.argeo
.cms
.ui
.util
.CmsUiUtils
.fillWidth
;
6 import java
.util
.ArrayList
;
7 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
.Property
;
15 import javax
.jcr
.RepositoryException
;
16 import javax
.jcr
.Session
;
17 import javax
.jcr
.nodetype
.NodeType
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.argeo
.cms
.CmsException
;
22 import org
.argeo
.cms
.ui
.CmsEditable
;
23 import org
.argeo
.cms
.ui
.CmsImageManager
;
24 import org
.argeo
.cms
.ui
.util
.CmsUiUtils
;
25 import org
.argeo
.cms
.ui
.viewers
.AbstractPageViewer
;
26 import org
.argeo
.cms
.ui
.viewers
.EditablePart
;
27 import org
.argeo
.cms
.ui
.viewers
.NodePart
;
28 import org
.argeo
.cms
.ui
.viewers
.PropertyPart
;
29 import org
.argeo
.cms
.ui
.viewers
.Section
;
30 import org
.argeo
.cms
.ui
.viewers
.SectionPart
;
31 import org
.argeo
.cms
.ui
.widgets
.EditableImage
;
32 import org
.argeo
.cms
.ui
.widgets
.EditableText
;
33 import org
.argeo
.cms
.ui
.widgets
.Img
;
34 import org
.argeo
.cms
.ui
.widgets
.StyledControl
;
35 import org
.argeo
.jcr
.JcrUtils
;
36 import org
.eclipse
.rap
.fileupload
.FileDetails
;
37 import org
.eclipse
.rap
.fileupload
.FileUploadEvent
;
38 import org
.eclipse
.rap
.fileupload
.FileUploadHandler
;
39 import org
.eclipse
.rap
.fileupload
.FileUploadListener
;
40 import org
.eclipse
.rap
.rwt
.RWT
;
41 import org
.eclipse
.swt
.SWT
;
42 import org
.eclipse
.swt
.events
.KeyEvent
;
43 import org
.eclipse
.swt
.events
.KeyListener
;
44 import org
.eclipse
.swt
.events
.MouseAdapter
;
45 import org
.eclipse
.swt
.events
.MouseEvent
;
46 import org
.eclipse
.swt
.events
.MouseListener
;
47 import org
.eclipse
.swt
.graphics
.Point
;
48 import org
.eclipse
.swt
.widgets
.Composite
;
49 import org
.eclipse
.swt
.widgets
.Control
;
50 import org
.eclipse
.swt
.widgets
.Text
;
52 /** Base class for text viewers and editors. */
54 public abstract class AbstractTextViewer
extends AbstractPageViewer
implements
55 CmsNames
, KeyListener
, Observer
{
56 private static final long serialVersionUID
= -2401274679492339668L;
57 private final static Log log
= LogFactory
.getLog(AbstractTextViewer
.class);
59 private final Section mainSection
;
61 private TextInterpreter textInterpreter
= new TextInterpreterImpl();
62 private CmsImageManager imageManager
= CmsUiUtils
.getCmsView()
65 private FileUploadListener fileUploadListener
;
66 private TextContextMenu styledTools
;
68 private final boolean flat
;
70 protected AbstractTextViewer(Section parent
, int style
,
71 CmsEditable cmsEditable
) {
72 super(parent
, style
, cmsEditable
);
73 flat
= SWT
.FLAT
== (style
& SWT
.FLAT
);
75 if (getCmsEditable().canEdit()) {
76 fileUploadListener
= new FUL();
77 styledTools
= new TextContextMenu(this, parent
.getDisplay());
79 this.mainSection
= parent
;
80 initModelIfNeeded(mainSection
.getNode());
81 // layout(this.mainSection);
85 public Control
getControl() {
89 protected void refresh(Control control
) throws RepositoryException
{
90 if (!(control
instanceof Section
))
92 Section section
= (Section
) control
;
93 if (section
instanceof TextSection
) {
94 CmsUiUtils
.clear(section
);
95 Node node
= section
.getNode();
96 TextSection textSection
= (TextSection
) section
;
97 if (node
.hasProperty(Property
.JCR_TITLE
)) {
98 if (section
.getHeader() == null)
99 section
.createHeader();
100 if (node
.hasProperty(Property
.JCR_TITLE
)) {
101 SectionTitle title
= newSectionTitle(textSection
, node
);
102 title
.setLayoutData(CmsUiUtils
.fillWidth());
103 updateContent(title
);
107 for (NodeIterator ni
= node
.getNodes(CMS_P
); ni
.hasNext();) {
108 Node child
= ni
.nextNode();
109 final SectionPart sectionPart
;
110 if (child
.isNodeType(CmsTypes
.CMS_IMAGE
)
111 || child
.isNodeType(NodeType
.NT_FILE
)) {
112 sectionPart
= newImg(textSection
, child
);
113 } else if (child
.isNodeType(CmsTypes
.CMS_STYLED
)) {
114 sectionPart
= newParagraph(textSection
, child
);
116 sectionPart
= newSectionPart(textSection
, child
);
117 if (sectionPart
== null)
118 throw new CmsException("Unsupported node " + child
);
119 // TODO list node types in exception
121 if (sectionPart
instanceof Control
)
122 ((Control
) sectionPart
).setLayoutData(CmsUiUtils
.fillWidth());
126 for (NodeIterator ni
= section
.getNode().getNodes(CMS_H
); ni
128 Node child
= ni
.nextNode();
129 if (child
.isNodeType(CmsTypes
.CMS_SECTION
)) {
130 TextSection newSection
= new TextSection(section
,
132 newSection
.setLayoutData(CmsUiUtils
.fillWidth());
137 for (Section s
: section
.getSubSections().values())
143 /** To be overridden in order to provide additional SectionPart types */
144 protected SectionPart
newSectionPart(TextSection textSection
, Node node
) {
149 protected Paragraph
newParagraph(TextSection parent
, Node node
)
150 throws RepositoryException
{
151 Paragraph paragraph
= new Paragraph(parent
, parent
.getStyle(), node
);
152 updateContent(paragraph
);
153 paragraph
.setLayoutData(fillWidth());
154 paragraph
.setMouseListener(getMouseListener());
158 protected Img
newImg(TextSection parent
, Node node
)
159 throws RepositoryException
{
160 Img img
= new Img(parent
, parent
.getStyle(), node
) {
161 private static final long serialVersionUID
= 1297900641952417540L;
164 protected void setContainerLayoutData(Composite composite
) {
165 composite
.setLayoutData(CmsUiUtils
.grabWidth(SWT
.CENTER
,
170 protected void setControlLayoutData(Control control
) {
171 control
.setLayoutData(CmsUiUtils
.grabWidth(SWT
.CENTER
,
175 img
.setLayoutData(CmsUiUtils
.grabWidth(SWT
.CENTER
, SWT
.DEFAULT
));
177 img
.setMouseListener(getMouseListener());
181 protected SectionTitle
newSectionTitle(TextSection parent
, Node node
)
182 throws RepositoryException
{
183 SectionTitle title
= new SectionTitle(parent
.getHeader(),
184 parent
.getStyle(), node
.getProperty(JCR_TITLE
));
185 updateContent(title
);
186 title
.setMouseListener(getMouseListener());
190 protected SectionTitle
prepareSectionTitle(Section newSection
,
191 String titleText
) throws RepositoryException
{
192 Node sectionNode
= newSection
.getNode();
193 if (!sectionNode
.hasProperty(JCR_TITLE
))
194 sectionNode
.setProperty(Property
.JCR_TITLE
, "");
195 getTextInterpreter().write(sectionNode
.getProperty(Property
.JCR_TITLE
),
197 if (newSection
.getHeader() == null)
198 newSection
.createHeader();
199 SectionTitle sectionTitle
= newSectionTitle((TextSection
) newSection
,
204 protected void updateContent(EditablePart part
) throws RepositoryException
{
205 if (part
instanceof SectionPart
) {
206 SectionPart sectionPart
= (SectionPart
) part
;
207 Node partNode
= sectionPart
.getNode();
209 if (part
instanceof StyledControl
210 && (sectionPart
.getSection() instanceof TextSection
)) {
211 TextSection section
= (TextSection
) sectionPart
.getSection();
212 StyledControl styledControl
= (StyledControl
) part
;
213 if (partNode
.isNodeType(CmsTypes
.CMS_STYLED
)) {
214 String style
= partNode
.hasProperty(CMS_STYLE
) ? partNode
215 .getProperty(CMS_STYLE
).getString() : section
216 .getDefaultTextStyle();
217 styledControl
.setStyle(style
);
220 // use control AFTER setting style, since it may have been reset
222 if (part
instanceof EditableText
) {
223 EditableText paragraph
= (EditableText
) part
;
224 if (paragraph
== getEdited())
225 paragraph
.setText(textInterpreter
.read(partNode
));
227 paragraph
.setText(textInterpreter
.raw(partNode
));
228 } else if (part
instanceof EditableImage
) {
229 EditableImage editableImage
= (EditableImage
) part
;
230 imageManager
.load(partNode
, part
.getControl(),
231 editableImage
.getPreferredImageSize());
233 } else if (part
instanceof SectionTitle
) {
234 SectionTitle title
= (SectionTitle
) part
;
235 title
.setStyle(title
.getSection().getTitleStyle());
236 // use control AFTER setting style
237 if (title
== getEdited())
238 title
.setText(textInterpreter
.read(title
.getProperty()));
240 title
.setText(textInterpreter
.raw(title
.getProperty()));
244 // OVERRIDDEN FROM PARENT VIEWER
246 protected void save(EditablePart part
) throws RepositoryException
{
247 if (part
instanceof EditableText
) {
248 EditableText et
= (EditableText
) part
;
249 String text
= ((Text
) et
.getControl()).getText();
251 String
[] lines
= text
.split("[\r\n]+");
252 assert lines
.length
!= 0;
253 saveLine(part
, lines
[0]);
254 if (lines
.length
> 1) {
255 ArrayList
<Control
> toLayout
= new ArrayList
<Control
>();
256 if (part
instanceof Paragraph
) {
257 Paragraph currentParagraph
= (Paragraph
) et
;
258 Section section
= currentParagraph
.getSection();
259 Node sectionNode
= section
.getNode();
260 Node currentParagraphN
= currentParagraph
.getNode();
261 for (int i
= 1; i
< lines
.length
; i
++) {
262 Node newNode
= sectionNode
.addNode(CMS_P
);
263 newNode
.addMixin(CmsTypes
.CMS_STYLED
);
264 saveLine(newNode
, lines
[i
]);
265 // second node was create as last, if it is not the next
267 // means there are some in between and we can take the
269 // index+1 for the re-order
270 if (newNode
.getIndex() > currentParagraphN
.getIndex() + 1) {
271 sectionNode
.orderBefore(p(newNode
.getIndex()),
272 p(currentParagraphN
.getIndex() + 1));
274 Paragraph newParagraph
= newParagraph(
275 (TextSection
) section
, newNode
);
276 newParagraph
.moveBelow(currentParagraph
);
277 toLayout
.add(newParagraph
);
279 currentParagraph
= newParagraph
;
280 currentParagraphN
= newNode
;
282 persistChanges(sectionNode
);
284 // TODO or rather return the created paragarphs?
285 layout(toLayout
.toArray(new Control
[toLayout
.size()]));
290 protected void saveLine(EditablePart part
, String line
) {
291 if (part
instanceof NodePart
) {
292 saveLine(((NodePart
) part
).getNode(), line
);
293 } else if (part
instanceof PropertyPart
) {
294 saveLine(((PropertyPart
) part
).getProperty(), line
);
296 throw new CmsException("Unsupported part " + part
);
300 protected void saveLine(Item item
, String line
) {
302 textInterpreter
.write(item
, line
);
306 protected void prepare(EditablePart part
, Object caretPosition
) {
307 Control control
= part
.getControl();
308 if (control
instanceof Text
) {
309 Text text
= (Text
) control
;
310 if (caretPosition
!= null)
311 if (caretPosition
instanceof Integer
)
312 text
.setSelection((Integer
) caretPosition
);
313 else if (caretPosition
instanceof Point
) {
314 // TODO find a way to position the caret at the right place
316 text
.setData(RWT
.ACTIVE_KEYS
, new String
[] { "BACKSPACE", "ESC",
317 "TAB", "SHIFT+TAB", "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT",
318 "ALT+ARROW_UP", "ALT+ARROW_DOWN", "RETURN", "CTRL+RETURN",
319 "ENTER", "DELETE" });
320 text
.setData(RWT
.CANCEL_KEYS
, new String
[] { "RETURN",
321 "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT" });
322 text
.addKeyListener(this);
323 } else if (part
instanceof Img
) {
324 ((Img
) part
).setFileUploadListener(fileUploadListener
);
328 // REQUIRED BY CONTEXT MENU
329 void setParagraphStyle(Paragraph paragraph
, String style
) {
331 Node paragraphNode
= paragraph
.getNode();
332 paragraphNode
.setProperty(CMS_STYLE
, style
);
333 persistChanges(paragraphNode
);
334 updateContent(paragraph
);
336 } catch (RepositoryException e1
) {
337 throw new CmsException("Cannot set style " + style
+ " on "
342 void deletePart(SectionPart paragraph
) {
344 Node paragraphNode
= paragraph
.getNode();
345 Section section
= paragraph
.getSection();
346 Session session
= paragraphNode
.getSession();
347 paragraphNode
.remove();
349 if (paragraph
instanceof Control
)
350 ((Control
) paragraph
).dispose();
352 } catch (RepositoryException e1
) {
353 throw new CmsException("Cannot delete " + paragraph
, e1
);
357 String
getRawParagraphText(Paragraph paragraph
) {
358 return textInterpreter
.raw(paragraph
.getNode());
362 protected void splitEdit() {
365 if (getEdited() instanceof Paragraph
) {
366 Paragraph paragraph
= (Paragraph
) getEdited();
367 Text text
= (Text
) paragraph
.getControl();
368 int caretPosition
= text
.getCaretPosition();
369 String txt
= text
.getText();
370 String first
= txt
.substring(0, caretPosition
);
371 String second
= txt
.substring(caretPosition
);
372 Node firstNode
= paragraph
.getNode();
373 Node sectionNode
= firstNode
.getParent();
374 firstNode
.setProperty(CMS_CONTENT
, first
);
375 Node secondNode
= sectionNode
.addNode(CMS_P
);
376 secondNode
.addMixin(CmsTypes
.CMS_STYLED
);
377 // second node was create as last, if it is not the next one, it
378 // means there are some in between and we can take the one at
379 // index+1 for the re-order
380 if (secondNode
.getIndex() > firstNode
.getIndex() + 1) {
381 sectionNode
.orderBefore(p(secondNode
.getIndex()),
382 p(firstNode
.getIndex() + 1));
385 // if we die in between, at least we still have the whole text
388 textInterpreter
.write(secondNode
, second
);
389 textInterpreter
.write(firstNode
, first
);
390 } catch (Exception e
) {
391 // so that no additional nodes are created:
392 JcrUtils
.discardUnderlyingSessionQuietly(firstNode
);
396 persistChanges(firstNode
);
398 Paragraph secondParagraph
= paragraphSplitted(paragraph
,
400 edit(secondParagraph
, 0);
401 } else if (getEdited() instanceof SectionTitle
) {
402 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
403 Text text
= (Text
) sectionTitle
.getControl();
404 String txt
= text
.getText();
405 int caretPosition
= text
.getCaretPosition();
406 Section section
= sectionTitle
.getSection();
407 Node sectionNode
= section
.getNode();
408 Node paragraphNode
= sectionNode
.addNode(CMS_P
);
409 paragraphNode
.addMixin(CmsTypes
.CMS_STYLED
);
410 textInterpreter
.write(paragraphNode
,
411 txt
.substring(caretPosition
));
412 textInterpreter
.write(
413 sectionNode
.getProperty(Property
.JCR_TITLE
),
414 txt
.substring(0, caretPosition
));
415 sectionNode
.orderBefore(p(paragraphNode
.getIndex()), p(1));
416 persistChanges(sectionNode
);
418 Paragraph paragraph
= sectionTitleSplitted(sectionTitle
,
423 } catch (RepositoryException e
) {
424 throw new CmsException("Cannot split " + getEdited(), e
);
428 protected void mergeWithPrevious() {
431 Paragraph paragraph
= (Paragraph
) getEdited();
432 Text text
= (Text
) paragraph
.getControl();
433 String txt
= text
.getText();
434 Node paragraphNode
= paragraph
.getNode();
435 if (paragraphNode
.getIndex() == 1)
437 Node sectionNode
= paragraphNode
.getParent();
438 Node previousNode
= sectionNode
439 .getNode(p(paragraphNode
.getIndex() - 1));
440 String previousTxt
= textInterpreter
.read(previousNode
);
441 textInterpreter
.write(previousNode
, previousTxt
+ txt
);
442 paragraphNode
.remove();
443 persistChanges(sectionNode
);
445 Paragraph previousParagraph
= paragraphMergedWithPrevious(
446 paragraph
, previousNode
);
447 edit(previousParagraph
, previousTxt
.length());
448 } catch (RepositoryException e
) {
449 throw new CmsException("Cannot stop editing", e
);
453 protected void mergeWithNext() {
456 Paragraph paragraph
= (Paragraph
) getEdited();
457 Text text
= (Text
) paragraph
.getControl();
458 String txt
= text
.getText();
459 Node paragraphNode
= paragraph
.getNode();
460 Node sectionNode
= paragraphNode
.getParent();
461 NodeIterator paragraphNodes
= sectionNode
.getNodes(CMS_P
);
462 long size
= paragraphNodes
.getSize();
463 if (paragraphNode
.getIndex() == size
)
465 Node nextNode
= sectionNode
466 .getNode(p(paragraphNode
.getIndex() + 1));
467 String nextTxt
= textInterpreter
.read(nextNode
);
468 textInterpreter
.write(paragraphNode
, txt
+ nextTxt
);
470 Section section
= paragraph
.getSection();
471 Paragraph removed
= (Paragraph
) section
.getSectionPart(nextNode
475 persistChanges(sectionNode
);
477 paragraphMergedWithNext(paragraph
, removed
);
478 edit(paragraph
, txt
.length());
479 } catch (RepositoryException e
) {
480 throw new CmsException("Cannot stop editing", e
);
484 protected synchronized void upload(EditablePart part
) {
486 if (part
instanceof SectionPart
) {
487 SectionPart sectionPart
= (SectionPart
) part
;
488 Node partNode
= sectionPart
.getNode();
489 int partIndex
= partNode
.getIndex();
490 Section section
= sectionPart
.getSection();
491 Node sectionNode
= section
.getNode();
493 if (part
instanceof Paragraph
) {
494 Node newNode
= sectionNode
.addNode(CMS_P
, NodeType
.NT_FILE
);
495 newNode
.addNode(Node
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
496 JcrUtils
.copyBytesAsFile(sectionNode
,
497 p(newNode
.getIndex()), new byte[0]);
498 if (partIndex
< newNode
.getIndex() - 1) {
500 sectionNode
.orderBefore(p(newNode
.getIndex()),
503 // sectionNode.orderBefore(p(partNode.getIndex()),
504 // p(newNode.getIndex()));
505 persistChanges(sectionNode
);
506 Img img
= newImg((TextSection
) section
, newNode
);
508 layout(img
.getControl());
509 } else if (part
instanceof Img
) {
510 if (getEdited() == part
)
513 layout(part
.getControl());
516 } catch (RepositoryException e
) {
517 throw new CmsException("Cannot upload", e
);
521 protected void deepen() {
526 if (getEdited() instanceof Paragraph
) {
527 Paragraph paragraph
= (Paragraph
) getEdited();
528 Text text
= (Text
) paragraph
.getControl();
529 String txt
= text
.getText();
530 Node paragraphNode
= paragraph
.getNode();
531 Section section
= paragraph
.getSection();
532 Node sectionNode
= section
.getNode();
534 if (section
== mainSection
&& section
instanceof TextSection
535 && paragraphNode
.getIndex() == 1
536 && !sectionNode
.hasProperty(JCR_TITLE
)) {
537 SectionTitle sectionTitle
= prepareSectionTitle(section
,
539 edit(sectionTitle
, 0);
542 Node newSectionNode
= sectionNode
.addNode(CMS_H
,
543 CmsTypes
.CMS_SECTION
);
544 sectionNode
.orderBefore(h(newSectionNode
.getIndex()), h(1));
546 int paragraphIndex
= paragraphNode
.getIndex();
547 String sectionPath
= sectionNode
.getPath();
548 String newSectionPath
= newSectionNode
.getPath();
549 while (sectionNode
.hasNode(p(paragraphIndex
+ 1))) {
550 Node parag
= sectionNode
.getNode(p(paragraphIndex
+ 1));
551 sectionNode
.getSession().move(
552 sectionPath
+ '/' + p(paragraphIndex
+ 1),
553 newSectionPath
+ '/' + CMS_P
);
554 SectionPart sp
= section
.getSectionPart(parag
556 if (sp
instanceof Control
)
557 ((Control
) sp
).dispose();
560 newSectionNode
.setProperty(Property
.JCR_TITLE
, "");
561 getTextInterpreter().write(
562 newSectionNode
.getProperty(Property
.JCR_TITLE
), txt
);
564 TextSection newSection
= new TextSection(section
,
565 section
.getStyle(), newSectionNode
);
566 newSection
.setLayoutData(CmsUiUtils
.fillWidth());
567 newSection
.moveBelow(paragraph
);
570 paragraphNode
.remove();
574 newSection
.getParent().layout();
576 persistChanges(sectionNode
);
577 } else if (getEdited() instanceof SectionTitle
) {
578 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
579 Section section
= sectionTitle
.getSection();
580 Section parentSection
= section
.getParentSection();
581 if (parentSection
== null)
582 return;// cannot deepen main section
583 Node sectionN
= section
.getNode();
584 Node parentSectionN
= parentSection
.getNode();
585 if (sectionN
.getIndex() == 1)
586 return;// cannot deepen first section
587 Node previousSectionN
= parentSectionN
.getNode(h(sectionN
589 NodeIterator subSections
= previousSectionN
.getNodes(CMS_H
);
590 int subsectionsCount
= (int) subSections
.getSize();
591 previousSectionN
.getSession().move(
593 previousSectionN
.getPath() + "/"
594 + h(subsectionsCount
+ 1));
596 TextSection newSection
= new TextSection(section
,
597 section
.getStyle(), sectionN
);
599 persistChanges(previousSectionN
);
601 } catch (RepositoryException e
) {
602 throw new CmsException("Cannot deepen " + getEdited(), e
);
606 protected void undeepen() {
611 if (getEdited() instanceof Paragraph
) {
613 } else if (getEdited() instanceof SectionTitle
) {
614 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
615 Section section
= sectionTitle
.getSection();
616 Node sectionNode
= section
.getNode();
617 Section parentSection
= section
.getParentSection();
618 if (parentSection
== null)
619 return;// cannot undeepen main section
621 // choose in which section to merge
622 Section mergedSection
;
623 if (sectionNode
.getIndex() == 1)
624 mergedSection
= section
.getParentSection();
626 Map
<String
, Section
> parentSubsections
= parentSection
628 ArrayList
<Section
> lst
= new ArrayList
<Section
>(
629 parentSubsections
.values());
630 mergedSection
= lst
.get(sectionNode
.getIndex() - 1);
632 Node mergedNode
= mergedSection
.getNode();
633 boolean mergedHasSubSections
= mergedNode
.hasNode(CMS_H
);
635 // title as paragraph
636 Node newParagrapheNode
= mergedNode
.addNode(CMS_P
);
637 newParagrapheNode
.addMixin(CmsTypes
.CMS_STYLED
);
638 if (mergedHasSubSections
)
639 mergedNode
.orderBefore(p(newParagrapheNode
.getIndex()),
641 String txt
= getTextInterpreter().read(
642 sectionNode
.getProperty(Property
.JCR_TITLE
));
643 getTextInterpreter().write(newParagrapheNode
, txt
);
645 NodeIterator paragraphs
= sectionNode
.getNodes(CMS_P
);
646 while (paragraphs
.hasNext()) {
647 Node p
= paragraphs
.nextNode();
648 SectionPart sp
= section
.getSectionPart(p
.getIdentifier());
649 if (sp
instanceof Control
)
650 ((Control
) sp
).dispose();
651 mergedNode
.getSession().move(p
.getPath(),
652 mergedNode
.getPath() + '/' + CMS_P
);
653 if (mergedHasSubSections
)
654 mergedNode
.orderBefore(p(p
.getIndex()), h(1));
657 Iterator
<Section
> subsections
= section
.getSubSections()
658 .values().iterator();
659 // NodeIterator sections = sectionNode.getNodes(CMS_H);
660 while (subsections
.hasNext()) {
661 Section subsection
= subsections
.next();
662 Node s
= subsection
.getNode();
663 mergedNode
.getSession().move(s
.getPath(),
664 mergedNode
.getPath() + '/' + CMS_H
);
665 subsection
.dispose();
669 section
.getNode().remove();
672 refresh(mergedSection
);
673 mergedSection
.getParent().layout();
674 layout(mergedSection
);
675 persistChanges(mergedNode
);
677 } catch (RepositoryException e
) {
678 throw new CmsException("Cannot undeepen " + getEdited(), e
);
683 protected Paragraph
paragraphSplitted(Paragraph paragraph
, Node newNode
)
684 throws RepositoryException
{
685 Section section
= paragraph
.getSection();
686 updateContent(paragraph
);
687 Paragraph newParagraph
= newParagraph((TextSection
) section
, newNode
);
688 newParagraph
.setLayoutData(CmsUiUtils
.fillWidth());
689 newParagraph
.moveBelow(paragraph
);
690 layout(paragraph
.getControl(), newParagraph
.getControl());
694 protected Paragraph
sectionTitleSplitted(SectionTitle sectionTitle
,
695 Node newNode
) throws RepositoryException
{
696 updateContent(sectionTitle
);
697 Paragraph newParagraph
= newParagraph(sectionTitle
.getSection(),
699 // we assume beforeFirst is not null since there was a sectionTitle
700 newParagraph
.moveBelow(sectionTitle
.getSection().getHeader());
701 layout(sectionTitle
.getControl(), newParagraph
.getControl());
705 protected Paragraph
paragraphMergedWithPrevious(Paragraph removed
,
706 Node remaining
) throws RepositoryException
{
707 Section section
= removed
.getSection();
710 Paragraph paragraph
= (Paragraph
) section
.getSectionPart(remaining
712 updateContent(paragraph
);
713 layout(paragraph
.getControl());
717 protected void paragraphMergedWithNext(Paragraph remaining
,
718 Paragraph removed
) throws RepositoryException
{
720 updateContent(remaining
);
721 layout(remaining
.getControl());
725 protected String
p(Integer index
) {
726 StringBuilder sb
= new StringBuilder(6);
727 sb
.append(CMS_P
).append('[').append(index
).append(']');
728 return sb
.toString();
731 protected String
h(Integer index
) {
732 StringBuilder sb
= new StringBuilder(5);
733 sb
.append(CMS_H
).append('[').append(index
).append(']');
734 return sb
.toString();
738 public Section
getMainSection() {
742 public boolean isFlat() {
746 public TextInterpreter
getTextInterpreter() {
747 return textInterpreter
;
752 public void keyPressed(KeyEvent ke
) {
753 if (log
.isTraceEnabled())
756 if (getEdited() == null)
758 boolean altPressed
= (ke
.stateMask
& SWT
.ALT
) != 0;
759 boolean shiftPressed
= (ke
.stateMask
& SWT
.SHIFT
) != 0;
760 boolean ctrlPressed
= (ke
.stateMask
& SWT
.CTRL
) != 0;
764 if (ke
.keyCode
== SWT
.ESC
) {
766 } else if (ke
.character
== '\r') {
768 } else if (ke
.character
== 'S') {
771 } else if (ke
.character
== '\t') {
774 } else if (shiftPressed
) {
778 if (getEdited() instanceof Paragraph
) {
779 Paragraph paragraph
= (Paragraph
) getEdited();
780 Section section
= paragraph
.getSection();
781 if (altPressed
&& ke
.keyCode
== SWT
.ARROW_RIGHT
) {
782 edit(section
.nextSectionPart(paragraph
), 0);
783 } else if (altPressed
&& ke
.keyCode
== SWT
.ARROW_LEFT
) {
784 edit(section
.previousSectionPart(paragraph
), 0);
785 } else if (ke
.character
== SWT
.BS
) {
786 Text text
= (Text
) paragraph
.getControl();
787 int caretPosition
= text
.getCaretPosition();
788 if (caretPosition
== 0) {
791 } else if (ke
.character
== SWT
.DEL
) {
792 Text text
= (Text
) paragraph
.getControl();
793 int caretPosition
= text
.getCaretPosition();
794 int charcount
= text
.getCharCount();
795 if (caretPosition
== charcount
) {
801 } catch (Exception e
) {
803 notifyEditionException(e
);
808 public void keyReleased(KeyEvent e
) {
813 protected MouseListener
createMouseListener() {
817 private class ML
extends MouseAdapter
{
818 private static final long serialVersionUID
= 8526890859876770905L;
821 public void mouseDoubleClick(MouseEvent e
) {
823 Control source
= (Control
) e
.getSource();
824 if (getCmsEditable().canEdit()) {
825 if (getCmsEditable().isEditing()
826 && !(getEdited() instanceof Img
)) {
827 if (source
== mainSection
)
829 EditablePart part
= findDataParent(source
);
832 getCmsEditable().startEditing();
839 public void mouseDown(MouseEvent e
) {
840 if (getCmsEditable().isEditing()) {
842 Control source
= (Control
) e
.getSource();
843 EditablePart composite
= findDataParent(source
);
844 Point point
= new Point(e
.x
, e
.y
);
845 if (!(composite
instanceof Img
))
846 edit(composite
, source
.toDisplay(point
));
847 } else if (e
.button
== 3) {
848 EditablePart composite
= findDataParent((Control
) e
850 if (styledTools
!= null)
851 styledTools
.show(composite
, new Point(e
.x
, e
.y
));
857 public void mouseUp(MouseEvent e
) {
861 // FILE UPLOAD LISTENER
862 private class FUL
implements FileUploadListener
{
863 public void uploadProgress(FileUploadEvent event
) {
864 // TODO Monitor upload progress
867 public void uploadFailed(FileUploadEvent event
) {
868 throw new CmsException("Upload failed " + event
,
869 event
.getException());
872 public void uploadFinished(FileUploadEvent event
) {
873 for (FileDetails file
: event
.getFileDetails()) {
874 if (log
.isDebugEnabled())
875 log
.debug("Received: " + file
.getFileName());
877 mainSection
.getDisplay().syncExec(new Runnable() {
883 FileUploadHandler uploadHandler
= (FileUploadHandler
) event
885 uploadHandler
.dispose();