]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/viewers/AbstractPageViewer.java
5e6de37097ea226c9a0165eb16666739c13e1f3c
[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
9 import org.apache.commons.logging.Log;
10 import org.apache.commons.logging.LogFactory;
11 import org.argeo.cms.CmsEditable;
12 import org.argeo.cms.CmsException;
13 import org.argeo.cms.widgets.ScrolledPage;
14 import org.eclipse.jface.viewers.ContentViewer;
15 import org.eclipse.jface.viewers.ISelection;
16 import org.eclipse.jface.viewers.StructuredSelection;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.MouseAdapter;
19 import org.eclipse.swt.events.MouseListener;
20 import org.eclipse.swt.widgets.Composite;
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Widget;
23
24 /** Base class for viewers related to a page */
25 public abstract class AbstractPageViewer extends ContentViewer implements
26 Observer {
27 private static final long serialVersionUID = 5438688173410341485L;
28
29 private final static Log log = LogFactory.getLog(AbstractPageViewer.class);
30
31 private final boolean readOnly;
32 /** The basis for the layouts, typically a ScrolledPage. */
33 private final Composite page;
34 private final CmsEditable cmsEditable;
35
36 private MouseListener mouseListener;
37
38 private EditablePart edited;
39 private ISelection selection = StructuredSelection.EMPTY;
40
41 protected AbstractPageViewer(Section parent, int style,
42 CmsEditable cmsEditable) {
43 // read only at UI level
44 readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY);
45
46 this.cmsEditable = cmsEditable == null ? CmsEditable.NON_EDITABLE
47 : cmsEditable;
48 if (this.cmsEditable instanceof Observable)
49 ((Observable) this.cmsEditable).addObserver(this);
50
51 if (cmsEditable.canEdit()) {
52 mouseListener = createMouseListener();
53 }
54 page = findPage(parent);
55 }
56
57 /**
58 * Can be called to simplify the called to isModelInitialized() and
59 * initModel()
60 */
61 protected void initModelIfNeeded(Node node) {
62 try {
63 if (!isModelInitialized(node))
64 if (getCmsEditable().canEdit()) {
65 initModel(node);
66 node.getSession().save();
67 }
68 } catch (Exception e) {
69 throw new CmsException("Cannot initialize model", e);
70 }
71 }
72
73 /** Called if user can edit and model is not initialized */
74 protected Boolean isModelInitialized(Node node) throws RepositoryException {
75 return true;
76 }
77
78 /** Called if user can edit and model is not initialized */
79 protected void initModel(Node node) throws RepositoryException {
80 }
81
82 /** Create (retrieve) the MouseListener to use. */
83 protected MouseListener createMouseListener() {
84 return new MouseAdapter() {
85 private static final long serialVersionUID = 1L;
86 };
87 }
88
89 protected Composite findPage(Composite composite) {
90 if (composite instanceof ScrolledPage) {
91 return (ScrolledPage) composite;
92 } else {
93 if (composite.getParent() == null)
94 return composite;
95 return findPage(composite.getParent());
96 }
97 }
98
99 @Override
100 public void update(Observable o, Object arg) {
101 if (o == cmsEditable)
102 editingStateChanged(cmsEditable);
103 }
104
105 /** To be overridden in order to provide the actual refresh */
106 protected void refresh(Control control) throws RepositoryException {
107 }
108
109 /** To be overridden.Save the edited part. */
110 protected void save(EditablePart part) throws RepositoryException {
111 }
112
113 /** Prepare the edited part */
114 protected void prepare(EditablePart part, Object caretPosition) {
115 }
116
117 /** Notified when the editing state changed. Does nothing, to be overridden */
118 protected void editingStateChanged(CmsEditable cmsEditable) {
119 }
120
121 @Override
122 public void refresh() {
123 try {
124 if (cmsEditable.canEdit() && !readOnly)
125 mouseListener = createMouseListener();
126 else
127 mouseListener = null;
128 refresh(getControl());
129 layout(getControl());
130 } catch (RepositoryException e) {
131 throw new CmsException("Cannot refresh", e);
132 }
133 }
134
135 @Override
136 public void setSelection(ISelection selection, boolean reveal) {
137 this.selection = selection;
138 }
139
140 protected void updateContent(EditablePart part) throws RepositoryException {
141 }
142
143 // LOW LEVEL EDITION
144 protected void edit(EditablePart part, Object caretPosition) {
145 try {
146 if (edited == part)
147 return;
148
149 if (edited != null && edited != part)
150 stopEditing(true);
151
152 part.startEditing();
153 updateContent(part);
154 prepare(part, caretPosition);
155 edited = part;
156 layout(part.getControl());
157 } catch (RepositoryException e) {
158 throw new CmsException("Cannot edit " + part, e);
159 }
160 }
161
162 private void stopEditing(Boolean save) throws RepositoryException {
163 if (edited instanceof Widget && ((Widget) edited).isDisposed()) {
164 edited = null;
165 return;
166 }
167
168 assert edited != null;
169 if (edited == null) {
170 if (log.isTraceEnabled())
171 log.warn("Told to stop editing while not editing anything");
172 return;
173 }
174
175 if (save)
176 save(edited);
177
178 edited.stopEditing();
179 updateContent(edited);
180 layout(((EditablePart) edited).getControl());
181 edited = null;
182 }
183
184 // METHODS AVAILABLE TO EXTENDING CLASSES
185 protected void saveEdit() {
186 try {
187 if (edited != null)
188 stopEditing(true);
189 } catch (RepositoryException e) {
190 throw new CmsException("Cannot stop editing", e);
191 }
192 }
193
194 protected void cancelEdit() {
195 try {
196 if (edited != null)
197 stopEditing(false);
198 } catch (RepositoryException e) {
199 throw new CmsException("Cannot cancel editing", e);
200 }
201 }
202
203 /** Layout this controls from the related base page. */
204 public void layout(Control... controls) {
205 page.layout(controls);
206 }
207
208 // UTILITIES
209 /** Check whether the edited part is in a proper state */
210 protected void checkEdited() {
211 if (edited == null || (edited instanceof Widget)
212 && ((Widget) edited).isDisposed())
213 throw new CmsException(
214 "Edited should not be null or disposed at this stage");
215 }
216
217 // GETTERS / SETTERS
218 public boolean isReadOnly() {
219 return readOnly;
220 }
221
222 protected EditablePart getEdited() {
223 return edited;
224 }
225
226 public MouseListener getMouseListener() {
227 return mouseListener;
228 }
229
230 public CmsEditable getCmsEditable() {
231 return cmsEditable;
232 }
233
234 @Override
235 public ISelection getSelection() {
236 return selection;
237 }
238
239 }