2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.propertysheet
.namerelationswizard
;
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
;
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
;
55 * An all-in-one relation wizard page where the user chooses a related name, a
56 * relationship type, and the relation's directionality.
58 * Note: does not yet return relation to wizard.
64 public class ChooseRelatedNameWizardPage
extends WizardPage
{
65 private static final Logger logger
= Logger
66 .getLogger(ChooseRelatedNameWizardPage
.class);
68 private NameRelationWizardModel relationModel
;
70 private Text txtNewName
;
72 private boolean nameSelected
= false;
74 private Table searchResultsTable
;
75 private WritableList observableSearchResultsList
= new WritableList();
76 private NonViralName noResultsDummyName
= NonViralName
.NewInstance(null);
78 private Button btnSearch
;
80 public ChooseRelatedNameWizardPage(NameRelationWizardModel relationModel
) {
83 this.relationModel
= relationModel
;
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.");
89 public void createControl(Composite parent
) {
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
);
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
);
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));
108 // Listen for user hitting <CR> in input field
109 txtName
.addKeyListener(new KeyAdapter() {
110 public void keyReleased(KeyEvent e
) {
113 populateSearchResults();
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() {
125 // Populate search results resultsTable after clicking button
126 public void widgetSelected(SelectionEvent e
) {
127 populateSearchResults();
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() {
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);
144 // Create results viewer
145 createSearchResultsViewer(container
);
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);
154 btnNewName
.setEnabled(false);
155 btnSearch
.setEnabled(false);
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,
164 txtNewName
.setLayoutData(gd_txtNewName
);
165 txtNewName
.setFont(TaxEditorPlugin
.getDefault().getFont
166 (ITaxEditorConstants
.CHOOSE_NAME_TEXT_FONT
));
167 txtNewName
.setBackground(Display
.getCurrent().getSystemColor(
169 txtNewName
.setEditable(false);
171 // If editing an existing relation, show the related name
172 if (relationModel
.getRelatedName() != null) {
173 txtNewName
.setText(CdmUtil
.getDisplayName(relationModel
.getRelatedName()));
178 protected void populateSearchResults() {
179 String searchText
= txtName
.getText();
180 btnSearch
.setEnabled(false);
181 Set
<TaxonNameBase
> results
= CdmUtil
.getNameByName(searchText
);
183 observableSearchResultsList
.clear();
184 if (results
.size() == 0) {
185 // Populate observable list with dummy name
186 observableSearchResultsList
.add(noResultsDummyName
);
188 observableSearchResultsList
.addAll(results
);
190 btnSearch
.setEnabled(true);
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
);
198 // Add content provider
199 ObservableListContentProvider searchResultsProviderList
= new ObservableListContentProvider();
200 searchResultsViewer
.setContentProvider(searchResultsProviderList
);
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
));
209 // Listens for new taxa opened for editing
210 searchResultsViewer
.setInput(observableSearchResultsList
);
212 // Sort alphabetically
213 searchResultsViewer
.setComparator(new ViewerComparator());
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
220 Object element
= selection
.getFirstElement();
221 if (element
instanceof TaxonNameBase
) {
222 setNewName((TaxonNameBase
) element
);
227 searchResultsTable
= searchResultsViewer
.getTable();
228 searchResultsTable
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true,
230 searchResultsTable
.addListener(SWT
.PaintItem
, new Listener() {
232 * If MenuItem with dummy name is being drawn, put it in italics.
234 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
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.");
250 public boolean canFlipToNextPage() {
251 return isPageComplete();
254 public boolean isPageComplete() {
255 return (nameSelected
);
258 private void updatePage() {
259 getWizard().getContainer().updateButtons();
262 private void setNewName(TaxonNameBase name
) {
264 relationModel
.setRelatedName(name
);
265 txtNewName
.setText(CdmUtil
.getDisplayName(name
));
269 private void setRawNewName(String rawName
) {
271 NomenclaturalCode parentCode
= relationModel
.getBaseName().getNomenclaturalCode();
272 TaxonNameBase newName
= CdmParserController
.parseFullReference(rawName
, parentCode
, null);
273 relationModel
.setRelatedName(newName
);
274 txtNewName
.setText(rawName
+ " (new)");