1 package org
.argeo
.cms
.internal
.text
;
3 import static javax
.jcr
.Property
.JCR_TITLE
;
4 import static org
.argeo
.cms
.util
.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
.CmsTypes
;
26 import org
.argeo
.cms
.text
.Img
;
27 import org
.argeo
.cms
.text
.Paragraph
;
28 import org
.argeo
.cms
.text
.TextInterpreter
;
29 import org
.argeo
.cms
.text
.TextSection
;
30 import org
.argeo
.cms
.util
.CmsUtils
;
31 import org
.argeo
.cms
.viewers
.AbstractPageViewer
;
32 import org
.argeo
.cms
.viewers
.EditablePart
;
33 import org
.argeo
.cms
.viewers
.NodePart
;
34 import org
.argeo
.cms
.viewers
.PropertyPart
;
35 import org
.argeo
.cms
.viewers
.Section
;
36 import org
.argeo
.cms
.viewers
.SectionPart
;
37 import org
.argeo
.cms
.widgets
.EditableImage
;
38 import org
.argeo
.cms
.widgets
.EditableText
;
39 import org
.argeo
.cms
.widgets
.StyledControl
;
40 import org
.argeo
.jcr
.JcrUtils
;
41 import org
.eclipse
.rap
.addons
.fileupload
.FileDetails
;
42 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadEvent
;
43 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadHandler
;
44 import org
.eclipse
.rap
.addons
.fileupload
.FileUploadListener
;
45 import org
.eclipse
.rap
.rwt
.RWT
;
46 import org
.eclipse
.swt
.SWT
;
47 import org
.eclipse
.swt
.events
.KeyEvent
;
48 import org
.eclipse
.swt
.events
.KeyListener
;
49 import org
.eclipse
.swt
.events
.MouseAdapter
;
50 import org
.eclipse
.swt
.events
.MouseEvent
;
51 import org
.eclipse
.swt
.events
.MouseListener
;
52 import org
.eclipse
.swt
.graphics
.Point
;
53 import org
.eclipse
.swt
.widgets
.Composite
;
54 import org
.eclipse
.swt
.widgets
.Control
;
55 import org
.eclipse
.swt
.widgets
.Text
;
57 /** Base class for text viewers and editors. */
58 public abstract class AbstractTextViewer
extends AbstractPageViewer
implements
59 CmsNames
, KeyListener
, Observer
{
60 private static final long serialVersionUID
= -2401274679492339668L;
61 private final static Log log
= LogFactory
.getLog(AbstractTextViewer
.class);
63 private final Section mainSection
;
65 private TextInterpreter textInterpreter
= new TextInterpreterImpl();
66 private CmsImageManager imageManager
= CmsUtils
.getCmsView()
69 private FileUploadListener fileUploadListener
;
70 private TextContextMenu styledTools
;
72 private final boolean flat
;
74 protected AbstractTextViewer(Section parent
, int style
,
75 CmsEditable cmsEditable
) {
76 super(parent
, style
, cmsEditable
);
77 flat
= SWT
.FLAT
== (style
& SWT
.FLAT
);
79 if (getCmsEditable().canEdit()) {
80 fileUploadListener
= new FUL();
81 styledTools
= new TextContextMenu(this, parent
.getDisplay());
83 this.mainSection
= parent
;
84 initModelIfNeeded(mainSection
.getNode());
85 // layout(this.mainSection);
89 public Control
getControl() {
93 protected void refresh(Control control
) throws RepositoryException
{
94 if (!(control
instanceof Section
))
96 Section section
= (Section
) control
;
97 if (section
instanceof TextSection
) {
98 CmsUtils
.clear(section
);
99 Node node
= section
.getNode();
100 TextSection textSection
= (TextSection
) section
;
101 if (node
.hasProperty(Property
.JCR_TITLE
)) {
102 if (section
.getHeader() == null)
103 section
.createHeader();
104 if (node
.hasProperty(Property
.JCR_TITLE
)) {
105 SectionTitle title
= newSectionTitle(textSection
, node
);
106 title
.setLayoutData(CmsUtils
.fillWidth());
107 updateContent(title
);
111 for (NodeIterator ni
= node
.getNodes(CMS_P
); ni
.hasNext();) {
112 Node child
= ni
.nextNode();
113 final SectionPart sectionPart
;
114 if (child
.isNodeType(CmsTypes
.CMS_IMAGE
)
115 || child
.isNodeType(NodeType
.NT_FILE
)) {
116 sectionPart
= newImg(textSection
, child
);
117 } else if (child
.isNodeType(CmsTypes
.CMS_STYLED
)) {
118 sectionPart
= newParagraph(textSection
, child
);
120 sectionPart
= newSectionPart(textSection
, child
);
121 if (sectionPart
== null)
122 throw new CmsException("Unsupported node " + child
);
123 // TODO list node types in exception
125 if (sectionPart
instanceof Control
)
126 ((Control
) sectionPart
).setLayoutData(CmsUtils
.fillWidth());
130 for (NodeIterator ni
= section
.getNode().getNodes(CMS_H
); ni
132 Node child
= ni
.nextNode();
133 if (child
.isNodeType(CmsTypes
.CMS_SECTION
)) {
134 TextSection newSection
= new TextSection(section
,
136 newSection
.setLayoutData(CmsUtils
.fillWidth());
141 for (Section s
: section
.getSubSections().values())
147 /** To be overridden in order to provide additional SectionPart types */
148 protected SectionPart
newSectionPart(TextSection textSection
, Node node
) {
153 protected Paragraph
newParagraph(TextSection parent
, Node node
)
154 throws RepositoryException
{
155 Paragraph paragraph
= new Paragraph(parent
, parent
.getStyle(), node
);
156 updateContent(paragraph
);
157 paragraph
.setLayoutData(fillWidth());
158 paragraph
.setMouseListener(getMouseListener());
162 protected Img
newImg(TextSection parent
, Node node
)
163 throws RepositoryException
{
164 Img img
= new Img(parent
, parent
.getStyle(), node
) {
165 private static final long serialVersionUID
= 1297900641952417540L;
168 protected void setContainerLayoutData(Composite composite
) {
169 composite
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
,
174 protected void setControlLayoutData(Control control
) {
175 control
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
,
179 img
.setLayoutData(CmsUtils
.grabWidth(SWT
.CENTER
, SWT
.DEFAULT
));
181 img
.setMouseListener(getMouseListener());
185 protected SectionTitle
newSectionTitle(TextSection parent
, Node node
)
186 throws RepositoryException
{
187 SectionTitle title
= new SectionTitle(parent
.getHeader(),
188 parent
.getStyle(), node
.getProperty(JCR_TITLE
));
189 updateContent(title
);
190 title
.setMouseListener(getMouseListener());
194 protected SectionTitle
prepareSectionTitle(Section newSection
,
195 String titleText
) throws RepositoryException
{
196 Node sectionNode
= newSection
.getNode();
197 if (!sectionNode
.hasProperty(JCR_TITLE
))
198 sectionNode
.setProperty(Property
.JCR_TITLE
, "");
199 getTextInterpreter().write(sectionNode
.getProperty(Property
.JCR_TITLE
),
201 if (newSection
.getHeader() == null)
202 newSection
.createHeader();
203 SectionTitle sectionTitle
= newSectionTitle((TextSection
) newSection
,
208 protected void updateContent(EditablePart part
) throws RepositoryException
{
209 if (part
instanceof SectionPart
) {
210 SectionPart sectionPart
= (SectionPart
) part
;
211 Node partNode
= sectionPart
.getNode();
213 if (part
instanceof StyledControl
214 && (sectionPart
.getSection() instanceof TextSection
)) {
215 TextSection section
= (TextSection
) sectionPart
.getSection();
216 StyledControl styledControl
= (StyledControl
) part
;
217 if (partNode
.isNodeType(CmsTypes
.CMS_STYLED
)) {
218 String style
= partNode
.hasProperty(CMS_STYLE
) ? partNode
219 .getProperty(CMS_STYLE
).getString() : section
220 .getDefaultTextStyle();
221 styledControl
.setStyle(style
);
224 // use control AFTER setting style, since it may have been reset
226 if (part
instanceof EditableText
) {
227 EditableText paragraph
= (EditableText
) part
;
228 if (paragraph
== getEdited())
229 paragraph
.setText(textInterpreter
.read(partNode
));
231 paragraph
.setText(textInterpreter
.raw(partNode
));
232 } else if (part
instanceof EditableImage
) {
233 EditableImage editableImage
= (EditableImage
) part
;
234 imageManager
.load(partNode
, part
.getControl(),
235 editableImage
.getPreferredImageSize());
237 } else if (part
instanceof SectionTitle
) {
238 SectionTitle title
= (SectionTitle
) part
;
239 title
.setStyle(title
.getSection().getTitleStyle());
240 // use control AFTER setting style
241 if (title
== getEdited())
242 title
.setText(textInterpreter
.read(title
.getProperty()));
244 title
.setText(textInterpreter
.raw(title
.getProperty()));
248 // OVERRIDDEN FROM PARENT VIEWER
250 protected void save(EditablePart part
) throws RepositoryException
{
251 if (part
instanceof EditableText
) {
252 EditableText et
= (EditableText
) part
;
253 String text
= ((Text
) et
.getControl()).getText();
255 String
[] lines
= text
.split("[\r\n]+");
256 assert lines
.length
!= 0;
257 saveLine(part
, lines
[0]);
258 if (lines
.length
> 1) {
259 ArrayList
<Control
> toLayout
= new ArrayList
<Control
>();
260 if (part
instanceof Paragraph
) {
261 Paragraph currentParagraph
= (Paragraph
) et
;
262 Section section
= currentParagraph
.getSection();
263 Node sectionNode
= section
.getNode();
264 Node currentParagraphN
= currentParagraph
.getNode();
265 for (int i
= 1; i
< lines
.length
; i
++) {
266 Node newNode
= sectionNode
.addNode(CMS_P
);
267 newNode
.addMixin(CmsTypes
.CMS_STYLED
);
268 saveLine(newNode
, lines
[i
]);
269 // second node was create as last, if it is not the next
271 // means there are some in between and we can take the
273 // index+1 for the re-order
274 if (newNode
.getIndex() > currentParagraphN
.getIndex() + 1) {
275 sectionNode
.orderBefore(p(newNode
.getIndex()),
276 p(currentParagraphN
.getIndex() + 1));
278 Paragraph newParagraph
= newParagraph(
279 (TextSection
) section
, newNode
);
280 newParagraph
.moveBelow(currentParagraph
);
281 toLayout
.add(newParagraph
);
283 currentParagraph
= newParagraph
;
284 currentParagraphN
= newNode
;
286 persistChanges(sectionNode
);
288 // TODO or rather return the created paragarphs?
289 layout(toLayout
.toArray(new Control
[toLayout
.size()]));
294 protected void saveLine(EditablePart part
, String line
) {
295 if (part
instanceof NodePart
) {
296 saveLine(((NodePart
) part
).getNode(), line
);
297 } else if (part
instanceof PropertyPart
) {
298 saveLine(((PropertyPart
) part
).getProperty(), line
);
300 throw new CmsException("Unsupported part " + part
);
304 protected void saveLine(Item item
, String line
) {
306 textInterpreter
.write(item
, line
);
310 protected void prepare(EditablePart part
, Object caretPosition
) {
311 Control control
= part
.getControl();
312 if (control
instanceof Text
) {
313 Text text
= (Text
) control
;
314 if (caretPosition
!= null)
315 if (caretPosition
instanceof Integer
)
316 text
.setSelection((Integer
) caretPosition
);
317 else if (caretPosition
instanceof Point
) {
318 // TODO find a way to position the caret at the right place
320 text
.setData(RWT
.ACTIVE_KEYS
, new String
[] { "BACKSPACE", "ESC",
321 "TAB", "SHIFT+TAB", "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT",
322 "ALT+ARROW_UP", "ALT+ARROW_DOWN", "RETURN", "CTRL+RETURN",
323 "ENTER", "DELETE" });
324 text
.setData(RWT
.CANCEL_KEYS
, new String
[] { "RETURN",
325 "ALT+ARROW_LEFT", "ALT+ARROW_RIGHT" });
326 text
.addKeyListener(this);
327 } else if (part
instanceof Img
) {
328 ((Img
) part
).setFileUploadListener(fileUploadListener
);
332 // REQUIRED BY CONTEXT MENU
333 void setParagraphStyle(Paragraph paragraph
, String style
) {
335 Node paragraphNode
= paragraph
.getNode();
336 paragraphNode
.setProperty(CMS_STYLE
, style
);
337 persistChanges(paragraphNode
);
338 updateContent(paragraph
);
340 } catch (RepositoryException e1
) {
341 throw new CmsException("Cannot set style " + style
+ " on "
346 void deletePart(SectionPart paragraph
) {
348 Node paragraphNode
= paragraph
.getNode();
349 Section section
= paragraph
.getSection();
350 Session session
= paragraphNode
.getSession();
351 paragraphNode
.remove();
353 if (paragraph
instanceof Control
)
354 ((Control
) paragraph
).dispose();
356 } catch (RepositoryException e1
) {
357 throw new CmsException("Cannot delete " + paragraph
, e1
);
361 String
getRawParagraphText(Paragraph paragraph
) {
362 return textInterpreter
.raw(paragraph
.getNode());
366 protected void splitEdit() {
369 if (getEdited() instanceof Paragraph
) {
370 Paragraph paragraph
= (Paragraph
) getEdited();
371 Text text
= (Text
) paragraph
.getControl();
372 int caretPosition
= text
.getCaretPosition();
373 String txt
= text
.getText();
374 String first
= txt
.substring(0, caretPosition
);
375 String second
= txt
.substring(caretPosition
);
376 Node firstNode
= paragraph
.getNode();
377 Node sectionNode
= firstNode
.getParent();
378 firstNode
.setProperty(CMS_CONTENT
, first
);
379 Node secondNode
= sectionNode
.addNode(CMS_P
);
380 secondNode
.addMixin(CmsTypes
.CMS_STYLED
);
381 // second node was create as last, if it is not the next one, it
382 // means there are some in between and we can take the one at
383 // index+1 for the re-order
384 if (secondNode
.getIndex() > firstNode
.getIndex() + 1) {
385 sectionNode
.orderBefore(p(secondNode
.getIndex()),
386 p(firstNode
.getIndex() + 1));
389 // if we die in between, at least we still have the whole text
392 textInterpreter
.write(secondNode
, second
);
393 textInterpreter
.write(firstNode
, first
);
394 } catch (Exception e
) {
395 // so that no additional nodes are created:
396 JcrUtils
.discardUnderlyingSessionQuietly(firstNode
);
400 persistChanges(firstNode
);
402 Paragraph secondParagraph
= paragraphSplitted(paragraph
,
404 edit(secondParagraph
, 0);
405 } else if (getEdited() instanceof SectionTitle
) {
406 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
407 Text text
= (Text
) sectionTitle
.getControl();
408 String txt
= text
.getText();
409 int caretPosition
= text
.getCaretPosition();
410 Section section
= sectionTitle
.getSection();
411 Node sectionNode
= section
.getNode();
412 Node paragraphNode
= sectionNode
.addNode(CMS_P
);
413 paragraphNode
.addMixin(CmsTypes
.CMS_STYLED
);
414 textInterpreter
.write(paragraphNode
,
415 txt
.substring(caretPosition
));
416 textInterpreter
.write(
417 sectionNode
.getProperty(Property
.JCR_TITLE
),
418 txt
.substring(0, caretPosition
));
419 sectionNode
.orderBefore(p(paragraphNode
.getIndex()), p(1));
420 persistChanges(sectionNode
);
422 Paragraph paragraph
= sectionTitleSplitted(sectionTitle
,
427 } catch (RepositoryException e
) {
428 throw new CmsException("Cannot split " + getEdited(), e
);
432 protected void mergeWithPrevious() {
435 Paragraph paragraph
= (Paragraph
) getEdited();
436 Text text
= (Text
) paragraph
.getControl();
437 String txt
= text
.getText();
438 Node paragraphNode
= paragraph
.getNode();
439 if (paragraphNode
.getIndex() == 1)
441 Node sectionNode
= paragraphNode
.getParent();
442 Node previousNode
= sectionNode
443 .getNode(p(paragraphNode
.getIndex() - 1));
444 String previousTxt
= textInterpreter
.read(previousNode
);
445 textInterpreter
.write(previousNode
, previousTxt
+ txt
);
446 paragraphNode
.remove();
447 persistChanges(sectionNode
);
449 Paragraph previousParagraph
= paragraphMergedWithPrevious(
450 paragraph
, previousNode
);
451 edit(previousParagraph
, previousTxt
.length());
452 } catch (RepositoryException e
) {
453 throw new CmsException("Cannot stop editing", e
);
457 protected void mergeWithNext() {
460 Paragraph paragraph
= (Paragraph
) getEdited();
461 Text text
= (Text
) paragraph
.getControl();
462 String txt
= text
.getText();
463 Node paragraphNode
= paragraph
.getNode();
464 Node sectionNode
= paragraphNode
.getParent();
465 NodeIterator paragraphNodes
= sectionNode
.getNodes(CMS_P
);
466 long size
= paragraphNodes
.getSize();
467 if (paragraphNode
.getIndex() == size
)
469 Node nextNode
= sectionNode
470 .getNode(p(paragraphNode
.getIndex() + 1));
471 String nextTxt
= textInterpreter
.read(nextNode
);
472 textInterpreter
.write(paragraphNode
, txt
+ nextTxt
);
474 Section section
= paragraph
.getSection();
475 Paragraph removed
= (Paragraph
) section
.getSectionPart(nextNode
479 persistChanges(sectionNode
);
481 paragraphMergedWithNext(paragraph
, removed
);
482 edit(paragraph
, txt
.length());
483 } catch (RepositoryException e
) {
484 throw new CmsException("Cannot stop editing", e
);
488 protected synchronized void upload(EditablePart part
) {
490 if (part
instanceof SectionPart
) {
491 SectionPart sectionPart
= (SectionPart
) part
;
492 Node partNode
= sectionPart
.getNode();
493 int partIndex
= partNode
.getIndex();
494 Section section
= sectionPart
.getSection();
495 Node sectionNode
= section
.getNode();
497 if (part
instanceof Paragraph
) {
498 Node newNode
= sectionNode
.addNode(CMS_P
, NodeType
.NT_FILE
);
499 newNode
.addNode(Node
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
500 JcrUtils
.copyBytesAsFile(sectionNode
,
501 p(newNode
.getIndex()), new byte[0]);
502 if (partIndex
< newNode
.getIndex() - 1) {
504 sectionNode
.orderBefore(p(newNode
.getIndex()),
507 // sectionNode.orderBefore(p(partNode.getIndex()),
508 // p(newNode.getIndex()));
509 persistChanges(sectionNode
);
510 Img img
= newImg((TextSection
) section
, newNode
);
512 layout(img
.getControl());
513 } else if (part
instanceof Img
) {
514 if (getEdited() == part
)
517 layout(part
.getControl());
520 } catch (RepositoryException e
) {
521 throw new CmsException("Cannot upload", e
);
525 protected void deepen() {
530 if (getEdited() instanceof Paragraph
) {
531 Paragraph paragraph
= (Paragraph
) getEdited();
532 Text text
= (Text
) paragraph
.getControl();
533 String txt
= text
.getText();
534 Node paragraphNode
= paragraph
.getNode();
535 Section section
= paragraph
.getSection();
536 Node sectionNode
= section
.getNode();
538 if (section
== mainSection
&& section
instanceof TextSection
539 && paragraphNode
.getIndex() == 1
540 && !sectionNode
.hasProperty(JCR_TITLE
)) {
541 SectionTitle sectionTitle
= prepareSectionTitle(section
,
543 edit(sectionTitle
, 0);
546 Node newSectionNode
= sectionNode
.addNode(CMS_H
,
547 CmsTypes
.CMS_SECTION
);
548 sectionNode
.orderBefore(h(newSectionNode
.getIndex()), h(1));
550 int paragraphIndex
= paragraphNode
.getIndex();
551 String sectionPath
= sectionNode
.getPath();
552 String newSectionPath
= newSectionNode
.getPath();
553 while (sectionNode
.hasNode(p(paragraphIndex
+ 1))) {
554 Node parag
= sectionNode
.getNode(p(paragraphIndex
+ 1));
555 sectionNode
.getSession().move(
556 sectionPath
+ '/' + p(paragraphIndex
+ 1),
557 newSectionPath
+ '/' + CMS_P
);
558 SectionPart sp
= section
.getSectionPart(parag
560 if (sp
instanceof Control
)
561 ((Control
) sp
).dispose();
564 newSectionNode
.setProperty(Property
.JCR_TITLE
, "");
565 getTextInterpreter().write(
566 newSectionNode
.getProperty(Property
.JCR_TITLE
), txt
);
568 TextSection newSection
= new TextSection(section
,
569 section
.getStyle(), newSectionNode
);
570 newSection
.setLayoutData(CmsUtils
.fillWidth());
571 newSection
.moveBelow(paragraph
);
574 paragraphNode
.remove();
578 newSection
.getParent().layout();
580 persistChanges(sectionNode
);
581 } else if (getEdited() instanceof SectionTitle
) {
582 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
583 Section section
= sectionTitle
.getSection();
584 Section parentSection
= section
.getParentSection();
585 if (parentSection
== null)
586 return;// cannot deepen main section
587 Node sectionN
= section
.getNode();
588 Node parentSectionN
= parentSection
.getNode();
589 if (sectionN
.getIndex() == 1)
590 return;// cannot deepen first section
591 Node previousSectionN
= parentSectionN
.getNode(h(sectionN
593 NodeIterator subSections
= previousSectionN
.getNodes(CMS_H
);
594 int subsectionsCount
= (int) subSections
.getSize();
595 previousSectionN
.getSession().move(
597 previousSectionN
.getPath() + "/"
598 + h(subsectionsCount
+ 1));
600 TextSection newSection
= new TextSection(section
,
601 section
.getStyle(), sectionN
);
603 persistChanges(previousSectionN
);
605 } catch (RepositoryException e
) {
606 throw new CmsException("Cannot deepen " + getEdited(), e
);
610 protected void undeepen() {
615 if (getEdited() instanceof Paragraph
) {
617 } else if (getEdited() instanceof SectionTitle
) {
618 SectionTitle sectionTitle
= (SectionTitle
) getEdited();
619 Section section
= sectionTitle
.getSection();
620 Node sectionNode
= section
.getNode();
621 Section parentSection
= section
.getParentSection();
622 if (parentSection
== null)
623 return;// cannot undeepen main section
625 // choose in which section to merge
626 Section mergedSection
;
627 if (sectionNode
.getIndex() == 1)
628 mergedSection
= section
.getParentSection();
630 Map
<String
, Section
> parentSubsections
= parentSection
632 ArrayList
<Section
> lst
= new ArrayList
<Section
>(
633 parentSubsections
.values());
634 mergedSection
= lst
.get(sectionNode
.getIndex() - 1);
636 Node mergedNode
= mergedSection
.getNode();
637 boolean mergedHasSubSections
= mergedNode
.hasNode(CMS_H
);
639 // title as paragraph
640 Node newParagrapheNode
= mergedNode
.addNode(CMS_P
);
641 newParagrapheNode
.addMixin(CmsTypes
.CMS_STYLED
);
642 if (mergedHasSubSections
)
643 mergedNode
.orderBefore(p(newParagrapheNode
.getIndex()),
645 String txt
= getTextInterpreter().read(
646 sectionNode
.getProperty(Property
.JCR_TITLE
));
647 getTextInterpreter().write(newParagrapheNode
, txt
);
649 NodeIterator paragraphs
= sectionNode
.getNodes(CMS_P
);
650 while (paragraphs
.hasNext()) {
651 Node p
= paragraphs
.nextNode();
652 SectionPart sp
= section
.getSectionPart(p
.getIdentifier());
653 if (sp
instanceof Control
)
654 ((Control
) sp
).dispose();
655 mergedNode
.getSession().move(p
.getPath(),
656 mergedNode
.getPath() + '/' + CMS_P
);
657 if (mergedHasSubSections
)
658 mergedNode
.orderBefore(p(p
.getIndex()), h(1));
661 Iterator
<Section
> subsections
= section
.getSubSections()
662 .values().iterator();
663 // NodeIterator sections = sectionNode.getNodes(CMS_H);
664 while (subsections
.hasNext()) {
665 Section subsection
= subsections
.next();
666 Node s
= subsection
.getNode();
667 mergedNode
.getSession().move(s
.getPath(),
668 mergedNode
.getPath() + '/' + CMS_H
);
669 subsection
.dispose();
673 section
.getNode().remove();
676 refresh(mergedSection
);
677 mergedSection
.getParent().layout();
678 layout(mergedSection
);
679 persistChanges(mergedNode
);
681 } catch (RepositoryException e
) {
682 throw new CmsException("Cannot undeepen " + getEdited(), e
);
687 protected Paragraph
paragraphSplitted(Paragraph paragraph
, Node newNode
)
688 throws RepositoryException
{
689 Section section
= paragraph
.getSection();
690 updateContent(paragraph
);
691 Paragraph newParagraph
= newParagraph((TextSection
) section
, newNode
);
692 newParagraph
.setLayoutData(CmsUtils
.fillWidth());
693 newParagraph
.moveBelow(paragraph
);
694 layout(paragraph
.getControl(), newParagraph
.getControl());
698 protected Paragraph
sectionTitleSplitted(SectionTitle sectionTitle
,
699 Node newNode
) throws RepositoryException
{
700 updateContent(sectionTitle
);
701 Paragraph newParagraph
= newParagraph(sectionTitle
.getSection(),
703 // we assume beforeFirst is not null since there was a sectionTitle
704 newParagraph
.moveBelow(sectionTitle
.getSection().getHeader());
705 layout(sectionTitle
.getControl(), newParagraph
.getControl());
709 protected Paragraph
paragraphMergedWithPrevious(Paragraph removed
,
710 Node remaining
) throws RepositoryException
{
711 Section section
= removed
.getSection();
714 Paragraph paragraph
= (Paragraph
) section
.getSectionPart(remaining
716 updateContent(paragraph
);
717 layout(paragraph
.getControl());
721 protected void paragraphMergedWithNext(Paragraph remaining
,
722 Paragraph removed
) throws RepositoryException
{
724 updateContent(remaining
);
725 layout(remaining
.getControl());
729 protected String
p(Integer index
) {
730 StringBuilder sb
= new StringBuilder(6);
731 sb
.append(CMS_P
).append('[').append(index
).append(']');
732 return sb
.toString();
735 protected String
h(Integer index
) {
736 StringBuilder sb
= new StringBuilder(5);
737 sb
.append(CMS_H
).append('[').append(index
).append(']');
738 return sb
.toString();
742 public Section
getMainSection() {
746 public boolean isFlat() {
750 public TextInterpreter
getTextInterpreter() {
751 return textInterpreter
;
756 public void keyPressed(KeyEvent ke
) {
757 if (log
.isTraceEnabled())
760 if (getEdited() == null)
762 boolean altPressed
= (ke
.stateMask
& SWT
.ALT
) != 0;
763 boolean shiftPressed
= (ke
.stateMask
& SWT
.SHIFT
) != 0;
764 boolean ctrlPressed
= (ke
.stateMask
& SWT
.CTRL
) != 0;
768 if (ke
.keyCode
== SWT
.ESC
) {
770 } else if (ke
.character
== '\r') {
772 } else if (ke
.character
== 'S') {
775 } else if (ke
.character
== '\t') {
778 } else if (shiftPressed
) {
782 if (getEdited() instanceof Paragraph
) {
783 Paragraph paragraph
= (Paragraph
) getEdited();
784 Section section
= paragraph
.getSection();
785 if (altPressed
&& ke
.keyCode
== SWT
.ARROW_RIGHT
) {
786 edit(section
.nextSectionPart(paragraph
), 0);
787 } else if (altPressed
&& ke
.keyCode
== SWT
.ARROW_LEFT
) {
788 edit(section
.previousSectionPart(paragraph
), 0);
789 } else if (ke
.character
== SWT
.BS
) {
790 Text text
= (Text
) paragraph
.getControl();
791 int caretPosition
= text
.getCaretPosition();
792 if (caretPosition
== 0) {
795 } else if (ke
.character
== SWT
.DEL
) {
796 Text text
= (Text
) paragraph
.getControl();
797 int caretPosition
= text
.getCaretPosition();
798 int charcount
= text
.getCharCount();
799 if (caretPosition
== charcount
) {
805 } catch (Exception e
) {
807 notifyEditionException(e
);
812 public void keyReleased(KeyEvent e
) {
817 protected MouseListener
createMouseListener() {
821 private class ML
extends MouseAdapter
{
822 private static final long serialVersionUID
= 8526890859876770905L;
825 public void mouseDoubleClick(MouseEvent e
) {
827 Control source
= (Control
) e
.getSource();
828 if (getCmsEditable().canEdit()) {
829 if (getCmsEditable().isEditing()
830 && !(getEdited() instanceof Img
)) {
831 if (source
== mainSection
)
833 EditablePart part
= findDataParent(source
);
836 getCmsEditable().startEditing();
843 public void mouseDown(MouseEvent e
) {
844 if (getCmsEditable().isEditing()) {
846 Control source
= (Control
) e
.getSource();
847 EditablePart composite
= findDataParent(source
);
848 Point point
= new Point(e
.x
, e
.y
);
849 if (!(composite
instanceof Img
))
850 edit(composite
, source
.toDisplay(point
));
851 } else if (e
.button
== 3) {
852 EditablePart composite
= findDataParent((Control
) e
854 if (styledTools
!= null)
855 styledTools
.show(composite
, new Point(e
.x
, e
.y
));
861 public void mouseUp(MouseEvent e
) {
865 // FILE UPLOAD LISTENER
866 private class FUL
implements FileUploadListener
{
867 public void uploadProgress(FileUploadEvent event
) {
868 // TODO Monitor upload progress
871 public void uploadFailed(FileUploadEvent event
) {
872 throw new CmsException("Upload failed " + event
,
873 event
.getException());
876 public void uploadFinished(FileUploadEvent event
) {
877 for (FileDetails file
: event
.getFileDetails()) {
878 if (log
.isDebugEnabled())
879 log
.debug("Received: " + file
.getFileName());
881 mainSection
.getDisplay().syncExec(new Runnable() {
887 FileUploadHandler uploadHandler
= (FileUploadHandler
) event
889 uploadHandler
.dispose();