1) Term vocabularies (ranks, features, statii) are also transaction-dependent - if...
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / propertysheet / namerelationswizard / ChooseRelatedNameWizardPage.java
1 /**
2 * Copyright (C) 2007 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
10 package eu.etaxonomy.taxeditor.propertysheet.namerelationswizard;
11
12 import java.util.Set;
13
14 import org.apache.log4j.Logger;
15 import org.eclipse.core.databinding.beans.BeansObservables;
16 import org.eclipse.core.databinding.observable.list.WritableList;
17 import org.eclipse.core.databinding.observable.map.IObservableMap;
18 import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
19 import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
20 import org.eclipse.jface.viewers.ISelectionChangedListener;
21 import org.eclipse.jface.viewers.IStructuredSelection;
22 import org.eclipse.jface.viewers.SelectionChangedEvent;
23 import org.eclipse.jface.viewers.StructuredSelection;
24 import org.eclipse.jface.viewers.TableViewer;
25 import org.eclipse.jface.viewers.ViewerComparator;
26 import org.eclipse.jface.wizard.WizardPage;
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.events.KeyAdapter;
29 import org.eclipse.swt.events.KeyEvent;
30 import org.eclipse.swt.events.ModifyEvent;
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.Button;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Display;
39 import org.eclipse.swt.widgets.Event;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.Listener;
42 import org.eclipse.swt.widgets.Table;
43 import org.eclipse.swt.widgets.TableItem;
44 import org.eclipse.swt.widgets.Text;
45
46 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
47 import eu.etaxonomy.cdm.model.name.NonViralName;
48 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
49 import eu.etaxonomy.taxeditor.ITaxEditorConstants;
50 import eu.etaxonomy.taxeditor.TaxEditorPlugin;
51 import eu.etaxonomy.taxeditor.editor.name.CdmParserController;
52 import eu.etaxonomy.taxeditor.model.CdmUtil;
53
54 /**
55 * An all-in-one relation wizard page where the user chooses a related name, a
56 * relationship type, and the relation's directionality.
57 *
58 * Note: does not yet return relation to wizard.
59 *
60 * @author p.ciardelli
61 * @created 04.06.2008
62 * @version 1.0
63 */
64 public class ChooseRelatedNameWizardPage extends WizardPage {
65 private static final Logger logger = Logger
66 .getLogger(ChooseRelatedNameWizardPage.class);
67
68 private NameRelationWizardModel relationModel;
69
70 private Text txtNewName;
71 private Text txtName;
72 private boolean nameSelected = false;
73
74 private Table searchResultsTable;
75 private WritableList observableSearchResultsList = new WritableList();
76 private NonViralName noResultsDummyName = NonViralName.NewInstance(null);
77
78 private Button btnSearch;
79
80 public ChooseRelatedNameWizardPage(NameRelationWizardModel relationModel) {
81 super("");
82
83 this.relationModel = relationModel;
84
85 setTitle("Choose related name for '" + relationModel.getBaseName() + "\".");
86 setDescription("You can either choose from search results or create a new name. Use \"*\" for wildcard searching.");
87 }
88
89 public void createControl(Composite parent) {
90
91 // Create composite for popup dialog
92 Composite container = new Composite(parent, SWT.NULL);
93 final GridLayout gridLayout = new GridLayout();
94 gridLayout.numColumns = 3;
95 container.setLayout(gridLayout);
96 setControl(container);
97
98 // Create search text
99 final Label lblChooseName = new Label(container, SWT.NONE);
100 lblChooseName.setText("Choose name for relation:");
101 new Label(container, SWT.NONE);
102 new Label(container, SWT.NONE);
103
104 // Create input field for search term
105 txtName = new Text(container, SWT.BORDER);
106 txtName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
107
108 // Listen for user hitting <CR> in input field
109 txtName.addKeyListener(new KeyAdapter() {
110 public void keyReleased(KeyEvent e) {
111 int key = e.keyCode;
112 if (key == SWT.CR) {
113 populateSearchResults();
114 }
115 }
116 });
117
118 // Create "Search" button
119 btnSearch = new Button(container, SWT.NONE);
120 btnSearch.setEnabled(false);
121 btnSearch.setLayoutData(new GridData());
122 btnSearch.setText("Search");
123 btnSearch.addSelectionListener(new SelectionAdapter() {
124
125 // Populate search results resultsTable after clicking button
126 public void widgetSelected(SelectionEvent e) {
127 populateSearchResults();
128 }
129 });
130
131 // Create "Create New Name" button
132 final Button btnNewName = new Button(container, SWT.NONE);
133 btnNewName.setEnabled(false);
134 btnNewName.setText("Create New Name");
135 btnNewName.addSelectionListener(new SelectionAdapter() {
136
137 // Use input field text to create and select a new name
138 public void widgetSelected(SelectionEvent e) {
139 setRawNewName(txtName.getText());
140 btnNewName.setEnabled(false);
141 }
142 });
143
144 // Create results viewer
145 createSearchResultsViewer(container);
146
147 // Enable / disable buttons according to whether there is input text or not
148 txtName.addModifyListener(new ModifyListener() {
149 public void modifyText(ModifyEvent e) {
150 if (txtName.getText().length() > 0) {
151 btnNewName.setEnabled(true);
152 btnSearch.setEnabled(true);
153 } else {
154 btnNewName.setEnabled(false);
155 btnSearch.setEnabled(false);
156 }
157 }
158 });
159
160 // Create text field to display selected name
161 txtNewName = new Text(container, SWT.BORDER);
162 final GridData gd_txtNewName = new GridData(SWT.FILL, SWT.CENTER, true,
163 false, 3, 1);
164 txtNewName.setLayoutData(gd_txtNewName);
165 txtNewName.setFont(TaxEditorPlugin.getDefault().getFont
166 (ITaxEditorConstants.CHOOSE_NAME_TEXT_FONT));
167 txtNewName.setBackground(Display.getCurrent().getSystemColor(
168 SWT.COLOR_WHITE));
169 txtNewName.setEditable(false);
170
171 // If editing an existing relation, show the related name
172 if (relationModel.getRelatedName() != null) {
173 txtNewName.setText(CdmUtil.getDisplayName(relationModel.getRelatedName()));
174 nameSelected = true;
175 }
176 }
177
178 protected void populateSearchResults() {
179 String searchText = txtName.getText();
180 btnSearch.setEnabled(false);
181 Set<TaxonNameBase> results = CdmUtil.getNameByName(searchText);
182
183 observableSearchResultsList.clear();
184 if (results.size() == 0) {
185 // Populate observable list with dummy name
186 observableSearchResultsList.add(noResultsDummyName);
187 } else {
188 observableSearchResultsList.addAll(results);
189 }
190 btnSearch.setEnabled(true);
191 }
192
193 private void createSearchResultsViewer(Composite parent) {
194 // TODO no reason to use observable lists and all that nonsense
195 // implement à la propertysheet.reference.ReferenceSearchDialog instead
196 TableViewer searchResultsViewer = new TableViewer(parent, SWT.BORDER);
197
198 // Add content provider
199 ObservableListContentProvider searchResultsProviderList = new ObservableListContentProvider();
200 searchResultsViewer.setContentProvider(searchResultsProviderList);
201
202 // Label provider that listens for changes to name cache
203 IObservableMap[] searchResultsLabelProviderMaps = BeansObservables
204 .observeMaps(searchResultsProviderList.getKnownElements(),
205 TaxonNameBase.class, new String[] { "titleCache" });
206 searchResultsViewer.setLabelProvider(new ObservableMapLabelProvider(
207 searchResultsLabelProviderMaps));
208
209 // Listens for new taxa opened for editing
210 searchResultsViewer.setInput(observableSearchResultsList);
211
212 // Sort alphabetically
213 searchResultsViewer.setComparator(new ViewerComparator());
214
215 // On click, put name in new name field
216 searchResultsViewer.addSelectionChangedListener(new ISelectionChangedListener() {
217 public void selectionChanged(SelectionChangedEvent event) {
218 IStructuredSelection selection = (StructuredSelection) event
219 .getSelection();
220 Object element = selection.getFirstElement();
221 if (element instanceof TaxonNameBase) {
222 setNewName((TaxonNameBase) element);
223 }
224 }
225 });
226
227 searchResultsTable = searchResultsViewer.getTable();
228 searchResultsTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
229 true, 3, 1));
230 searchResultsTable.addListener(SWT.PaintItem, new Listener() {
231 /**
232 * If MenuItem with dummy name is being drawn, put it in italics.
233 *
234 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
235 */
236 public void handleEvent(Event event) {
237 Object data = event.item.getData();
238 if (data instanceof TaxonNameBase
239 && ((TaxonNameBase) data).equals(noResultsDummyName)) {
240 TableItem item = (TableItem) event.item;
241 item.setFont(TaxEditorPlugin.getDefault().getFont(
242 ITaxEditorConstants.MENU_ITEM_ITALICS_FONT));
243 item.setText("Search returned no results.");
244 }
245 }
246 });
247 }
248
249 @Override
250 public boolean canFlipToNextPage() {
251 return isPageComplete();
252 }
253
254 public boolean isPageComplete() {
255 return (nameSelected);
256 }
257
258 private void updatePage() {
259 getWizard().getContainer().updateButtons();
260 }
261
262 private void setNewName(TaxonNameBase name) {
263 nameSelected = true;
264 relationModel.setRelatedName(name);
265 txtNewName.setText(CdmUtil.getDisplayName(name));
266 updatePage();
267 }
268
269 private void setRawNewName(String rawName) {
270 nameSelected = true;
271 NomenclaturalCode parentCode = relationModel.getBaseName().getNomenclaturalCode();
272 TaxonNameBase newName = CdmParserController.parseFullReference(rawName, parentCode, null);
273 relationModel.setRelatedName(newName);
274 txtNewName.setText(rawName + " (new)");
275 updatePage();
276 }
277 }