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
.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
;
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
;
54 * An all-in-one relation wizard page where the user chooses a related name, a
55 * relationship type, and the relation's directionality.
57 * Note: does not yet return relation to wizard.
63 public class ChooseRelatedNameWizardPage
extends WizardPage
{
64 private static final Logger logger
= Logger
65 .getLogger(ChooseRelatedNameWizardPage
.class);
67 private NameRelationWizardModel relationModel
;
69 private Text txtNewName
;
71 private boolean nameSelected
= false;
73 private Table searchResultsTable
;
74 private WritableList observableSearchResultsList
= new WritableList();
75 private NonViralName noResultsDummyName
= NonViralName
.NewInstance(null);
77 private Button btnSearch
;
79 public ChooseRelatedNameWizardPage(NameRelationWizardModel relationModel
) {
82 this.relationModel
= relationModel
;
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.");
88 public void createControl(Composite parent
) {
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
);
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
);
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));
107 // Listen for user hitting <CR> in input field
108 txtName
.addKeyListener(new KeyAdapter() {
109 public void keyReleased(KeyEvent e
) {
112 populateSearchResults();
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() {
124 // Populate search results resultsTable after clicking button
125 public void widgetSelected(SelectionEvent e
) {
126 populateSearchResults();
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() {
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);
143 // Create results viewer
144 createSearchResultsViewer(container
);
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);
153 btnNewName
.setEnabled(false);
154 btnSearch
.setEnabled(false);
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,
163 txtNewName
.setLayoutData(gd_txtNewName
);
164 txtNewName
.setFont(TaxEditorPlugin
.getDefault().getFont
165 (ITaxEditorConstants
.CHOOSE_NAME_TEXT_FONT
));
166 txtNewName
.setBackground(Display
.getCurrent().getSystemColor(
168 txtNewName
.setEditable(false);
170 // If editing an existing relation, show the related name
171 if (relationModel
.getRelatedName() != null) {
172 txtNewName
.setText(CdmUtil
.getDisplayName(relationModel
.getRelatedName()));
177 protected void populateSearchResults() {
178 String searchText
= txtName
.getText();
179 btnSearch
.setEnabled(false);
180 Set
<TaxonNameBase
> results
= CdmUtil
.getNameByName(searchText
);
182 observableSearchResultsList
.clear();
183 if (results
.size() == 0) {
184 // Populate observable list with dummy name
185 observableSearchResultsList
.add(noResultsDummyName
);
187 observableSearchResultsList
.addAll(results
);
189 btnSearch
.setEnabled(true);
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
);
197 // Add content provider
198 ObservableListContentProvider searchResultsProviderList
= new ObservableListContentProvider();
199 searchResultsViewer
.setContentProvider(searchResultsProviderList
);
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
));
208 // Listens for new taxa opened for editing
209 searchResultsViewer
.setInput(observableSearchResultsList
);
211 // Sort alphabetically
212 searchResultsViewer
.setComparator(new ViewerComparator());
214 // On double click, open name editor
215 searchResultsViewer
.addDoubleClickListener(new IDoubleClickListener() {
217 public void doubleClick(DoubleClickEvent 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
= CdmUtil
.parseFullReference(rawName
, parentCode
, null);
273 relationModel
.setRelatedName(newName
);
274 txtNewName
.setText(rawName
+ " (new)");