1 /*******************************************************************************
2  * Copyright (c) 2000, 2018 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.contentassist;
15 
16 import org.eclipse.swt.events.FocusEvent;
17 import org.eclipse.swt.events.FocusListener;
18 import org.eclipse.swt.widgets.Combo;
19 import org.eclipse.swt.widgets.Control;
20 import org.eclipse.swt.widgets.Text;
21 
22 import org.eclipse.core.commands.AbstractHandler;
23 import org.eclipse.core.commands.ExecutionEvent;
24 import org.eclipse.core.commands.ExecutionException;
25 import org.eclipse.core.commands.IHandler;
26 
27 import org.eclipse.jface.bindings.TriggerSequence;
28 import org.eclipse.jface.contentassist.AbstractControlContentAssistSubjectAdapter;
29 import org.eclipse.jface.contentassist.ComboContentAssistSubjectAdapter;
30 import org.eclipse.jface.contentassist.SubjectControlContentAssistant;
31 import org.eclipse.jface.contentassist.TextContentAssistSubjectAdapter;
32 import org.eclipse.jface.viewers.ILabelProvider;
33 import org.eclipse.jface.viewers.LabelProvider;
34 
35 import org.eclipse.ui.PlatformUI;
36 import org.eclipse.ui.handlers.IHandlerActivation;
37 import org.eclipse.ui.handlers.IHandlerService;
38 import org.eclipse.ui.internal.texteditor.NLSUtility;
39 import org.eclipse.ui.keys.IBindingService;
40 
41 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
42 
43 
44 /**
45  * A content assistant handler which handles the key binding and
46  * the cue for a {@link org.eclipse.jface.text.contentassist.ContentAssistant}
47  * and its subject adapter.
48  *
49  * @since 3.0
50  * @deprecated As of 3.2, replaced by JFace field assist support
51  */
52 @Deprecated
53 public class ContentAssistHandler {
54 	/**
55 	 * The target control.
56 	 */
57 	private Control fControl;
58 	/**
59 	 * The content assist subject adapter.
60 	 */
61 	private AbstractControlContentAssistSubjectAdapter fContentAssistSubjectAdapter;
62 	/**
63 	 * The content assistant.
64 	 */
65 	private SubjectControlContentAssistant fContentAssistant;
66 	/**
67 	 * The currently installed FocusListener, or <code>null</code> iff none installed.
68 	 * This is also used as flag to tell whether content assist is enabled
69 	 */
70 	private FocusListener fFocusListener;
71 	/**
72 	 * The currently installed IHandlerActivation, or <code>null</code> iff none installed.
73 	 */
74 	private IHandlerActivation fHandlerActivation;
75 
76 	/**
77 	 * Creates a new {@link ContentAssistHandler} for the given {@link Combo}.
78 	 * Only a single {@link ContentAssistHandler} may be installed on a {@link Combo} instance.
79 	 * Content Assist is enabled by default.
80 	 *
81 	 * @param combo target combo
82 	 * @param contentAssistant a configured content assistant
83 	 * @return a new {@link ContentAssistHandler}
84 	 */
createHandlerForCombo(Combo combo, SubjectControlContentAssistant contentAssistant)85 	public static ContentAssistHandler createHandlerForCombo(Combo combo, SubjectControlContentAssistant contentAssistant) {
86 		return new ContentAssistHandler(combo, new ComboContentAssistSubjectAdapter(combo), contentAssistant);
87 	}
88 
89 	/**
90 	 * Creates a new {@link ContentAssistHandler} for the given {@link Text}.
91 	 * Only a single {@link ContentAssistHandler} may be installed on a {@link Text} instance.
92 	 * Content Assist is enabled by default.
93 	 *
94 	 * @param text target text
95 	 * @param contentAssistant a configured content assistant
96 	 * @return a new {@link ContentAssistHandler}
97 	 */
createHandlerForText(Text text, SubjectControlContentAssistant contentAssistant)98 	public static ContentAssistHandler createHandlerForText(Text text, SubjectControlContentAssistant contentAssistant) {
99 		return new ContentAssistHandler(text, new TextContentAssistSubjectAdapter(text), contentAssistant);
100 	}
101 
102 	/**
103 	 * Internal constructor.
104 	 *
105 	 * @param control target control
106 	 * @param subjectAdapter content assist subject adapter
107 	 * @param contentAssistant content assistant
108 	 */
ContentAssistHandler( Control control, AbstractControlContentAssistSubjectAdapter subjectAdapter, SubjectControlContentAssistant contentAssistant)109 	private ContentAssistHandler(
110 			Control control,
111 			AbstractControlContentAssistSubjectAdapter subjectAdapter,
112 			SubjectControlContentAssistant contentAssistant) {
113 		fControl= control;
114 		fContentAssistant= contentAssistant;
115 		fContentAssistSubjectAdapter= subjectAdapter;
116 		setEnabled(true);
117 		fControl.addDisposeListener(e -> setEnabled(false));
118 	}
119 
120 	/**
121 	 * @return <code>true</code> iff content assist is enabled
122 	 */
isEnabled()123 	public boolean isEnabled() {
124 		return fFocusListener != null;
125 	}
126 
127 	/**
128 	 * Controls enablement of content assist.
129 	 * When enabled, a cue is shown next to the focused field
130 	 * and the affordance hover shows the shortcut.
131 	 *
132 	 * @param enable enable content assist iff true
133 	 */
setEnabled(boolean enable)134 	public void setEnabled(boolean enable) {
135 		if (enable == isEnabled())
136 			return;
137 
138 		if (enable)
139 			enable();
140 		else
141 			disable();
142 	}
143 
144 	/**
145 	 * Enable content assist.
146 	 */
enable()147 	private void enable() {
148 		if (! fControl.isDisposed()) {
149 			fContentAssistant.install(fContentAssistSubjectAdapter);
150 			installCueLabelProvider();
151 			installFocusListener();
152 			if (fControl.isFocusControl())
153 				activateHandler();
154 		}
155 	}
156 
157 	/**
158 	 * Disable content assist.
159 	 */
disable()160 	private void disable() {
161 		if (! fControl.isDisposed()) {
162 			fContentAssistant.uninstall();
163 			fContentAssistSubjectAdapter.setContentAssistCueProvider(null);
164 			fControl.removeFocusListener(fFocusListener);
165 			fFocusListener= null;
166 			if (fHandlerActivation != null)
167 				deactivateHandler();
168 		}
169 	}
170 
171 	/**
172 	 * Create and install the {@link LabelProvider} for fContentAssistSubjectAdapter.
173 	 */
installCueLabelProvider()174 	private void installCueLabelProvider() {
175 		ILabelProvider labelProvider= new LabelProvider() {
176 			@Override
177 			public String getText(Object element) {
178 				IBindingService bindingService= PlatformUI.getWorkbench().getAdapter(IBindingService.class);
179 				TriggerSequence[] activeBindings= bindingService.getActiveBindingsFor(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
180 				if (activeBindings.length == 0)
181 					return ContentAssistMessages.ContentAssistHandler_contentAssistAvailable;
182 				return NLSUtility.format(ContentAssistMessages.ContentAssistHandler_contentAssistAvailableWithKeyBinding, activeBindings[0].format());
183 			}
184 		};
185 		fContentAssistSubjectAdapter.setContentAssistCueProvider(labelProvider);
186 	}
187 
188 	/**
189 	 * Create fFocusListener and install it on fControl.
190 	 */
installFocusListener()191 	private void installFocusListener() {
192 		fFocusListener= new FocusListener() {
193 			@Override
194 			public void focusGained(final FocusEvent e) {
195 				if (fHandlerActivation == null)
196 					activateHandler();
197 			}
198 			@Override
199 			public void focusLost(FocusEvent e) {
200 				if (fHandlerActivation != null)
201 					deactivateHandler();
202 			}
203 		};
204 		fControl.addFocusListener(fFocusListener);
205 	}
206 
207 	/**
208 	 * Create and register fHandlerSubmission.
209 	 */
activateHandler()210 	private void activateHandler() {
211 		IHandlerService handlerService= PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
212 		if (handlerService == null)
213 			return;
214 
215 		IHandler handler= new AbstractHandler() {
216 			@Override
217 			public Object execute(ExecutionEvent event) throws ExecutionException {
218 				if (ContentAssistHandler.this.isEnabled()) // don't call AbstractHandler#isEnabled()!
219 					fContentAssistant.showPossibleCompletions();
220 				return null;
221 			}
222 		};
223 		fHandlerActivation= handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, handler);
224 	}
225 
226 	/**
227 	 * Unregister the {@link IHandlerActivation} from the shell.
228 	 */
deactivateHandler()229 	private void deactivateHandler() {
230 		IHandlerService handlerService= PlatformUI.getWorkbench().getAdapter(IHandlerService.class);
231 		if (handlerService != null)
232 			handlerService.deactivateHandler(fHandlerActivation);
233 		fHandlerActivation= null;
234 	}
235 }
236