Project

General

Profile

Download (21.3 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2007 EDIT
4
 * European Distributed Institute of Taxonomy
5
 * http://www.e-taxonomy.eu
6
 *
7
 * The contents of this file are subject to the Mozilla Public License Version 1.1
8
 * See LICENSE.TXT at the top of this package for the full license terms.
9
 */
10

    
11
package eu.etaxonomy.taxeditor.editor.view.checklist;
12

    
13
import java.util.ArrayList;
14
import java.util.Arrays;
15
import java.util.Collections;
16
import java.util.HashMap;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.SortedSet;
20

    
21
import org.apache.log4j.Logger;
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.Status;
25
import org.eclipse.core.runtime.jobs.Job;
26
import org.eclipse.jface.viewers.ISelection;
27
import org.eclipse.jface.viewers.StructuredViewer;
28
import org.eclipse.jface.viewers.TableViewer;
29
import org.eclipse.jface.viewers.TableViewerColumn;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.events.ModifyListener;
32
import org.eclipse.swt.events.SelectionAdapter;
33
import org.eclipse.swt.events.SelectionEvent;
34
import org.eclipse.swt.layout.GridData;
35
import org.eclipse.swt.layout.GridLayout;
36
import org.eclipse.swt.widgets.Composite;
37
import org.eclipse.swt.widgets.Display;
38
import org.eclipse.swt.widgets.Label;
39
import org.eclipse.swt.widgets.Menu;
40
import org.eclipse.swt.widgets.Table;
41
import org.eclipse.swt.widgets.TableColumn;
42
import org.eclipse.swt.widgets.Text;
43
import org.eclipse.swt.widgets.ToolBar;
44
import org.eclipse.swt.widgets.ToolItem;
45
import org.eclipse.ui.IEditorInput;
46
import org.eclipse.ui.IEditorSite;
47
import org.eclipse.ui.IMemento;
48
import org.eclipse.ui.ISelectionListener;
49
import org.eclipse.ui.ISelectionService;
50
import org.eclipse.ui.IWorkbenchPart;
51
import org.eclipse.ui.PartInitException;
52
import org.eclipse.ui.part.EditorPart;
53
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
54

    
55
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
56
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
57
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
58
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
59
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
60
import eu.etaxonomy.cdm.model.taxon.Classification;
61
import eu.etaxonomy.cdm.model.taxon.Taxon;
62
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
63
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
64
import eu.etaxonomy.taxeditor.editor.EditorUtil;
65
import eu.etaxonomy.taxeditor.editor.SimpleSelectionProvider;
66
import eu.etaxonomy.taxeditor.editor.view.checklist.edit.DistributionEditingSupport;
67
import eu.etaxonomy.taxeditor.editor.view.checklist.edit.RankEditingSupport;
68
import eu.etaxonomy.taxeditor.editor.view.checklist.filter.ChecklistEditorFilter;
69
import eu.etaxonomy.taxeditor.editor.view.checklist.listener.ChecklistDropdownSelectionListener;
70
import eu.etaxonomy.taxeditor.editor.view.checklist.listener.ChecklistFocusListener;
71
import eu.etaxonomy.taxeditor.editor.view.checklist.listener.ChecklistModifyListener;
72
import eu.etaxonomy.taxeditor.model.IContextListener;
73
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
74
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
75
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
76
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
77
import eu.etaxonomy.taxeditor.preference.Resources;
78
import eu.etaxonomy.taxeditor.store.CdmStore;
79

    
80
/**
81
 * <p>
82
 * ChecklistViewPart class.
83
 * </p>
84
 *
85
 * @author a.oppermann
86
 * @created 30.04.2014
87
 * @version 1.0
88
 */
89
public class ChecklistEditor extends EditorPart implements ISelectionListener, IPartContentHasFactualData,
90
        IConversationEnabled, IContextListener, IPartContentHasDetails, IDirtyMarkable {
91

    
92
    private static final Logger logger = Logger.getLogger(ChecklistEditor.class);
93
    /**
94
     * Key used for storing Checklist Editor View
95
     */
96
    private static final String CHECKLIST_EDITOR_MEMENTO_KEY = "checklistEditor";
97

    
98
    private class ChecklistJob extends Job {
99

    
100
        private List<TaxonNode> taxonNodes;
101

    
102
        /**
103
         * @param name
104
         */
105
        public ChecklistJob(String title, List<TaxonNode> listTaxonNodes) {
106
            super(title);
107
            this.taxonNodes = listTaxonNodes;
108

    
109
        }
110

    
111
        /*
112
         * (non-Javadoc)
113
         *
114
         * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
115
         * IProgressMonitor)
116
         */
117
        @Override
118
        public IStatus run(final IProgressMonitor monitor) {
119
            try {
120
                logger.debug("Begin of eclipse core runtime Job to Retrieve datasources");
121
                monitor.beginTask("Retrieving TaxonNodes", taxonNodes.size() + 1);
122

    
123
                final List<Taxon> taxonList = new ArrayList<Taxon>();
124

    
125
                for (TaxonNode taxonNode : taxonNodes) {
126
                    HibernateProxyHelper hh = new HibernateProxyHelper();
127
                    Taxon taxon = hh.deproxy(taxonNode.getTaxon(), Taxon.class);
128
                    taxonList.add(taxon);
129
                }
130
                // set View input
131
                Display.getDefault().asyncExec(new Runnable() {
132

    
133
                    @Override
134
                    public void run() {
135
                        viewer.setInput(taxonList);
136
                    }
137
                });
138
                monitor.worked(1);
139

    
140
            } finally {
141
                monitor.done();
142
                taxonNodes = null;
143
            }
144
            return Status.OK_STATUS;
145
        }
146
    }
147

    
148
    /**
149
     * Constant
150
     * <code>ID="eu.etaxonomy.taxeditor.store.datasource"{trunked}</code>
151
     */
152
    public static String ID = "eu.etaxonomy.taxeditor.editor.view.checklist.ChecklistEditor";
153

    
154
    private TableViewer viewer;
155

    
156
    private String partNameCache;
157

    
158
    private IWorkbenchSiteProgressService service;
159

    
160
    private ITaxonNodeService taxonNodeService;
161

    
162
    private ChecklistEditorComparator comparator;
163

    
164
    private ChecklistEditorInput checklistEditorInput;
165

    
166
    private SimpleSelectionProvider simpleSelectionProvider;
167

    
168
    private ISelectionService selectionService;
169

    
170
    private ConversationHolder conversation;
171

    
172
    private Integer countNodes;
173

    
174
    private List<TaxonNode> selectedTaxonNodes;
175

    
176
    private boolean dirty;
177

    
178
    private ChecklistEditorFilter filter;
179

    
180
    private Menu headerMenu;
181

    
182
    private Label statusLabel;
183

    
184
    private SortedSet<DefinedTermBase> terms = null;
185

    
186
    /**
187
     * @return the selectedTaxonNodes
188
     */
189
    public List<TaxonNode> getSelectedTaxonNodes() {
190
        return selectedTaxonNodes;
191
    }
192

    
193
    /**
194
     * @param selectedTaxonNodes
195
     *            the selectedTaxonNodes to set
196
     */
197
    public void setSelectedTaxonNodes(List<TaxonNode> selectedTaxonNodes) {
198
        this.selectedTaxonNodes = selectedTaxonNodes;
199
    }
200

    
201
    /**
202
     * <p>
203
     * Constructor for CdmDataSourceViewPart.
204
     * </p>
205
     */
206
    public ChecklistEditor() {
207
    }
208

    
209
    /** {@inheritDoc} */
210
    @Override
211
    public void createPartControl(Composite parent) {
212
        service = (IWorkbenchSiteProgressService) getSite().getAdapter(IWorkbenchSiteProgressService.class);
213
        taxonNodeService = CdmStore.getService(ITaxonNodeService.class);
214
        selectionService = getSite().getWorkbenchWindow().getSelectionService();
215
        selectionService.addSelectionListener(this);
216
        filter = new ChecklistEditorFilter();
217
        ChecklistLabelProvider labelProvider = new ChecklistLabelProvider();
218
        terms = (SortedSet<DefinedTermBase>) labelProvider.getTermsOrderedByLabels(labelProvider.getNamedAreas(),
219
                CdmStore.getDefaultLanguage());
220
        createTopComposite(parent);
221
        loadDataInput();
222
    }
223

    
224
    /**
225
     * @param parent
226
     */
227
    private void createTopComposite(Composite parent) {
228
        GridLayout gridLayout = new GridLayout(3, false);
229
        gridLayout.marginWidth = 0;
230
        gridLayout.marginHeight = 0;
231
        parent.setLayout(gridLayout);
232

    
233
        final Text searchText = createSearchBar(parent);
234

    
235
//        if (terms != null && !terms.isEmpty()) {
236
            createToolbar(parent);
237
//        }
238
        viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
239
        getSite().setSelectionProvider(viewer);
240

    
241
        final ModifyListener modifyListener = new ChecklistModifyListener(viewer, filter, searchText);
242

    
243
        searchText.addFocusListener(new ChecklistFocusListener(searchText, modifyListener));
244
        searchText.addModifyListener(modifyListener);
245

    
246
        // Layout the viewer
247
        GridData gridData = new GridData();
248
        gridData.verticalAlignment = GridData.FILL;
249
        gridData.horizontalSpan = 3;
250
        gridData.grabExcessHorizontalSpace = true;
251
        gridData.grabExcessVerticalSpace = true;
252
        gridData.horizontalAlignment = GridData.FILL;
253
        viewer.getControl().setLayoutData(gridData);
254

    
255
        viewer.addFilter(filter);
256
        createColumns(viewer);
257

    
258
        viewer.setContentProvider(new ChecklistContentProvider());
259
        viewer.setLabelProvider(new ChecklistLabelProvider());
260
        comparator = new ChecklistEditorComparator();
261
        viewer.setComparator(comparator);
262

    
263
        createStatusBar(parent);
264
    }
265

    
266
    /**
267
     * @param parent
268
     * @return
269
     */
270
    private Text createSearchBar(Composite parent) {
271
        Label searchLabel = new Label(parent, SWT.NONE);
272
        searchLabel.setText("Search: ");
273
        final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.CANCEL);
274
        searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
275
        searchText.setForeground(EditorUtil.getColor(Resources.SEARCH_VIEW_FOREGROUND));
276
        searchText.setText("type filter text");
277
        return searchText;
278
    }
279

    
280
    /**
281
     * @param parent
282
     */
283
    private void createToolbar(Composite parent) {
284
        ToolBar toolBar = new ToolBar(parent, SWT.NONE);
285
        ToolItem toolItem = new ToolItem(toolBar, SWT.DROP_DOWN | SWT.BORDER);
286
        toolItem.setText("Distribution Status");
287
        toolItem.setToolTipText("Show Distribution Status for selected Areas");
288
        ChecklistDropdownSelectionListener dropListener = new ChecklistDropdownSelectionListener(toolItem, this, terms);
289
        for (DefinedTermBase<DefinedTermBase> term : terms) {
290
            if(term!=null){
291
                dropListener.add(term);
292
            }
293
        }
294
        toolItem.addSelectionListener(dropListener);
295
        toolBar.pack();
296
    }
297

    
298
    private void createStatusBar(Composite composite) {
299
        GridData gridData = new GridData();
300
        gridData.horizontalSpan = 3;
301
        gridData.grabExcessHorizontalSpace = true;
302
        gridData.horizontalAlignment = GridData.FILL;
303

    
304
        statusLabel = new Label(composite, SWT.LEFT);
305
        statusLabel.setText("Anzahl der Elemente: " + (countNodes != null ? countNodes : "uknown"));
306
        statusLabel.setLayoutData(gridData);
307
    }
308

    
309
    // This will create the columns for the table
310
    private void createColumns(TableViewer viewer) {
311
        Table table = viewer.getTable();
312
        List<String> titles = new ArrayList<String>();
313
        Collections.addAll(titles, "Taxon", "Author", "Reference", "Rank");
314
        List<Integer> bounds = new ArrayList<Integer>();
315
        Collections.addAll(bounds, 300, 200, 200, 200);
316
        Map<Integer, Boolean>restoreColumnWidth = new HashMap<Integer, Boolean>();
317
        if (terms != null) {
318
            int i = 4;
319
            for (DefinedTermBase<DefinedTermBase> term : terms) {
320
                if(term != null){
321
                    restoreColumnWidth.put(i, PreferencesUtil.getPreferenceStore().getBoolean(term.getUuid().toString()));
322
                    titles.add(term.getTitleCache());
323
                    bounds.add(200);
324
                    i++;
325
                }
326
            }
327
        }
328

    
329
        for (int i = 0; i < titles.size(); i++) {
330
            TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
331
            column.getColumn().setText(titles.get(i));
332
            column.getColumn().setWidth(bounds.get(i));
333
            column.getColumn().setResizable(true);
334
            column.getColumn().setMoveable(true);
335
            column.getColumn().addSelectionListener(getSelectionAdapter(column.getColumn(), i));
336
            if (i == 1) {
337
                table.setSortColumn(column.getColumn());
338
            }
339
            if (i == 3) {
340
                column.setEditingSupport(new RankEditingSupport(viewer, this));
341
            }
342
            if (i >= 4) {
343
                //read PrefrenceStore to setWidth according to last saved state
344
                if(restoreColumnWidth.get(i)){
345
                    column.getColumn().setWidth(100);
346
                }else{
347
                    column.getColumn().setWidth(0);
348
                }
349
                column.setEditingSupport(new DistributionEditingSupport(viewer, this, i));
350
            }
351
        }
352
        table.setSortDirection(SWT.DOWN);
353
        table.setHeaderVisible(true);
354
        table.setLinesVisible(true);
355
    }
356

    
357
    /**
358
     *
359
     * pull data from database and set input for view
360
     *
361
     */
362
    private void loadDataInput() {
363
        Classification classification = checklistEditorInput.getClassification();
364
        TaxonNode taxonNode = checklistEditorInput.getTaxonNode();
365
        if (classification != null && taxonNode == null) {
366
            countNodes = taxonNodeService.countAllNodesForClassification(classification);
367
            statusLabel.setText("Anzahl der Elemente: " + (countNodes != null ? countNodes : "uknown"));
368
            // This should not kill the view nor the editor if something goes
369
            // wrong
370
            // TODO: don't load the whole taxonNode Object but rather a small
371
            // and simple Solution
372
            // FIXME: May be don't open classification which are greater than
373
            // 3000 Taxa
374
            selectedTaxonNodes = taxonNodeService.listAllNodesForClassification(classification, 0, countNodes);
375
            getService().schedule(new ChecklistJob("loading Taxa", selectedTaxonNodes), Job.LONG);
376
        }
377
        if (taxonNode != null) {
378
            selectedTaxonNodes = taxonNodeService.loadChildNodesOfTaxonNode(taxonNode, NODE_INIT_STRATEGY, true, false);
379
            getService().schedule(new ChecklistJob("loading Taxa", selectedTaxonNodes), Job.LONG);
380
        }
381
    }
382

    
383
    /** {@inheritDoc} */
384
    @Override
385
    public void dispose() {
386
        super.dispose();
387
    }
388

    
389
    /** {@inheritDoc} */
390
    @Override
391
    public void setFocus() {
392
        viewer.getControl().setFocus();
393
    }
394

    
395
    /*
396
     * (non-Javadoc)
397
     *
398
     * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
399
     */
400
    /** {@inheritDoc} */
401
    @Override
402
    public void showBusy(boolean busy) {
403
        super.showBusy(busy);
404
        // viewer.getTable().setEnabled(!busy);
405
        if (busy) {
406
            partNameCache = getPartName();
407
            setPartName("Loading " + countNodes + " Taxa...");
408
        } else {
409
            if (partNameCache != null) {
410
                setPartName(partNameCache);
411
            }
412
        }
413
    }
414

    
415
    /**
416
     * <p>
417
     * Getter for the field <code>viewer</code>.
418
     * </p>
419
     *
420
     * @return a {@link org.eclipse.jface.viewers.StructuredViewer} object.
421
     */
422
    public StructuredViewer getViewer() {
423
        return viewer;
424
    }
425

    
426
    public void refresh() {
427
        viewer.refresh();
428
    }
429

    
430
    /**
431
     * <p>
432
     * Getter for the field <code>service</code>.
433
     * </p>
434
     *
435
     * @return the service
436
     */
437
    public IWorkbenchSiteProgressService getService() {
438
        return service;
439
    }
440

    
441
    private SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) {
442
        SelectionAdapter selectionAdapter = new SelectionAdapter() {
443
            @Override
444
            public void widgetSelected(SelectionEvent e) {
445
                comparator.setColumn(index);
446
                int dir = viewer.getTable().getSortDirection();
447
                if (viewer.getTable().getSortColumn() == column) {
448
                    dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
449
                } else {
450
                    dir = SWT.DOWN;
451
                }
452
                viewer.getTable().setSortDirection(dir);
453
                viewer.getTable().setSortColumn(column);
454
                viewer.refresh();
455
            }
456
        };
457
        return selectionAdapter;
458
    }
459

    
460
    @Override
461
    public void doSave(IProgressMonitor monitor) {
462
        try {
463
            monitor.beginTask("Saving Editor", 1);
464
            getConversationHolder().bind();
465
            getConversationHolder().commit(true);
466
            setDirty(false);
467
            monitor.worked(1);
468
        } finally {
469
            monitor.done();
470
        }
471

    
472
    }
473

    
474
    @Override
475
    public void doSaveAs() {
476
        // TODO Auto-generated method stub
477

    
478
    }
479

    
480
    @Override
481
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
482
        setSite(site);
483
        setInput(input);
484
        if (input instanceof ChecklistEditorInput) {
485
            checklistEditorInput = (ChecklistEditorInput) input;
486
            setPartName(getPartName() + ": " + checklistEditorInput.getName());
487
            conversation = ((ChecklistEditorInput) input).getConversationHolder();
488
        }
489
        simpleSelectionProvider = new SimpleSelectionProvider();
490
        getSite().setSelectionProvider(simpleSelectionProvider);
491
    }
492

    
493
    @Override
494
    public boolean isSaveAsAllowed() {
495
        // TODO Auto-generated method stub
496
        return false;
497
    }
498

    
499
    /*
500
     * (non-Javadoc)
501
     *
502
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
503
     * IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
504
     */
505
    @Override
506
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
507
        // TODO Auto-generated method stub
508

    
509
    }
510

    
511
    /*
512
     * (non-Javadoc)
513
     *
514
     * @see
515
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update
516
     * (eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
517
     */
518
    @Override
519
    public void update(CdmDataChangeMap changeEvents) {
520

    
521
    }
522

    
523
    /*
524
     * (non-Javadoc)
525
     *
526
     * @see
527
     * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
528
     * ()
529
     */
530
    @Override
531
    public ConversationHolder getConversationHolder() {
532
        return conversation;
533
    }
534

    
535
    /*
536
     * (non-Javadoc)
537
     *
538
     * @see
539
     * eu.etaxonomy.taxeditor.model.IContextListener#contextAboutToStop(org.
540
     * eclipse.ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
541
     */
542

    
543
    @Override
544
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
545

    
546
    }
547

    
548
    /*
549
     * (non-Javadoc)
550
     *
551
     * @see
552
     * eu.etaxonomy.taxeditor.model.IContextListener#contextStop(org.eclipse
553
     * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
554
     */
555
    @Override
556
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
557
        // TODO Auto-generated method stub
558
//        IStructuredSelection sel = (IStructuredSelection) this.viewer.getSelection();
559
//        if (sel.isEmpty()) {
560
//            return;
561
//        }
562
//        memento = memento.createChild("tree-selections");
563
//        Iterator iter = sel.iterator();
564
//        while (iter.hasNext()) {
565
//            String nodeName = (String) iter.next();
566
//            memento.createChild("selected-nodes", nodeName);
567
//        }
568
    }
569

    
570
    /*
571
     * (non-Javadoc)
572
     *
573
     * @see
574
     * eu.etaxonomy.taxeditor.model.IContextListener#contextStart(org.eclipse
575
     * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
576
     */
577
    @Override
578
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
579

    
580
    }
581

    
582
    /*
583
     * (non-Javadoc)
584
     *
585
     * @see
586
     * eu.etaxonomy.taxeditor.model.IContextListener#contextRefresh(org.eclipse
587
     * .core.runtime.IProgressMonitor)
588
     */
589
    @Override
590
    public void contextRefresh(IProgressMonitor monitor) {
591
        // TODO Auto-generated method stub
592

    
593
    }
594

    
595
    /*
596
     * (non-Javadoc)
597
     *
598
     * @see
599
     * eu.etaxonomy.taxeditor.model.IContextListener#workbenchShutdown(org.eclipse
600
     * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
601
     */
602
    @Override
603
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
604
        conversation.clear();
605
        conversation.close();
606
        conversation = null;
607
    }
608

    
609
    private static final List<String> NODE_INIT_STRATEGY = Arrays.asList(new String[] { "descriptions",
610
            "descriptions.*", "description.state", "feature", "feature.*", "childNodes", "childNodes.taxon",
611
            "childNodes.taxon.name", "taxonNodes", "taxonNodes.*", "taxonNodes.taxon.*", "taxon.*",
612
            "taxon.descriptions", "taxon.sec", "taxon.name.*", "taxon.synonymRelations", "terms", "name.*",
613
            "name.rank.representations", "name.status.type.representations", "sources.$", "stateData.$" });
614

    
615
    /*
616
     * (non-Javadoc)
617
     *
618
     * @see
619
     * eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#changed(
620
     * java.lang.Object)
621
     */
622
    @Override
623
    public void changed(Object element) {
624
        if (element != null) {
625
            viewer.update(element, null);
626
            setDirty(true);
627
            firePropertyChange(PROP_DIRTY);
628
        }
629
    }
630

    
631
    /* (non-Javadoc)
632
     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
633
     */
634
    @Override
635
    public void forceDirty() {
636
        changed(null);
637
    }
638

    
639
    public void setDirty(boolean dirty) {
640
        this.dirty = dirty;
641
        firePropertyChange(PROP_DIRTY);
642
    }
643

    
644
    /*
645
     * (non-Javadoc)
646
     *
647
     * @see org.eclipse.ui.forms.editor.FormEditor#isDirty()
648
     */
649
    @Override
650
    public boolean isDirty() {
651
        return dirty;
652
    }
653
}
(2-2/5)