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 PartInitException e = new PartInitException(
162 "Data loading failed.", ex);
163 EuroMath
164 .log(
165 IStatus.ERROR,
166 0,
167 "Error loading document. Opening file is probably not xml valid/wellformed file.", e);
168 MessageDialog.openError(getEditorSite().getShell(), Messages
169 .getString("ERROR"),
170 Messages.getString("MultiViewXMLEditor.LoadingDocumentError")
171 + ex.getLocalizedMessage());
172 }
173 } /***
174 * Creates one view = page for document which was just opened or
175 * created.
176 */
177 @Override
178 protected void createPages() {
179 addNewView();
180 setPartName(getEditorInput().getName());
181 setContentDescription(getEditorInput().getToolTipText());
182 getContainer().setMenu(createViewPopupMenu());
183 }
184
185 /***
186 * Checks if input is correct.
187 */
188 @Override
189 protected void setInput(IEditorInput input) {
190
191
192 if ((input instanceof LocalFilesystemEditorInput)
193 || (input instanceof NewDocumentEditorInput)) {
194 super.setInput(input);
195 return;
196 }
197
198
199
200 Object ifile;
201 try {
202 final Method m = input.getClass().getDeclaredMethod("getFile",
203 new Class[] {});
204 ifile = m.invoke(input, (Object[]) null);
205 if (ifile == null)
206 throw new NullPointerException("file is null");
207 } catch (NoSuchMethodException ex) {
208 throw new IllegalArgumentException(
209 "input does not define getFile() method", ex);
210 } catch (InvocationTargetException ex) {
211 throw new RuntimeException("getFile() has thrown an exception", ex);
212 } catch (IllegalAccessException ex) {
213 throw new IllegalArgumentException(ex);
214 }
215
216
217 try {
218 Method m;
219 try {
220 m = ifile.getClass()
221 .getMethod("getRawLocation", new Class[] {});
222 } catch (NoSuchMethodException ex) {
223 m = ifile.getClass().getMethod("getFullPath",
224 new Class[] {});
225 }
226 final IPath path = (IPath) m.invoke(ifile, (Object[]) null);
227 if (path == null)
228 throw new NullPointerException("path is null");
229 super.setInput(new LocalFilesystemEditorInput(path, input));
230 } catch (NoSuchMethodException ex) {
231 throw new IllegalArgumentException(
232 "IFile does not define getFullPath() nor getRawLocation() method", ex);
233 } catch (InvocationTargetException ex) {
234 throw new RuntimeException(
235 "getFullPath() has thrown an exception", ex);
236 } catch (IllegalAccessException ex) {
237 throw new IllegalArgumentException(ex);
238 }
239 }
240
241 /***
242 * Creates popup menu for opening new view and closing opened.
243 *
244 * @return menu with open and close view actions.
245 */
246 private Menu createViewPopupMenu() {
247 Menu result = new Menu(getContainer());
248
249 MenuItem item;
250
251 item = new MenuItem(result, SWT.NONE);
252 item.setText(Messages
253 .getString("MultiViewXMLEditor.OpenPresentationActionText"));
254 item.setAccelerator(SWT.CONTROL | SWT.ALT | 'N');
255 item.addSelectionListener(new SelectionAdapter() {
256 @Override
257 public void widgetSelected(SelectionEvent e) {
258 addNewView();
259 }
260 });
261
262 item = new MenuItem(result, SWT.NONE);
263 item.setText(Messages
264 .getString("MultiViewXMLEditor.ClosePresentationActionText"));
265 item.setAccelerator(SWT.CONTROL | SWT.ALT | SWT.F4);
266 item.addSelectionListener(new SelectionAdapter() {
267 @Override
268 public void widgetSelected(SelectionEvent e) {
269 closeActiveView();
270 }
271 });
272 return result;
273 }
274
275 /***
276 * Closes active view.
277 *
278 */
279 public void closeActiveView() {
280 if (getPageCount() == 1)
281 return;
282 if (getActiveView() != null) {
283 removePage(getActivePage());
284 }
285 }
286
287 /***
288 * Return active view.
289 *
290 * @return EditorSite
291 */
292 public EditorSite getActiveView() {
293 return (EditorSite) getActiveEditor();
294 }
295
296 /***
297 * Returns the document instance.
298 *
299 * @return the document instance.
300 */
301 public final XMLAccess getXMLAccess() {
302 return getResourceManipulator().getXmlAccess();
303 }
304
305 /***
306 * When view is activated, selection is synchronized with outline.
307 */
308 @Override
309 protected void pageChange(int newPageIndex) {
310 super.pageChange(newPageIndex);
311 if (outlineAvailable()) {
312 DOMIntervalSet sel = getContentOutlinePage().getDOMSelection();
313 getActiveView().setSelection(sel);
314 }
315 }
316
317 @Override
318 public void doSave(IProgressMonitor monitor) {
319 if (getPageCount() > 0)
320 getActiveView().doSave(monitor);
321 }
322
323 @Override
324 public void doSaveAs() {
325 if (getPageCount() > 0)
326 getActiveView().doSaveAs();
327 }
328
329 @Override
330 public boolean isSaveAsAllowed() {
331 return (getPageCount() > 0) && getActiveView().isSaveAsAllowed();
332 }
333
334 /***
335 * Adds view listener.
336 *
337 * @param listener
338 * to add
339 */
340 public void addViewListener(IViewListener listener) {
341 this.listeners.add(listener);
342 }
343
344 /***
345 * Removes view listener.
346 *
347 * @param listener
348 * to remove
349 */
350 public void removeViewListener(IViewListener listener) {
351 this.listeners.remove(listener);
352 }
353
354
355
356
357
358
359
360
361
362
363 /***
364 * @return Returns the resourceManipulator.
365 */
366 public XMLResourceManipulator getResourceManipulator() {
367 return this.resourceManipulator;
368 }
369
370 }