1 package org
.argeo
.cms
.viewers
;
3 import java
.util
.Observable
;
4 import java
.util
.Observer
;
7 import javax
.jcr
.RepositoryException
;
8 import javax
.jcr
.Session
;
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
.FocusEvent
;
20 import org
.eclipse
.swt
.events
.FocusListener
;
21 import org
.eclipse
.swt
.events
.MouseAdapter
;
22 import org
.eclipse
.swt
.events
.MouseListener
;
23 import org
.eclipse
.swt
.widgets
.Composite
;
24 import org
.eclipse
.swt
.widgets
.Control
;
25 import org
.eclipse
.swt
.widgets
.Widget
;
26 import org
.xml
.sax
.SAXParseException
;
28 /** Base class for viewers related to a page */
29 public abstract class AbstractPageViewer
extends ContentViewer
implements
31 private static final long serialVersionUID
= 5438688173410341485L;
33 private final static Log log
= LogFactory
.getLog(AbstractPageViewer
.class);
35 private final boolean readOnly
;
36 /** The basis for the layouts, typically a ScrolledPage. */
37 private final Composite page
;
38 private final CmsEditable cmsEditable
;
40 private MouseListener mouseListener
;
41 private FocusListener focusListener
;
43 private EditablePart edited
;
44 private ISelection selection
= StructuredSelection
.EMPTY
;
46 protected AbstractPageViewer(Section parent
, int style
,
47 CmsEditable cmsEditable
) {
48 // read only at UI level
49 readOnly
= SWT
.READ_ONLY
== (style
& SWT
.READ_ONLY
);
51 this.cmsEditable
= cmsEditable
== null ? CmsEditable
.NON_EDITABLE
53 if (this.cmsEditable
instanceof Observable
)
54 ((Observable
) this.cmsEditable
).addObserver(this);
56 if (cmsEditable
.canEdit()) {
57 mouseListener
= createMouseListener();
58 focusListener
= createFocusListener();
60 page
= findPage(parent
);
64 * Can be called to simplify the called to isModelInitialized() and
67 protected void initModelIfNeeded(Node node
) {
69 if (!isModelInitialized(node
))
70 if (getCmsEditable().canEdit()) {
72 node
.getSession().save();
74 } catch (Exception e
) {
75 throw new CmsException("Cannot initialize model", e
);
79 /** Called if user can edit and model is not initialized */
80 protected Boolean
isModelInitialized(Node node
) throws RepositoryException
{
84 /** Called if user can edit and model is not initialized */
85 protected void initModel(Node node
) throws RepositoryException
{
88 /** Create (retrieve) the MouseListener to use. */
89 protected MouseListener
createMouseListener() {
90 return new MouseAdapter() {
91 private static final long serialVersionUID
= 1L;
95 /** Create (retrieve) the FocusListener to use. */
96 protected FocusListener
createFocusListener() {
97 return new FocusListener() {
98 private static final long serialVersionUID
= 1L;
101 public void focusLost(FocusEvent event
) {
105 public void focusGained(FocusEvent event
) {
110 protected Composite
findPage(Composite composite
) {
111 if (composite
instanceof ScrolledPage
) {
112 return (ScrolledPage
) composite
;
114 if (composite
.getParent() == null)
116 return findPage(composite
.getParent());
121 public void update(Observable o
, Object arg
) {
122 if (o
== cmsEditable
)
123 editingStateChanged(cmsEditable
);
126 /** To be overridden in order to provide the actual refresh */
127 protected void refresh(Control control
) throws RepositoryException
{
130 /** To be overridden.Save the edited part. */
131 protected void save(EditablePart part
) throws RepositoryException
{
134 /** Prepare the edited part */
135 protected void prepare(EditablePart part
, Object caretPosition
) {
138 /** Notified when the editing state changed. Does nothing, to be overridden */
139 protected void editingStateChanged(CmsEditable cmsEditable
) {
143 public void refresh() {
145 if (cmsEditable
.canEdit() && !readOnly
)
146 mouseListener
= createMouseListener();
148 mouseListener
= null;
149 refresh(getControl());
150 layout(getControl());
151 } catch (RepositoryException e
) {
152 throw new CmsException("Cannot refresh", e
);
157 public void setSelection(ISelection selection
, boolean reveal
) {
158 this.selection
= selection
;
161 protected void updateContent(EditablePart part
) throws RepositoryException
{
165 protected void edit(EditablePart part
, Object caretPosition
) {
170 if (edited
!= null && edited
!= part
) {
171 EditablePart previouslyEdited
= edited
;
174 } catch (Exception e
) {
175 notifyEditionException(e
);
176 edit(previouslyEdited
, caretPosition
);
183 prepare(part
, caretPosition
);
185 layout(part
.getControl());
186 } catch (RepositoryException e
) {
187 throw new CmsException("Cannot edit " + part
, e
);
191 private void stopEditing(Boolean save
) throws RepositoryException
{
192 if (edited
instanceof Widget
&& ((Widget
) edited
).isDisposed()) {
197 assert edited
!= null;
198 if (edited
== null) {
199 if (log
.isTraceEnabled())
200 log
.warn("Told to stop editing while not editing anything");
207 edited
.stopEditing();
208 updateContent(edited
);
209 layout(((EditablePart
) edited
).getControl());
213 // METHODS AVAILABLE TO EXTENDING CLASSES
214 protected void saveEdit() {
218 } catch (RepositoryException e
) {
219 throw new CmsException("Cannot stop editing", e
);
223 protected void cancelEdit() {
227 } catch (RepositoryException e
) {
228 throw new CmsException("Cannot cancel editing", e
);
232 /** Layout this controls from the related base page. */
233 public void layout(Control
... controls
) {
234 page
.layout(controls
);
238 * Find the first {@link EditablePart} in the parents hierarchy of this
241 protected EditablePart
findDataParent(Control parent
) {
242 if (parent
instanceof EditablePart
) {
243 return (EditablePart
) parent
;
245 if (parent
.getParent() != null)
246 return findDataParent(parent
.getParent());
248 throw new CmsException("No data parent found");
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");
260 /** Persist all changes. */
261 protected void persistChanges(Session session
) throws RepositoryException
{
263 session
.refresh(false);
264 // TODO notify that changes have been persisted
267 /** Convenience method using a Node in order to save the underlying session. */
268 protected void persistChanges(Node anyNode
) throws RepositoryException
{
269 persistChanges(anyNode
.getSession());
272 /** Notify edition exception */
273 protected void notifyEditionException(Throwable e
) {
274 Throwable eToLog
= e
;
275 if (e
instanceof IllegalArgumentException
)
276 if (e
.getCause() instanceof SAXParseException
)
277 eToLog
= e
.getCause();
278 log
.error(eToLog
.getMessage());
279 if (log
.isTraceEnabled())
280 log
.trace("Full stack of " + eToLog
.getMessage(), e
);
281 // TODO Light error notification popup
285 public boolean isReadOnly() {
289 protected EditablePart
getEdited() {
293 public MouseListener
getMouseListener() {
294 return mouseListener
;
297 public FocusListener
getFocusListener() {
298 return focusListener
;
301 public CmsEditable
getCmsEditable() {
306 public ISelection
getSelection() {