tmf.ui: Introduce TmfFileDialogFactory
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.ui / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / ui / handler / ManageXMLAnalysisDialog.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.handler;
10
11 import java.io.File;
12 import java.util.ArrayList;
13 import java.util.Map;
14
15 import org.eclipse.core.filesystem.EFS;
16 import org.eclipse.core.resources.IProject;
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.core.resources.ResourcesPlugin;
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IPath;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.Path;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.eclipse.jface.dialogs.Dialog;
25 import org.eclipse.jface.dialogs.IDialogConstants;
26 import org.eclipse.jface.dialogs.MessageDialog;
27 import org.eclipse.jface.viewers.ISelection;
28 import org.eclipse.jface.viewers.ISelectionProvider;
29 import org.eclipse.jface.viewers.TreeSelection;
30 import org.eclipse.osgi.util.NLS;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.events.SelectionEvent;
33 import org.eclipse.swt.events.SelectionListener;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Control;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.FileDialog;
41 import org.eclipse.swt.widgets.Label;
42 import org.eclipse.swt.widgets.List;
43 import org.eclipse.swt.widgets.Shell;
44 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource;
45 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
46 import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.Activator;
47 import org.eclipse.tracecompass.tmf.ui.dialog.TmfFileDialogFactory;
48 import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement;
49 import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
50 import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectModelElement;
51 import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry;
52 import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
53 import org.eclipse.ui.IEditorPart;
54 import org.eclipse.ui.IPropertyListener;
55 import org.eclipse.ui.ISaveablePart;
56 import org.eclipse.ui.IWorkbenchPage;
57 import org.eclipse.ui.IWorkbenchPart;
58 import org.eclipse.ui.IWorkbenchWindow;
59 import org.eclipse.ui.PlatformUI;
60 import org.eclipse.ui.ide.IDE;
61
62 /**
63 * Dialog for XML analysis files
64 *
65 * @author Jean-Christian Kouame
66 */
67 public class ManageXMLAnalysisDialog extends Dialog {
68
69 private final String XML_FILTER_EXTENSION = "*.xml"; //$NON-NLS-1$
70 private List fAnalysesList;
71 private Button fDeleteButton;
72 private Button fImportButton;
73 private Button fExportButton;
74 private Button fEditButton;
75 private Label fInvalidFileLabel;
76
77 /**
78 * Constructor
79 *
80 * @param parent
81 * Parent shell of this dialog
82 */
83 public ManageXMLAnalysisDialog(Shell parent) {
84 super(parent);
85 setShellStyle(SWT.RESIZE | SWT.MAX | getShellStyle());
86 }
87
88 @Override
89 protected Control createDialogArea(Composite parent) {
90 getShell().setText(Messages.ManageXMLAnalysisDialog_ManageXmlAnalysesFiles);
91
92 Composite composite = (Composite) super.createDialogArea(parent);
93 composite.setLayout(new GridLayout(2, false));
94
95 Composite listContainer = new Composite(composite, SWT.NONE);
96 listContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
97 GridLayout lcgl = new GridLayout();
98 lcgl.marginHeight = 0;
99 lcgl.marginWidth = 0;
100 listContainer.setLayout(lcgl);
101
102 fAnalysesList = new List(listContainer, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
103 fAnalysesList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
104 fAnalysesList.addSelectionListener(new SelectionListener() {
105 @Override
106 public void widgetDefaultSelected(SelectionEvent e) {
107 }
108
109 @Override
110 public void widgetSelected(SelectionEvent e) {
111 if (fAnalysesList.getSelectionCount() == 0) {
112 fDeleteButton.setEnabled(false);
113 fExportButton.setEnabled(false);
114 fEditButton.setEnabled(false);
115 } else {
116 fDeleteButton.setEnabled(true);
117 fExportButton.setEnabled(true);
118 fEditButton.setEnabled(true);
119 handleSelection(fAnalysesList.getSelection());
120 }
121 }
122 });
123
124 fInvalidFileLabel = new Label(listContainer, SWT.ICON_ERROR);
125 fInvalidFileLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
126 fInvalidFileLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_RED));
127 fInvalidFileLabel.setText(Messages.ManageXMLAnalysisDialog_FileValidationError);
128 fInvalidFileLabel.setVisible(false);
129
130 Composite buttonContainer = new Composite(composite, SWT.NULL);
131 buttonContainer.setLayout(new GridLayout());
132 buttonContainer.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));
133
134 fImportButton = new Button(buttonContainer, SWT.PUSH);
135 fImportButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
136 fImportButton.setText(Messages.ManageXMLAnalysisDialog_Import);
137 fImportButton.addSelectionListener(new SelectionListener() {
138 @Override
139 public void widgetDefaultSelected(SelectionEvent e) {
140 }
141
142 @Override
143 public void widgetSelected(SelectionEvent e) {
144 importAnalysis();
145 }
146 });
147
148 fExportButton = new Button(buttonContainer, SWT.PUSH);
149 fExportButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
150 fExportButton.setText(Messages.ManageXMLAnalysisDialog_Export);
151 fExportButton.setEnabled(false);
152 fExportButton.addSelectionListener(new SelectionListener() {
153 @Override
154 public void widgetDefaultSelected(SelectionEvent e) {
155 }
156
157 @Override
158 public void widgetSelected(SelectionEvent e) {
159 exportAnalysis();
160 }
161 });
162
163 fEditButton = new Button(buttonContainer, SWT.PUSH);
164 fEditButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
165 fEditButton.setText(Messages.ManageXMLAnalysisDialog_Edit);
166 fEditButton.setEnabled(false);
167 fEditButton.addSelectionListener(new SelectionListener() {
168 @Override
169 public void widgetDefaultSelected(SelectionEvent e) {
170 }
171
172 @Override
173 public void widgetSelected(SelectionEvent e) {
174 editAnalysis();
175 }
176
177 });
178
179 fDeleteButton = new Button(buttonContainer, SWT.PUSH);
180 fDeleteButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
181 fDeleteButton.setText(Messages.ManageXMLAnalysisDialog_Delete);
182 fDeleteButton.setEnabled(false);
183 fDeleteButton.addSelectionListener(new SelectionListener() {
184 @Override
185 public void widgetDefaultSelected(SelectionEvent e) {
186 }
187
188 @Override
189 public void widgetSelected(SelectionEvent e) {
190 deleteAnalysis();
191 }
192
193 });
194
195 fillAnalysesList();
196
197 getShell().setMinimumSize(300, 275);
198 return composite;
199 }
200
201 private void handleSelection(String[] selection) {
202 Map<String, File> files = XmlUtils.listFiles();
203 File file = files.get(createXmlFileString(selection[0]));
204 if (file != null && XmlUtils.xmlValidate(file).isOK()) {
205 fInvalidFileLabel.setVisible(false);
206 } else {
207 fInvalidFileLabel.setVisible(true);
208 }
209 }
210
211 private static void deleteSupplementaryFile(String xmlFile) {
212 // 1. Look for all traces that have this analysis
213 // 2. Close them if they are opened.
214 // 3. Delete the related supplementary files
215 java.util.List<IResource> resourceToDelete = new ArrayList<>();
216 java.util.List<String> ids = XmlUtils.getAnalysisIdsFromFile(xmlFile);
217 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(0);
218 for (IProject project : projects) {
219 TmfProjectElement pElement = TmfProjectRegistry.getProject(project);
220 if (pElement != null) {
221 java.util.List<TmfCommonProjectElement> tElements = new ArrayList<>();
222 tElements.addAll(pElement.getTracesFolder().getTraces());
223 tElements.addAll(pElement.getExperimentsFolder().getExperiments());
224 for (TmfCommonProjectElement tElement : tElements) {
225 boolean closeEditor = false;
226 for (IResource resource : tElement.getSupplementaryResources()) {
227 for (String id : ids) {
228 if (resource.getName().startsWith(id)) {
229 resourceToDelete.add(resource);
230 closeEditor = true;
231 }
232 }
233 }
234 if (closeEditor) {
235 tElement.closeEditors();
236 }
237 }
238 }
239 }
240 for (IResource resource : resourceToDelete) {
241 try {
242 resource.delete(false, null);
243 } catch (CoreException e) {
244 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteFileError, resource.getName()));
245 }
246 }
247 }
248
249 @Override
250 protected void createButtonsForButtonBar(Composite parent) {
251 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.CLOSE_LABEL, false);
252 }
253
254 private void fillAnalysesList() {
255 fAnalysesList.removeAll();
256 Map<String, File> files = XmlUtils.listFiles();
257 for (String file : files.keySet()) {
258 // Remove the extension from the file path. The extension is at the
259 // end of the file path
260 IPath path = new Path(file);
261 fAnalysesList.add(path.removeFileExtension().toString());
262 }
263 fDeleteButton.setEnabled(false);
264 fExportButton.setEnabled(false);
265 }
266
267 private void importAnalysis() {
268 FileDialog dialog = TmfFileDialogFactory.create(Display.getCurrent().getActiveShell(), SWT.OPEN);
269 dialog.setText(Messages.ManageXMLAnalysisDialog_SelectFileImport);
270 dialog.setFilterNames(new String[] { Messages.ManageXMLAnalysisDialog_ImportXmlFile + " (*.xml)" }); //$NON-NLS-1$
271 dialog.setFilterExtensions(new String[] { XML_FILTER_EXTENSION });
272 String path = dialog.open();
273 if (path != null) {
274 File file = new File(path);
275 if (loadXmlFile(file, true)) {
276 fillAnalysesList();
277 }
278 }
279 }
280
281 private static boolean loadXmlFile(File file, boolean addFile) {
282 IStatus status = XmlUtils.xmlValidate(file);
283 if (status.isOK()) {
284 deleteSupplementaryFile(file.getName());
285 if (addFile) {
286 status = XmlUtils.addXmlFile(file);
287 }
288 if (status.isOK()) {
289 XmlAnalysisModuleSource.notifyModuleChange();
290 /*
291 * FIXME: It refreshes the list of analysis under a trace,
292 * but since modules are instantiated when the trace opens,
293 * the changes won't apply to an opened trace, it needs to
294 * be closed then reopened
295 */
296 refreshProject();
297 return true;
298 }
299
300 Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed);
301 TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage());
302 } else {
303 Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed);
304 TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage());
305 }
306 return false;
307 }
308
309 private void exportAnalysis() {
310 FileDialog dialog = TmfFileDialogFactory.create(Display.getCurrent().getActiveShell(), SWT.SAVE);
311 dialog.setText(NLS.bind(Messages.ManageXMLAnalysisDialog_SelectFileExport, fAnalysesList.getSelection()[0]));
312 dialog.setFilterExtensions(new String[] { XML_FILTER_EXTENSION, "*" }); //$NON-NLS-1$
313 String selection = createXmlFileString(fAnalysesList.getSelection()[0]);
314 dialog.setFileName(selection);
315 String path = dialog.open();
316 if (path != null) {
317 if (!XmlUtils.exportXmlFile(selection, path).isOK()) {
318 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToExport, selection));
319 }
320 }
321 }
322
323 private void editAnalysis() {
324 String selection = createXmlFileString(fAnalysesList.getSelection()[0]);
325 @Nullable
326 File file = XmlUtils.listFiles().get(selection);
327 if (file == null) {
328 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
329 TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
330 return;
331 }
332 try {
333 IEditorPart editorPart = IDE.openEditorOnFileStore(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), EFS.getStore(file.toURI()));
334 editorPart.addPropertyListener(new IPropertyListener() {
335 @Override
336 public void propertyChanged(Object source, int propId) {
337 if (ISaveablePart.PROP_DIRTY == propId) {
338 if (!editorPart.isDirty()) {
339 // Editor is not dirty anymore, i.e. it was saved
340 loadXmlFile(file, false);
341 }
342 }
343 }
344 });
345 close();
346 } catch (CoreException e) {
347 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
348 TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), e.getMessage());
349 }
350 }
351
352 private void deleteAnalysis() {
353 boolean confirm = MessageDialog.openQuestion(
354 getShell(),
355 Messages.ManageXMLAnalysisDialog_DeleteFile,
356 NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteConfirmation, fAnalysesList.getSelection()[0]));
357 if (confirm) {
358 String selection = createXmlFileString(fAnalysesList.getSelection()[0]);
359 deleteSupplementaryFile(selection);
360 XmlUtils.deleteFile(selection);
361 fillAnalysesList();
362 fInvalidFileLabel.setVisible(false);
363 XmlAnalysisModuleSource.notifyModuleChange();
364 /*
365 * FIXME: It refreshes the list of analysis under a trace, but since
366 * modules are instantiated when the trace opens, the changes won't
367 * apply to an opened trace, it needs to be closed then reopened
368 */
369 refreshProject();
370 }
371 }
372
373 /**
374 * Refresh the selected project with the new XML file import
375 */
376 private static void refreshProject() {
377 // Check if we are closing down
378 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
379 if (window == null) {
380 return;
381 }
382
383 // Get the selection
384 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
385 IWorkbenchPart part = page.getActivePart();
386 if (part == null) {
387 return;
388 }
389 ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
390 if (selectionProvider == null) {
391 return;
392 }
393 ISelection selection = selectionProvider.getSelection();
394
395 if (selection instanceof TreeSelection) {
396 TreeSelection sel = (TreeSelection) selection;
397 // There should be only one item selected as per the plugin.xml
398 Object element = sel.getFirstElement();
399 if (element instanceof TmfProjectModelElement) {
400 ((TmfProjectModelElement) element).getProject().refresh();
401 }
402 }
403 }
404
405 private static String createXmlFileString(String baseName) {
406 IPath path = new Path(baseName).addFileExtension(XmlUtils.XML_EXTENSION);
407 return path.toString();
408 }
409 }
This page took 0.039827 seconds and 5 git commands to generate.