Project

General

Profile

Download (11.6 KB) Statistics
| Branch: | Tag: | Revision:
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.navigation.search;
11

    
12
import java.util.List;
13

    
14
import javax.annotation.PostConstruct;
15
import javax.inject.Inject;
16

    
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.e4.ui.model.application.MApplication;
19
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
20
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
21
import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
22
import org.eclipse.e4.ui.workbench.modeling.EModelService;
23
import org.eclipse.e4.ui.workbench.modeling.EPartService;
24
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.events.FocusEvent;
27
import org.eclipse.swt.events.FocusListener;
28
import org.eclipse.swt.events.KeyAdapter;
29
import org.eclipse.swt.events.KeyEvent;
30
import org.eclipse.swt.events.SelectionAdapter;
31
import org.eclipse.swt.events.SelectionEvent;
32
import org.eclipse.swt.graphics.Point;
33
import org.eclipse.swt.graphics.Rectangle;
34
import org.eclipse.swt.layout.RowData;
35
import org.eclipse.swt.layout.RowLayout;
36
import org.eclipse.swt.widgets.Composite;
37
import org.eclipse.swt.widgets.Control;
38
import org.eclipse.swt.widgets.Menu;
39
import org.eclipse.swt.widgets.MenuItem;
40
import org.eclipse.swt.widgets.Text;
41
import org.eclipse.swt.widgets.ToolBar;
42
import org.eclipse.swt.widgets.ToolItem;
43
import org.eclipse.ui.IMemento;
44
import org.eclipse.ui.PlatformUI;
45
import org.eclipse.ui.swt.IFocusService;
46

    
47
import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;
48
import eu.etaxonomy.taxeditor.model.AbstractUtility;
49
import eu.etaxonomy.taxeditor.model.IContextListener;
50
import eu.etaxonomy.taxeditor.model.MessagingUtils;
51
import eu.etaxonomy.taxeditor.navigation.AppModelId;
52
import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
53
import eu.etaxonomy.taxeditor.navigation.search.e4.SearchResultViewE4;
54
import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
55
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
56
import eu.etaxonomy.taxeditor.preference.Resources;
57
import eu.etaxonomy.taxeditor.store.CdmStore;
58
import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
59

    
60
/**
61
 * @author n.hoffmann
62
 * @author e.-m.lee
63
 * @created 15.04.2009
64
 * @version 1.0
65
 */
66
public class SearchBar implements IContextListener{
67

    
68
    public static final String NAVIGATION_STACK_ID = "navigation";
69

    
70
    private Text text_search;
71
	private ToolBar toolBar;
72

    
73
	private final String defaultText = Messages.SearchBar_0;
74

    
75
	@Inject
76
	private EPartService partService;
77

    
78
	@Inject
79
	private MApplication application;
80

    
81
	@Inject
82
	private EModelService modelService;
83

    
84
	final private ConfigurationSelectionListener configurationListener = new ConfigurationSelectionListener();
85

    
86
	/** {@inheritDoc} */
87
	@PostConstruct
88
	protected Control createControl(Composite parent) {
89
		Composite composite = new Composite(parent, SWT.NONE);
90

    
91
		createLayout(composite);
92
		createSearchTextField(composite);
93
		createToolBar(composite);
94
		registerAtFocusService();
95
		//register for context refreshes
96
		CdmStore.getContextManager().addContextListener(this);
97

    
98
		return composite;
99
	}
100

    
101
	/**
102
	 * Handles focus changes for the search textfield.
103
	 */
104
	private void registerAtFocusService() {
105
		IFocusService focusService =
106
			PlatformUI.getWorkbench().getService(IFocusService.class);
107
		if (focusService != null) {
108
			focusService.addFocusTracker(text_search, "navigation.textControlId");
109
		}
110
	}
111

    
112
	/**
113
	 * Creates the search toolbar.
114
	 * @param composite
115
	 */
116
	private void createToolBar(Composite composite) {
117
		toolBar = new ToolBar(composite, SWT.NULL);
118

    
119
		ToolItem toolItem = new ToolItem(toolBar, SWT.DROP_DOWN | SWT.BORDER);
120
		toolItem.setText(Messages.SearchBar_1);
121
		toolBar.setEnabled(false);
122

    
123
		DropdownSelectionListener dropdownListener = new DropdownSelectionListener(
124
				toolItem);
125

    
126
		for(SearchOption searchOption : SearchOption.values()){
127
			dropdownListener.add(searchOption);
128
		}
129

    
130
		toolItem.addSelectionListener(dropdownListener);
131
	}
132

    
133
	/**
134
	 * Creates the search textfield.
135
	 * @param composite
136
	 */
137
	private void createSearchTextField(Composite composite) {
138
		// TODO for some reason the text_search composite has a margin when
139
		// either SWT.BORDER or SWT.SEARCH
140
		// is applied. I am not sure how to get rid of this.
141
		text_search = new Text(composite, SWT.BORDER | SWT.SINGLE
142
				| SWT.FULL_SELECTION);
143
		text_search.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOREGROUND));
144
		text_search.setText(defaultText);
145
        text_search.setEnabled(false);
146
        RowData layoutData = new RowData();
147
        layoutData.width = 150;
148
        text_search.setLayoutData(layoutData);
149

    
150
		addTextListeners();
151
	}
152

    
153
	/**
154
	 * Adds listeners to the search textfield.
155
	 */
156
	private void addTextListeners() {
157
		text_search.addFocusListener(new FocusListener() {
158

    
159
			@Override
160
            public void focusGained(FocusEvent e) {
161
				text_search.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOCUS));
162
				if (defaultText.equals(text_search.getText())) {
163
					text_search.setText("");
164
				}
165
			}
166

    
167
			@Override
168
            public void focusLost(FocusEvent e) {
169
				if (text_search.getText() == "") {
170
					text_search.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOREGROUND));
171
					text_search.setText(defaultText);
172
				}
173
			}
174
		});
175

    
176
		text_search.addKeyListener(new KeyAdapter() {
177
			@Override
178
			public void keyPressed(KeyEvent e) {
179
				if (e.keyCode == SWT.CR) {
180
					search();
181
				}
182
			}
183
		});
184
	}
185

    
186
	/**
187
	 * Creates the search layout.
188
	 * @param composite
189
	 */
190
	private void createLayout(Composite composite) {
191
		final RowLayout layout = new RowLayout();
192
		layout.wrap = false;
193
		layout.pack = false;
194
		layout.justify = false;
195
		layout.type = SWT.HORIZONTAL;
196
		layout.marginLeft = 5;
197
		layout.marginTop = 0;
198
		layout.marginRight = 5;
199
		layout.marginBottom = 0;
200
		layout.spacing = 0;
201
		composite.setLayout(layout);
202
	}
203

    
204
	private void search(){
205
		final String searchString = getSearchString();
206
		if(searchString == null){
207
			return;
208
		}
209

    
210
		if(!searchString.trim().matches(".*\\p{L}+.*")){
211
			MessagingUtils.warningDialog(Messages.SearchBar_2, this, Messages.SearchBar_3);
212
			return;
213
		}
214

    
215

    
216
		IFindTaxaAndNamesConfigurator<?> configurator = configurationListener.getConfigurator();
217
		configurator.setTitleSearchString(searchString);
218
		openSearchResultsView(configurator);
219

    
220
	}
221

    
222
	private String getSearchString(){
223
		String searchString = text_search.getText().trim();
224
		if (searchString.equals(defaultText) || searchString.length() == 0) {
225
            return null;
226
        }
227
		return searchString;
228
	}
229

    
230
	/**
231
	 * Opens a new instance of the search result view to display the result to the user.
232
	 *
233
	 * @param searchResult
234
	 */
235
	private void openSearchResultsView(IFindTaxaAndNamesConfigurator<?> configurator) {
236
		boolean openResultInSeparateWindows = PreferencesUtil.getPreferenceStore().getBoolean((IPreferenceKeys.SEARCH_OPEN_RESULTS_IN_SEPARATE_WINDOWS));
237
		String partId = AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_NAVIGATION_SEARCH_E4_SEARCHRESULTVIEWE4;
238

    
239
		MPart part = null;
240
		List<MPart> resultViews = modelService.findElements(application, partId, MPart.class, null);
241
		for (MPart mPart : resultViews) {
242
            if(mPart.getObject()!=null && mPart.isToBeRendered()){
243
                part = mPart;
244
                break;
245
            }
246
        }
247
		if(part==null){
248
		    part = partService.findPart(partId);
249
		}
250
		if(openResultInSeparateWindows && part.getObject()!=null){
251
		    MPartStack resultViewPartStack = getSearchResulPartStack(partId);
252
		    part = partService.createPart(partId);
253
		    //FIXME E4 this part stack id has to re-used or a adapted after migration
254
		    if(resultViewPartStack==null){
255
		        resultViewPartStack = WorkbenchUtility.getPartStack(NAVIGATION_STACK_ID, application, modelService);
256
		    }
257
		    if(resultViewPartStack!=null){
258
		        resultViewPartStack.getChildren().add(part);
259
		    }
260
		}
261
        part = partService.showPart(part, PartState.ACTIVATE);
262
        SearchResultViewE4 resultView = (SearchResultViewE4)part.getObject();
263
        resultView.performSearch(configurator);
264
	}
265

    
266
	private MPartStack getSearchResulPartStack(String partId){
267
        List<MPartStack> elements = modelService.findElements(application, null, MPartStack.class, null);
268
        for (MPartStack partStack : elements) {
269
            List<MStackElement> children = partStack.getChildren();
270
            for (MStackElement mStackElement : children) {
271
                if(mStackElement.getElementId().equals(partId)){
272
                    return partStack;
273
                }
274
            }
275
        }
276
        return null;
277
	}
278

    
279
	/**
280
	 * Handles drop down menu selection. Available items are defined in the enumeration SearchOption.
281
	 *
282
	 * @author n.hoffmann
283
	 * @created Feb 2, 2010
284
	 * @version 1.0
285
	 */
286
	class DropdownSelectionListener extends SelectionAdapter {
287

    
288
		private final Menu menu;
289

    
290
		public DropdownSelectionListener(ToolItem dropdown) {
291
			menu = new Menu(dropdown.getParent().getShell());
292
		}
293

    
294
		public void add(SearchOption option) {
295
			MenuItem menuItem = new MenuItem(menu, SWT.CHECK);
296
			menuItem.setData(option);
297
			menuItem.setText(option.getLabel());
298
			menuItem.setSelection(option.getPreference());
299
			menuItem.addSelectionListener(configurationListener);
300
		}
301

    
302
		@Override
303
		public void widgetSelected(SelectionEvent event) {
304
			if (event.detail == SWT.ARROW) {
305
				ToolItem item = (ToolItem) event.widget;
306
				Rectangle rect = item.getBounds();
307
				Point pt = item.getParent().toDisplay(new Point(rect.x, rect.y));
308
				menu.setLocation(pt.x, pt.y + rect.height);
309
				menu.setVisible(true);
310
			} else {
311
				search();
312
			}
313
		}
314
	}
315

    
316
	/**
317
	 * Handles search configuration selection.
318
	 *
319
	 * @author n.hoffmann
320
	 * @created Feb 2, 2010
321
	 */
322
	class ConfigurationSelectionListener extends SelectionAdapter {
323

    
324
		private IFindTaxaAndNamesConfigurator<?> configurator = PreferencesUtil.getSearchConfigurator();
325

    
326
		@Override
327
		public void widgetSelected(SelectionEvent e) {
328
			SearchOption option = (SearchOption) e.widget.getData();
329

    
330
			switch (option){
331
			case TAXON:
332
				configurator.setDoTaxa(configurator.isDoTaxa() ? false : true);
333
				break;
334
			case SYNONYM:
335
				configurator.setDoSynonyms(configurator.isDoSynonyms() ? false : true);
336
				break;
337
			case NAME:
338
				configurator.setDoNamesWithoutTaxa(configurator.isDoNamesWithoutTaxa() ? false : true);
339
				break;
340
			case COMMON_NAME:
341
				configurator.setDoTaxaByCommonNames(getConfigurator().isDoTaxaByCommonNames() ? false : true);
342
				break;
343
			}
344

    
345
			saveConfigurator();
346
		}
347

    
348
		public IFindTaxaAndNamesConfigurator<?> getConfigurator() {
349
			return configurator;
350
		}
351

    
352
		private void saveConfigurator() {
353
			PreferencesUtil.setSearchConfigurator(getConfigurator());
354
			this.configurator = PreferencesUtil.getSearchConfigurator();
355
		}
356
	}
357

    
358
    @Override
359
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
360
    }
361

    
362
    @Override
363
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
364
        if(!text_search.isDisposed()){
365
            text_search.setEnabled(false);
366
        }
367
        if(!toolBar.isDisposed()){
368
            toolBar.setEnabled(false);
369
        }
370
    }
371

    
372
    @Override
373
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
374
        if(!text_search.isDisposed()){
375
            text_search.setEnabled(true);
376
        }
377
        if(!toolBar.isDisposed()){
378
            toolBar.setEnabled(true);
379
        }
380
    }
381

    
382
    @Override
383
    public void contextRefresh(IProgressMonitor monitor) {
384
    }
385

    
386
    @Override
387
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
388
    }
389
}
(1-1/3)