Taxonomic tree provider substantially re-programmed, cleaned up.
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / view / SelectTaxonDialog.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.view;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import org.apache.log4j.Logger;
16 import org.eclipse.core.databinding.observable.set.IObservableSet;
17 import org.eclipse.jface.dialogs.Dialog;
18 import org.eclipse.jface.dialogs.IDialogConstants;
19 import org.eclipse.jface.viewers.DoubleClickEvent;
20 import org.eclipse.jface.viewers.IDoubleClickListener;
21 import org.eclipse.jface.viewers.StructuredSelection;
22 import org.eclipse.jface.viewers.TableViewer;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.events.FocusEvent;
25 import org.eclipse.swt.events.FocusListener;
26 import org.eclipse.swt.events.SelectionAdapter;
27 import org.eclipse.swt.events.SelectionEvent;
28 import org.eclipse.swt.graphics.Font;
29 import org.eclipse.swt.graphics.FontData;
30 import org.eclipse.swt.graphics.Point;
31 import org.eclipse.swt.layout.FillLayout;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.layout.RowData;
35 import org.eclipse.swt.layout.RowLayout;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Control;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.Event;
41 import org.eclipse.swt.widgets.Group;
42 import org.eclipse.swt.widgets.Label;
43 import org.eclipse.swt.widgets.Listener;
44 import org.eclipse.swt.widgets.Shell;
45 import org.eclipse.swt.widgets.Text;
46 import org.eclipse.swt.widgets.TreeItem;
47
48 import com.swtdesigner.SWTResourceManager;
49
50 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
51 import eu.etaxonomy.cdm.model.taxon.Taxon;
52 import eu.etaxonomy.taxeditor.ITaxEditorConstants;
53 import eu.etaxonomy.taxeditor.TaxEditorPlugin;
54 import eu.etaxonomy.taxeditor.model.CdmUtil;
55
56 /**
57 * This is a generic dialog that allows the user to choose a taxon via the
58 * taxonomic tree, recently selected names, or search.
59 *
60 * @author p.ciardelli
61 * @created 27.05.2008
62 * @version 1.0
63 */
64 public class SelectTaxonDialog extends Dialog {
65 private static final Logger logger = Logger
66 .getLogger(SelectTaxonDialog.class);
67
68 public static final String TAXON_TO_SYNONYM = "taxontosynonym";
69
70 private String dialogType;
71 private String shellText;
72 private String descriptionText;
73 private Text taxonNameText;
74
75 private TaxonomicTreeViewer treeViewer;
76 private Taxon taxon;
77 private Taxon destinationTaxon;
78
79 private List<Button> buttons = new ArrayList<Button>();
80
81 private Composite selectComposite;
82
83 public SelectTaxonDialog(Shell parentShell, String dialogType) {
84 super(parentShell);
85 this.dialogType = dialogType;
86 }
87
88 public Taxon open(Taxon taxon) {
89 this.taxon = taxon;
90
91 if (dialogType.equals(TAXON_TO_SYNONYM)) {
92 this.shellText = "Choose an accepted name for \""
93 + CdmUtil.getDisplayName(taxon) + "\"";
94 this.descriptionText = "You have chosen to turn \""
95 + CdmUtil.getDisplayName(taxon)
96 + "\" into a synonym. Please choose a new accepted name from one of the following options.";
97 }
98
99 int returnCode = super.open();
100 if (returnCode == OK) {
101 return destinationTaxon;
102 }
103 return null;
104 }
105
106 /**
107 * Create contents of the dialog
108 *
109 * @param parent
110 */
111 @Override
112 protected Control createDialogArea(Composite parent) {
113 parent.setRedraw(true);
114 Composite container = (Composite) super.createDialogArea(parent);
115 final GridLayout gridLayout = new GridLayout();
116 gridLayout.numColumns = 2;
117 container.setLayout(gridLayout);
118
119 final Label descriptionLabel = new Label(container, SWT.WRAP);
120 descriptionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, true,
121 false, 2, 1));
122 descriptionLabel.setText(descriptionText);
123
124 final Group taxTreeGroup = new Group(container, SWT.NONE);
125 taxTreeGroup.setLayout(new GridLayout());
126 final GridData gd_group_1 = new GridData(SWT.FILL, SWT.FILL, true, true);
127 gd_group_1.heightHint = 83;
128 taxTreeGroup.setLayoutData(gd_group_1);
129
130 final Button chooseTreeButton = new Button(taxTreeGroup, SWT.RADIO);
131 buttons.add(chooseTreeButton);
132 chooseTreeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
133 false));
134 chooseTreeButton.setText("Choose from taxonomic tree");
135
136 Composite taxTreeComposite = new Composite(taxTreeGroup, SWT.BORDER);
137 taxTreeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
138 true));
139 taxTreeComposite.setLayout(new FillLayout());
140 taxTreeComposite.setBackground(Display.getCurrent().getSystemColor(
141 SWT.COLOR_WHITE));
142
143 treeViewer = new TaxonomicTreeViewer(taxTreeComposite);
144
145 IObservableSet observableTaxonSet = TaxEditorPlugin.getDefault()
146 .getObservableSessionTaxa();
147 treeViewer.setLabelProvider(new TaxonomicTreeLabelProvider(
148 observableTaxonSet) {
149
150 });
151 treeViewer.getTree().addFocusListener(
152 new SelectButtonFocusListener(chooseTreeButton));
153 treeViewer.addDoubleClickListener(new SelectTaxonDoubleClickListener());
154 treeViewer.getTree().addListener(SWT.PaintItem, new Listener() {
155
156 /** If MenuItem with taxon is being drawn, put it in italics.
157 *
158 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
159 **/
160 public void handleEvent(Event event) {
161 Object data = event.item.getData();
162 if (data instanceof Taxon && ((Taxon) data).equals(taxon)) {
163 ((TreeItem) event.item).setFont(TaxEditorPlugin.getDefault().getFont
164 (ITaxEditorConstants.MENU_ITEM_ITALICS));
165 }
166 }
167 });
168
169 // Open up tree to reveal taxon
170 treeViewer.revealTaxon(taxon);
171
172 final Composite rightPaneComposite = new Composite(container, SWT.NONE);
173 rightPaneComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
174 true));
175 rightPaneComposite.setLayout(new FillLayout(SWT.VERTICAL
176 | SWT.HORIZONTAL));
177
178 final Group recentNamesGroup = new Group(rightPaneComposite, SWT.NONE);
179 recentNamesGroup.setLayout(new GridLayout());
180
181 final Button chooseRecentNamesButton = new Button(recentNamesGroup,
182 SWT.RADIO);
183 buttons.add(chooseRecentNamesButton);
184 chooseRecentNamesButton.setText("Choose from recently viewed taxa");
185
186 Composite recentNamesComposite = new Composite(recentNamesGroup,
187 SWT.BORDER);
188 recentNamesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
189 true, true));
190 recentNamesComposite.setLayout(new FillLayout());
191 recentNamesComposite.setBackground(Display.getCurrent().getSystemColor(
192 SWT.COLOR_WHITE));
193
194 TableViewer recentNamesViewer = new RecentNamesTableViewer(
195 recentNamesComposite);
196 recentNamesViewer
197 .addDoubleClickListener(new SelectTaxonDoubleClickListener());
198 recentNamesViewer.getTable().addFocusListener(
199 new SelectButtonFocusListener(chooseRecentNamesButton));
200
201 final Group searchGroup = new Group(rightPaneComposite, SWT.NONE);
202 final GridLayout gridLayout_1 = new GridLayout();
203 gridLayout_1.numColumns = 2;
204 searchGroup.setLayout(gridLayout_1);
205
206 final Button searchForNameButton = new Button(searchGroup, SWT.RADIO);
207 buttons.add(searchForNameButton);
208 searchForNameButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER,
209 true, false));
210 searchForNameButton.setText("Search for name of accepted taxon");
211 new Label(searchGroup, SWT.NONE);
212
213 final Text searchText = new Text(searchGroup, SWT.BORDER);
214 searchText
215 .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
216 searchText.setForeground(SWTResourceManager.getColor(192, 192, 192));
217 searchText.setText("Use \"*\" for wildcard searching");
218 searchText.addFocusListener(new SelectButtonFocusListener(
219 searchForNameButton) {
220
221 public void focusGained(FocusEvent e) {
222 selectButton(button);
223 searchText.setForeground(SWTResourceManager.getColor(0, 0, 0));
224 searchText.setText("");
225 }
226
227 public void focusLost(FocusEvent e) {
228 if (searchText.getText() == "") {
229 searchText.setForeground(SWTResourceManager.getColor(192,
230 192, 192));
231 searchText.setText("Use \"*\" for wildcard searching");
232 }
233 }
234
235 });
236
237 final Button searchButton = new Button(searchGroup, SWT.NONE);
238 searchButton.setLayoutData(new GridData());
239 searchButton.setText("Search");
240
241 selectComposite = new Composite(container, SWT.NONE);
242 selectComposite.setLayout(new RowLayout());
243 selectComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.BOTTOM, true,
244 false, 2, 1));
245
246 taxonNameText = new Text(selectComposite, SWT.BORDER);
247 taxonNameText.setFont(SWTResourceManager.getFont("", 12, SWT.BOLD));
248 taxonNameText.setBackground(SWTResourceManager.getColor(255, 255, 255));
249 final RowData rd_text = new RowData();
250 rd_text.width = 400;
251 taxonNameText.setLayoutData(rd_text);
252 taxonNameText.setEditable(false);
253
254 //
255 initButtons();
256
257 return container;
258 }
259
260 public void setSelectedTaxon(Taxon taxon) {
261
262 this.destinationTaxon = taxon;
263 TaxonNameBase taxonName = taxon.getName();
264 if (taxonName == null) {
265 return;
266 }
267
268 taxonNameText.setText(taxonName.getTitleCache());
269
270 setOkEnabled(true);
271 }
272
273 /**
274 * Create contents of the button bar
275 *
276 * @param parent
277 */
278 @Override
279 protected void createButtonsForButtonBar(Composite parent) {
280 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
281 true);
282 setOkEnabled(false);
283 createButton(parent, IDialogConstants.CANCEL_ID,
284 IDialogConstants.CANCEL_LABEL, false);
285 }
286
287 public void setOkEnabled(boolean enabled) {
288 getButton(IDialogConstants.OK_ID).setEnabled(enabled);
289 }
290
291 private void initButtons() {
292 for (Button button : buttons) {
293 button.addSelectionListener(new SelectionAdapter() {
294 public void widgetSelected(final SelectionEvent e) {
295 selectButton((Button) e.getSource());
296 }
297 });
298 }
299 }
300
301 /**
302 * Since buttons are not in the same layout group, the others are not
303 * automatically deselected when one is selected. This method takes care of
304 * that.
305 *
306 * @param button
307 */
308 private void selectButton(Button selectedButton) {
309 for (Button button : buttons) {
310 if (button == selectedButton)
311 button.setSelection(true);
312 else
313 button.setSelection(false);
314 }
315 }
316
317 /**
318 * Return the initial size of the dialog
319 */
320 @Override
321 protected Point getInitialSize() {
322 return new Point(700, 500);
323 }
324
325 protected void configureShell(Shell newShell) {
326 super.configureShell(newShell);
327 newShell.setImage(TaxEditorPlugin.getDefault().getImage(
328 ITaxEditorConstants.EDIT_ICON));
329 newShell.setText(shellText);
330 }
331
332 class SelectButtonFocusListener implements FocusListener {
333
334 /**
335 * The button whose group has gained focus.
336 */
337 Button button;
338
339 SelectButtonFocusListener(Button button) {
340 this.button = button;
341 }
342
343 public void focusGained(FocusEvent e) {
344 selectButton(button);
345 }
346
347 public void focusLost(FocusEvent e) {
348 }
349
350 }
351
352 class SelectTaxonDoubleClickListener implements IDoubleClickListener {
353
354 public void doubleClick(DoubleClickEvent event) {
355 Taxon taxon = null;
356 try {
357 taxon = (Taxon) ((StructuredSelection) event.getSelection())
358 .getFirstElement();
359 } catch (Exception e) {
360 e.printStackTrace();
361 taxon = null;
362 }
363 if (taxon.equals(SelectTaxonDialog.this.taxon)) {
364 return;
365 }
366
367 setSelectedTaxon(taxon);
368 }
369 }
370 }