Revision 2274

tmp/org.txm.rcp/src/main/java/org/txm/rcp/editors/TXMEditor.java (revision 2274)
89 89
import org.txm.utils.logger.Log;
90 90

  
91 91
/**
92
 * Base TXM result <code>EditorPart</code> composed of 
92
 * Base TXM result <code>EditorPart</code> composed of
93 93
 * - a main toolbar at the top
94 94
 * - display area
95 95
 * - a bottom toolbar at the bottom of the editor
......
99 99
 *
100 100
 */
101 101
public abstract class TXMEditor<T extends TXMResult> extends EditorPart implements ITXMResultEditor<T> {
102

  
102
	
103 103
	/**
104 104
	 * ID to use in plugin.xml to contribute to the top toolbar.
105 105
	 */
106 106
	public final static String TOP_TOOLBAR_ID = "TXMEditorTopToolBar"; //$NON-NLS-1$
107
	
107 108
	public final static String BOTTOM_TOOLBAR_ID = "TXMEditorBottomToolBar"; //$NON-NLS-1$
108

  
109
	//FIXME: SJ: bad idea to use the ID as title, need to change the system
109
	
110
	// FIXME: SJ: bad idea to use the ID as title, need to change the system
110 111
	public final static String COMPUTING_PARAMETERS_GROUP_ID = TXMUIMessages.parameters;
111

  
112
	
112 113
	/**
113 114
	 * ID defined in plugin.xml for the compute button contribution.
114 115
	 */
115 116
	public final static String TOP_TOOLBAR_COMPUTE_BUTTON_ID = "compute"; //$NON-NLS-1$
116

  
117
	
117 118
	/**
118 119
	 * The editor main tool bar, positioned at the top of the editor.
119 120
	 */
120 121
	protected TXMEditorToolBar topToolBar;
121

  
122
	
122 123
	/**
123 124
	 * The main panel containing the displayed result
124 125
	 */
125 126
	private GLComposite resultArea;
126

  
127
	
127 128
	/**
128 129
	 * The editor bottom tool bar, positioned at the bottom of the editor.
129 130
	 */
130 131
	protected TXMEditorToolBar bottomToolBar;
131

  
132
	
132 133
	/**
133 134
	 * The parameters groups are added to this composite. contains the sub widgets of the default Top toolbar
134 135
	 */
135 136
	private GLComposite extendedParametersComposite;
136

  
137
	
137 138
	/**
138
	 * Command main parameters that are always visible in the toolbar. 
139
	 * Command main parameters that are always visible in the toolbar.
139 140
	 */
140 141
	protected GLComposite mainParametersComposite;
141

  
142

  
142
	
143
	
143 144
	/**
144 145
	 * Command extended parameters group that can be hidden.
145 146
	 */
146 147
	protected Group extendedParametersGroup;
147

  
148
	
148 149
	/**
149 150
	 * The SWT parent Composite.
150 151
	 */
151 152
	protected Composite parent;
152

  
153
	
153 154
	/**
154 155
	 * contains the default bottom toolbars widget
155 156
	 */
156 157
	protected Composite bottomToolBarContainer;
157

  
158
	
158 159
	/**
159 160
	 * Computing tool item button.
160 161
	 */
161 162
	protected ToolItem computeButton;
162

  
163
	
163 164
	/**
164
	 * To keep track of the parameters used for the last computing and updates only the widgets if a parameter has changed. 
165
	 * To keep track of the parameters used for the last computing and updates only the widgets if a parameter has changed.
165 166
	 */
166 167
	// FIXME: SJ: useless?
167
	//protected HashMap<String, Object> lastComputingParameters = new HashMap<String, Object>();
168

  
168
	// protected HashMap<String, Object> lastComputingParameters = new HashMap<String, Object>();
169
	
169 170
	/**
170 171
	 * contains bottom toolbar subwidgets (installed grouped, etc.)
171 172
	 */
172 173
	private GLComposite bottomSubWidgetsComposite;
174
	
173 175
	private GLComposite firstLineComposite;
176
	
174 177
	private boolean createPartControlDoneSucessfully = true; // FIXME: MD: for now... muahahaha
175

  
178
	
176 179
	/**
177 180
	 * installed extensions
178 181
	 */
179 182
	protected HashSet<TXMEditorExtension<T>> extensions = new HashSet<TXMEditorExtension<T>>();
180

  
181

  
183
	
184
	
182 185
	/**
183 186
	 * Linked editors.
184 187
	 */
185 188
	protected ArrayList<EditorPart> linkedEditors = null;
186

  
189
	
187 190
	/**
188 191
	 * debug purpose variable -> easier to fetch information that the getResult() method
189 192
	 */
190 193
	protected T result;
191

  
194
	
192 195
	/**
193 196
	 * To store or edit the dirty state of the editor from widget.
194 197
	 */
195 198
	protected boolean dirty = true;
199
	
196 200
	private boolean locked = false;
197

  
198

  
201
	
199 202
	/**
200 203
	 * Default constructor.
201 204
	 */
202 205
	public TXMEditor() {
206
		
203 207
		super();
204 208
	}
205

  
209
	
206 210
	/**
207 211
	 * Creates an editor and an editor input containing the specified result.
212
	 * 
208 213
	 * @param result
209 214
	 */
210 215
	public TXMEditor(TXMResult result) {
216
		
211 217
		this(new TXMResultEditorInput<TXMResult>(result));
212 218
	}
213

  
214

  
219
	
215 220
	/**
216 221
	 * Creates an editor with the specified editor input.
222
	 * 
217 223
	 * @param editorInput
218 224
	 */
219 225
	public TXMEditor(TXMResultEditorInput<TXMResult> editorInput) {
220
		this.setInput(editorInput); // FIXME: SJ: the input is defined twice, on time here and one time in init(), need to see if we still need the assignment here in the constructor		
226
		
227
		this.setInput(editorInput); // FIXME: SJ: the input is defined twice, on time here and one time in init(), need to see if we still need the assignment here in the constructor
221 228
	}
222

  
223

  
229
	
224 230
	@Override
225 231
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
232
		
226 233
		this.setSite(site);
227 234
		this.setInput(input);
228 235
		this.result = this.getEditorInput().getResult(); // store result for debug purpose
229
		//		this.result.addResultListener(this);
236
		// this.result.addResultListener(this);
230 237
		// FIXME: see how to use the Adapters and AdapterFactory to define image and title of Editor in the contributing plug-ins
231
		// another way is to use editors extension in plug-ins and redefine icon and name, using this solution the problem is that the name (which is also editor title) can not be dynamic according to the result data
238
		// another way is to use editors extension in plug-ins and redefine icon and name, using this solution the problem is that the name (which is also editor title) can not be dynamic according to
239
		// the result data
232 240
		// so it seems better to use Adapters if it's possible or keep this solution below
233 241
		this.setPartName(input.getName());
234

  
242
		
235 243
		// fetch extensions
236 244
		this.initExtensions();
237 245
	}
238

  
239

  
246
	
240 247
	/**
241 248
	 * Initializes plug-ins extensions.
242 249
	 */
243
	public void initExtensions()	{
244

  
250
	public void initExtensions() {
251
		
245 252
		IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TXMEditorExtension.EXTENSION_ID);
246 253
		if (config.length > 0) {
247

  
254
			
248 255
			for (IConfigurationElement e : config) {
249 256
				try {
250
					Log.finer(" "+e.getName()+" from "+e.getContributor().getName()); //$NON-NLS-1$ //$NON-NLS-2$
257
					Log.finer(" " + e.getName() + " from " + e.getContributor().getName()); //$NON-NLS-1$ //$NON-NLS-2$
251 258
					final Object o = e.createExecutableExtension("class"); //$NON-NLS-1$
252 259
					if (o instanceof TXMEditorExtension) {
253 260
						ISafeRunnable runnable = new ISafeRunnable() {
254

  
261
							
255 262
							@Override
256 263
							public void handleException(Throwable exception) {
257
								Log.severe("Error while installing: "+o+": "+ exception.getLocalizedMessage()); //$NON-NLS-1$ //$NON-NLS-2$
264
								
265
								Log.severe("Error while installing: " + o + ": " + exception.getLocalizedMessage()); //$NON-NLS-1$ //$NON-NLS-2$
258 266
							}
259

  
267
							
260 268
							@Override
261 269
							public void run() throws Exception {
270
								
262 271
								@SuppressWarnings("unchecked")
263 272
								TXMEditorExtension<T> ext = ((TXMEditorExtension<T>) o);
264 273
								TXMResult r = getResult();
265 274
								if (r == null) return;
266

  
275
								
267 276
								if (ext.getTXMResultValidClasses() == null || ext.getTXMResultValidClasses().contains(getResult().getClass())) {
268
									Log.finer("Installing TXMEditorExtension: "+ext.getName()); //$NON-NLS-1$
277
									Log.finer("Installing TXMEditorExtension: " + ext.getName()); //$NON-NLS-1$
269 278
									ext.setEditor(TXMEditor.this);
270 279
									extensions.add(ext);
271 280
								}
......
273 282
						};
274 283
						SafeRunner.run(runnable);
275 284
					}
276
				} catch (Exception ex) {
285
				}
286
				catch (Exception ex) {
277 287
					Log.severe("Exception while installing " + e.getName() + ": " + ex.getLocalizedMessage()); //$NON-NLS-1$ //$NON-NLS-2$
278 288
				}
279 289
			}
280 290
		}
281

  
291
		
282 292
		IPartListener2 pl = new IPartListener2() {
293
			
283 294
			// ... Other methods
284 295
			public void partClosed(IWorkbenchPartReference partRef) {
285

  
286
				//				if (getResult() != null) {
287
				//					getResult().removeResultListener(TXMEditor.this);
288
				//				}
289

  
296
				
297
				// if (getResult() != null) {
298
				// getResult().removeResultListener(TXMEditor.this);
299
				// }
300
				
290 301
				if (partRef.getId().equals(TXMEditor.this.getClass().getName())) { // called after this.doSave()
291

  
292
					//System.out.println("EVENT partClosed");
302
					
303
					// System.out.println("EVENT partClosed");
293 304
					for (TXMEditorExtension<T> extension : extensions) {
294 305
						try {
295 306
							if (extension.isDirty()) {
296 307
								extension.discardChanges();
297 308
							}
298
						} catch (Exception e) {
309
						}
310
						catch (Exception e) {
299 311
							// TODO Auto-generated catch block
300 312
							e.printStackTrace();
301 313
						}
302 314
					}
303 315
				}
304 316
			}
305

  
317
			
306 318
			@Override
307 319
			public void partActivated(IWorkbenchPartReference partRef) {
308
				// FIXME: SJ: why? when opening a new Editor the view will be refreshed twice... 
320
				
321
				// FIXME: SJ: why? when opening a new Editor the view will be refreshed twice...
309 322
				CorporaView.refresh();
310 323
			}
311

  
324
			
312 325
			@Override
313
			public void partBroughtToTop(IWorkbenchPartReference partRef) { }
314

  
326
			public void partBroughtToTop(IWorkbenchPartReference partRef) {}
327
			
315 328
			@Override
316
			public void partDeactivated(IWorkbenchPartReference partRef) { }
317

  
329
			public void partDeactivated(IWorkbenchPartReference partRef) {}
330
			
318 331
			@Override
319
			public void partOpened(IWorkbenchPartReference partRef) { }
320

  
332
			public void partOpened(IWorkbenchPartReference partRef) {}
333
			
321 334
			@Override
322
			public void partHidden(IWorkbenchPartReference partRef) { }
323

  
335
			public void partHidden(IWorkbenchPartReference partRef) {}
336
			
324 337
			@Override
325
			public void partVisible(IWorkbenchPartReference partRef) { }
326

  
338
			public void partVisible(IWorkbenchPartReference partRef) {}
339
			
327 340
			@Override
328
			public void partInputChanged(IWorkbenchPartReference partRef) { }
329

  
341
			public void partInputChanged(IWorkbenchPartReference partRef) {}
342
			
330 343
		};
331 344
		this.getEditorSite().getPage().addPartListener(pl);
332 345
	}
333

  
346
	
334 347
	/**
335 348
	 * the composite containing the main parameters, the top toolbar and eventually other top toolbars
349
	 * 
336 350
	 * @return
337 351
	 */
338 352
	public GLComposite getFirstLineComposite() {
353
		
339 354
		return firstLineComposite;
340 355
	}
341

  
342

  
356
	
357
	
343 358
	/**
344 359
	 * Gets the shell of the parent composite if exists and not disposed otherwise the Display default active shell.
360
	 * 
345 361
	 * @return
346 362
	 */
347 363
	public Shell getShell() {
348
		if (parent !=null && !parent.isDisposed()) {
349
			return parent.getShell();
350
		}
364
		
365
		if (parent != null && !parent.isDisposed()) { return parent.getShell(); }
351 366
		return Display.getDefault().getActiveShell();
352 367
	}
353

  
368
	
354 369
	/**
355
	 *  
370
	 * 
356 371
	 * @return the composite displayed before the toptoolbar, containing the minimal parameters widgets
357 372
	 */
358 373
	public GLComposite getMainParametersComposite() {
374
		
359 375
		return mainParametersComposite;
360 376
	}
361

  
377
	
362 378
	/**
363 379
	 * Creates the default toolbar (empty) and default result area (empty).
364 380
	 * 
365 381
	 */
366 382
	@Override
367 383
	public final void createPartControl(Composite parent) {
368

  
384
		
369 385
		try {
370 386
			this.parent = parent;
371

  
387
			
372 388
			// disable the rendering while creating the widgets
373 389
			// FIXME: SJ: would be very nice to do that to avoid to see the empty tables before the refresh() that fill the UI.
374 390
			// the re-enabling is done in refresh() but the EditionEditor doesn't seem to call refresh() so it breaks it
375
			//this.parent.setRedraw(false);
376

  
391
			// this.parent.setRedraw(false);
392
			
377 393
			// to hide and display the extended parameters composite
378 394
			this.initParentLayout(parent, 1);
379

  
395
			
380 396
			// contains the minimal panels and top toolbars
381 397
			this.firstLineComposite = new GLComposite(parent, SWT.NONE, "Editor first line"); //$NON-NLS-1$
382 398
			this.firstLineComposite.getLayout().numColumns = 2;
383 399
			this.firstLineComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
384

  
400
			
385 401
			this.mainParametersComposite = new GLComposite(this.firstLineComposite, SWT.NONE, "Main parameters area"); //$NON-NLS-1$
386 402
			this.mainParametersComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false));
387 403
			this.mainParametersComposite.getLayout().marginLeft = 5;
388 404
			this.mainParametersComposite.getLayout().horizontalSpacing = 5;
389

  
405
			
390 406
			this.extendedParametersComposite = new GLComposite(parent, SWT.NONE, "Extended parameters area"); //$NON-NLS-1$
391 407
			this.extendedParametersComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
392

  
408
			
393 409
			this.topToolBar = new TXMEditorToolBar(this, this.firstLineComposite, this.extendedParametersComposite, SWT.FLAT | SWT.RIGHT, TOP_TOOLBAR_ID);
394

  
410
			
395 411
			// store the Compute button to access if later, especially from subclasses
396 412
			this.computeButton = topToolBar.getItemByContributionId(TOP_TOOLBAR_COMPUTE_BUTTON_ID);
397 413
			
398
//			this.computeButton = new ToolItem(topToolBar, SWT.PUSH);//.topToolBar.getItemByContributionId(TOP_TOOLBAR_COMPUTE_BUTTON_ID);
399
//			this.computeButton.setImage(IImageKeys.getImage(IImageKeys.START));
400
//			this.computeButton.addSelectionListener(new ComputeSelectionListener(this, true));
414
			// this.computeButton = new ToolItem(topToolBar, SWT.PUSH);//.topToolBar.getItemByContributionId(TOP_TOOLBAR_COMPUTE_BUTTON_ID);
415
			// this.computeButton.setImage(IImageKeys.getImage(IImageKeys.START));
416
			// this.computeButton.addSelectionListener(new ComputeSelectionListener(this, true));
401 417
			
402 418
			// computing parameters components
403 419
			boolean showExtendedParameters = false;
404 420
			// only show the area if the result can not compute and is dirty
405
			// FIXME: to discuss about when hiding or showing the extended parameters 
406
			//			if(!this.getResult().canCompute() && this.getResult().isDirty())	{
407
			//				showExtendedParameters = true;
408
			//			}
409
			this.extendedParametersGroup = this.topToolBar.installGroup(COMPUTING_PARAMETERS_GROUP_ID, TXMUIMessages.showHideCommandParameters, 
421
			// FIXME: to discuss about when hiding or showing the extended parameters
422
			// if(!this.getResult().canCompute() && this.getResult().isDirty()) {
423
			// showExtendedParameters = true;
424
			// }
425
			this.extendedParametersGroup = this.topToolBar.installGroup(COMPUTING_PARAMETERS_GROUP_ID, TXMUIMessages.showHideCommandParameters,
410 426
					"icons/show_computing_parameters.png",  //$NON-NLS-1$
411 427
					"icons/hide_computing_parameters.png",  //$NON-NLS-1$
412 428
					showExtendedParameters);
413

  
429
			
414 430
			// display main area
415 431
			this.resultArea = new GLComposite(parent, SWT.NONE, "Result area"); //$NON-NLS-1$
416 432
			this.resultArea.setLayoutData(new GridData(GridData.FILL_BOTH));
417

  
433
			
418 434
			// create the bottom tool bar
419 435
			this.bottomToolBarContainer = new Composite(parent, SWT.NONE);
420 436
			this.bottomToolBarContainer.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
421 437
			RowLayout rl = new RowLayout(SWT.HORIZONTAL);
422 438
			rl.marginTop = rl.marginHeight = rl.marginWidth = rl.marginBottom = 0;
423
			//rl.center = true;
424
			//rl.justify = true;
439
			// rl.center = true;
440
			// rl.justify = true;
425 441
			this.bottomToolBarContainer.setLayout(rl);
426

  
442
			
427 443
			this.bottomSubWidgetsComposite = new GLComposite(parent, SWT.NONE, "Bottom parameters area"); //$NON-NLS-1$
428
			if (parent.getLayout() instanceof GridLayout)	{
444
			if (parent.getLayout() instanceof GridLayout) {
429 445
				this.bottomSubWidgetsComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
430 446
			}
431

  
447
			
432 448
			this.bottomToolBar = new TXMEditorToolBar(this, this.bottomToolBarContainer, this.bottomSubWidgetsComposite, SWT.FLAT, "bottom"); //$NON-NLS-1$
433

  
449
			
434 450
			this.notifyExtensions("notifyStartOfCreatePartControl"); //$NON-NLS-1$
435 451
			this._createPartControl(); // child editor creates its parameters and displays widgets
436 452
			this.notifyExtensions("notifyEndOfCreatePartControl"); //$NON-NLS-1$
437

  
453
			
438 454
			this.firstLineComposite.pack();
439 455
			this.extendedParametersGroup.pack();
440

  
441

  
456
			
457
			
442 458
			// remove empty toolbar
443
			//TODO SJ: Hack? MD: yeah -> need to find a way to not display the bottom toolbar on Windows instead
459
			// TODO SJ: Hack? MD: yeah -> need to find a way to not display the bottom toolbar on Windows instead
444 460
			if (this.bottomToolBar.getItems().length == 0) {
445 461
				this.bottomToolBar.dispose();
446 462
			}
447

  
463
			
448 464
			// remove empty toolbar
449
			//TODO SJ: Hack? MD: yeah -> need to find a way to not display the bottom toolbar on Windows instead
465
			// TODO SJ: Hack? MD: yeah -> need to find a way to not display the bottom toolbar on Windows instead
450 466
			if (this.topToolBar.getItems().length == 0) {
451 467
				this.topToolBar.dispose();
452 468
			}
453

  
469
			
454 470
			// uninstall parameters group if not used
455 471
			if (this.extendedParametersGroup.getChildren().length == 0) {
456 472
				this.topToolBar.unInstallGroup(COMPUTING_PARAMETERS_GROUP_ID);
457 473
			}
458

  
474
			
459 475
			// FIXME: SJ: this code doesn't work even if we call removeComputeButton()
460 476
			// remove empty first line composite
461
			//			if(this.mainParametersComposite.getChildren().length == 0 && this.topToolBar.isDisposed())	{
462
			//				this.firstLineComposite.dispose();
463
			//			}
464

  
465

  
477
			// if(this.mainParametersComposite.getChildren().length == 0 && this.topToolBar.isDisposed()) {
478
			// this.firstLineComposite.dispose();
479
			// }
480
			
481
			
466 482
			if (this.getResult() != null && this.getResult().isLocked()) {
467 483
				this.setLocked(true);
468 484
			}
469

  
485
			
470 486
			// disable the compute button, it will be re-enable or not later when the UI will check if the editor is dirty or not
471
			//			ToolItem computeButton = this.topToolBar.getItemByContributionId(TOP_TOOLBAR_COMPUTE_BUTTON_ID);
472
			//			if (computeButton != null) {
473
			//				computeButton.setEnabled(false);
474
			//			}
475

  
487
			// ToolItem computeButton = this.topToolBar.getItemByContributionId(TOP_TOOLBAR_COMPUTE_BUTTON_ID);
488
			// if (computeButton != null) {
489
			// computeButton.setEnabled(false);
490
			// }
476 491
			
492
			
477 493
			// dirty state according to the future compute that will be launched by TXMEditor.openEditor()
478
			if(this.getResult().canCompute())	{
494
			if (this.getResult().canCompute()) {
479 495
				this.dirty = false;
480 496
			}
481

  
497
			
482 498
			this.setDirty(this.dirty);
483

  
484
			//this.parent.setRedraw(true);
485

  
486 499
			
500
			// this.parent.setRedraw(true);
501
			
502
			
487 503
		}
488
		catch(Throwable e) {
504
		catch (Throwable e) {
489 505
			Log.severe(TXMCoreMessages.bind("TXMEditor.createPartControl(): can not create the editor for result {0}.", this.getResult())); //$NON-NLS-1$
490 506
			e.printStackTrace();
491 507
			createPartControlDoneSucessfully = false;
492 508
		}
493

  
509
		
494 510
	}
495

  
511
	
496 512
	public void setLocked(boolean b) {
513
		
497 514
		this.locked = b;
498 515
		this.firstLineComposite.setEnabled(!b);
499 516
	}
500

  
517
	
501 518
	public boolean isLocked() {
519
		
502 520
		return locked;
503 521
	}
504

  
522
	
505 523
	/**
506 524
	 * shortcut to call the notify* methods of all extension
507 525
	 * 
......
522 540
	 * @throws NoSuchMethodException
523 541
	 */
524 542
	protected void notifyExtensions(final String step) {
543
		
525 544
		if (!step.startsWith("notify")) return; //$NON-NLS-1$
526

  
545
		
527 546
		ArrayList<TXMEditorExtension<T>> errors = new ArrayList<TXMEditorExtension<T>>();
528 547
		for (final TXMEditorExtension<T> ext : extensions) {
529
			//			ISafeRunnable runnable = new ISafeRunnable() {
530
			//				@Override
531
			//				public void handleException(Throwable exception) {
532
			//					System.out.println("Error while installing: "+ext+": "+ exception.getLocalizedMessage());
533
			//				}
548
			// ISafeRunnable runnable = new ISafeRunnable() {
549
			// @Override
550
			// public void handleException(Throwable exception) {
551
			// System.out.println("Error while installing: "+ext+": "+ exception.getLocalizedMessage());
552
			// }
534 553
			//
535
			//				@Override
536
			//				public void run() throws Exception {
554
			// @Override
555
			// public void run() throws Exception {
537 556
			try {
538 557
				java.lang.reflect.Method method;
539 558
				method = ext.getClass().getMethod(step);
540 559
				if (method != null) {
541 560
					method.invoke(ext);
542
				} else {
561
				}
562
				else {
543 563
					ext.notify(step);
544 564
				}
545
			} catch(Throwable e) {
546
				//errors.add(ext);
547
				Log.warning("Can't notify of "+step+" the \"+ext+\" extension: "+e);
565
			}
566
			catch (Throwable e) {
567
				// errors.add(ext);
568
				Log.warning("Can't notify of " + step + " the \"+ext+\" extension: " + e);
548 569
				Log.printStackTrace(e);
549 570
			}
550
			//				}
551
			//			};
552
			//			SafeRunner.run(runnable);
571
			// }
572
			// };
573
			// SafeRunner.run(runnable);
553 574
		}
554 575
		extensions.removeAll(errors);
555 576
	}
556

  
577
	
557 578
	/**
558 579
	 * Subclasses manual creation method called after TXMEditor.createPartControl is called.
559 580
	 * 
560 581
	 * Use this method to set your own widgets in the minimal parameters area, the top toolbar, parameters group, the result area and the bottom toolbar
561
	 * @throws Exception 
582
	 * 
583
	 * @throws Exception
562 584
	 */
563 585
	public abstract void _createPartControl() throws Exception;
564

  
586
	
565 587
	/**
566 588
	 * Use this method to add widget next to the default Bottom toolbar
567 589
	 * 
568
	 * @return the composite that contains the default Bottom toolbar. 
590
	 * @return the composite that contains the default Bottom toolbar.
569 591
	 */
570 592
	public Composite getBottomToolBarContainer() {
593
		
571 594
		return bottomToolBarContainer;
572 595
	}
573

  
596
	
574 597
	/**
575 598
	 * Gets the top toolbar.
599
	 * 
576 600
	 * @return the default Top toolbar of TXMEditors
577 601
	 */
578 602
	public TXMEditorToolBar getTopToolbar() {
603
		
579 604
		return topToolBar;
580 605
	}
581

  
606
	
582 607
	/**
583 608
	 * Gets the result display area.
584 609
	 * The user must configure its layout.
610
	 * 
585 611
	 * @return
586 612
	 */
587 613
	public GLComposite getResultArea() {
614
		
588 615
		return resultArea;
589 616
	}
590

  
617
	
591 618
	/**
592 619
	 * Gets the bottom toolbar.
620
	 * 
593 621
	 * @return the default bottom toolbar of editors
594 622
	 */
595 623
	public TXMEditorToolBar getBottomToolbar() {
624
		
596 625
		return bottomToolBar;
597 626
	}
598

  
627
	
599 628
	/**
600 629
	 * Creates the parent layout with some configuration to make children composite visible/invisible.
601 630
	 * 
602 631
	 * @param colSpan
603 632
	 */
604
	public void initParentLayout(Composite parent, int colSpan)	{
633
	public void initParentLayout(Composite parent, int colSpan) {
634
		
605 635
		GridLayout gl = GLComposite.createDefaultLayout(1);
606 636
		parent.setLayout(gl);
607 637
	}
608

  
638
	
609 639
	/**
610 640
	 * Gets the extended parameters Group widget.
611 641
	 * Put here you main parameter widgets using RowData data layout.
612 642
	 * 
613
	 * @return the extendedParametersGroup 
643
	 * @return the extendedParametersGroup
614 644
	 */
615 645
	public Group getExtendedParametersGroup() {
646
		
616 647
		return this.extendedParametersGroup;
617 648
	}
618

  
619

  
649
	
650
	
620 651
	@Override
621 652
	public boolean isSaveAsAllowed() {
653
		
622 654
		// TODO Auto-generated method stub
623 655
		return false;
624 656
	}
625

  
657
	
626 658
	@Override
627 659
	public void doSave(final IProgressMonitor monitor) {
628 660
		// FIXME: SJ: to discuss. A this moment the save is automatically done or not in TXMResult.compute() according to a preference of the TBX
629
		//		if (TBXPreferences.getInstance().getBoolean(TBXPreferences.AUTO_SAVE_RESULTS)) { // ?
630
		//			getResult().saveParameters();
631
		//		}
632

  
661
		// if (TBXPreferences.getInstance().getBoolean(TBXPreferences.AUTO_SAVE_RESULTS)) { // ?
662
		// getResult().saveParameters();
663
		// }
664
		
633 665
		/// FIXME: SJ: dirty state tests
634 666
		if (parent != null && !parent.isDisposed()) {
635 667
			parent.getDisplay().asyncExec(new Runnable() {
636

  
668
				
637 669
				@Override
638 670
				public void run() {
671
					
639 672
					compute(true);
640 673
					TXMEditor.this.setDirty(false);
641 674
				}
642 675
			});
643 676
		}
644

  
677
		
645 678
		notifyExtensions("notifyDoSave"); //$NON-NLS-1$
646 679
		firePropertyChange(IEditorPart.PROP_DIRTY);
647 680
	}
648

  
681
	
649 682
	@Override
650 683
	public void doSaveAs() {
651 684
		// TODO Auto-generated method stub
652 685
	}
653

  
686
	
654 687
	@Override
655 688
	public void dispose() {
689
		
656 690
		notifyExtensions("notifyDispose"); //$NON-NLS-1$
657 691
		super.dispose();
658 692
	}
659

  
693
	
660 694
	/**
661 695
	 * Sets the dirty state of the editor.
662 696
	 * Also sets the result dirty state to true if editor is dirty.
......
665 699
	 * @param dirty
666 700
	 */
667 701
	public void setDirty(boolean dirty) {
702
		
668 703
		this.dirty = dirty;
669

  
704
		
670 705
		// FIXME: SJ: future version that enable the button ONLY if the result can compute
671 706
		// need to check all canCompute() result methods before enabling it
672
		//		try {
673
		//			// enable/disable the compute button according to dirty state of the editor
674
		//			if (this.computeButton != null && !this.computeButton.isDisposed()) {
675
		//				this.computeButton.setEnabled(this.getResult().canCompute() && dirty && !this.getResult().isLocked());
676
		//			}
677
		//		}
678
		//		catch (Exception e) {
679
		//			// TODO Auto-generated catch block
680
		//			e.printStackTrace();
681
		//		}
682

  
683
//		// FIXME: sometime the button is enable/disable when it should not
684
//		// enable/disable the compute button according to dirty state of the editor
685
//		if (this.computeButton != null && !this.computeButton.isDisposed()) {
686
//			this.computeButton.setEnabled(this.dirty && !this.getResult().isLocked());
687
//		}
688

  
707
		// try {
708
		// // enable/disable the compute button according to dirty state of the editor
709
		// if (this.computeButton != null && !this.computeButton.isDisposed()) {
710
		// this.computeButton.setEnabled(this.getResult().canCompute() && dirty && !this.getResult().isLocked());
711
		// }
712
		// }
713
		// catch (Exception e) {
714
		// // TODO Auto-generated catch block
715
		// e.printStackTrace();
716
		// }
717
		
718
		// // FIXME: sometime the button is enable/disable when it should not
719
		// // enable/disable the compute button according to dirty state of the editor
720
		// if (this.computeButton != null && !this.computeButton.isDisposed()) {
721
		// this.computeButton.setEnabled(this.dirty && !this.getResult().isLocked());
722
		// }
723
		
689 724
		firePropertyChange(IEditorPart.PROP_DIRTY);
690 725
		CorporaView.refreshObject(this.result);
691 726
	}
692

  
727
	
693 728
	@Override
694 729
	public boolean isDirty() {
695

  
730
		
696 731
		boolean dirty = this.dirty;
697

  
732
		
698 733
		for (TXMEditorExtension<T> extension : this.extensions) {
699 734
			try {
700 735
				dirty = dirty || extension.isDirty();
701
			} catch (Exception e) {
736
			}
737
			catch (Exception e) {
702 738
				e.printStackTrace();
703 739
			}
704 740
		}
705 741
		return dirty;
706 742
	}
707

  
743
	
708 744
	@Override
709 745
	public boolean isSaveOnCloseNeeded() {
746
		
710 747
		boolean needed = false;
711

  
748
		
712 749
		for (TXMEditorExtension<T> extension : this.extensions) {
713 750
			try {
714 751
				needed = needed || (extension.isSaveOnCloseNeeded() && extension.isDirty());
715
			} catch (Exception e) {
752
			}
753
			catch (Exception e) {
716 754
				e.printStackTrace();
717 755
			}
718 756
		}
719 757
		return needed;
720

  
758
		
721 759
	}
722

  
723

  
724

  
760
	
725 761
	@Override
726 762
	public void setFocus() {
727
		//	this.resultArea.setFocus();
763
		
764
		// this.resultArea.setFocus();
728 765
		// FIXME SJ: this code leads to a bug, the focus must not be regiven to the main parameter after each computing of all result editors
729
		//		if (mainParametersComposite != null && !mainParametersComposite.isDisposed()) {
730
		//			mainParametersComposite.setFocus();
731
		//		}
766
		// if (mainParametersComposite != null && !mainParametersComposite.isDisposed()) {
767
		// mainParametersComposite.setFocus();
768
		// }
732 769
		CorporaView.focus(this.getResult());
733 770
	}
734

  
735

  
771
	
736 772
	@SuppressWarnings("unchecked")
737 773
	@Override
738 774
	public TXMResultEditorInput<T> getEditorInput() {
775
		
739 776
		return (TXMResultEditorInput<T>) super.getEditorInput();
740 777
	}
741

  
778
	
742 779
	/**
743 780
	 * Returns the result object associated with the editor through its editor input.
781
	 * 
744 782
	 * @return
745 783
	 */
746
	public T getResult()	{
784
	public T getResult() {
785
		
747 786
		return this.getEditorInput().getResult();
748 787
	}
749

  
788
	
750 789
	/**
751 790
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
791
	 * 
752 792
	 * @param key
753 793
	 * @return
754 794
	 */
755
	public int getIntParameterValue(String key)	{
795
	public int getIntParameterValue(String key) {
796
		
756 797
		return this.getEditorInput().getResult().getIntParameterValue(key);
757 798
	}
758

  
799
	
759 800
	/**
760 801
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
802
	 * 
761 803
	 * @param key
762 804
	 * @return
763 805
	 */
764
	public float getFloatParameterValue(String key)	{
806
	public float getFloatParameterValue(String key) {
807
		
765 808
		return this.getEditorInput().getResult().getFloatParameterValue(key);
766 809
	}
767

  
810
	
768 811
	/**
769 812
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
813
	 * 
770 814
	 * @param key
771 815
	 * @return
772 816
	 */
773
	public double getDoubleParameterValue(String key)	{
817
	public double getDoubleParameterValue(String key) {
818
		
774 819
		return this.getEditorInput().getResult().getDoubleParameterValue(key);
775 820
	}
776

  
777

  
821
	
778 822
	/**
779 823
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
824
	 * 
780 825
	 * @param key
781 826
	 * @return
782 827
	 */
783
	public boolean getBooleanParameterValue(String key)	{
828
	public boolean getBooleanParameterValue(String key) {
829
		
784 830
		return this.getEditorInput().getResult().getBooleanParameterValue(key);
785 831
	}
786

  
832
	
787 833
	/**
788 834
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
835
	 * 
789 836
	 * @param key
790 837
	 * @return
791 838
	 */
792
	public long getLongParameterValue(String key)	{
839
	public long getLongParameterValue(String key) {
840
		
793 841
		return this.getEditorInput().getResult().getLongParameterValue(key);
794 842
	}
795

  
843
	
796 844
	/**
797 845
	 * Gets the value of the specified key in parameters, local result node or default preferences nodes.
846
	 * 
798 847
	 * @param key
799 848
	 * @return
800 849
	 */
801
	public String getStringParameterValue(String key)	{
850
	public String getStringParameterValue(String key) {
851
		
802 852
		return this.getEditorInput().getResult().getStringParameterValue(key);
803 853
	}
804

  
805 854
	
806 855
	// FIXME: SJ: tests to enable/disable when computing
807
//	public void recursiveSetEnabled(boolean enabled) {
808
//		this.recursiveSetEnabled(this.parent, enabled);
809
//	}
856
	// public void recursiveSetEnabled(boolean enabled) {
857
	// this.recursiveSetEnabled(this.parent, enabled);
858
	// }
810 859
	
811 860
	// FIXME: SJ: tests to enable/disable when computing
812
//	public void recursiveSetEnabled(Control ctrl, boolean enabled) {
813
//		   if (ctrl instanceof Composite) {
814
//		      Composite comp = (Composite) ctrl;
815
//		      for (Control c : comp.getChildren())
816
//		         recursiveSetEnabled(c, enabled);
817
//		   } else {
818
//		      ctrl.setEnabled(enabled);
819
//		   }
820
//		}
861
	// public void recursiveSetEnabled(Control ctrl, boolean enabled) {
862
	// if (ctrl instanceof Composite) {
863
	// Composite comp = (Composite) ctrl;
864
	// for (Control c : comp.getChildren())
865
	// recursiveSetEnabled(c, enabled);
866
	// } else {
867
	// ctrl.setEnabled(enabled);
868
	// }
869
	// }
821 870
	
822 871
	/**
823 872
	 * Computes the TXMResult if all required parameters are set then refreshes the editor UI.
......
826 875
	 * @param result
827 876
	 * @param update force the editor to update its result parameters
828 877
	 */
829
	public JobHandler compute(final boolean update)	{
830

  
878
	public JobHandler compute(final boolean update) {
879
		
831 880
		StatusLine.setMessage(TXMCoreMessages.bind(TXMUIMessages.computing, this.getResult().getName()));
832

  
881
		
833 882
		JobHandler job = new JobHandler(TXMCoreMessages.bind(TXMUIMessages.computing, this.getResult().getName())) {
834

  
883
			
835 884
			@Override
836 885
			protected IStatus run(IProgressMonitor monitor) {
837

  
886
				
838 887
				this.runInit(monitor);
839

  
840
				if (isLocked()) {
841
					return Status.CANCEL_STATUS;
842
				}
843

  
888
				
889
				if (isLocked()) { return Status.CANCEL_STATUS; }
890
				
844 891
				try {
845 892
					JobsTimer.start();
846

  
893
					
847 894
					// FIXME: SJ: tests
848
					//showBusy(true);
849

  
895
					// showBusy(true);
896
					
850 897
					this.syncExec(new Runnable() {
898
						
851 899
						@Override
852 900
						public void run() {
853

  
901
							
854 902
							// FIXME: SJ: tests to enable/disable the editor widgets when computing
855
							//recursiveSetEnabled(false);
903
							// recursiveSetEnabled(false);
856 904
							
857
							if(update)	{
858

  
905
							if (update) {
906
								
859 907
								// popup alert to inform user that the result has been manually edited
860 908
								if (TXMEditor.this.getResult().isAltered()
861
										&& !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning, TXMCoreMessages.bind(TXMUIMessages.warning_popup_theP0HasBeenEditedItsChangesWillBeLost, TXMEditor.this.getResult().getResultType()))) {
909
										&& !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning, TXMCoreMessages.bind(
910
												TXMUIMessages.warning_popup_theP0HasBeenEditedItsChangesWillBeLost, TXMEditor.this.getResult().getResultType()))) {
862 911
									setCanceled(true);
863 912
								}
864 913
								// popup alert to inform user that children results will be recomputed
865
								if(!TBXPreferences.getInstance().getBoolean(TBXPreferences.EXPERT_USER)
866
										&& TXMEditor.this.getResult().hasVisibleChild() && !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning, TXMUIMessages.warning_popup_allDescendantResultsWillBeUpdated))	{
914
								if (!TBXPreferences.getInstance().getBoolean(TBXPreferences.EXPERT_USER)
915
										&& TXMEditor.this.getResult().hasVisibleChild() && !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning,
916
												TXMUIMessages.warning_popup_allDescendantResultsWillBeUpdated)) {
867 917
									setCanceled(true);
868 918
								}
869

  
870

  
871

  
919
								
920
								
921
								
872 922
								// subclasses manual result updating from editor fields
873 923
								Log.finer("TXMEditor.compute(): " + TXMEditor.this.getClass().getSimpleName() + ": manually updating result from editor."); //$NON-NLS-1$
874 924
								updateResultFromEditor();
875

  
925
								
876 926
								// auto updating result parameters from parameter annotations of editor
877 927
								Log.finer("TXMEditor.compute(): " + TXMEditor.this.getClass().getSimpleName() + ": auto updating result from editor."); //$NON-NLS-1$
878 928
								autoUpdateResultFromEditorParameters();
879

  
880

  
881

  
929
								
930
								
931
								
882 932
								// FIXME: SJ: useless at this time?
883
								// Stores the last parameters before the computing to later auto-update the Widgets only if some parameters have changed 
884
								//setLastComputingParameters(TXMEditor.this.getResult().getLastParametersFromHistory());
933
								// Stores the last parameters before the computing to later auto-update the Widgets only if some parameters have changed
934
								// setLastComputingParameters(TXMEditor.this.getResult().getLastParametersFromHistory());
885 935
							}
886 936
							// FIXME: SJ: there is a bug when deleting LT lines for example, the popup alert to inform user that children results will be recomputed is not triggered
887
							// problem here is the DeleteLines commands, etc. call TXMEditor.compute(false) at this moment, they should call TXMEditor.compute(true) but the LT Editor is not ready to manage that
888
							//							else if(TXMEditor.this.getResult().hasBeenComputedOnce())	 {
889
							//								// popup alert to inform user that children results will be recomputed
890
							//								if(!TBXPreferences.getInstance().getBoolean(TBXPreferences.EXPERT_USER)
891
							//										&& TXMEditor.this.getResult().hasVisibleChild() && !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning, TXMUIMessages.warning_popup_allDescendantResultsWillBeUpdated))	{
892
							//									setCanceled(true);
893
							//								}
937
							// problem here is the DeleteLines commands, etc. call TXMEditor.compute(false) at this moment, they should call TXMEditor.compute(true) but the LT Editor is not ready to
938
							// manage that
939
							// else if(TXMEditor.this.getResult().hasBeenComputedOnce()) {
940
							// // popup alert to inform user that children results will be recomputed
941
							// if(!TBXPreferences.getInstance().getBoolean(TBXPreferences.EXPERT_USER)
942
							// && TXMEditor.this.getResult().hasVisibleChild() && !MessageDialog.openQuestion(getShell(), TXMCoreMessages.common_warning,
943
							// TXMUIMessages.warning_popup_allDescendantResultsWillBeUpdated)) {
944
							// setCanceled(true);
945
							// }
894 946
							//
895
							//							}
947
							// }
896 948
						}
897 949
					});
898

  
899
					if (this.isCanceled()) {
900
						return Status.CANCEL_STATUS;
901
					}
902

  
950
					
951
					if (this.isCanceled()) { return Status.CANCEL_STATUS; }
952
					
903 953
					// computing result
904 954
					monitor.beginTask(TXMUIMessages.computing_3, 100);
905

  
906
					notifyExtensions("notifyStartOfCompute"); //$NON-NLS-1$	
907

  
955
					
956
					notifyExtensions("notifyStartOfCompute"); //$NON-NLS-1$
957
					
908 958
					// user log info
909 959
					if (update && TXMEditor.this.getResult().canCompute() && !TXMEditor.this.getResult().getComputingStartMessage().isEmpty()) {
910 960
						Log.info(TXMEditor.this.getResult().getComputingStartMessage());
......
914 964
						Log.fine("TXMEditor.compute(): " + TXMEditor.this.getClass().getSimpleName() + ": computing failed.");
915 965
					}
916 966
					// user log info
917
					else if (update && !TXMEditor.this.getResult().getComputingDoneMessage().isEmpty())	{
967
					else if (update && !TXMEditor.this.getResult().getComputingDoneMessage().isEmpty()) {
918 968
						Log.info(TXMEditor.this.getResult().getComputingDoneMessage());
919 969
					}
920 970
					
921

  
971
					
922 972
					notifyExtensions("notifyEndOfCompute"); //$NON-NLS-1$
923

  
973
					
924 974
					monitor.worked(50);
925

  
975
					
926 976
					// refreshing the UI
927 977
					this.syncExec(new Runnable() {
978
						
928 979
						@Override
929 980
						public void run() {
981
							
930 982
							try {
931 983
								refresh(update);
932

  
933
								// focus in the main widget 
984
								
985
								// focus in the main widget
934 986
								setFocus();
935 987
								
936 988
								StatusLine.setMessage(null);
937

  
989
								
938 990
								// FIXME: SJ: tests to enable/disable the editor widgets when computing
939
								//recursiveSetEnabled(true);
991
								// recursiveSetEnabled(true);
940 992
								
941
							} catch (Exception e) {
993
							}
994
							catch (Exception e) {
942 995
								Log.finer("TXMEditor.compute(): " + TXMEditor.this.getClass().getSimpleName() + ": Error while refreshing the editor: " + e); //$NON-NLS-1$
943 996
								Log.printStackTrace(e);
944 997
							}
......
964 1017
		};
965 1018
		job.setPriority(Job.DECORATE);
966 1019
		// FIXME: SJ tests
967
		//job.setPriority(Job.INTERACTIVE);
1020
		// job.setPriority(Job.INTERACTIVE);
968 1021
		job.setUser(true);
969 1022
		job.schedule();
970

  
1023
		
971 1024
		return job;
972 1025
	}
973

  
1026
	
974 1027
	/**
975 1028
	 * Opens an editor specified by its id, computes the specified result then refreshes the editor components.
976 1029
	 * If the editor was already opened, the computing is skipped and the focus is given to the editor.
......
978 1031
	 * @param result
979 1032
	 * @param editorPartId
980 1033
	 */
981
	public static TXMEditor openEditor(TXMResult result, String editorPartId)	{
1034
	public static TXMEditor openEditor(TXMResult result, String editorPartId) {
1035
		
982 1036
		return openEditor(new TXMResultEditorInput<TXMResult>(result), editorPartId);
983 1037
	}
984

  
985

  
1038
	
986 1039
	/**
987 1040
	 * Opens an editor specified by its id, computes the result stored in the specified editor input then refreshes the editor components.
988 1041
	 * If the editor was already opened, the computing is skipped and the focus is given to the editor.
1042
	 * 
989 1043
	 * @param editorInput
990 1044
	 * @param editorId
991 1045
	 * @return
992 1046
	 */
993 1047
	@SuppressWarnings("unchecked")
994
	public static TXMEditor<? extends TXMResult> openEditor(TXMResultEditorInput<? extends TXMResult> editorInput, String editorId)	{
1048
	public static TXMEditor<? extends TXMResult> openEditor(TXMResultEditorInput<? extends TXMResult> editorInput, String editorId) {
1049
		
995 1050
		TXMEditor<? extends TXMResult> editor = null;
996 1051
		IWorkbenchWindow window = TXMWindows.getActiveWindow();
997 1052
		IWorkbenchPage page = window.getActivePage();
......
1006 1061
			else {
1007 1062
				return null;
1008 1063
			}
1009

  
1064
			
1010 1065
			if (wasAlreadyOpened) {
1011 1066
				
1012
			} else {
1013
				//TODO until the TXMResult don't know if its parameters are set by the user or by the default preference value, we need to use the AUTO_COMPUTE_ON_EDITOR_OPEN preference
1067
			}
1068
			else {
1069
				// TODO until the TXMResult don't know if its parameters are set by the user or by the default preference value, we need to use the AUTO_COMPUTE_ON_EDITOR_OPEN preference
1014 1070
				// compute the result only if the editor wasn't already opened
1015
				if ((RCPPreferences.getInstance().getBoolean(RCPPreferences.AUTO_COMPUTE_ON_EDITOR_OPEN)))	{
1071
				if ((RCPPreferences.getInstance().getBoolean(RCPPreferences.AUTO_COMPUTE_ON_EDITOR_OPEN))) {
1016 1072
					editor.compute(false);
1017
				} else {
1073
				}
1074
				else {
1018 1075
					editor.refresh(false);
1019 1076
				}
1020 1077
			}
......
1025 1082
		}
1026 1083
		return editor;
1027 1084
	}
1028

  
1085
	
1029 1086
	/**
1030 1087
	 * Synchronizes the editor from the result and refreshes the corpus view.
1031 1088
	 * Also fires a dirty property change.
1089
	 * 
1032 1090
	 * @param update
1033
	 * @throws Exception 
1091
	 * @throws Exception
1034 1092
	 */
1035 1093
	public final void refresh(boolean update) throws Exception {
1094
		
1036 1095
		if (this.parent.isDisposed()) return; // nothing to refresh
1037 1096
		
1038 1097
		// skip refresh if the part creation has failed
1039
		if (!createPartControlDoneSucessfully) {
1040
			return;
1041
		}
1042

  
1043
		//this.parent.setRedraw(false);
1098
		if (!createPartControlDoneSucessfully) { return; }
1044 1099
		
1100
		// this.parent.setRedraw(false);
1101
		
1045 1102
		this.notifyExtensions("notifyStartOfRefresh"); //$NON-NLS-1$
1046

  
1103
		
1047 1104
		TXMResult result = this.getResult();
1048

  
1105
		
1049 1106
		// disable the component rendering to avoid strange behaviors when modifying the result area widget
1050
		//this.getContainer().setRedraw(false);
1051

  
1107
		// this.getContainer().setRedraw(false);
1108
		
1052 1109
		String title = result.getName();
1053 1110
		if (title.length() > 41) { // limit title length
1054
			title = title.substring(0, 40)+"..."; 
1111
			title = title.substring(0, 40) + "...";
1055 1112
		}
1056 1113
		this.setPartName(title);
1057
		//this.firePropertyChange(TXMEditor.PROP_DIRTY);
1058

  
1059
		//MD commented 'if (!update) {...}'
1114
		// this.firePropertyChange(TXMEditor.PROP_DIRTY);
1115
		
1116
		// MD commented 'if (!update) {...}'
1060 1117
		// SJ need to check all works, it also was dedicated to not refresh the Editor from result after a computing, it's not needed since the computing has been done
1061 1118
		// from fields themselves
1062
		//if (!update) {
1119
		// if (!update) {
1063 1120
		// FIXME: debug
1064 1121
		Log.finest("TXMEditor.refresh(): " + this.getClass().getSimpleName() + ": auto updating editor from result."); //$NON-NLS-1$
1065 1122
		this.autoUpdateEditorFieldsFromResult(update); // auto update from Parameter annotations
1066

  
1123
		
1067 1124
		// FIXME: debug
1068 1125
		Log.finest("TXMEditor.refresh(): " + this.getClass().getSimpleName() + ": updating subclass editor from result."); //$NON-NLS-1$ //$NON-NLS-2$
1069 1126
		this.updateEditorFromResult(update); // subclasses manual settings
1070
		//}
1071

  
1127
		// }
1128
		
1072 1129
		// Hide the computing parameter area if the editor wasn't open and the result is computed
1073 1130
		if (!update && !result.isDirty() && !this.topToolBar.isDisposed()) {
1074 1131
			this.topToolBar.setComputingParametersVisible(false);
1075 1132
		}
1076

  
1133
		
1077 1134
		if (!topToolBar.isDisposed()) this.topToolBar.redraw();
1078

  
1135
		
1079 1136
		CorporaView.refreshObject(this);
1080 1137
		TXMResultDebugView.refreshView();
1081

  
1138
		
1082 1139
		// re-enable the component rendering
1083 1140
		this.getContainer().setRedraw(true);
1084

  
1141
		
1085 1142
		// FIXME: SJ: this code breaks the dirty/chart dirty separation state, eg. if a non electric rendering parameter is changed then the chart is dirty but not the result, need to check this
1086 1143
		this.setDirty(this.getResult().isDirty());
1087

  
1144
		
1088 1145
		// FIXME: update all open editors of the children result but also of the result itself
1089 1146
		// FIXME: debug
1090 1147
		Log.finest("TXMEditor.refresh(): " + this.getClass().getSimpleName() + ": synchronizing and refreshing result children opened editors."); //$NON-NLS-1$ //$NON-NLS-2$
1091

  
1148
		
1092 1149
		List<TXMResult> results = this.getResult().getDeepChildren();
1093

  
1150
		
1094 1151
		for (int i = 0; i < results.size(); i++) {
1095
			ArrayList<ITXMResultEditor<?>> editors = SWTEditorsUtils.getEditors(results.get(i)) ;
1152
			ArrayList<ITXMResultEditor<?>> editors = SWTEditorsUtils.getEditors(results.get(i));
1096 1153
			for (int j = 0; j < editors.size(); j++) {
1097 1154
				ITXMResultEditor<?> txmEditor = editors.get(j);
1098
				if(txmEditor != this
1099
						//&& txmEditor.isDirty()
1100
						)	{
1101
					//txmEditor.synchronizeResultFromEditor();
1102

  
1155
				if (txmEditor != this
1156
				// && txmEditor.isDirty()
1157
				) {
1158
					// txmEditor.synchronizeResultFromEditor();
1159
					
1103 1160
					// FIXME: SJ: need to prove/test this code
1104
					// recreate all if the parent result is altered 
1105
					//txmEditor.refresh(!this.getResult().isAltered());
1161
					// recreate all if the parent result is altered
1162
					// txmEditor.refresh(!this.getResult().isAltered());
1106 1163
					txmEditor.refresh(true);
1107 1164
				}
1108 1165
			}
1109 1166
		}
1110

  
1167
		
1111 1168
		this.notifyExtensions("notifyEndOfRefresh"); //$NON-NLS-1$
1112 1169
		
1113 1170
		// re-enable the rendering that has been disabled in createPartControl()
1114 1171
		// FIXME: SJ: would be very nice to do that to avoid to see the empty tables before the refresh() that fill the UI.
1115 1172
		// the disabling is done in createPartControl() but the EditionEditor doesn't seem to call refresh() so it breaks it
1116
		//this.parent.setRedraw(true);
1173
		// this.parent.setRedraw(true);
1117 1174
	}
1118

  
1175
	
1119 1176
	/**
1120 1177
	 * Synchronizes the result parameters with editor widgets.
1121 1178
	 * <p>
1122 1179
	 * It should be called or called itself in the UI thread when accessing Widget parameters.
1123 1180
	 */
1124 1181
	public abstract void updateResultFromEditor();
1125

  
1182
	
1126 1183
	/**
1127
	 * Synchronizes the editor widgets with the result parameters. 
1184
	 * Synchronizes the editor widgets with the result parameters.
1128 1185
	 * Dedicated to dynamically change the editor components from the stored result.
1129 1186
	 * 
1130 1187
	 * Use this method if you need to save parameter with Type not managed by the autoUpdateEditorFieldsFromResult method.
1131
	 * @throws Exception 
1188
	 * 
1189
	 * @throws Exception
1132 1190
	 */
1133 1191
	public abstract void updateEditorFromResult(boolean update) throws Exception;
1134

  
1135

  
1136

  
1192
	
1193
	
1194
	
1137 1195
	/**
1138 1196
	 * Updates the editor fields from TXMResult and declared parameters annotations in both TXMEditor and TXMResult.
1139 1197
	 * Manages these widgets at this moment:
1140
	 *  
1141
	 * ToolItem (Boolean) 
1142
	 * FloatSpinner (Float) 
1143
	 * Spinner (Integer) 
1144
	 * Text (String), 
1198
	 * 
1199
	 * ToolItem (Boolean)
1200
	 * FloatSpinner (Float)
1201
	 * Spinner (Integer)
1202
	 * Text (String),
1145 1203
	 * Button (Boolean)
1146 1204
	 * Viewer (Object)
1147 1205
	 * PropertiesSelector (Property and List<Property>)
......
1150 1208
	 * QueryWidget (String, from Query)
1151 1209
	 * 
1152 1210
	 */
1153
	public void autoUpdateEditorFieldsFromResult(boolean update)	{
1154

  
1211
	public void autoUpdateEditorFieldsFromResult(boolean update) {
1212
		
1155 1213
		List<Field> fields = this.getAllParameterFields();
1156

  
1214
		
1157 1215
		for (Field f : fields) {
1158 1216
			Parameter parameter = f.getAnnotation(Parameter.class);
1159 1217
			if (parameter == null || parameter.key().isEmpty()) {
1160 1218
				continue;
1161 1219
			}
1162

  
1220
			
1163 1221
			Object object = null;
1164 1222
			Object value = null;
1165

  
1223
			
1166 1224
			try {
1167 1225
				f.setAccessible(true);
1168 1226
				object = f.get(this);
1169 1227
				
1170 1228
				// propagate to all parents
1171 1229
				value = this.getResult().getParameter(parameter.key(), true);
1172

  
1230
				
1173 1231
				if (value == null) {
1174
					//System.out.println("Warning: "+this.getPartName()+" result "+this.getResult()+" "+parameter.key()+" is not initialized.");
1232
					// System.out.println("Warning: "+this.getPartName()+" result "+this.getResult()+" "+parameter.key()+" is not initialized.");
1175 1233
					continue; // not initialized
1176 1234
				}
1177
				if(object instanceof ToolItem)	{
1178
					((ToolItem)object).setSelection((Boolean) value); 
1235
				if (object instanceof ToolItem) {
1236
					((ToolItem) object).setSelection((Boolean) value);
1179 1237
				}
1180
				else if(object instanceof FloatSpinner)	{
1181

  
1182
					((FloatSpinner)object).setData(BaseAbstractComputeListener.IGNORE_EVENT, true);
1183

  
1184
					if(value instanceof Double) {
1185
						((FloatSpinner)object).setSelection((Double) value);	
1238
				else if (object instanceof FloatSpinner) {
1239
					
1240
					((FloatSpinner) object).setData(BaseAbstractComputeListener.IGNORE_EVENT, true);
1241
					
1242
					if (value instanceof Double) {
1243
						((FloatSpinner) object).setSelection((Double) value);
1186 1244
					}
1187 1245
					else {
1188
						((FloatSpinner)object).setSelection((Float) value);
1246
						((FloatSpinner) object).setSelection((Float) value);
1189 1247
					}
1190

  
1191
					((FloatSpinner)object).setData(BaseAbstractComputeListener.IGNORE_EVENT, false);
1248
					
1249
					((FloatSpinner) object).setData(BaseAbstractComputeListener.IGNORE_EVENT, false);
1192 1250
				}
1193
				else if(object instanceof Spinner)	{
1194
					((Spinner)object).setData(BaseAbstractComputeListener.IGNORE_EVENT, true);
1195
					((Spinner)object).setSelection((Integer) value); 
1196
					((Spinner)object).setData(BaseAbstractComputeListener.IGNORE_EVENT, false);
1251
				else if (object instanceof Spinner) {
1252
					((Spinner) object).setData(BaseAbstractComputeListener.IGNORE_EVENT, true);
1253
					((Spinner) object).setSelection((Integer) value);
1254
					((Spinner) object).setData(BaseAbstractComputeListener.IGNORE_EVENT, false);
1197 1255
				}
1198
				else if(object instanceof Text)	{
1199
					((Text)object).setText(String.valueOf(value)); 
1256
				else if (object instanceof Text) {
1257
					((Text) object).setText(String.valueOf(value));
1200 1258
				}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff