<CR> in name relation - select name now the same as clicking the "Search" button.
[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.DoubleClickEvent;
21 import org.eclipse.jface.viewers.IDoubleClickListener;
22 import org.eclipse.jface.viewers.IStructuredSelection;
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.model.CdmUtil;
52
53 /**
54 * An all-in-one relation wizard page where the user chooses a related name, a
55 * relationship type, and the relation's directionality.
56 *
57 * Note: does not yet return relation to wizard.
58 *
59 * @author p.ciardelli
60 * @created 04.06.2008
61 * @version 1.0
62 */
63 public class ChooseRelatedNameWizardPage extends WizardPage {
64 private static final Logger logger = Logger
65 .getLogger(ChooseRelatedNameWizardPage.class);
66
67 private NameRelationWizardModel relationModel;
68
69 private Text txtNewName;
70 private Text txtName;
71 private boolean nameSelected = false;
72
73 private Table searchResultsTable;
74 private WritableList observableSearchResultsList = new WritableList();
75 private NonViralName noResultsDummyName = NonViralName.NewInstance(null);
76
77 private Button btnSearch;
78
79 public ChooseRelatedNameWizardPage(NameRelationWizardModel relationModel) {
80 super("");
81
82 this.relationModel = relationModel;
83
84 setTitle("Choose related name for '" + relationModel.getBaseName() + "\".");
85 setDescription("You can either choose from search results or create a new name. Use \"*\" for wildcard searching.");
86 }
87
88 public void createControl(Composite parent) {
89
90 // Create composite for popup dialog
91 Composite container = new Composite(parent, SWT.NULL);
92 final GridLayout gridLayout = new GridLayout();
93 gridLayout.numColumns = 3;
94 container.setLayout(gridLayout);
95 setControl(container);
96
97 // Create search text
98 final Label lblChooseName = new Label(container, SWT.NONE);
99 lblChooseName.setText("Choose name for relation:");
100 new Label(container, SWT.NONE);
101 new Label(container, SWT.NONE);
102
103 // Create input field for search term
104 txtName = new Text(container, SWT.BORDER);
105 txtName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
106
107 // Listen for user hitting <CR> in input field
108 txtName.addKeyListener(new KeyAdapter() {
109 public void keyReleased(KeyEvent e) {
110 int key = e.keyCode;
111 if (key == SWT.CR) {
112 populateSearchResults();
113 }
114 }
115 });
116
117 // Create "Search" button
118 btnSearch = new Button(container, SWT.NONE);
119 btnSearch.setEnabled(false);
120 btnSearch.setLayoutData(new GridData());
121 btnSearch.setText("Search");
122 btnSearch.addSelectionListener(new SelectionAdapter() {
123
124 // Populate search results resultsTable after clicking button
125 public void widgetSelected(SelectionEvent e) {
126 populateSearchResults();
127 }
128 });
129
130 // Create "Create New Name" button
131 final Button btnNewName = new Button(container, SWT.NONE);
132 btnNewName.setEnabled(false);
133 btnNewName.setText("Create New Name");
134 btnNewName.addSelectionListener(new SelectionAdapter() {
135
136 // Use input field text to create and select a new name
137 public void widgetSelected(SelectionEvent e) {
138 setRawNewName(txtName.getText());
139 btnNewName.setEnabled(false);
140 }
141 });
142
143 // Create results viewer
144 createSearchResultsViewer(container);
145
146 // Enable / disable buttons according to whether there is input text or not
147 txtName.addModifyListener(new ModifyListener() {
148 public void modifyText(ModifyEvent e) {
149 if (txtName.getText().length() > 0) {
150 btnNewName.setEnabled(true);
151 btnSearch.setEnabled(true);
152 } else {
153 btnNewName.setEnabled(false);
154 btnSearch.setEnabled(false);
155 }
156 }
157 });
158
159 // Create text field to display selected name
160 txtNewName = new Text(container, SWT.BORDER);
161 final GridData gd_txtNewName = new GridData(SWT.FILL, SWT.CENTER, true,
162 false, 3, 1);
163 txtNewName.setLayoutData(gd_txtNewName);
164 txtNewName.setFont(TaxEditorPlugin.getDefault().getFont
165 (ITaxEditorConstants.CHOOSE_NAME_TEXT_FONT));
166 txtNewName.setBackground(Display.getCurrent().getSystemColor(
167 SWT.COLOR_WHITE));
168 txtNewName.setEditable(false);
169
170 // If editing an existing relation, show the related name
171 if (relationModel.getRelatedName() != null) {
172 txtNewName.setText(CdmUtil.getDisplayName(relationModel.getRelatedName()));
173 nameSelected = true;
174 }
175 }
176
177 protected void populateSearchResults() {
178 String searchText = txtName.getText();
179 btnSearch.setEnabled(false);
180 Set<TaxonNameBase> results = CdmUtil.getNameByName(searchText);
181
182 observableSearchResultsList.clear();
183 if (results.size() == 0) {
184 // Populate observable list with dummy name
185 observableSearchResultsList.add(noResultsDummyName);
186 } else {
187 observableSearchResultsList.addAll(results);
188 }
189 btnSearch.setEnabled(true);
190 }
191
192 private void createSearchResultsViewer(Composite parent) {
193 // TODO no reason to use observable lists and all that nonsense
194 // implement à la propertysheet.reference.ReferenceSearchDialog instead
195 TableViewer searchResultsViewer = new TableViewer(parent, SWT.BORDER);
196
197 // Add content provider
198 ObservableListContentProvider searchResultsProviderList = new ObservableListContentProvider();
199 searchResultsViewer.setContentProvider(searchResultsProviderList);
200
201 // Label provider that listens for changes to name cache
202 IObservableMap[] searchResultsLabelProviderMaps = BeansObservables
203 .observeMaps(searchResultsProviderList.getKnownElements(),
204 TaxonNameBase.class, new String[] { "titleCache" });
205 searchResultsViewer.setLabelProvider(new ObservableMapLabelProvider(
206 searchResultsLabelProviderMaps));
207
208 // Listens for new taxa opened for editing
209 searchResultsViewer.setInput(observableSearchResultsList);
210
211 // Sort alphabetically
212 searchResultsViewer.setComparator(new ViewerComparator());
213
214 // On double click, open name editor
215 searchResultsViewer.addDoubleClickListener(new IDoubleClickListener() {
216
217 public void doubleClick(DoubleClickEvent 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 = CdmUtil.parseFullReference(rawName, parentCode, null);
273 relationModel.setRelatedName(newName);
274 txtNewName.setText(rawName + " (new)");
275 updatePage();
276 }
277 }