1 package org
.argeo
.cms
.internal
.text
;
3 import static javax
.jcr
.Property
.JCR_TITLE
;
4 import static org
.argeo
.cms
.CmsUtils
.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
.CmsEditable
;
22 import org
.argeo
.cms
.CmsException
;
23 import org
.argeo
.cms
.CmsImageManager
;
24 import org
.argeo
.cms
.CmsNames
;
25 import org
.argeo
.cms
.CmsSession
;
26 import org
.argeo
.cms
.CmsTypes
;
27 import org
.argeo
.cms
.CmsUtils
;
28 import org
.argeo
.cms
.IdentityTextInterpreter
;
29 import org
.argeo
.cms
.TextInterpreter
;
30 import org
.argeo
.cms
.text
.Img
;
31 import org
.argeo
.cms
.text
.Paragraph
;
32 import org
.argeo
.cms
.text
.TextSection
;
33 import org
.argeo
.cms
.viewers
.AbstractPageViewer
;
34 import org
.argeo
.cms
.viewers
.EditablePart
;
35 import org
.argeo
.cms
.viewers
.NodePart
;
36 import org
.argeo
.cms
.viewers
.PropertyPart
;
37 import org
.argeo
.cms
.viewers
.Section
;
38 import org
.argeo
.cms
.viewers
.SectionPart
;
39 import org
.argeo
.cms
.widgets
.EditableImage
;
40 import org
.argeo
.cms
.widgets
.EditableText
;
41 import org
.argeo
.cms
.widgets
.StyledControl
;
42 import org
.argeo
.jcr
.JcrUtils
;
43 import org
.eclipse
.rap
.addons
.fileupload
.FileDetails
;
44 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadEvent
;
45 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadHandler
;
46 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadListener
;
47 import org
.eclipse
.rap
.rwt
.RWT
;
48 import org
.eclipse
.swt
.SWT
;
49 import org
.eclipse
.swt
.events
.KeyEvent
;
50 import org
.eclipse
.swt
.events
.KeyListener
;
51 import org
.eclipse
.swt
.events
.MouseAdapter
;
52 import org
.eclipse
.swt
.events
.MouseEvent
;
53 import org
.eclipse
.swt
.events
.MouseListener
;
54 import org
.eclipse
.swt
.graphics
.Point
;
55 import org
.eclipse
.swt
.widgets
.Composite
;
56 import org
.eclipse
.swt
.widgets
.Control
;
57 import org
.eclipse
.swt
.widgets
.Text
;
59 /** Base class for text viewers and editors. */
60 public abstract class AbstractTextViewer
extends AbstractPageViewer
implements
61 CmsNames
, KeyListener
, Observer
{
62 private static final long serialVersionUID
= -2401274679492339668L;
63 private final static Log log
= LogFactory
.getLog(AbstractTextViewer
.class);
65 private final Section mainSection
;
67 private TextInterpreter textInterpreter
= new IdentityTextInterpreter();
68 private CmsImageManager imageManager
= CmsSession
.current
.get()
71 private FileUploadListener fileUploadListener
;
72 private TextContextMenu styledTools
;
74 private final boolean flat
;
76 protected AbstractTextViewer(Section parent
, int style
,
77 CmsEditable cmsEditable
) {
78 super(parent
, style
, cmsEditable
);
79 flat
= SWT
.FLAT
== (style
& SWT
.FLAT
);
81 if (getCmsEditable().canEdit()) {
82 fileUploadListener
= new FUL();
83 styledTools
= new TextContextMenu(this, parent
.getDisplay());
85 this.mainSection
= parent
;
86 initModelIfNeeded(mainSection
.getNode());
87 // layout(this.mainSection);
91 public Control
getControl() {
95 protected void refresh(Control control
) throws RepositoryException
{
96 if (!(control
instanceof Section
))
98 Section section
= (Section
) control
;
99 if (section
instanceof TextSection
) {
100 CmsUtils
.clear(section
);
101 Node node
= section
.getNode();
102 TextSection textSection
= (TextSection
) section
;
103 if (node
.hasProperty(Property
.JCR_TITLE
)) {
104 if (section
.getHeader() == null)
105 section
.createHeader();
106 if (node
.hasProperty(Property
.JCR_TITLE
)) {
107 SectionTitle title
= newSectionTitle(textSection
, node
);
108 title
.setLayoutData(CmsUtils
.fillWidth());
109 updateContent(title
);
113 for (NodeIterator ni
= node
.getNodes(CMS_P
); ni
.hasNext();) {
114 Node child
= ni
.nextNode();
115 final SectionPart sectionPart
;
116 if (child
.isNodeType(CmsTypes
.CMS_IMAGE
)
117 || child
.isNodeType(NodeType
.NT_FILE
)) {
118 sectionPart
= newImg(textSection
, child
);
119 } else if (child
.isNodeType(CmsTypes
.CMS_STYLED
)) {
120 sectionPart
= newParagraph(textSection
, child
);
122 sectionPart
= newSectionPart(textSection
, child
);
123 if (sectionPart
== null)
124 throw new CmsException("Unsupported node " + child
);
125 // TODO list node types in exception
127 if (sectionPart
instanceof Control
)
128 ((Control
) sectionPart
).setLayoutData(CmsUtils
.fillWidth());
132 for (NodeIterator ni
= section
.getNode().getNodes(CMS_H
); ni
134 Node child
= ni
.nextNode();
135 if (child
.isNodeType(CmsTypes
.CMS_SECTION
)) {
136 TextSection newSection
= new TextSection(section
,
138 newSection
.setLayoutData(CmsUtils
.fillWidth());
143 for (Section s
: section
.getSubSections().values())
149 /** To be overridden in order to provide additional SectionPart types */
150 protected SectionPart
newSectionPart(TextSection textSection
, Node node
) {
155 protected Paragraph
newParagraph(TextSection parent
, Node node
)
156 throws RepositoryException
{
157 Paragraph paragraph
= new Paragraph(parent
, parent
.getStyle(), node
);
158 updateContent(paragraph
);
159 paragraph
.setLayoutData(fillWidth());
160 paragraph
.setMouseListener(getMouseListener());
164 protected Img
newImg(TextSection parent
, Node node
)
165 throws RepositoryException
{
166 Img img
= new Img(parent
, parent
.getStyle(), node
) {
167 private static final long serialVersionUID
= 1297900641952417540L;
170 protected void setContainerLayoutData(Composite composite
) {
171 composite
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
,
176 protected void setControlLayoutData(Control control
) {
177 control
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
,
181 img
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
, SWT
.DEFAULT
));
183 img
.setMouseListener(getMouseListener());
187 protected SectionTitle
newSectionTitle(TextSection parent
, Node node
)
188 throws RepositoryException
{
189 SectionTitle title
= new SectionTitle(parent
.getHeader(),
190 parent
.getStyle(), node
.getProperty(JCR_TITLE
));
191 updateContent(title
);
192 title
.setMouseListener(getMouseListener());
196 protected SectionTitle
prepareSectionTitle(Section newSection
,
197 String titleText
) throws RepositoryException
{
198 Node sectionNode
= newSection
.getNode();
199 if (!sectionNode
.hasProperty(JCR_TITLE
))
200 sectionNode
.setProperty(Property
.JCR_TITLE
, "");
201 getTextInterpreter().write(sectionNode
.getProperty(Property
.JCR_TITLE
),
203 if (newSection
.getHeader() == null)
204 newSection
.createHeader();
205 SectionTitle sectionTitle
= newSectionTitle((TextSection
) newSection
,
210 protected void updateContent(EditablePart part
) throws RepositoryException
{
211 if (part
instanceof SectionPart
) {
212 SectionPart sectionPart
= (SectionPart
) part
;
213 Node partNode
= sectionPart
.getNode();
215 if (part
instanceof StyledControl
216 && (sectionPart
.getSection() instanceof TextSection
)) {
217 TextSection section
= (TextSection
) sectionPart
.getSection();
218 StyledControl styledControl
= (StyledControl
) part
;
219 if (partNode
.isNodeType(CmsTypes
.CMS_STYLED
)) {
220 String style
= partNode
.hasProperty(CMS_STYLE
) ? partNode
221 .getProperty(CMS_STYLE
).getString() : section
222 .getDefaultTextStyle();
223 styledControl
.setStyle(style
);
226 // use control AFTER setting style, since it may have been reset
228 if (part
instanceof EditableText
) {
229 EditableText paragraph
= (EditableText
) part
;
230 if (paragraph
== getEdited())
231 paragraph
.setText(textInterpreter
.read(partNode
));
233 paragraph
.setText(textInterpreter
.raw(partNode
));
234 } else if (part
instanceof EditableImage
) {
235 EditableImage editableImage
= (EditableImage
) part
;
236 imageManager
.load(partNode
, part
.getControl(),
237 editableImage
.getPreferredImageSize());
239 } else if (part
instanceof SectionTitle
) {
240 SectionTitle title
= (SectionTitle
) part
;
241 title
.setStyle(title
.getSection().getTitleStyle());
242 // use control AFTER setting style
243 if (title
== getEdited())
244 title
.setText(textInterpreter
.read(title
.getProperty()));
246 title
.setText(textInterpreter
.raw(title
.getProperty()));
250 // OVERRIDDEN FROM PARENT VIEWER
252 protected void save(EditablePart part
) throws RepositoryException
{
253 if (part
instanceof EditableText
) {
254 EditableText et
= (EditableText
) part
;
255 String text
= ((Text
) et
.getControl()).getText();
257 String
[] lines
= text
.split("[\r\n]+");
258 assert lines
.length
!= 0;
259 saveLine(part
, lines
[0]);
260 if (lines
.length
> 1) {
261 ArrayList
<Control
> toLayout
= new ArrayList
<Control
>();
262 if (part
instanceof Paragraph
) {
263 Paragraph currentParagraph
= (Paragraph
) et
;
264 Section section
= currentParagraph
.getSection();
265 Node sectionNode
= section
.getNode();
266 Node currentParagraphN
= currentParagraph
.getNode();
267 for (int i
= 1; i
< lines
.length
; i
++) {
268 Node newNode
= sectionNode
.addNode(CMS_P
);
269 newNode
.addMixin(CmsTypes
.CMS_STYLED
);
270 saveLine(newNode
, lines
[i
]);
271 // second node was create as last, if it is not the next
273 // means there are some in between and we can take the
275 // index+1 for the re-order
276 if (newNode
.getIndex() > currentParagraphN
.getIndex() + 1) {
277 sectionNode
.orderBefore(p(newNode
.getIndex()),
278 p(currentParagraphN
.getIndex() + 1));
280 Paragraph newParagraph
= newParagraph(
281 (TextSection
) section
, newNode
);
282 newParagraph
.moveBelow(currentParagraph
);
283 toLayout
.add(newParagraph
);
285 currentParagraph
= newParagraph
;
286 currentParagraphN
= newNode
;
289 // TODO or rather return the created paragarphs?
290 layout(toLayout
.toArray(new Control
[toLayout
.size()]));
295 protected void saveLine(EditablePart part
, String line
) {
296 if (part
instanceof NodePart
) {
297 saveLine(((NodePart
) part
).getNode(), line
);
298 } else if (part
instanceof PropertyPart
) {
299 saveLine(((PropertyPart
) part
).getProperty(), line
);
301 throw new CmsException("Unsupported part " + part
);
305 protected void saveLine(Item item
, String line
) {
307 textInterpreter
.write(item
, line
);
311 protected void prepare(EditablePart part
, Object caretPosition
) {
312 Control control
= part
.getControl();
313 if (control
instanceof Text
) {
314 Text text
= (Text
) control
;
315 if (caretPosition
!= null)
316 if (caretPosition
instanceof Integer
)
317 text
.setSelection((Integer
) caretPosition
);
318 else if (caretPosition
instanceof Point
) {
319 // TODO find a way to position the caret at the right place
321 text
.setData(RWT
.ACTIVE_KEYS
, new String
[] { "BACKSPACE", "ESC",
322 "TAB", "SHIFT+TAB", "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT",
323 "ALT+ARROW_UP", "ALT+ARROW_DOWN", "RETURN", "CTRL+RETURN",
324 "ENTER", "DELETE" });
325 text
.setData(RWT
.CANCEL_KEYS
, new String
[] { "ALT+ARROW_LEFT",
326 "ALT+ARROW_RIGHT" });
327 text
.addKeyListener(this);
328 } else if (part
instanceof Img
) {
329 ((Img
) part
).setFileUploadListener(fileUploadListener
);
333 // REQUIRED BY CONTEXT MENU
334 void setParagraphStyle(Paragraph paragraph
, String style
) {
336 Node paragraphNode
= paragraph
.getNode();
337 paragraphNode
.setProperty(CMS_STYLE
, style
);
338 paragraphNode
.getSession().save();
339 updateContent(paragraph
);
341 } catch (RepositoryException e1
) {
342 throw new CmsException("Cannot set style " + style
+ " on "
347 void deletePart(SectionPart paragraph
) {
349 Node paragraphNode
= paragraph
.getNode();
350 Section section
= paragraph
.getSection();
351 Session session
= paragraphNode
.getSession();
352 paragraphNode
.remove();
354 if (paragraph
instanceof Control
)
355 ((Control
) paragraph
).dispose();
357 } catch (RepositoryException e1
) {
358 throw new CmsException("Cannot delete " + paragraph
, e1
);
362 String
getRawParagraphText(Paragraph paragraph
) {
363 return textInterpreter
.raw(paragraph
.getNode());
367 protected void splitEdit() {
370 if (getEdited() instanceof Paragraph
) {
371 Paragraph paragraph
= (Paragraph
) getEdited();
372 Text text
= (Text
) paragraph
.getControl();
373 int caretPosition
= text
.getCaretPosition();
374 String txt
= text
.getText();
375 String first
= txt
.substring(0, caretPosition
);
376 String second
= txt
.substring(caretPosition
);
377 Node firstNode
= paragraph
.getNode();
378 Node sectionNode
= firstNode
.getParent();
379 firstNode
.setProperty(CMS_CONTENT
, first
);
380 Node secondNode
= sectionNode
.addNode(CMS_P
);
381 secondNode
.addMixin(CmsTypes
.CMS_STYLED
);
382 // second node was create as last, if it is not the next one, it
383 // means there are some in between and we can take the one at
384 // index+1 for the re-order
385 if (secondNode
.getIndex() > firstNode
.getIndex() + 1) {
386 sectionNode
.orderBefore(p(secondNode
.getIndex()),
387 p(firstNode
.getIndex() + 1));
390 // if we die in between, at least we still have the whole text
392 textInterpreter
.write(secondNode
, second
);
393 textInterpreter
.write(firstNode
, first
);
395 Paragraph secondParagraph
= paragraphSplitted(paragraph
,
397 edit(secondParagraph
, 0);
398 } else if (getEdited() instanceof SectionTitle
) {
399 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
400 Text text
= (Text
) sectionTitle
.getControl();
401 String txt
= text
.getText();
402 int caretPosition
= text
.getCaretPosition();
403 Section section
= sectionTitle
.getSection();
404 Node sectionNode
= section
.getNode();
405 Node paragraphNode
= sectionNode
.addNode(CMS_P
);
406 paragraphNode
.addMixin(CmsTypes
.CMS_STYLED
);
407 textInterpreter
.write(paragraphNode
,
408 txt
.substring(caretPosition
));
409 textInterpreter
.write(
410 sectionNode
.getProperty(Property
.JCR_TITLE
),
411 txt
.substring(0, caretPosition
));
412 sectionNode
.orderBefore(p(paragraphNode
.getIndex()), p(1));
413 sectionNode
.getSession().save();
415 Paragraph paragraph
= sectionTitleSplitted(sectionTitle
,
420 } catch (RepositoryException e
) {
421 throw new CmsException("Cannot split " + getEdited(), e
);
425 protected void mergeWithPrevious() {
428 Paragraph paragraph
= (Paragraph
) getEdited();
429 Text text
= (Text
) paragraph
.getControl();
430 String txt
= text
.getText();
431 Node paragraphNode
= paragraph
.getNode();
432 if (paragraphNode
.getIndex() == 1)
434 Node sectionNode
= paragraphNode
.getParent();
435 Node previousNode
= sectionNode
436 .getNode(p(paragraphNode
.getIndex() - 1));
437 String previousTxt
= textInterpreter
.read(previousNode
);
438 textInterpreter
.write(previousNode
, previousTxt
+ txt
);
439 paragraphNode
.remove();
440 sectionNode
.getSession().save();
442 Paragraph previousParagraph
= paragraphMergedWithPrevious(
443 paragraph
, previousNode
);
444 edit(previousParagraph
, previousTxt
.length());
445 } catch (RepositoryException e
) {
446 throw new CmsException("Cannot stop editing", e
);
450 protected void mergeWithNext() {
453 Paragraph paragraph
= (Paragraph
) getEdited();
454 Text text
= (Text
) paragraph
.getControl();
455 String txt
= text
.getText();
456 Node paragraphNode
= paragraph
.getNode();
457 Node sectionNode
= paragraphNode
.getParent();
458 NodeIterator paragraphNodes
= sectionNode
.getNodes(CMS_P
);
459 long size
= paragraphNodes
.getSize();
460 if (paragraphNode
.getIndex() == size
)
462 Node nextNode
= sectionNode
463 .getNode(p(paragraphNode
.getIndex() + 1));
464 String nextTxt
= textInterpreter
.read(nextNode
);
465 textInterpreter
.write(paragraphNode
, txt
+ nextTxt
);
467 Section section
= paragraph
.getSection();
468 Paragraph removed
= (Paragraph
) section
.getSectionPart(nextNode
472 sectionNode
.getSession().save();
474 paragraphMergedWithNext(paragraph
, removed
);
475 edit(paragraph
, txt
.length());
476 } catch (RepositoryException e
) {
477 throw new CmsException("Cannot stop editing", e
);
481 protected synchronized void upload(EditablePart part
) {
483 if (part
instanceof SectionPart
) {
484 SectionPart sectionPart
= (SectionPart
) part
;
485 Node partNode
= sectionPart
.getNode();
486 int partIndex
= partNode
.getIndex();
487 Section section
= sectionPart
.getSection();
488 Node sectionNode
= section
.getNode();
490 if (part
instanceof Paragraph
) {
491 Node newNode
= sectionNode
.addNode(CMS_P
, NodeType
.NT_FILE
);
492 newNode
.addNode(Node
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
493 JcrUtils
.copyBytesAsFile(sectionNode
,
494 p(newNode
.getIndex()), new byte[0]);
495 if (partIndex
< newNode
.getIndex() - 1) {
497 sectionNode
.orderBefore(p(newNode
.getIndex()),
500 // sectionNode.orderBefore(p(partNode.getIndex()),
501 // p(newNode.getIndex()));
502 sectionNode
.getSession().save();
503 Img img
= newImg((TextSection
) section
, newNode
);
505 layout(img
.getControl());
506 } else if (part
instanceof Img
) {
507 if (getEdited() == part
)
510 layout(part
.getControl());
513 } catch (RepositoryException e
) {
514 throw new CmsException("Cannot upload", e
);
518 protected void deepen() {
523 if (getEdited() instanceof Paragraph
) {
524 Paragraph paragraph
= (Paragraph
) getEdited();
525 Text text
= (Text
) paragraph
.getControl();
526 String txt
= text
.getText();
527 Node paragraphNode
= paragraph
.getNode();
528 Section section
= paragraph
.getSection();
529 Node sectionNode
= section
.getNode();
531 if (section
== mainSection
&& section
instanceof TextSection
532 && paragraphNode
.getIndex() == 1
533 && !sectionNode
.hasProperty(JCR_TITLE
)) {
534 SectionTitle sectionTitle
= prepareSectionTitle(section
,
536 edit(sectionTitle
, 0);
539 Node newSectionNode
= sectionNode
.addNode(CMS_H
,
540 CmsTypes
.CMS_SECTION
);
541 sectionNode
.orderBefore(h(newSectionNode
.getIndex()), h(1));
543 int paragraphIndex
= paragraphNode
.getIndex();
544 String sectionPath
= sectionNode
.getPath();
545 String newSectionPath
= newSectionNode
.getPath();
546 while (sectionNode
.hasNode(p(paragraphIndex
+ 1))) {
547 Node parag
= sectionNode
.getNode(p(paragraphIndex
+ 1));
548 sectionNode
.getSession().move(
549 sectionPath
+ '/' + p(paragraphIndex
+ 1),
550 newSectionPath
+ '/' + CMS_P
);
551 SectionPart sp
= section
.getSectionPart(parag
553 if (sp
instanceof Control
)
554 ((Control
) sp
).dispose();
557 newSectionNode
.setProperty(Property
.JCR_TITLE
, "");
558 getTextInterpreter().write(
559 newSectionNode
.getProperty(Property
.JCR_TITLE
), txt
);
561 TextSection newSection
= new TextSection(section
,
562 section
.getStyle(), newSectionNode
);
563 newSection
.setLayoutData(CmsUtils
.fillWidth());
564 newSection
.moveBelow(paragraph
);
567 paragraphNode
.remove();
571 newSection
.getParent().layout();
573 newSectionNode
.getSession().save();
574 } else if (getEdited() instanceof SectionTitle
) {
575 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
576 Section section
= sectionTitle
.getSection();
577 Section parentSection
= section
.getParentSection();
578 if (parentSection
== null)
579 return;// cannot deepen main section
580 Node sectionN
= section
.getNode();
581 Node parentSectionN
= parentSection
.getNode();
582 if (sectionN
.getIndex() == 1)
583 return;// cannot deepen first section
584 Node previousSectionN
= parentSectionN
.getNode(h(sectionN
586 NodeIterator subSections
= previousSectionN
.getNodes(CMS_H
);
587 int subsectionsCount
= (int) subSections
.getSize();
588 previousSectionN
.getSession().move(
590 previousSectionN
.getPath() + "/"
591 + h(subsectionsCount
+ 1));
593 TextSection newSection
= new TextSection(section
,
594 section
.getStyle(), sectionN
);
596 previousSectionN
.getSession().save();
598 } catch (RepositoryException e
) {
599 throw new CmsException("Cannot deepen " + getEdited(), e
);
603 protected void undeepen() {
608 if (getEdited() instanceof Paragraph
) {
610 } else if (getEdited() instanceof SectionTitle
) {
611 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
612 Section section
= sectionTitle
.getSection();
613 Node sectionNode
= section
.getNode();
614 Section parentSection
= section
.getParentSection();
615 if (parentSection
== null)
616 return;// cannot undeepen main section
618 // choose in which section to merge
619 Section mergedSection
;
620 if (sectionNode
.getIndex() == 1)
621 mergedSection
= section
.getParentSection();
623 Map
<String
, Section
> parentSubsections
= parentSection
625 ArrayList
<Section
> lst
= new ArrayList
<Section
>(
626 parentSubsections
.values());
627 mergedSection
= lst
.get(sectionNode
.getIndex() - 1);
629 Node mergedNode
= mergedSection
.getNode();
630 boolean mergedHasSubSections
= mergedNode
.hasNode(CMS_H
);
632 // title as paragraph
633 Node newParagrapheNode
= mergedNode
.addNode(CMS_P
);
634 newParagrapheNode
.addMixin(CmsTypes
.CMS_STYLED
);
635 if (mergedHasSubSections
)
636 mergedNode
.orderBefore(p(newParagrapheNode
.getIndex()),
638 String txt
= getTextInterpreter().read(
639 sectionNode
.getProperty(Property
.JCR_TITLE
));
640 getTextInterpreter().write(newParagrapheNode
, txt
);
642 NodeIterator paragraphs
= sectionNode
.getNodes(CMS_P
);
643 while (paragraphs
.hasNext()) {
644 Node p
= paragraphs
.nextNode();
645 SectionPart sp
= section
.getSectionPart(p
.getIdentifier());
646 if (sp
instanceof Control
)
647 ((Control
) sp
).dispose();
648 mergedNode
.getSession().move(p
.getPath(),
649 mergedNode
.getPath() + '/' + CMS_P
);
650 if (mergedHasSubSections
)
651 mergedNode
.orderBefore(p(p
.getIndex()), h(1));
654 Iterator
<Section
> subsections
= section
.getSubSections()
655 .values().iterator();
656 // NodeIterator sections = sectionNode.getNodes(CMS_H);
657 while (subsections
.hasNext()) {
658 Section subsection
= subsections
.next();
659 Node s
= subsection
.getNode();
660 mergedNode
.getSession().move(s
.getPath(),
661 mergedNode
.getPath() + '/' + CMS_H
);
662 subsection
.dispose();
666 section
.getNode().remove();
669 refresh(mergedSection
);
670 mergedSection
.getParent().layout();
671 layout(mergedSection
);
672 mergedNode
.getSession().save();
674 } catch (RepositoryException e
) {
675 throw new CmsException("Cannot undeepen " + getEdited(), e
);
680 protected Paragraph
paragraphSplitted(Paragraph paragraph
, Node newNode
)
681 throws RepositoryException
{
682 Section section
= paragraph
.getSection();
683 updateContent(paragraph
);
684 Paragraph newParagraph
= newParagraph((TextSection
) section
, newNode
);
685 newParagraph
.setLayoutData(CmsUtils
.fillWidth());
686 newParagraph
.moveBelow(paragraph
);
687 layout(paragraph
.getControl(), newParagraph
.getControl());
691 protected Paragraph
sectionTitleSplitted(SectionTitle sectionTitle
,
692 Node newNode
) throws RepositoryException
{
693 updateContent(sectionTitle
);
694 Paragraph newParagraph
= newParagraph(sectionTitle
.getSection(),
696 // we assume beforeFirst is not null since there was a sectionTitle
697 newParagraph
.moveBelow(sectionTitle
.getSection().getHeader());
698 layout(sectionTitle
.getControl(), newParagraph
.getControl());
702 protected Paragraph
paragraphMergedWithPrevious(Paragraph removed
,
703 Node remaining
) throws RepositoryException
{
704 Section section
= removed
.getSection();
707 Paragraph paragraph
= (Paragraph
) section
.getSectionPart(remaining
709 updateContent(paragraph
);
710 layout(paragraph
.getControl());
714 protected void paragraphMergedWithNext(Paragraph remaining
,
715 Paragraph removed
) throws RepositoryException
{
717 updateContent(remaining
);
718 layout(remaining
.getControl());
722 protected String
p(Integer index
) {
723 StringBuilder sb
= new StringBuilder(6);
724 sb
.append(CMS_P
).append('[').append(index
).append(']');
725 return sb
.toString();
728 protected String
h(Integer index
) {
729 StringBuilder sb
= new StringBuilder(5);
730 sb
.append(CMS_H
).append('[').append(index
).append(']');
731 return sb
.toString();
735 public Section
getMainSection() {
739 public boolean isFlat() {
743 public TextInterpreter
getTextInterpreter() {
744 return textInterpreter
;
749 public void keyPressed(KeyEvent e
) {
750 if (log
.isTraceEnabled())
753 if (getEdited() == null)
755 boolean altPressed
= (e
.stateMask
& SWT
.ALT
) != 0;
756 boolean shiftPressed
= (e
.stateMask
& SWT
.SHIFT
) != 0;
757 boolean ctrlPressed
= (e
.stateMask
& SWT
.CTRL
) != 0;
760 if (e
.keyCode
== SWT
.ESC
) {
762 } else if (e
.character
== '\r') {
764 } else if (e
.character
== 'S') {
767 } else if (e
.character
== '\t') {
770 } else if (shiftPressed
) {
774 if (getEdited() instanceof Paragraph
) {
775 Paragraph paragraph
= (Paragraph
) getEdited();
776 Section section
= paragraph
.getSection();
777 if (altPressed
&& e
.keyCode
== SWT
.ARROW_RIGHT
) {
778 edit(section
.nextSectionPart(paragraph
), 0);
779 } else if (altPressed
&& e
.keyCode
== SWT
.ARROW_LEFT
) {
780 edit(section
.previousSectionPart(paragraph
), 0);
781 } else if (e
.character
== SWT
.BS
) {
782 Text text
= (Text
) paragraph
.getControl();
783 int caretPosition
= text
.getCaretPosition();
784 if (caretPosition
== 0) {
787 } else if (e
.character
== SWT
.DEL
) {
788 Text text
= (Text
) paragraph
.getControl();
789 int caretPosition
= text
.getCaretPosition();
790 int charcount
= text
.getCharCount();
791 if (caretPosition
== charcount
) {
800 public void keyReleased(KeyEvent e
) {
805 protected MouseListener
createMouseListener() {
809 private class ML
extends MouseAdapter
{
810 private static final long serialVersionUID
= 8526890859876770905L;
813 public void mouseDoubleClick(MouseEvent e
) {
815 Control source
= (Control
) e
.getSource();
816 if (getCmsEditable().canEdit()) {
817 if (getCmsEditable().isEditing()
818 && !(getEdited() instanceof Img
)) {
819 if (source
== mainSection
)
821 EditablePart part
= findDataParent(source
);
824 getCmsEditable().startEditing();
831 public void mouseDown(MouseEvent e
) {
832 if (getCmsEditable().isEditing()) {
834 Control source
= (Control
) e
.getSource();
835 EditablePart composite
= findDataParent(source
);
836 Point point
= new Point(e
.x
, e
.y
);
837 if (!(composite
instanceof Img
))
838 edit(composite
, source
.toDisplay(point
));
839 } else if (e
.button
== 3) {
840 EditablePart composite
= findDataParent((Control
) e
842 if (styledTools
!= null)
843 styledTools
.show(composite
, new Point(e
.x
, e
.y
));
848 private EditablePart
findDataParent(Control parent
) {
849 if (parent
instanceof EditablePart
) {
850 return (EditablePart
) parent
;
852 if (parent
.getParent() != null)
853 return findDataParent(parent
.getParent());
855 throw new CmsException("No data parent found");
859 public void mouseUp(MouseEvent e
) {
863 // FILE UPLOAD LISTENER
864 private class FUL
implements FileUploadListener
{
865 public void uploadProgress(FileUploadEvent event
) {
866 // TODO Monitor upload progress
869 public void uploadFailed(FileUploadEvent event
) {
870 throw new CmsException("Upload failed " + event
,
871 event
.getException());
874 public void uploadFinished(FileUploadEvent event
) {
875 for (FileDetails file
: event
.getFileDetails()) {
876 if (log
.isDebugEnabled())
877 log
.debug("Received: " + file
.getFileName());
879 mainSection
.getDisplay().syncExec(new Runnable() {
885 FileUploadHandler uploadHandler
= (FileUploadHandler
) event
887 uploadHandler
.dispose();