1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.editor;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.util.ArrayList;
17 import java.util.List;
18
19 import org.eclipse.core.runtime.IPath;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.jface.dialogs.MessageDialog;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.events.SelectionAdapter;
25 import org.eclipse.swt.events.SelectionEvent;
26 import org.eclipse.swt.widgets.Menu;
27 import org.eclipse.swt.widgets.MenuItem;
28 import org.eclipse.ui.IEditorInput;
29 import org.eclipse.ui.IEditorSite;
30 import org.eclipse.ui.PartInitException;
31 import org.eclipse.ui.part.MultiPageEditorPart;
32 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
33
34 import sk.baka.ikslibs.interval.DOMIntervalSet;
35 import sk.uniba.euromath.EuroMath;
36 import sk.uniba.euromath.document.XMLAccess;
37 import sk.uniba.euromath.editor.lang.ErrorMessages;
38 import sk.uniba.euromath.editor.lang.Messages;
39 import sk.uniba.euromath.plugin.views.outline.XMLOutlinePage;
40
41 /***
42 * <h6>Is an IEditorPart suporting views</h6>
43 * <p>
44 * For every opening file = IEditorInput new instance is created by workbench
45 * (or by us, somewhere in rcp, openfilewizard) and view for file is added.
46 * </p>
47 * <p>
48 * For opened file new view can be opened by invoking ViewPopupMenu. Navigation
49 * between views is provided by pages localized at left-bottom of editor
50 * control, there can be also invoked ViewPopupMenu.
51 * </p>
52 * <h6>View is presented by EditorSite located on page within this editor.</h6>
53 * <p>
54 * View is defined by selecting XSLT transformation, stylesheet. So views
55 * differs by XSLT transformation used on common input with other views - edited
56 * document. View implements IEditorPart, is a true compound editor and must be
57 * EditorSite or extended.
58 * </p>
59 *
60 * @author Tomáš Studva 31.7.2005
61 */
62 public class MultiViewXMLEditor extends MultiPageEditorPart {
63
64 /***
65 * Holds IViewListeners.
66 */
67 private final List<IViewListener> listeners = new ArrayList<IViewListener>();
68
69 /***
70 * Holds resource manipulator.
71 */
72 private XMLResourceManipulator resourceManipulator;
73
74 /***
75 * With this id is registered as IEditorPart.
76 */
77 public static final String ID = "sk.uniba.euromath.editor.MultiViewXMLEditor";
78
79 /***
80 * Adds new EditorSite as new view and activate it.
81 */
82 private void addNewView() {
83 try {
84 EditorSite view = new EditorSite(this);
85 int pageIndex = addPage(view, getEditorInput());
86 setActivePage(pageIndex);
87 setPageText(pageIndex, Messages
88 .getString("MultiViewXMLEditor.ViewCaption") + pageIndex);
89 fireViewAdded(view);
90 } catch (PartInitException e) {
91 EuroMath.log(IStatus.ERROR, 0,
92 "Error during creation of inner editor", e);
93 MessageDialog
94 .openError(
95 getEditorSite().getWorkbenchWindow().getShell(),
96 ErrorMessages.getString("Error"), Messages.getString("MultiViewXMLEditor.EditorInitializationError")
97 + e.getLocalizedMessage());
98 return;
99 }
100 }
101
102 /***
103 * Fires viewAdded event to listeners.
104 *
105 * @param view
106 * which was added
107 */
108 private void fireViewAdded(EditorSite view) {
109 for (IViewListener listener : this.listeners) {
110 listener.viewAdded(view);
111 }
112 }
113
114 /***
115 * Constructor.
116 */
117 public MultiViewXMLEditor() {
118 super();
119 }
120
121 @Override
122 public Object getAdapter(Class adapter) {
123 if (adapter.equals(IContentOutlinePage.class))
124 return getContentOutlinePage();
125
126 return super.getAdapter(adapter);
127 }
128
129 /***
130 * Returns content outline.
131 *
132 * @return content outline
133 */
134 private XMLOutlinePage getContentOutlinePage() {
135 if (getActiveView() != null)
136 return getActiveView().getOutlinePage();
137 return null;
138 }
139
140 /***
141 * Tests if outline is created/ready.
142 *
143 * @return true, if outline is avalaible
144 */
145 public boolean outlineAvailable() {
146 return (getContentOutlinePage() != null);
147 }
148
149 @Override
150 public void init(IEditorSite site, IEditorInput input)
151 throws PartInitException {
152 super.init(site, input);
153
154 if (getEditorInput() == null) {
155 throw new PartInitException("null input");
156 }
157 this.resourceManipulator = new XMLResourceManipulator(getEditorInput());
158 try {
159 getResourceManipulator().load();
160 } catch (Exception ex) {
161 MessageDialog.openError(getEditorSite().getShell(), Messages
162 .getString("ERROR"),
163 Messages.getString("MultiViewXMLEditor.LoadingDocumentError")
164 + ex.getLocalizedMessage());
165 PartInitException e = new PartInitException(
166 "Data loading failed. Opening file is probably not xml valid/wellformed file.", ex);
167 throw e;
168 }
169 } /***
170 * Creates one view = page for document which was just opened or
171 * created.
172 */
173 @Override
174 protected void createPages() {
175 addNewView();
176 setPartName(getEditorInput().getName());
177 setContentDescription(getEditorInput().getToolTipText());
178 getContainer().setMenu(createViewPopupMenu());
179 }
180
181 /***
182 * Checks if input is correct.
183 */
184 @Override
185 protected void setInput(IEditorInput input) {
186
187
188 if ((input instanceof LocalFilesystemEditorInput)
189 || (input instanceof NewDocumentEditorInput)) {
190 super.setInput(input);
191 return;
192 }
193
194
195
196 Object ifile;
197 try {
198 final Method m = input.getClass().getDeclaredMethod("getFile",
199 new Class[] {});
200 ifile = m.invoke(input, (Object[]) null);
201 if (ifile == null)
202 throw new NullPointerException("file is null");
203 } catch (NoSuchMethodException ex) {
204 throw new IllegalArgumentException(
205 "input does not define getFile() method", ex);
206 } catch (InvocationTargetException ex) {
207 throw new RuntimeException("getFile() has thrown an exception", ex);
208 } catch (IllegalAccessException ex) {
209 throw new IllegalArgumentException(ex);
210 }
211
212
213 try {
214 Method m;
215 try {
216 m = ifile.getClass()
217 .getMethod("getRawLocation", new Class[] {});
218 } catch (NoSuchMethodException ex) {
219 m = ifile.getClass().getMethod("getFullPath",
220 new Class[] {});
221 }
222 final IPath path = (IPath) m.invoke(ifile, (Object[]) null);
223 if (path == null)
224 throw new NullPointerException("path is null");
225 super.setInput(new LocalFilesystemEditorInput(path, input));
226 } catch (NoSuchMethodException ex) {
227 throw new IllegalArgumentException(
228 "IFile does not define getFullPath() nor getRawLocation() method", ex);
229 } catch (InvocationTargetException ex) {
230 throw new RuntimeException(
231 "getFullPath() has thrown an exception", ex);
232 } catch (IllegalAccessException ex) {
233 throw new IllegalArgumentException(ex);
234 }
235 }
236
237 /***
238 * Creates popup menu for opening new view and closing opened.
239 *
240 * @return menu with open and close view actions.
241 */
242 private Menu createViewPopupMenu() {
243 Menu result = new Menu(getContainer());
244
245 MenuItem item;
246
247 item = new MenuItem(result, SWT.NONE);
248 item.setText(Messages
249 .getString("MultiViewXMLEditor.OpenPresentationActionText"));
250 item.setAccelerator(SWT.CONTROL | SWT.ALT | 'N');
251 item.addSelectionListener(new SelectionAdapter() {
252 @Override
253 public void widgetSelected(SelectionEvent e) {
254 addNewView();
255 }
256 });
257
258 item = new MenuItem(result, SWT.NONE);
259 item.setText(Messages
260 .getString("MultiViewXMLEditor.ClosePresentationActionText"));
261 item.setAccelerator(SWT.CONTROL | SWT.ALT | SWT.F4);
262 item.addSelectionListener(new SelectionAdapter() {
263 @Override
264 public void widgetSelected(SelectionEvent e) {
265 closeActiveView();
266 }
267 });
268 return result;
269 }
270
271 /***
272 * Closes active view.
273 *
274 */
275 public void closeActiveView() {
276 if (getPageCount() == 1)
277 return;
278 if (getActiveView() != null) {
279 removePage(getActivePage());
280 }
281 }
282
283 /***
284 * Return active view.
285 *
286 * @return EditorSite
287 */
288 public EditorSite getActiveView() {
289 return (EditorSite) getActiveEditor();
290 }
291
292 /***
293 * Returns the document instance.
294 *
295 * @return the document instance.
296 */
297 public final XMLAccess getXMLAccess() {
298 return getResourceManipulator().getXmlAccess();
299 }
300
301 /***
302 * When view is activated, selection is synchronized with outline.
303 */
304 @Override
305 protected void pageChange(int newPageIndex) {
306 super.pageChange(newPageIndex);
307 if (outlineAvailable()) {
308 DOMIntervalSet sel = getContentOutlinePage().getDOMSelection();
309 getActiveView().setSelection(sel);
310 }
311 }
312
313 @Override
314 public void doSave(IProgressMonitor monitor) {
315 if (getPageCount() > 0)
316 getActiveView().doSave(monitor);
317 }
318
319 @Override
320 public void doSaveAs() {
321 if (getPageCount() > 0)
322 getActiveView().doSaveAs();
323 }
324
325 @Override
326 public boolean isSaveAsAllowed() {
327 return (getPageCount() > 0) && getActiveView().isSaveAsAllowed();
328 }
329
330 /***
331 * Adds view listener.
332 *
333 * @param listener
334 * to add
335 */
336 public void addViewListener(IViewListener listener) {
337 this.listeners.add(listener);
338 }
339
340 /***
341 * Removes view listener.
342 *
343 * @param listener
344 * to remove
345 */
346 public void removeViewListener(IViewListener listener) {
347 this.listeners.remove(listener);
348 }
349
350
351
352
353
354
355
356
357
358
359 /***
360 * @return Returns the resourceManipulator.
361 */
362 public XMLResourceManipulator getResourceManipulator() {
363 return this.resourceManipulator;
364 }
365
366 }