OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011, the Dart project authors. | 2 * Copyright (c) 2011, the Dart project authors. |
3 * | 3 * |
4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
6 * | 6 * |
7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
8 * | 8 * |
9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
(...skipping 16 matching lines...) Expand all Loading... |
27 import org.eclipse.swt.events.MouseTrackAdapter; | 27 import org.eclipse.swt.events.MouseTrackAdapter; |
28 import org.eclipse.swt.graphics.Point; | 28 import org.eclipse.swt.graphics.Point; |
29 import org.eclipse.swt.widgets.Composite; | 29 import org.eclipse.swt.widgets.Composite; |
30 import org.eclipse.swt.widgets.Control; | 30 import org.eclipse.swt.widgets.Control; |
31 import org.eclipse.swt.widgets.Display; | 31 import org.eclipse.swt.widgets.Display; |
32 import org.eclipse.swt.widgets.Event; | 32 import org.eclipse.swt.widgets.Event; |
33 import org.eclipse.swt.widgets.Listener; | 33 import org.eclipse.swt.widgets.Listener; |
34 import org.eclipse.swt.widgets.Menu; | 34 import org.eclipse.swt.widgets.Menu; |
35 import org.eclipse.swt.widgets.Text; | 35 import org.eclipse.swt.widgets.Text; |
36 import org.eclipse.ui.IWorkbenchWindow; | 36 import org.eclipse.ui.IWorkbenchWindow; |
| 37 import org.eclipse.ui.PlatformUI; |
| 38 import org.eclipse.ui.keys.IBindingService; |
37 import org.eclipse.ui.menus.WorkbenchWindowControlContribution; | 39 import org.eclipse.ui.menus.WorkbenchWindowControlContribution; |
38 | 40 |
39 import java.util.HashMap; | 41 import java.util.HashMap; |
40 import java.util.Map; | 42 import java.util.Map; |
41 import java.util.Map.Entry; | 43 import java.util.Map.Entry; |
42 | 44 |
43 /** | 45 /** |
44 * Contributes the omnibox toolbar control. | 46 * Contributes the omnibox toolbar control. |
45 */ | 47 */ |
46 public class OmniBoxControlContribution extends WorkbenchWindowControlContributi
on { | 48 public class OmniBoxControlContribution extends WorkbenchWindowControlContributi
on { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 * keybinding). | 93 * keybinding). |
92 * | 94 * |
93 * @param window the host window | 95 * @param window the host window |
94 * @return the location to root the popup | 96 * @return the location to root the popup |
95 */ | 97 */ |
96 public static Point getPopupLocation(IWorkbenchWindow window) { | 98 public static Point getPopupLocation(IWorkbenchWindow window) { |
97 OmniBoxControlContribution contrib = CONTROL_MAP.get(window); | 99 OmniBoxControlContribution contrib = CONTROL_MAP.get(window); |
98 if (contrib == null) { | 100 if (contrib == null) { |
99 return new Point(0, 0); | 101 return new Point(0, 0); |
100 } | 102 } |
101 return locationRelativeToControl(contrib.control); | 103 return locationRelativeToControl(contrib.textControl); |
102 } | 104 } |
103 | 105 |
104 private static Point locationRelativeToControl(Text control) { | 106 private static Point locationRelativeToControl(Text control) { |
105 return control.toDisplay(0 + POPUP_PIXEL_HORIZ_NUDGE, control.getSize().y | 107 return control.toDisplay(0 + POPUP_PIXEL_HORIZ_NUDGE, control.getSize().y |
106 + POPUP_PIXEL_VERT_NUDGE); | 108 + POPUP_PIXEL_VERT_NUDGE); |
107 } | 109 } |
108 | 110 |
109 private Text control; | 111 private Text textControl; |
110 | 112 |
111 private boolean inControl; | 113 private boolean inControl; |
112 | 114 |
113 private OmniBoxPopup popup; | 115 private OmniBoxPopup popup; |
114 | 116 |
115 //used to track whether text is being modified programmatically (e.g., waterma
rk-setting) | 117 //used to track whether text is being modified programmatically (e.g., waterma
rk-setting) |
116 private boolean listenForTextModify = true; | 118 private boolean listenForTextModify = true; |
117 | 119 |
118 //used when we want to advance focus off of the text control (ideally to resto
re previous) | 120 //used when we want to advance focus off of the text control (ideally to resto
re previous) |
119 private Control previousFocusControl; | 121 private Control previousFocusControl; |
(...skipping 11 matching lines...) Expand all Loading... |
131 disposedWindow = entry.getKey(); | 133 disposedWindow = entry.getKey(); |
132 break; | 134 break; |
133 } | 135 } |
134 } | 136 } |
135 if (disposedWindow != null) { | 137 if (disposedWindow != null) { |
136 CONTROL_MAP.remove(disposedWindow); | 138 CONTROL_MAP.remove(disposedWindow); |
137 } | 139 } |
138 } | 140 } |
139 | 141 |
140 public void giveFocus() { | 142 public void giveFocus() { |
141 cacheFocusControl(control.getDisplay().getFocusControl()); | 143 cacheFocusControl(textControl.getDisplay().getFocusControl()); |
142 control.setFocus(); | 144 textControl.setFocus(); |
143 clearWatermark(); | 145 clearWatermark(); |
144 } | 146 } |
145 | 147 |
146 @Override | 148 @Override |
147 protected Control createControl(Composite parent) { | 149 protected Control createControl(Composite parent) { |
148 control = createTextControl(parent); | 150 textControl = createTextControl(parent); |
149 setWatermarkText(); | 151 setWatermarkText(); |
150 hookupListeners(); | 152 hookupListeners(); |
151 CONTROL_MAP.put(getWorkbenchWindow(), this); | 153 CONTROL_MAP.put(getWorkbenchWindow(), this); |
152 return control; | 154 return textControl; |
153 } | 155 } |
154 | 156 |
155 protected void defocus() { | 157 protected void defocus() { |
156 if (previousFocusControl != null && !previousFocusControl.isDisposed()) { | 158 if (previousFocusControl != null && !previousFocusControl.isDisposed()) { |
157 previousFocusControl.setFocus(); | 159 previousFocusControl.setFocus(); |
158 } else { | 160 } else { |
159 control.getParent().setFocus(); | 161 textControl.getParent().setFocus(); |
160 } | 162 } |
161 } | 163 } |
162 | 164 |
163 protected void handleMouseEnter() { | |
164 inControl = true; | |
165 //cache on mouse enter to ensure we can restore focus after an invocation in
itiated by a mouse click | |
166 cacheFocusControl(control.getDisplay().getFocusControl()); | |
167 } | |
168 | |
169 protected void handleMouseExit() { | |
170 inControl = false; | |
171 } | |
172 | |
173 protected void handleSelection() { | |
174 clearWatermark(); | |
175 } | |
176 | |
177 protected void refreshPopup() { | 165 protected void refreshPopup() { |
178 if (popup != null && !popup.isDisposed()) { | 166 if (popup != null && !popup.isDisposed()) { |
179 popup.refresh(getFilterText()); | 167 popup.refresh(getFilterText()); |
180 } | 168 } |
181 } | 169 } |
182 | 170 |
183 private void cacheFocusControl(Control focusControl) { | 171 private void cacheFocusControl(Control focusControl) { |
184 //since the point of caching the control is to restore focus away from us, | 172 //since the point of caching the control is to restore focus away from us, |
185 //ignore any sets to "self" | 173 //ignore any sets to "self" |
186 if (focusControl != control) { | 174 if (focusControl != textControl) { |
187 previousFocusControl = focusControl; | 175 previousFocusControl = focusControl; |
188 } | 176 } |
189 } | 177 } |
190 | 178 |
191 private void clearWatermark() { | 179 private void clearWatermark() { |
192 //ensure watermark (or valid text) does not get re-cleared | 180 //ensure watermark (or valid text) does not get re-cleared |
193 if (control.getForeground().equals(OmniBoxColors.SEARCHBOX_TEXT_COLOR)) { | 181 if (textControl.getForeground().equals(OmniBoxColors.SEARCHBOX_TEXT_COLOR))
{ |
194 return; | 182 return; |
195 } | 183 } |
196 silentSetControlText(""); //$NON-NLS-1$ | 184 silentSetControlText(""); //$NON-NLS-1$ |
197 control.setForeground(OmniBoxColors.SEARCHBOX_TEXT_COLOR); | 185 textControl.setForeground(OmniBoxColors.SEARCHBOX_TEXT_COLOR); |
198 } | 186 } |
199 | 187 |
200 private Text createTextControl(Composite parent) { | 188 private Text createTextControl(Composite parent) { |
201 Text text = new Text(parent, SEARCH_BOX_STYLE_BITS); | 189 Text text = new Text(parent, SEARCH_BOX_STYLE_BITS); |
202 text.setToolTipText(OmniBoxMessages.OmniBoxControlContribution_control_toolt
ip); | 190 text.setToolTipText(OmniBoxMessages.OmniBoxControlContribution_control_toolt
ip); |
203 // Disables the default context menu for native SWT text boxes | 191 // Disables the default context menu for native SWT text boxes |
204 text.setMenu(new Menu(parent)); | 192 text.setMenu(new Menu(parent)); |
205 return text; | 193 return text; |
206 } | 194 } |
207 | 195 |
208 private String getFilterText() { | 196 private String getFilterText() { |
209 return control.getText().toLowerCase(); | 197 return textControl.getText().toLowerCase(); |
| 198 } |
| 199 |
| 200 private void handleFocusGained() { |
| 201 //disable global keybinding handlers so we can trap copy/paste/etc |
| 202 ((IBindingService) PlatformUI.getWorkbench().getService(IBindingService.clas
s)).setKeyFilterEnabled(false); |
| 203 clearWatermark(); |
| 204 } |
| 205 |
| 206 private void handleFocusLost() { |
| 207 //re-enable global keybinding handlers |
| 208 ((IBindingService) PlatformUI.getWorkbench().getService(IBindingService.clas
s)).setKeyFilterEnabled(true); |
| 209 |
| 210 //GTK linux requires special casing to handle the case where a click |
| 211 //outside the search box (or popup) should cause the popup to close |
| 212 //We identify this case by keying off focus changes --- if focus |
| 213 //is transfered to another control we trigger a close |
| 214 if (Util.isLinux()) { |
| 215 //Exec async to ensure that it occurs after the focus change |
| 216 Display.getDefault().asyncExec(new Runnable() { |
| 217 @Override |
| 218 public void run() { |
| 219 Control focusControl = Display.getDefault().getFocusControl(); |
| 220 if (focusControl != textControl && popup != null && focusControl != po
pup.table) { |
| 221 popup.close(); |
| 222 } |
| 223 } |
| 224 }); |
| 225 } |
| 226 if (popupClosed()) { |
| 227 setWatermarkText(); |
| 228 } |
| 229 } |
| 230 |
| 231 private void handleKeyPressed(KeyEvent e) { |
| 232 if (SWT.ARROW_DOWN == e.keyCode) { |
| 233 if (popupClosed()) { |
| 234 openPopup(); |
| 235 refreshPopup(); |
| 236 } |
| 237 |
| 238 } |
| 239 |
| 240 if (popupClosed()) { |
| 241 //have escape defocus |
| 242 if (SWT.ESC == e.character) { |
| 243 defocus(); |
| 244 return; |
| 245 } |
| 246 //and don't let other control characters invoke the popup |
| 247 if (Character.isISOControl(e.character)) { |
| 248 return; |
| 249 } |
| 250 openPopup(); |
| 251 } |
| 252 |
| 253 if (popup != null && !popup.isDisposed()) { |
| 254 popup.sendKeyPress(e); |
| 255 } |
| 256 } |
| 257 |
| 258 private void handleModifyText() { |
| 259 if (!listenForTextModify) { |
| 260 return; |
| 261 } |
| 262 String filterText = getFilterText(); |
| 263 if (filterText.length() > 0) { |
| 264 if (popupClosed()) { |
| 265 openPopup(); |
| 266 } |
| 267 refreshPopup(); |
| 268 } else { |
| 269 popup.close(); |
| 270 } |
| 271 } |
| 272 |
| 273 private void handleMouseEnter() { |
| 274 inControl = true; |
| 275 //cache on mouse enter to ensure we can restore focus after an invocation in
itiated by a mouse click |
| 276 cacheFocusControl(textControl.getDisplay().getFocusControl()); |
| 277 } |
| 278 |
| 279 private void handleMouseExit() { |
| 280 inControl = false; |
| 281 } |
| 282 |
| 283 private void handleMouseUp() { |
| 284 if (inControl) { |
| 285 handleSelection(); |
| 286 } |
| 287 } |
| 288 |
| 289 private void handleSelection() { |
| 290 clearWatermark(); |
210 } | 291 } |
211 | 292 |
212 private void hookupListeners() { | 293 private void hookupListeners() { |
213 control.addMouseListener(new MouseAdapter() { | 294 textControl.addMouseListener(new MouseAdapter() { |
214 @Override | 295 @Override |
215 public void mouseUp(MouseEvent e) { | 296 public void mouseUp(MouseEvent e) { |
216 if (inControl) { | 297 handleMouseUp(); |
217 handleSelection(); | |
218 } | |
219 } | 298 } |
220 }); | 299 }); |
221 | 300 |
222 control.addMouseTrackListener(new MouseTrackAdapter() { | 301 textControl.addMouseTrackListener(new MouseTrackAdapter() { |
223 @Override | 302 @Override |
224 public void mouseEnter(MouseEvent e) { | 303 public void mouseEnter(MouseEvent e) { |
225 handleMouseEnter(); | 304 handleMouseEnter(); |
226 } | 305 } |
227 | 306 |
228 @Override | 307 @Override |
229 public void mouseExit(MouseEvent e) { | 308 public void mouseExit(MouseEvent e) { |
230 handleMouseExit(); | 309 handleMouseExit(); |
231 } | 310 } |
232 }); | 311 }); |
233 | 312 |
234 control.addModifyListener(new ModifyListener() { | 313 textControl.addModifyListener(new ModifyListener() { |
235 @Override | 314 @Override |
236 public void modifyText(ModifyEvent e) { | 315 public void modifyText(ModifyEvent e) { |
237 if (!listenForTextModify) { | 316 handleModifyText(); |
238 return; | |
239 } | |
240 String filterText = getFilterText(); | |
241 if (filterText.length() > 0) { | |
242 if (popupClosed()) { | |
243 openPopup(); | |
244 } | |
245 refreshPopup(); | |
246 } else { | |
247 popup.close(); | |
248 } | |
249 } | 317 } |
250 }); | 318 }); |
251 | 319 |
252 control.addKeyListener(new KeyAdapter() { | 320 textControl.addKeyListener(new KeyAdapter() { |
253 @Override | 321 @Override |
254 public void keyPressed(KeyEvent e) { | 322 public void keyPressed(KeyEvent e) { |
255 | 323 handleKeyPressed(e); |
256 if (SWT.ARROW_DOWN == e.keyCode) { | |
257 if (popupClosed()) { | |
258 openPopup(); | |
259 refreshPopup(); | |
260 } | |
261 | |
262 } | |
263 | |
264 if (popupClosed()) { | |
265 //have escape defocus | |
266 if (SWT.ESC == e.character) { | |
267 defocus(); | |
268 return; | |
269 } | |
270 //and don't let other control characters invoke the popup | |
271 if (Character.isISOControl(e.character)) { | |
272 return; | |
273 } | |
274 openPopup(); | |
275 } | |
276 | |
277 if (popup != null && !popup.isDisposed()) { | |
278 popup.sendKeyPress(e); | |
279 } | |
280 } | 324 } |
281 }); | 325 }); |
282 | 326 |
283 control.addFocusListener(new FocusListener() { | 327 textControl.addFocusListener(new FocusListener() { |
284 @Override | 328 @Override |
285 public void focusGained(FocusEvent e) { | 329 public void focusGained(FocusEvent e) { |
286 clearWatermark(); | 330 handleFocusGained(); |
287 } | 331 } |
288 | 332 |
289 @Override | 333 @Override |
290 public void focusLost(FocusEvent e) { | 334 public void focusLost(FocusEvent e) { |
291 //GTK linux requires special casing to handle the case where a click | 335 handleFocusLost(); |
292 //outside the search box (or popup) should cause the popup to close | |
293 //We identify this case by keying off focus changes --- if focus | |
294 //is transfered to another control we trigger a close | |
295 if (Util.isLinux()) { | |
296 //Exec async to esnure that it occurs after the focus change | |
297 Display.getDefault().asyncExec(new Runnable() { | |
298 @Override | |
299 public void run() { | |
300 Control focusControl = Display.getDefault().getFocusControl(); | |
301 if (focusControl != control && popup != null && focusControl != po
pup.table) { | |
302 popup.close(); | |
303 } | |
304 } | |
305 }); | |
306 } | |
307 if (popupClosed()) { | |
308 setWatermarkText(); | |
309 } | |
310 } | 336 } |
311 }); | 337 }); |
312 } | 338 } |
313 | 339 |
314 private void openPopup() { | 340 private void openPopup() { |
315 popup = new OmniBoxPopup(getWorkbenchWindow(), null) { | 341 popup = new OmniBoxPopup(getWorkbenchWindow(), null) { |
316 @Override | 342 @Override |
317 public boolean close() { | 343 public boolean close() { |
318 setWatermarkText(); | 344 setWatermarkText(); |
319 defocus(); | 345 defocus(); |
320 return super.close(); | 346 return super.close(); |
321 } | 347 } |
322 | 348 |
323 @Override | 349 @Override |
324 protected Point getDefaultLocation(Point initialSize) { | 350 protected Point getDefaultLocation(Point initialSize) { |
325 return locationRelativeToControl(control); | 351 return locationRelativeToControl(textControl); |
326 } | 352 } |
327 | 353 |
328 @Override | 354 @Override |
329 protected Point getDefaultSize() { | 355 protected Point getDefaultSize() { |
330 return new Point(control.getSize().x - POPUP_PIXEL_HORIZ_NUDGE * 2, 360)
; | 356 return new Point(textControl.getSize().x - POPUP_PIXEL_HORIZ_NUDGE * 2,
360); |
331 } | 357 } |
332 | 358 |
333 }; | 359 }; |
334 popup.setFilterControl(control); | 360 popup.setFilterControl(textControl); |
335 popup.open(); | 361 popup.open(); |
336 | 362 |
337 if (Util.isMac()) { | 363 if (Util.isMac()) { |
338 control.addListener(SWT.Deactivate, new Listener() { | 364 textControl.addListener(SWT.Deactivate, new Listener() { |
339 @Override | 365 @Override |
340 public void handleEvent(Event event) { | 366 public void handleEvent(Event event) { |
341 //selecting the scrollbar will deactivate but in that case we don't wa
nt to close | 367 //selecting the scrollbar will deactivate but in that case we don't wa
nt to close |
342 if (event.display.getFocusControl() != popup.table) { | 368 if (event.display.getFocusControl() != popup.table) { |
343 popup.close(); | 369 popup.close(); |
344 } | 370 } |
345 control.removeListener(SWT.Deactivate, this); | 371 textControl.removeListener(SWT.Deactivate, this); |
346 } | 372 } |
347 }); | 373 }); |
348 } | 374 } |
349 } | 375 } |
350 | 376 |
351 private boolean popupClosed() { | 377 private boolean popupClosed() { |
352 return popup == null || popup.isDisposed(); | 378 return popup == null || popup.isDisposed(); |
353 } | 379 } |
354 | 380 |
355 private void setWatermarkText() { | 381 private void setWatermarkText() { |
356 silentSetControlText(WATERMARK_TEXT); | 382 silentSetControlText(WATERMARK_TEXT); |
357 control.setForeground(OmniBoxColors.WATERMARK_TEXT_COLOR); | 383 textControl.setForeground(OmniBoxColors.WATERMARK_TEXT_COLOR); |
358 } | 384 } |
359 | 385 |
360 //set text without notifying listeners | 386 //set text without notifying listeners |
361 private void silentSetControlText(String txt) { | 387 private void silentSetControlText(String txt) { |
362 listenForTextModify = false; | 388 listenForTextModify = false; |
363 control.setText(txt); | 389 textControl.setText(txt); |
364 listenForTextModify = true; | 390 listenForTextModify = true; |
365 } | 391 } |
366 | 392 |
367 } | 393 } |
OLD | NEW |