ref #8539 Add association when adding specimens to the matrix
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / descriptiveDataSet / matrix / SpecimenSelectionDialog.java
1 /**
2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.taxeditor.editor.descriptiveDataSet.matrix;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.Comparator;
15 import java.util.List;
16 import java.util.stream.Collectors;
17
18 import org.eclipse.jface.dialogs.Dialog;
19 import org.eclipse.jface.viewers.ArrayContentProvider;
20 import org.eclipse.jface.viewers.ColumnLabelProvider;
21 import org.eclipse.jface.viewers.IStructuredSelection;
22 import org.eclipse.jface.viewers.ITableLabelProvider;
23 import org.eclipse.jface.viewers.TableViewer;
24 import org.eclipse.jface.viewers.TableViewerColumn;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.custom.ScrolledComposite;
27 import org.eclipse.swt.events.FocusEvent;
28 import org.eclipse.swt.events.FocusListener;
29 import org.eclipse.swt.events.SelectionAdapter;
30 import org.eclipse.swt.events.SelectionEvent;
31 import org.eclipse.swt.graphics.Image;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Button;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Control;
37 import org.eclipse.swt.widgets.Label;
38 import org.eclipse.swt.widgets.Shell;
39 import org.eclipse.swt.widgets.Table;
40 import org.eclipse.swt.widgets.Text;
41
42 import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
43 import eu.etaxonomy.cdm.common.CdmUtils;
44 import eu.etaxonomy.cdm.persistence.dto.SpecimenNodeWrapper;
45 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
46 import eu.etaxonomy.taxeditor.model.AbstractUtility;
47 import eu.etaxonomy.taxeditor.model.ImageResources;
48 import eu.etaxonomy.taxeditor.preference.Resources;
49 import eu.etaxonomy.taxeditor.store.CdmStore;
50 import eu.etaxonomy.taxeditor.store.StoreUtil;
51
52 /**
53 * Dialog to choose specimens for the character matrix.<br>
54 * Filters specimens that have already been added.
55 * @author pplitzner
56 * @since Jan 3, 2018
57 *
58 */
59 public class SpecimenSelectionDialog extends Dialog {
60
61 private static String TEXT_FILTER_DEFAULT = "Enter text filter";
62
63 private TableViewer list;
64
65 private Collection<SpecimenNodeWrapper> selectedSpecimens = new ArrayList<>();
66 private CharacterMatrix matrix;
67 private Text txtTextFilter;
68
69 protected SpecimenSelectionDialog(Shell parentShell, CharacterMatrix matrix) {
70 super(parentShell);
71 this.matrix = matrix;
72 }
73
74 @Override
75 protected Control createDialogArea(Composite parent) {
76 Composite composite = (Composite) super.createDialogArea(parent);
77 GridLayout gl_composite = new GridLayout();
78 gl_composite.numColumns = 2;
79 composite.setLayout(gl_composite);
80
81 Composite composite_1 = new Composite(composite, SWT.NONE);
82 composite_1.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
83 composite_1.setLayout(new GridLayout(4, false));
84
85 txtTextFilter = new Text(composite_1, SWT.BORDER);
86 txtTextFilter.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
87 txtTextFilter.setText(TEXT_FILTER_DEFAULT);
88 txtTextFilter.addFocusListener(new FocusListener() {
89
90 @Override
91 public void focusGained(FocusEvent e) {
92 txtTextFilter.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOCUS));
93 if (TEXT_FILTER_DEFAULT.equals(txtTextFilter.getText())) {
94 StoreUtil.setTextWithoutModifyListeners(txtTextFilter, "");
95 }
96 }
97
98 @Override
99 public void focusLost(FocusEvent e) {
100 if (CdmUtils.isBlank(txtTextFilter.getText())){
101 txtTextFilter.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOREGROUND));
102 StoreUtil.setTextWithoutModifyListeners(txtTextFilter, TEXT_FILTER_DEFAULT);
103 }
104 }
105 });
106 txtTextFilter.addModifyListener(e->applyFilter());
107
108 Button btnRefreshButton = new Button(composite_1, SWT.NONE);
109 btnRefreshButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
110 btnRefreshButton.setToolTipText(Messages.SpecimenSelectionDialog_REFRESH);
111 btnRefreshButton.setImage(ImageResources.getImage(ImageResources.REFRESH));
112 btnRefreshButton.addSelectionListener(new SelectionAdapter() {
113 @Override
114 public void widgetSelected(SelectionEvent e) {
115 loadSpecimens();
116 refreshInput(matrix.getSpecimenCache());
117 }
118 });
119
120 Label lblNewLabel = new Label(composite, SWT.NONE);
121 lblNewLabel.setImage(ImageResources.getImage(ImageResources.WARNING_ICON));
122
123 Label lblNewLabel_1 = new Label(composite, SWT.NONE);
124 lblNewLabel_1.setText(": Specimen not associated with taxon");
125
126 ScrolledComposite scrolledComposite = new ScrolledComposite(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
127 scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
128 scrolledComposite.setExpandHorizontal(true);
129 scrolledComposite.setExpandVertical(true);
130 //table
131 list = new TableViewer(scrolledComposite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI);
132 Table table = list.getTable();
133
134 //table columns
135 TableViewerColumn columnTaxon = new TableViewerColumn(list, SWT.NONE);
136 columnTaxon.getColumn().setText("Taxon");
137 columnTaxon.getColumn().setWidth(200);
138 columnTaxon.getColumn().setResizable(true);
139 columnTaxon.getColumn().setMoveable(true);
140 TableViewerColumn columnType = new TableViewerColumn(list, SWT.NONE);
141 columnType.getColumn().setText("Type");
142 columnType.getColumn().setWidth(150);
143 columnType.getColumn().setResizable(true);
144 columnType.getColumn().setMoveable(true);
145 TableViewerColumn columnSpecimen = new TableViewerColumn(list, SWT.NONE);
146 columnSpecimen.getColumn().setText("Specimen");
147 columnSpecimen.getColumn().setResizable(true);
148 columnSpecimen.getColumn().setMoveable(true);
149 columnSpecimen.getColumn().setWidth(400);
150
151 table.setHeaderVisible(true);
152 table.setLinesVisible(true);
153 scrolledComposite.setContent(table);
154 scrolledComposite.setMinSize(table.computeSize(SWT.DEFAULT, SWT.DEFAULT));
155 list.setContentProvider(new ArrayContentProvider());
156 list.setLabelProvider(new SpecimenListLabelProvider());
157
158 //gather specimens
159 if(matrix.getSpecimenCache()==null){
160 loadSpecimens();
161 }
162
163 refreshInput(matrix.getSpecimenCache());
164
165 columnSpecimen.getColumn().pack();
166
167 return composite;
168 }
169
170 private void refreshInput(Object input){
171 list.setInput(input);
172 }
173
174 private void applyFilter(){
175 List<SpecimenNodeWrapper> result = new ArrayList<>();
176 Collection<SpecimenNodeWrapper> specimenCache = matrix.getSpecimenCache();
177 String text = txtTextFilter.getText();
178 if(CdmUtils.isBlank(text)){
179 result = new ArrayList<>(specimenCache);
180 }
181 else{
182 if(!txtTextFilter.getForeground().equals(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOREGROUND))
183 &&!CdmUtils.isBlank(text)){
184 result.addAll(specimenCache.stream()
185 .filter(wrapper->wrapper.getUuidAndTitleCache().getTitleCache().toLowerCase().contains(text.toLowerCase()))
186 .collect(Collectors.toList()));
187 result.addAll(specimenCache.stream()
188 .filter(wrapper->wrapper.getTaxonNode().getTaxon().getTitleCache().toLowerCase().contains(text.toLowerCase()))
189 .collect(Collectors.toList()));
190 }
191 }
192 refreshInput(result);
193 }
194
195 private void loadSpecimens(){
196 ArrayList<SpecimenNodeWrapper> specimenList = new ArrayList<>(CdmStore.getService(IDescriptiveDataSetService.class).loadSpecimens(matrix.getDescriptiveDataSet()));
197 Collections.sort(specimenList, new Comparator<SpecimenNodeWrapper>() {
198
199 @Override
200 public int compare(SpecimenNodeWrapper o1, SpecimenNodeWrapper o2) {
201 if(o1 == null){
202 if(o2 == null){
203 return 0;
204 }
205 return -1;
206 }
207 if(o2==null){
208 return 1;
209 }
210 try{
211 return o1.getTaxonNode().getTaxon().getTitleCache().compareTo(o2.getTaxonNode().getTaxon().getTitleCache());
212 }
213 catch(NullPointerException e){
214 return 0;
215 }
216 }
217 });
218 matrix.setSpecimenCache(specimenList);
219 }
220
221 @Override
222 protected void configureShell(Shell newShell) {
223 super.configureShell(newShell);
224 newShell.setText(Messages.SpecimenSelectionDialog_SELECT_SPECIMENS);
225 newShell.setMinimumSize(500, 600);
226 newShell.setSize(800, 600);
227 }
228
229 @Override
230 protected void okPressed() {
231 selectedSpecimens.clear();
232 selectedSpecimens = ((IStructuredSelection)list.getSelection()).toList();
233 super.okPressed();
234 }
235
236 @Override
237 protected boolean isResizable() {
238 return true;
239 }
240
241 public Collection<SpecimenNodeWrapper> getSpecimen(){
242 return selectedSpecimens;
243 }
244
245 private class SpecimenListLabelProvider extends ColumnLabelProvider implements ITableLabelProvider {
246
247 @Override
248 public String getToolTipText(Object element) {
249 if(element instanceof SpecimenNodeWrapper
250 && !((SpecimenNodeWrapper) element).isIndividualsAssociation()){
251 return "Does not have and IndividualsAssociation with the taxon";
252 }
253 return null;
254 }
255
256 @Override
257 public Image getColumnImage(Object element, int columnIndex) {
258 if(element instanceof SpecimenNodeWrapper && columnIndex == 2
259 && !((SpecimenNodeWrapper) element).isIndividualsAssociation()){
260 return ImageResources.getImage(ImageResources.WARNING_ICON);
261 }
262 return null;
263 }
264
265 @Override
266 public String getColumnText(Object element, int columnIndex) {
267 if(element instanceof SpecimenNodeWrapper){
268 SpecimenNodeWrapper wrapper = (SpecimenNodeWrapper)element;
269 switch (columnIndex) {
270 case 0:
271 return wrapper.getTaxonNode().getTaxon().getName().getTitleCache();
272 case 1:
273 return wrapper.getType().getMessage();
274 case 2:
275 return wrapper.getUuidAndTitleCache().getTitleCache();
276 default:
277 break;
278 }
279 }
280 return "";
281 }
282 }
283 }