package org.argeo.docbook.ui;
import static org.argeo.cms.ui.util.CmsUiUtils.fillWidth;
+import static org.argeo.docbook.DbkType.para;
import static org.argeo.docbook.DbkUtils.addDbk;
import static org.argeo.docbook.DbkUtils.isDbk;
-import static org.argeo.docbook.DocBookType.para;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.text.Paragraph;
-import org.argeo.cms.text.TextInterpreter;
-import org.argeo.cms.text.TextSection;
import org.argeo.cms.ui.CmsEditable;
import org.argeo.cms.ui.util.CmsUiUtils;
import org.argeo.cms.ui.viewers.AbstractPageViewer;
import org.argeo.cms.ui.viewers.SectionPart;
import org.argeo.cms.ui.widgets.EditableText;
import org.argeo.cms.ui.widgets.StyledControl;
+import org.argeo.docbook.DbkAttr;
+import org.argeo.docbook.DbkType;
import org.argeo.docbook.DbkUtils;
-import org.argeo.docbook.DocBookNames;
-import org.argeo.docbook.DocBookType;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
import org.argeo.jcr.JcrUtils;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/** Base class for text viewers and editors. */
private final boolean flat;
+ private boolean showMainTitle = true;
+
+ private Integer maxMediaWidth = null;
+ private String defaultSectionStyle;
+
protected AbstractDbkViewer(Section parent, int style, CmsEditable cmsEditable) {
super(parent, style, cmsEditable);
// CmsView cmsView = CmsView.getCmsView(parent);
CmsUiUtils.clear(section);
Node node = section.getNode();
TextSection textSection = (TextSection) section;
- if (node.hasNode(DocBookType.title.get())) {
- if (section.getHeader() == null)
- section.createHeader();
- Node titleNode = node.getNode(DocBookType.title.get());
- DocBookSectionTitle title = newSectionTitle(textSection, titleNode);
- title.setLayoutData(CmsUiUtils.fillWidth());
- updateContent(title);
+ String style = node.hasProperty(DbkAttr.role.name()) ? node.getProperty(DbkAttr.role.name()).getString()
+ : getDefaultSectionStyle();
+ if (style != null)
+ CmsUiUtils.style(textSection, style);
+
+ // Title
+ Node titleNode = null;
+ // We give priority to ./title vs ./info/title, like the DocBook XSL
+ if (node.hasNode(DbkType.title.get())) {
+ titleNode = node.getNode(DbkType.title.get());
+ } else if (node.hasNode(DbkType.info.get() + '/' + DbkType.title.get())) {
+ titleNode = node.getNode(DbkType.info.get() + '/' + DbkType.title.get());
+ }
+
+ if (titleNode != null) {
+ boolean showTitle = getMainSection() == section ? showMainTitle : true;
+ if (showTitle) {
+ if (section.getHeader() == null)
+ section.createHeader();
+ DocBookSectionTitle title = newSectionTitle(textSection, titleNode);
+ title.setLayoutData(CmsUiUtils.fillWidth());
+ updateContent(title);
+ }
}
+ // content
for (NodeIterator ni = node.getNodes(); ni.hasNext();) {
Node child = ni.nextNode();
SectionPart sectionPart = null;
- if (isDbk(child, DocBookType.mediaobject)) {
- if (child.hasNode(DocBookType.imageobject.get())) {
- Node imageDataNode = child.getNode(DocBookType.imageobject.get())
- .getNode(DocBookType.imagedata.get());
- sectionPart = newImg(textSection, imageDataNode);
+ if (isDbk(child, DbkType.mediaobject)) {
+ if (child.hasNode(DbkType.imageobject.get())) {
+ sectionPart = newImg(textSection, child);
+ } else if (child.hasNode(DbkType.videoobject.get())) {
+ sectionPart = newVideo(textSection, child);
+ } else {
+ throw new IllegalArgumentException("Unsupported media object " + child);
}
+ } else if (isDbk(child, DbkType.info)) {
+ // TODO enrich UI based on info
+ } else if (isDbk(child, DbkType.title)) {
+ // already managed
} else if (isDbk(child, para)) {
sectionPart = newParagraph(textSection, child);
- } else {
+ } else if (isDbk(child, DbkType.section)) {
sectionPart = newSectionPart(textSection, child);
// if (sectionPart == null)
// throw new IllegalArgumentException("Unsupported node " + child);
// TODO list node types in exception
+ } else {
+ throw new IllegalArgumentException("Unsupported node type for " + child);
}
if (sectionPart != null && sectionPart instanceof Control)
((Control) sectionPart).setLayoutData(CmsUiUtils.fillWidth());
}
// if (!flat)
- for (NodeIterator ni = section.getNode().getNodes(DocBookType.section.get()); ni.hasNext();) {
+ for (NodeIterator ni = section.getNode().getNodes(DbkType.section.get()); ni.hasNext();) {
Node child = ni.nextNode();
- if (isDbk(child, DocBookType.section)) {
- TextSection newSection = new TextSection(section, SWT.NONE, child);
+ if (isDbk(child, DbkType.section)) {
+ TextSection newSection = newTextSection(section, child);
newSection.setLayoutData(CmsUiUtils.fillWidth());
refresh(newSection);
}
// section.layout(true, true);
}
+ /** To be overridden in order to provide additional SectionPart types */
+ protected TextSection newTextSection(Section section, Node node) {
+ return new TextSection(section, SWT.NONE, node);
+ }
+
/** To be overridden in order to provide additional SectionPart types */
protected SectionPart newSectionPart(TextSection textSection, Node node) {
return null;
updateContent(paragraph);
paragraph.setLayoutData(fillWidth());
paragraph.setMouseListener(getMouseListener());
+ paragraph.setFocusListener(getFocusListener());
return paragraph;
}
protected DbkImg newImg(TextSection parent, Node node) {
try {
DbkImg img = new DbkImg(parent, parent.getStyle(), node, imageManager);
- img.setLayoutData(CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT));
+ GridData imgGd;
+ if (maxMediaWidth != null) {
+ imgGd = new GridData(SWT.CENTER, SWT.FILL, false, false);
+ imgGd.widthHint = maxMediaWidth;
+ img.setPreferredSize(new Point(maxMediaWidth, 0));
+ } else {
+ imgGd = CmsUiUtils.grabWidth(SWT.CENTER, SWT.DEFAULT);
+ }
+ img.setLayoutData(imgGd);
updateContent(img);
img.setMouseListener(getMouseListener());
+ img.setFocusListener(getFocusListener());
return img;
} catch (RepositoryException e) {
throw new JcrException("Cannot add new image " + node, e);
}
}
+ protected DbkVideo newVideo(TextSection parent, Node node) {
+ try {
+// node.getSession();
+// Composite wrapper = new Composite(parent, SWT.NONE);
+// new Label(wrapper,SWT.NONE).setText("TEST");
+ DbkVideo video = new DbkVideo(parent, SWT.BORDER, node);
+ GridData gd;
+ if (maxMediaWidth != null) {
+ gd = new GridData(SWT.CENTER, SWT.FILL, false, false);
+ // TODO, manage size
+ gd.widthHint = maxMediaWidth;
+ gd.heightHint = (int) (gd.heightHint * 0.5625);
+// img.setPreferredSize(new Point(maxMediaWidth, 0));
+ } else {
+ gd = new GridData(SWT.CENTER, SWT.FILL, false, false);
+ gd.widthHint = video.getWidth();
+ gd.heightHint = video.getHeight();
+// gd = new GridData(video.getWidth(),video.getHeight());
+ }
+// wrapper.setLayoutData(gd);
+ video.setLayoutData(gd);
+ updateContent(video);
+ return null;
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot add new image " + node, e);
+ }
+ }
+
protected DocBookSectionTitle newSectionTitle(TextSection parent, Node titleNode) throws RepositoryException {
int style = parent.getStyle();
Composite titleParent = newSectionHeader(parent);
DocBookSectionTitle title = new DocBookSectionTitle(titleParent, style, titleNode);
updateContent(title);
title.setMouseListener(getMouseListener());
+ title.setFocusListener(getFocusListener());
return title;
}
protected DocBookSectionTitle prepareSectionTitle(Section newSection, String titleText) throws RepositoryException {
Node sectionNode = newSection.getNode();
- Node titleNode = DbkUtils.getOrAddDbk(sectionNode, DocBookType.title);
+ Node titleNode = DbkUtils.getOrAddDbk(sectionNode, DbkType.title);
getTextInterpreter().write(titleNode, titleText);
if (newSection.getHeader() == null)
newSection.createHeader();
TextSection section = (TextSection) sectionPart.getSection();
StyledControl styledControl = (StyledControl) part;
if (isDbk(partNode, para)) {
- String style = partNode.hasProperty(DocBookNames.DBK_ROLE)
- ? partNode.getProperty(DocBookNames.DBK_ROLE).getString()
+ String style = partNode.hasProperty(DbkAttr.role.name())
+ ? partNode.getProperty(DbkAttr.role.name()).getString()
: section.getDefaultTextStyle();
styledControl.setStyle(style);
}
} else if (part instanceof DbkImg) {
DbkImg editableImage = (DbkImg) part;
imageManager.load(partNode, part.getControl(), editableImage.getPreferredImageSize());
+ } else if (part instanceof DbkVideo) {
+ DbkVideo video = (DbkVideo) part;
+ video.load(part.getControl());
}
} else if (part instanceof DocBookSectionTitle) {
DocBookSectionTitle title = (DocBookSectionTitle) part;
if (title == getEdited())
title.setText(textInterpreter.read(title.getNode()));
else
- title.setText(textInterpreter.raw(title.getNode()));
+ title.setText(textInterpreter.readSimpleHtml(title.getNode()));
}
}
if (caretPosition instanceof Integer)
text.setSelection((Integer) caretPosition);
else if (caretPosition instanceof Point) {
- // TODO find a way to position the caret at the right place
+// layout(text);
+// // TODO find a way to position the caret at the right place
+// Point clickLocation = (Point) caretPosition;
+// Point withinText = text.toControl(clickLocation);
+// Rectangle bounds = text.getBounds();
+// int width = bounds.width;
+// int height = bounds.height;
+// int textLength = text.getText().length();
+// float area = width * height;
+// float proportion = withinText.y * width + withinText.x;
+// int pos = (int) (textLength * (proportion / area));
+// text.setSelection(pos);
}
text.setData(RWT.ACTIVE_KEYS, new String[] { "BACKSPACE", "ESC", "TAB", "SHIFT+TAB", "ALT+ARROW_LEFT",
"ALT+ARROW_RIGHT", "ALT+ARROW_UP", "ALT+ARROW_DOWN", "RETURN", "CTRL+RETURN", "ENTER", "DELETE" });
try {
Node paragraphNode = paragraph.getNode();
if (style == null) {// default
- if (paragraphNode.hasProperty(DocBookNames.DBK_ROLE))
- paragraphNode.getProperty(DocBookNames.DBK_ROLE).remove();
+ if (paragraphNode.hasProperty(DbkAttr.role.name()))
+ paragraphNode.getProperty(DbkAttr.role.name()).remove();
} else {
- paragraphNode.setProperty(DocBookNames.DBK_ROLE, style);
+ paragraphNode.setProperty(DbkAttr.role.name(), style);
}
persistChanges(paragraphNode);
updateContent(paragraph);
}
}
- void insertPart(Section section, Node node) {
+ SectionPart insertPart(Section section, Node node) {
try {
refresh(section);
layoutPage();
+ for (Control control : section.getChildren()) {
+ if (control instanceof SectionPart) {
+ SectionPart sectionPart = (SectionPart) control;
+ Node partNode = sectionPart.getNode();
+ if (partNode.getPath().equals(node.getPath()))
+ return sectionPart;
+ }
+ }
+ throw new IllegalStateException("New section part " + node + "not found");
} catch (RepositoryException e) {
throw new JcrException("Cannot insert part " + node + " in section " + section.getNode(), e);
}
}
+ void addParagraph(SectionPart partBefore, String txt) {
+ Section section = partBefore.getSection();
+ SectionPart nextSectionPart = section.nextSectionPart(partBefore);
+ Node newNode = addDbk(section.getNode(), para);
+ textInterpreter.write(newNode, txt != null ? txt : "");
+ if (nextSectionPart != null) {
+ try {
+ Node nextNode = nextSectionPart.getNode();
+ section.getNode().orderBefore(Jcr.getIndexedName(newNode), Jcr.getIndexedName(nextNode));
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot order " + newNode + " before " + nextSectionPart.getNode(), e);
+ }
+ }
+ Jcr.save(newNode);
+ Paragraph paragraph = (Paragraph) insertPart(partBefore.getSection(), newNode);
+ edit(paragraph, 0);
+ }
+
void deletePart(SectionPart sectionPart) {
try {
Node node = sectionPart.getNode();
Session session = node.getSession();
if (sectionPart instanceof DbkImg) {
- // FIXME make it more robust
- node = node.getParent().getParent();
- if (!isDbk(node, DocBookType.mediaobject))
+ if (!isDbk(node, DbkType.mediaobject))
throw new IllegalArgumentException("Node " + node + " is not a media object.");
}
node.remove();
// paragraphNode.addMixin(CmsTypes.CMS_STYLED);
textInterpreter.write(paragraphNode, txt.substring(caretPosition));
- textInterpreter.write(sectionNode.getNode(DocBookType.title.get()), txt.substring(0, caretPosition));
+ textInterpreter.write(sectionNode.getNode(DbkType.title.get()), txt.substring(0, caretPosition));
sectionNode.orderBefore(p(paragraphNode.getIndex()), p(1));
persistChanges(sectionNode);
String txt = text.getText();
Node paragraphNode = paragraph.getNode();
Node sectionNode = paragraphNode.getParent();
- NodeIterator paragraphNodes = sectionNode.getNodes(DocBookType.para.get());
+ NodeIterator paragraphNodes = sectionNode.getNodes(DbkType.para.get());
long size = paragraphNodes.getSize();
if (paragraphNode.getIndex() == size)
return;// do nothing
Node sectionNode = section.getNode();
// main title
if (section == mainSection && section instanceof TextSection && paragraphNode.getIndex() == 1
- && !sectionNode.hasNode(DocBookType.title.get())) {
+ && !sectionNode.hasNode(DbkType.title.get())) {
DocBookSectionTitle sectionTitle = prepareSectionTitle(section, txt);
edit(sectionTitle, 0);
return;
}
- Node newSectionNode = addDbk(sectionNode, DocBookType.section);
+ Node newSectionNode = addDbk(sectionNode, DbkType.section);
// newSectionNode.addMixin(NodeType.MIX_TITLE);
sectionNode.orderBefore(h(newSectionNode.getIndex()), h(1));
while (sectionNode.hasNode(p(paragraphIndex + 1))) {
Node parag = sectionNode.getNode(p(paragraphIndex + 1));
sectionNode.getSession().move(sectionPath + '/' + p(paragraphIndex + 1),
- newSectionPath + '/' + DocBookType.para.get());
+ newSectionPath + '/' + DbkType.para.get());
SectionPart sp = section.getSectionPart(parag.getIdentifier());
if (sp instanceof Control)
((Control) sp).dispose();
}
// create title
- Node titleNode = DbkUtils.addDbk(newSectionNode, DocBookType.title);
+ Node titleNode = DbkUtils.addDbk(newSectionNode, DbkType.title);
// newSectionNode.addNode(DocBookType.TITLE, DocBookType.TITLE);
getTextInterpreter().write(titleNode, txt);
if (sectionN.getIndex() == 1)
return;// cannot deepen first section
Node previousSectionN = parentSectionN.getNode(h(sectionN.getIndex() - 1));
- NodeIterator subSections = previousSectionN.getNodes(DocBookType.section.get());
+ NodeIterator subSections = previousSectionN.getNodes(DbkType.section.get());
int subsectionsCount = (int) subSections.getSize();
previousSectionN.getSession().move(sectionN.getPath(),
previousSectionN.getPath() + "/" + h(subsectionsCount + 1));
mergedSection = lst.get(sectionNode.getIndex() - 1);
}
Node mergedNode = mergedSection.getNode();
- boolean mergedHasSubSections = mergedNode.hasNode(DocBookType.section.get());
+ boolean mergedHasSubSections = mergedNode.hasNode(DbkType.section.get());
// title as paragraph
Node newParagrapheNode = addDbk(mergedNode, para);
// newParagrapheNode.addMixin(CmsTypes.CMS_STYLED);
if (mergedHasSubSections)
mergedNode.orderBefore(p(newParagrapheNode.getIndex()), h(1));
- String txt = getTextInterpreter().read(sectionNode.getNode(DocBookType.title.get()));
+ String txt = getTextInterpreter().read(sectionNode.getNode(DbkType.title.get()));
getTextInterpreter().write(newParagrapheNode, txt);
// move
NodeIterator paragraphs = sectionNode.getNodes(para.get());
while (subsections.hasNext()) {
Section subsection = subsections.next();
Node s = subsection.getNode();
- mergedNode.getSession().move(s.getPath(), mergedNode.getPath() + '/' + DocBookType.section.get());
+ mergedNode.getSession().move(s.getPath(), mergedNode.getPath() + '/' + DbkType.section.get());
subsection.dispose();
}
protected String h(Integer index) {
StringBuilder sb = new StringBuilder(5);
- sb.append(DocBookType.section.get()).append('[').append(index).append(']');
+ sb.append(DbkType.section.get()).append('[').append(index).append(']');
return sb.toString();
}
getCmsEditable().startEditing();
}
}
- } else
+ } else if (source instanceof Label) {
+ Label lbl = (Label) source;
+ Rectangle bounds = lbl.getBounds();
+ float width = bounds.width;
+ float height = bounds.height;
+ float textLength = lbl.getText().length();
+ float area = width * height;
+ float charArea = area / textLength;
+ float lines = textLength / width;
+ float proportion = point.y * width + point.x;
+ int pos = (int) (textLength * (proportion / area));
+ // TODO refine it
+ edit(composite, (Integer) pos);
+ } else {
edit(composite, source.toDisplay(point));
+ }
}
}
return new ArrayList<>();
}
- public void export(Path directory, String fileName) {
- Path filePath = directory.resolve(fileName);
- try {
- Files.createDirectories(directory);
- try (OutputStream out = Files.newOutputStream(filePath)) {
- exportXml(out);
- }
- if (log.isDebugEnabled())
- log.debug("DocBook " + getMainSection().getNode() + " exported to " + filePath.toAbsolutePath());
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ public void setMaxMediaWidth(Integer maxMediaWidth) {
+ this.maxMediaWidth = maxMediaWidth;
}
- public void exportXml(OutputStream out) throws IOException {
- Node node = getMainSection().getNode();
- try {
- node.getSession().exportDocumentView(node.getPath(), out, false, false);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot export " + node + " to XML", e);
- }
+ public void setShowMainTitle(boolean showMainTitle) {
+ this.showMainTitle = showMainTitle;
+ }
+
+ public String getDefaultSectionStyle() {
+ return defaultSectionStyle;
+ }
+
+ public void setDefaultSectionStyle(String defaultSectionStyle) {
+ this.defaultSectionStyle = defaultSectionStyle;
}
// FILE UPLOAD LISTENER