Project

General

Profile

Download (11.5 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.RowLayout;
35
import org.eclipse.swt.widgets.Composite;
36
import org.eclipse.swt.widgets.Control;
37
import org.eclipse.swt.widgets.Menu;
38
import org.eclipse.swt.widgets.MenuItem;
39
import org.eclipse.swt.widgets.Text;
40
import org.eclipse.swt.widgets.ToolBar;
41
import org.eclipse.swt.widgets.ToolItem;
42
import org.eclipse.ui.IMemento;
43
import org.eclipse.ui.PlatformUI;
44
import org.eclipse.ui.swt.IFocusService;
45

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

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

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

    
69
    private Text text_search;
70
	private ToolBar toolBar;
71

    
72
	private final String defaultText = Messages.SearchBar_0;
73

    
74
	@Inject
75
	private EPartService partService;
76

    
77
	@Inject
78
	private MApplication application;
79

    
80
	@Inject
81
	private EModelService modelService;
82

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

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

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

    
97
		return composite;
98
	}
99

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

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

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

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

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

    
129
		toolItem.addSelectionListener(dropdownListener);
130
	}
131

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

    
146
		addTextListeners();
147
	}
148

    
149
	/**
150
	 * Adds listeners to the search textfield.
151
	 */
152
	private void addTextListeners() {
153
		text_search.addFocusListener(new FocusListener() {
154

    
155
			@Override
156
            public void focusGained(FocusEvent e) {
157
				text_search.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOCUS));
158
				if (defaultText.equals(text_search.getText())) {
159
					text_search.setText("");
160
				}
161
			}
162

    
163
			@Override
164
            public void focusLost(FocusEvent e) {
165
				if (text_search.getText() == "") {
166
					text_search.setForeground(AbstractUtility.getColor(Resources.SEARCH_VIEW_FOREGROUND));
167
					text_search.setText(defaultText);
168
				}
169
			}
170
		});
171

    
172
		text_search.addKeyListener(new KeyAdapter() {
173
			@Override
174
			public void keyPressed(KeyEvent e) {
175
				if (e.keyCode == SWT.CR) {
176
					search();
177
				}
178
			}
179
		});
180
	}
181

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

    
200
	private void search(){
201
		final String searchString = getSearchString();
202
		if(searchString == null){
203
			return;
204
		}
205

    
206
		if(!searchString.trim().matches(".*\\p{L}+.*")){
207
			MessagingUtils.warningDialog(Messages.SearchBar_2, this, Messages.SearchBar_3);
208
			return;
209
		}
210

    
211

    
212
		IFindTaxaAndNamesConfigurator configurator = configurationListener.getConfigurator();
213
		configurator.setTitleSearchString(searchString);
214
		openSearchResultsView(configurator);
215

    
216
	}
217

    
218
	private String getSearchString(){
219
		String searchString = text_search.getText().trim();
220
		if (searchString.equals(defaultText) || searchString.length() == 0) {
221
            return null;
222
        }
223
		return searchString;
224
	}
225

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

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

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

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

    
284
		private final Menu menu;
285

    
286
		public DropdownSelectionListener(ToolItem dropdown) {
287
			menu = new Menu(dropdown.getParent().getShell());
288
		}
289

    
290
		public void add(SearchOption option) {
291
			MenuItem menuItem = new MenuItem(menu, SWT.CHECK);
292
			menuItem.setData(option);
293
			menuItem.setText(option.getLabel());
294
			menuItem.setSelection(option.getPreference());
295
			menuItem.addSelectionListener(configurationListener);
296
		}
297

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

    
312
	/**
313
	 * Handles search configuration selection.
314
	 *
315
	 * @author n.hoffmann
316
	 * @created Feb 2, 2010
317
	 * @version 1.0
318
	 */
319
	class ConfigurationSelectionListener extends SelectionAdapter {
320

    
321
		private IFindTaxaAndNamesConfigurator configurator = PreferencesUtil.getSearchConfigurator();
322

    
323
		@Override
324
		public void widgetSelected(SelectionEvent e) {
325
			SearchOption option = (SearchOption) e.widget.getData();
326

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

    
342
			saveConfigurator();
343
		}
344

    
345
		public IFindTaxaAndNamesConfigurator getConfigurator() {
346
			return configurator;
347
		}
348

    
349
		private void saveConfigurator() {
350
			PreferencesUtil.setSearchConfigurator(getConfigurator());
351
			this.configurator = PreferencesUtil.getSearchConfigurator();
352
		}
353
	}
354

    
355
    @Override
356
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
357
    }
358

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

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

    
379
    @Override
380
    public void contextRefresh(IProgressMonitor monitor) {
381
    }
382

    
383
    @Override
384
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
385
    }
386
}
(1-1/4)