]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/viewers/AbstractPageViewer.java
First tests of refreshing session before displaying.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / viewers / AbstractPageViewer.java
1 package org.argeo.cms.viewers;
2
3 import java.util.Observable;
4 import java.util.Observer;
5
6 import javax.jcr.Node;
7 import javax.jcr.RepositoryException;
8 import javax.jcr.Session;
9
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.argeo.cms.CmsEditable;
13 import org.argeo.cms.CmsException;
14 import org.argeo.cms.widgets.ScrolledPage;
15 import org.eclipse.jface.viewers.ContentViewer;
16 import org.eclipse.jface.viewers.ISelection;
17 import org.eclipse.jface.viewers.StructuredSelection;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.events.MouseAdapter;
20 import org.eclipse.swt.events.MouseListener;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Widget;
24 import org.xml.sax.SAXParseException;
25
26 /** Base class for viewers related to a page */
27 public abstract class AbstractPageViewer extends ContentViewer implements
28 Observer {
29 private static final long serialVersionUID = 5438688173410341485L;
30
31 private final static Log log = LogFactory.getLog(AbstractPageViewer.class);
32
33 private final boolean readOnly;
34 /** The basis for the layouts, typically a ScrolledPage. */
35 private final Composite page;
36 private final CmsEditable cmsEditable;
37
38 private MouseListener mouseListener;
39
40 private EditablePart edited;
41 private ISelection selection = StructuredSelection.EMPTY;
42
43 // FIXME Added by BSinou to manage non-section Composite.
44 // Is it the correct method?
45 @Deprecated
46 protected AbstractPageViewer(Composite parent, int style,
47 CmsEditable cmsEditable) {
48 // read only at UI level
49 readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY);
50
51 this.cmsEditable = cmsEditable == null ? CmsEditable.NON_EDITABLE
52 : cmsEditable;
53 if (this.cmsEditable instanceof Observable)
54 ((Observable) this.cmsEditable).addObserver(this);
55
56 if (cmsEditable.canEdit()) {
57 mouseListener = createMouseListener();
58 }
59 page = findPage(parent);
60 }
61
62 protected AbstractPageViewer(Section parent, int style,
63 CmsEditable cmsEditable) {
64 // read only at UI level
65 readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY);
66
67 this.cmsEditable = cmsEditable == null ? CmsEditable.NON_EDITABLE
68 : cmsEditable;
69 if (this.cmsEditable instanceof Observable)
70 ((Observable) this.cmsEditable).addObserver(this);
71
72 if (cmsEditable.canEdit()) {
73 mouseListener = createMouseListener();
74 }
75 page = findPage(parent);
76 }
77
78 /**
79 * Can be called to simplify the called to isModelInitialized() and
80 * initModel()
81 */
82 protected void initModelIfNeeded(Node node) {
83 try {
84 if (!isModelInitialized(node))
85 if (getCmsEditable().canEdit()) {
86 initModel(node);
87 node.getSession().save();
88 }
89 } catch (Exception e) {
90 throw new CmsException("Cannot initialize model", e);
91 }
92 }
93
94 /** Called if user can edit and model is not initialized */
95 protected Boolean isModelInitialized(Node node) throws RepositoryException {
96 return true;
97 }
98
99 /** Called if user can edit and model is not initialized */
100 protected void initModel(Node node) throws RepositoryException {
101 }
102
103 /** Create (retrieve) the MouseListener to use. */
104 protected MouseListener createMouseListener() {
105 return new MouseAdapter() {
106 private static final long serialVersionUID = 1L;
107 };
108 }
109
110 protected Composite findPage(Composite composite) {
111 if (composite instanceof ScrolledPage) {
112 return (ScrolledPage) composite;
113 } else {
114 if (composite.getParent() == null)
115 return composite;
116 return findPage(composite.getParent());
117 }
118 }
119
120 @Override
121 public void update(Observable o, Object arg) {
122 if (o == cmsEditable)
123 editingStateChanged(cmsEditable);
124 }
125
126 /** To be overridden in order to provide the actual refresh */
127 protected void refresh(Control control) throws RepositoryException {
128 }
129
130 /** To be overridden.Save the edited part. */
131 protected void save(EditablePart part) throws RepositoryException {
132 }
133
134 /** Prepare the edited part */
135 protected void prepare(EditablePart part, Object caretPosition) {
136 }
137
138 /** Notified when the editing state changed. Does nothing, to be overridden */
139 protected void editingStateChanged(CmsEditable cmsEditable) {
140 }
141
142 @Override
143 public void refresh() {
144 try {
145 if (cmsEditable.canEdit() && !readOnly)
146 mouseListener = createMouseListener();
147 else
148 mouseListener = null;
149 refresh(getControl());
150 layout(getControl());
151 } catch (RepositoryException e) {
152 throw new CmsException("Cannot refresh", e);
153 }
154 }
155
156 @Override
157 public void setSelection(ISelection selection, boolean reveal) {
158 this.selection = selection;
159 }
160
161 protected void updateContent(EditablePart part) throws RepositoryException {
162 }
163
164 // LOW LEVEL EDITION
165 protected void edit(EditablePart part, Object caretPosition) {
166 try {
167 if (edited == part)
168 return;
169
170 if (edited != null && edited != part) {
171 EditablePart previouslyEdited = edited;
172 try {
173 stopEditing(true);
174 } catch (Exception e) {
175 notifyEditionException(e);
176 edit(previouslyEdited, caretPosition);
177 return;
178 }
179 }
180
181 part.startEditing();
182 updateContent(part);
183 prepare(part, caretPosition);
184 edited = part;
185 layout(part.getControl());
186 } catch (RepositoryException e) {
187 throw new CmsException("Cannot edit " + part, e);
188 }
189 }
190
191 private void stopEditing(Boolean save) throws RepositoryException {
192 if (edited instanceof Widget && ((Widget) edited).isDisposed()) {
193 edited = null;
194 return;
195 }
196
197 assert edited != null;
198 if (edited == null) {
199 if (log.isTraceEnabled())
200 log.warn("Told to stop editing while not editing anything");
201 return;
202 }
203
204 if (save)
205 save(edited);
206
207 edited.stopEditing();
208 updateContent(edited);
209 layout(((EditablePart) edited).getControl());
210 edited = null;
211 }
212
213 // METHODS AVAILABLE TO EXTENDING CLASSES
214 protected void saveEdit() {
215 try {
216 if (edited != null)
217 stopEditing(true);
218 } catch (RepositoryException e) {
219 throw new CmsException("Cannot stop editing", e);
220 }
221 }
222
223 protected void cancelEdit() {
224 try {
225 if (edited != null)
226 stopEditing(false);
227 } catch (RepositoryException e) {
228 throw new CmsException("Cannot cancel editing", e);
229 }
230 }
231
232 /** Layout this controls from the related base page. */
233 public void layout(Control... controls) {
234 page.layout(controls);
235 }
236
237 /**
238 * Find the first {@link EditablePart} in the parents hierarchy of this
239 * control
240 */
241 protected EditablePart findDataParent(Control parent) {
242 if (parent instanceof EditablePart) {
243 return (EditablePart) parent;
244 }
245 if (parent.getParent() != null)
246 return findDataParent(parent.getParent());
247 else
248 throw new CmsException("No data parent found");
249 }
250
251 // UTILITIES
252 /** Check whether the edited part is in a proper state */
253 protected void checkEdited() {
254 if (edited == null || (edited instanceof Widget)
255 && ((Widget) edited).isDisposed())
256 throw new CmsException(
257 "Edited should not be null or disposed at this stage");
258 }
259
260 /** Persist all changes. */
261 protected void persistChanges(Session session) throws RepositoryException {
262 session.save();
263 // TODO notify that changes have been persisted
264 }
265
266 /** Convenience method using a Node in order to save the underlying session. */
267 protected void persistChanges(Node anyNode) throws RepositoryException {
268 persistChanges(anyNode.getSession());
269 }
270
271 /** Notify edition exception */
272 protected void notifyEditionException(Throwable e) {
273 Throwable eToLog = e;
274 if (e instanceof IllegalArgumentException)
275 if (e.getCause() instanceof SAXParseException)
276 eToLog = e.getCause();
277 log.error(eToLog.getMessage());
278 if (log.isTraceEnabled())
279 log.trace("Full stack of " + eToLog.getMessage(), e);
280 // TODO Light error notification popup
281 }
282
283 // GETTERS / SETTERS
284 public boolean isReadOnly() {
285 return readOnly;
286 }
287
288 protected EditablePart getEdited() {
289 return edited;
290 }
291
292 public MouseListener getMouseListener() {
293 return mouseListener;
294 }
295
296 public CmsEditable getCmsEditable() {
297 return cmsEditable;
298 }
299
300 @Override
301 public ISelection getSelection() {
302 return selection;
303 }
304
305 }