]> git.argeo.org Git - gpl/argeo-suite.git/blob - docbook/DocBookViewer.java
Prepare next development cycle
[gpl/argeo-suite.git] / docbook / DocBookViewer.java
1 package org.argeo.app.swt.docbook;
2
3 import static org.argeo.app.docbook.DbkAcrUtils.isDbk;
4 import static org.argeo.app.docbook.DbkType.para;
5
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Optional;
9
10 import org.argeo.api.acr.Content;
11 import org.argeo.api.cms.ux.Cms2DSize;
12 import org.argeo.api.cms.ux.CmsEditable;
13 import org.argeo.app.docbook.DbkAttr;
14 import org.argeo.app.docbook.DbkType;
15 import org.argeo.cms.swt.CmsSwtUtils;
16 import org.argeo.cms.swt.SwtEditablePart;
17 import org.argeo.cms.swt.acr.AbstractPageViewer;
18 import org.argeo.cms.swt.acr.SwtSection;
19 import org.argeo.cms.swt.acr.SwtSectionPart;
20 import org.argeo.cms.swt.widgets.EditableText;
21 import org.argeo.cms.swt.widgets.StyledControl;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.layout.GridData;
24 import org.eclipse.swt.widgets.Composite;
25 import org.eclipse.swt.widgets.Control;
26
27 /** Displays DocBook content. */
28 public class DocBookViewer extends AbstractPageViewer {
29
30 private TextInterpreter textInterpreter = new DbkTextInterpreter();
31 private DbkImageManager imageManager;
32
33 private TextSection mainSection;
34
35 private boolean showMainTitle = true;
36
37 private Integer maxMediaWidth = null;
38 private String defaultSectionStyle;
39
40 public DocBookViewer(Composite parent, int style, Content item, CmsEditable cmsEditable) {
41 super(parent, style, cmsEditable);
42 imageManager = new DbkImageManager(item);
43
44 for (Content child : item) {
45 if (child.hasContentClass(DbkType.article)) {
46 if (mainSection != null)
47 throw new IllegalStateException("Main section already created");
48 mainSection = new TextSection(parent, 0, child);
49 mainSection.setLayoutData(CmsSwtUtils.fillAll());
50 }
51 }
52 }
53
54 @Override
55 protected void refresh(Control control) {
56 if (!(control instanceof SwtSection))
57 return;
58 // long begin = System.currentTimeMillis();
59 SwtSection section = (SwtSection) control;
60 if (section instanceof TextSection) {
61 CmsSwtUtils.clear(mainSection);
62 refreshTextSection(mainSection);
63
64 }
65 // long duration = System.currentTimeMillis() - begin;
66 // System.out.println(duration + " ms - " + DbkUtils.getTitle(section.getNode()));
67
68 }
69
70 protected void refreshTextSection(TextSection section) {
71 Content sectionContent = section.getContent();
72 // Style
73 Optional<String> roleAttr = sectionContent.get(DbkAttr.role, String.class);
74 String style = roleAttr.orElse(section.getDefaultTextStyle());
75 if (style != null)
76 CmsSwtUtils.style(section, style);
77
78 // Title
79 Optional<Content> titleContent = sectionContent.soleChild(DbkType.title.qName());
80
81 if (titleContent.isPresent()) {
82 boolean showTitle = getMainSection() == section ? showMainTitle : true;
83 if (showTitle) {
84 if (section.getHeader() == null)
85 section.createHeader();
86 DbkSectionTitle title = newSectionTitle(section, titleContent.get());
87 title.setLayoutData(CmsSwtUtils.fillWidth());
88 updateContent(title);
89 }
90 }
91
92 boolean processingSubSections = false;
93 for (Content child : section.getContent()) {
94 if (child.hasContentClass(DbkType.section)) {
95 processingSubSections = true;
96 TextSection childSection = newTextSection(section, child); // new TextSection(section, 0, child);
97 childSection.setLayoutData(CmsSwtUtils.fillWidth());
98 refreshTextSection(childSection);
99 } else {
100 if (processingSubSections)
101 throw new IllegalStateException(child + " is below a subsection");
102 SwtSectionPart sectionPart = null;
103 if (child.hasContentClass(DbkType.para)) {
104 sectionPart = newParagraph(section, child);
105 } else if (child.hasContentClass(DbkType.mediaobject)) {
106 if (child.hasChild(DbkType.imageobject)) {
107 sectionPart = newImg(section, child);
108 } else if (child.hasChild(DbkType.videoobject)) {
109 sectionPart = newVideo(section, child);
110 } else {
111 throw new IllegalArgumentException("Unsupported media object " + child);
112 }
113 } else if (isDbk(child, DbkType.info)) {
114 // TODO enrich UI based on info
115 } else if (isDbk(child, DbkType.title)) {
116 // already managed
117 // TODO check that it is first?
118 } else {
119 throw new IllegalArgumentException("Unsupported type for " + child);
120 }
121 if (sectionPart != null && sectionPart instanceof Control)
122 ((Control) sectionPart).setLayoutData(CmsSwtUtils.fillWidth());
123 }
124 }
125 }
126
127 protected void updateContent(SwtEditablePart part) {
128 if (part instanceof SwtSectionPart) {
129 SwtSectionPart sectionPart = (SwtSectionPart) part;
130 Content partContent = sectionPart.getContent();
131
132 if (part instanceof StyledControl && (sectionPart.getSection() instanceof TextSection)) {
133 TextSection section = (TextSection) sectionPart.getSection();
134 StyledControl styledControl = (StyledControl) part;
135 if (isDbk(partContent, para)) {
136 Optional<String> roleAttr = partContent.get(DbkAttr.role.qName(), String.class);
137 String style = roleAttr.orElse(section.getDefaultTextStyle());
138 styledControl.setStyle(style);
139 }
140 }
141 // use control AFTER setting style, since it may have been reset
142
143 if (part instanceof EditableText) {
144 EditableText paragraph = (EditableText) part;
145 if (paragraph == getEdited())
146 paragraph.setText(textInterpreter.raw(partContent));
147 else
148 paragraph.setText(textInterpreter.readSimpleHtml(partContent));
149 // paragraph.setText(textInterpreter.readSimpleHtml(partContent));
150
151 } else if (part instanceof DbkImg) {
152 DbkImg editableImage = (DbkImg) part;
153 imageManager.load(partContent, part.getControl(), editableImage.getPreferredImageSize(), null);
154 } else if (part instanceof DbkVideo) {
155 DbkVideo video = (DbkVideo) part;
156 video.load(part.getControl());
157 }
158 } else if (part instanceof DbkSectionTitle) {
159 DbkSectionTitle title = (DbkSectionTitle) part;
160 title.setStyle(title.getSection().getTitleStyle());
161 // use control AFTER setting style
162 if (title == getEdited())
163 title.setText(textInterpreter.read(title.getContent()));
164 else
165 title.setText(textInterpreter.readSimpleHtml(title.getContent()));
166 }
167 }
168
169 /** To be overridden in order to provide additional SectionPart types */
170 protected TextSection newTextSection(SwtSection section, Content node) {
171 return new TextSection(section, SWT.NONE, node);
172 }
173
174 protected Paragraph newParagraph(TextSection parent, Content node) {
175 Paragraph paragraph = new Paragraph(parent, parent.getStyle(), node);
176 updateContent(paragraph);
177 paragraph.setLayoutData(CmsSwtUtils.fillWidth());
178 paragraph.setMouseListener(getMouseListener());
179 paragraph.setFocusListener(getFocusListener());
180 return paragraph;
181 }
182
183 protected DbkSectionTitle newSectionTitle(TextSection parent, Content titleNode) {
184 int style = parent.getStyle();
185 Composite titleParent = newSectionHeader(parent);
186 if (parent.isTitleReadOnly())
187 style = style | SWT.READ_ONLY;
188 DbkSectionTitle title = new DbkSectionTitle(titleParent, style, titleNode);
189 updateContent(title);
190 title.setMouseListener(getMouseListener());
191 title.setFocusListener(getFocusListener());
192 return title;
193 }
194
195 protected DbkImg newImg(TextSection parent, Content node) {
196 DbkImg img = new DbkImg(parent, parent.getStyle(), node, imageManager);
197 GridData imgGd;
198 if (maxMediaWidth != null) {
199 imgGd = new GridData(SWT.CENTER, SWT.FILL, false, false);
200 imgGd.widthHint = maxMediaWidth;
201 img.setPreferredSize(new Cms2DSize(maxMediaWidth, 0));
202 } else {
203 imgGd = CmsSwtUtils.grabWidth(SWT.CENTER, SWT.DEFAULT);
204 }
205 img.setLayoutData(imgGd);
206 updateContent(img);
207 img.setMouseListener(getMouseListener());
208 img.setFocusListener(getFocusListener());
209 return img;
210 }
211
212 protected DbkVideo newVideo(TextSection parent, Content node) {
213 DbkVideo video = new DbkVideo(parent, getCmsEditable().canEdit() ? SWT.NONE : SWT.READ_ONLY, node);
214 GridData gd;
215 if (maxMediaWidth != null) {
216 gd = new GridData(SWT.CENTER, SWT.FILL, false, false);
217 // TODO, manage size
218 // gd.widthHint = maxMediaWidth;
219 // gd.heightHint = (int) (gd.heightHint * 0.5625);
220 } else {
221 gd = new GridData(SWT.CENTER, SWT.FILL, false, false);
222 // gd.widthHint = video.getWidth();
223 // gd.heightHint = video.getHeight();
224 }
225 video.setLayoutData(gd);
226 updateContent(video);
227 return video;
228 }
229
230 /**
231 * To be overridden in order to provide additional processing at the section
232 * level.
233 *
234 * @return the parent to use for the {@link DbkSectionTitle}, by default
235 * {@link SwtSection#getHeader()}
236 */
237 protected Composite newSectionHeader(TextSection section) {
238 return section.getHeader();
239 }
240
241 protected List<String> getAvailableStyles(SwtEditablePart editablePart) {
242 return new ArrayList<>();
243 }
244
245 public TextSection getMainSection() {
246 return mainSection;
247 }
248
249 public void setShowMainTitle(boolean showMainTitle) {
250 this.showMainTitle = showMainTitle;
251 }
252
253 public String getDefaultSectionStyle() {
254 return defaultSectionStyle;
255 }
256
257 public void setDefaultSectionStyle(String defaultSectionStyle) {
258 this.defaultSectionStyle = defaultSectionStyle;
259 }
260
261 public void setMaxMediaWidth(Integer maxMediaWidth) {
262 this.maxMediaWidth = maxMediaWidth;
263 }
264
265 @Override
266 public Control getControl() {
267 return mainSection;
268 }
269
270 }