KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > refactoring > reorg > RenameInformationPopup


1 /*******************************************************************************
2  * Copyright (c) 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.internal.ui.refactoring.reorg;
13
14 import org.eclipse.core.runtime.IProgressMonitor;
15 import org.eclipse.core.runtime.IStatus;
16 import org.eclipse.core.runtime.Status;
17 import org.eclipse.core.runtime.jobs.Job;
18
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.custom.StyleRange;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.events.ControlAdapter;
23 import org.eclipse.swt.events.ControlEvent;
24 import org.eclipse.swt.events.ControlListener;
25 import org.eclipse.swt.events.DisposeEvent;
26 import org.eclipse.swt.events.DisposeListener;
27 import org.eclipse.swt.events.KeyEvent;
28 import org.eclipse.swt.events.KeyListener;
29 import org.eclipse.swt.events.MouseAdapter;
30 import org.eclipse.swt.events.MouseEvent;
31 import org.eclipse.swt.events.MouseListener;
32 import org.eclipse.swt.events.PaintEvent;
33 import org.eclipse.swt.events.PaintListener;
34 import org.eclipse.swt.events.SelectionAdapter;
35 import org.eclipse.swt.events.SelectionEvent;
36 import org.eclipse.swt.events.ShellAdapter;
37 import org.eclipse.swt.events.ShellEvent;
38 import org.eclipse.swt.graphics.Color;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.graphics.Point;
41 import org.eclipse.swt.graphics.Rectangle;
42 import org.eclipse.swt.graphics.Region;
43 import org.eclipse.swt.layout.GridLayout;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Control;
46 import org.eclipse.swt.widgets.Display;
47 import org.eclipse.swt.widgets.Menu;
48 import org.eclipse.swt.widgets.Shell;
49 import org.eclipse.swt.widgets.ToolBar;
50 import org.eclipse.swt.widgets.ToolItem;
51 import org.eclipse.swt.widgets.Tracker;
52
53 import org.eclipse.jface.action.Action;
54 import org.eclipse.jface.action.IAction;
55 import org.eclipse.jface.action.IMenuListener2;
56 import org.eclipse.jface.action.IMenuManager;
57 import org.eclipse.jface.action.MenuManager;
58 import org.eclipse.jface.action.Separator;
59 import org.eclipse.jface.bindings.keys.IKeyLookup;
60 import org.eclipse.jface.bindings.keys.KeyLookupFactory;
61 import org.eclipse.jface.bindings.keys.KeyStroke;
62 import org.eclipse.jface.dialogs.IDialogSettings;
63 import org.eclipse.jface.util.Geometry;
64
65 import org.eclipse.jface.text.ITextListener;
66 import org.eclipse.jface.text.ITextViewerExtension5;
67 import org.eclipse.jface.text.IViewportListener;
68 import org.eclipse.jface.text.IWidgetTokenKeeper;
69 import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
70 import org.eclipse.jface.text.IWidgetTokenOwner;
71 import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
72 import org.eclipse.jface.text.TextEvent;
73 import org.eclipse.jface.text.link.LinkedPosition;
74 import org.eclipse.jface.text.source.ISourceViewer;
75
76 import org.eclipse.ui.IPartListener2;
77 import org.eclipse.ui.IWorkbenchPart;
78 import org.eclipse.ui.IWorkbenchPartReference;
79 import org.eclipse.ui.PlatformUI;
80 import org.eclipse.ui.dialogs.PreferencesUtil;
81 import org.eclipse.ui.keys.IBindingService;
82 import org.eclipse.ui.progress.UIJob;
83
84 import org.eclipse.jdt.internal.corext.util.Messages;
85
86 import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds;
87
88 import org.eclipse.jdt.internal.ui.JavaPlugin;
89 import org.eclipse.jdt.internal.ui.JavaPluginImages;
90 import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
91 import org.eclipse.jdt.internal.ui.preferences.JavaBasePreferencePage;
92
93 public class RenameInformationPopup implements IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
94     
95     private class PopupVisibilityManager implements IPartListener2, ControlListener, MouseListener, KeyListener, ITextListener, IViewportListener {
96         
97         public void start() {
98             fEditor.getSite().getWorkbenchWindow().getPartService().addPartListener(this);
99             final ISourceViewer viewer= fEditor.getViewer();
100             final StyledText textWidget= viewer.getTextWidget();
101             textWidget.addControlListener(this);
102             textWidget.addMouseListener(this);
103             textWidget.addKeyListener(this);
104             fEditor.getSite().getShell().addControlListener(this);
105             viewer.addTextListener(this);
106             viewer.addViewportListener(this);
107             fPopup.addDisposeListener(new DisposeListener() {
108                 public void widgetDisposed(DisposeEvent e) {
109                     fEditor.getSite().getWorkbenchWindow().getPartService().removePartListener(PopupVisibilityManager.this);
110                     if (! textWidget.isDisposed()) {
111                         textWidget.removeControlListener(PopupVisibilityManager.this);
112                         textWidget.removeMouseListener(PopupVisibilityManager.this);
113                         textWidget.removeKeyListener(PopupVisibilityManager.this);
114                     }
115                     fEditor.getSite().getShell().removeControlListener(PopupVisibilityManager.this);
116                     viewer.removeTextListener(PopupVisibilityManager.this);
117                     viewer.removeViewportListener(PopupVisibilityManager.this);
118                     if (fMenuImage != null) {
119                         fMenuImage.dispose();
120                         fMenuImage= null;
121                     }
122                     if (fMenuManager != null) {
123                         fMenuManager.dispose();
124                         fMenuManager= null;
125                     }
126                     fRenameLinkedMode.cancel();
127                 }
128             });
129         }
130         
131         public void partActivated(IWorkbenchPartReference partRef) {
132             IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
133             if (partRef.getPart(false) == fPart) {
134                 updateVisibility();
135             }
136         }
137
138         public void partBroughtToTop(IWorkbenchPartReference partRef) {
139         }
140
141         public void partClosed(IWorkbenchPartReference partRef) {
142         }
143
144         public void partDeactivated(IWorkbenchPartReference partRef) {
145             IWorkbenchPart fPart= fEditor.getEditorSite().getPart();
146             if (fPopup != null && ! fPopup.isDisposed() && partRef.getPart(false) == fPart) {
147                 fPopup.setVisible(false);
148             }
149         }
150
151         public void partHidden(IWorkbenchPartReference partRef) {
152         }
153
154         public void partInputChanged(IWorkbenchPartReference partRef) {
155         }
156
157         public void partOpened(IWorkbenchPartReference partRef) {
158         }
159
160         public void partVisible(IWorkbenchPartReference partRef) {
161         }
162
163
164         public void controlMoved(ControlEvent e) {
165             updatePopupLocation(true);
166             updateVisibility(); //only for hiding outside editor area
167
}
168
169         public void controlResized(ControlEvent e) {
170             updatePopupLocation(true);
171             updateVisibility(); //only for hiding outside editor area
172
}
173         
174         
175         public void mouseDoubleClick(MouseEvent e) {
176         }
177
178         public void mouseDown(MouseEvent e) {
179         }
180
181         public void mouseUp(MouseEvent e) {
182             updatePopupLocation(false);
183             updateVisibility();
184         }
185
186         public void keyPressed(KeyEvent e) {
187             updatePopupLocation(false);
188             updateVisibility();
189         }
190
191         public void keyReleased(KeyEvent e) {
192         }
193         
194
195         public void textChanged(TextEvent event) {
196             updatePopupLocation(false);
197             updateVisibility(); //only for hiding outside editor area
198
}
199         
200         public void viewportChanged(int verticalOffset) {
201             updatePopupLocation(true);
202             updateVisibility(); //only for hiding outside editor area
203
}
204     }
205
206     /**
207      * Cached platform flags for dealing with platform-specific issues.
208      */

209     private static boolean CARBON = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
210

211     private static final int WIDGET_PRIORITY= 1000;
212     
213     private static final String JavaDoc DIALOG_SETTINGS_SECTION= "RenameInformationPopup"; //$NON-NLS-1$
214
private static final String JavaDoc SNAP_POSITION_KEY= "snap_position"; //$NON-NLS-1$
215

216     private static final int SNAP_POSITION_UNDER_RIGHT_FIELD= 0;
217     private static final int SNAP_POSITION_OVER_RIGHT_FIELD= 1;
218     private static final int SNAP_POSITION_UNDER_LEFT_FIELD= 2;
219     private static final int SNAP_POSITION_OVER_LEFT_FIELD= 3;
220     private static final int SNAP_POSITION_LOWER_RIGHT= 4;
221     
222     private static final int POPUP_VISIBILITY_DELAY= 300;
223
224     /**
225      * Offset of info hover arrow from the left or right side.
226      */

227     private static final int HAO= 10;
228
229     /**
230      * Width of info hover arrow.
231      */

232     private static final int HAW= 8;
233
234     /**
235      * Height of info hover arrow.
236      */

237     private static final int HAH= 10;
238
239     /**
240      * Gap between linked position and popup.
241      */

242     private static final int GAP= 2;
243
244     private final CompilationUnitEditor fEditor;
245     private final RenameLinkedMode fRenameLinkedMode;
246     
247     private int fSnapPosition;
248     private Shell fPopup;
249     private GridLayout fPopupLayout;
250     private Region fRegion;
251
252     private Image fMenuImage;
253     private MenuManager fMenuManager;
254     private ToolBar fToolBar;
255     private String JavaDoc fOpenDialogBinding= ""; //$NON-NLS-1$
256
private boolean fIsMenuUp= false;
257     
258     private boolean fDelayJobFinished= false;
259     
260     public RenameInformationPopup(CompilationUnitEditor editor, RenameLinkedMode renameLinkedMode) {
261         fEditor= editor;
262         fRenameLinkedMode= renameLinkedMode;
263         restoreSnapPosition();
264     }
265
266     private void restoreSnapPosition() {
267         IDialogSettings settings= getDialogSettings();
268         try {
269             fSnapPosition= settings.getInt(SNAP_POSITION_KEY);
270         } catch (NumberFormatException JavaDoc e) {
271             // default:
272
fSnapPosition= SNAP_POSITION_UNDER_LEFT_FIELD;
273         }
274     }
275
276     private IDialogSettings getDialogSettings() {
277         return JavaPlugin.getDefault().getDialogSettingsSection(DIALOG_SETTINGS_SECTION);
278     }
279
280     public void open() {
281         // Must cache here, since editor context is not available in menu from popup shell:
282
fOpenDialogBinding= getOpenDialogBinding();
283         
284         Shell workbenchShell= fEditor.getSite().getShell();
285         final Display display= workbenchShell.getDisplay();
286         
287         fPopup= new Shell(workbenchShell, SWT.ON_TOP | SWT.NO_TRIM | SWT.TOOL);
288         fPopupLayout= new GridLayout(2, false);
289         fPopupLayout.marginWidth= 1;
290         fPopupLayout.marginHeight= 1;
291         fPopupLayout.marginLeft= 4;
292         fPopupLayout.horizontalSpacing= 0;
293         fPopup.setLayout(fPopupLayout);
294         
295         createContent(fPopup);
296         updatePopupLocation(true);
297         new PopupVisibilityManager().start();
298         
299         // Leave linked mode when popup loses focus
300
// (except when focus goes back to workbench window or menu is open):
301
fPopup.addShellListener(new ShellAdapter() {
302             public void shellDeactivated(ShellEvent e) {
303                 if (fIsMenuUp)
304                     return;
305                 
306                 final Shell editorShell= fEditor.getSite().getShell();
307                 display.asyncExec(new Runnable JavaDoc() {
308                     // post to UI thread since editor shell only gets activated after popup has lost focus
309
public void run() {
310                         Shell activeShell= display.getActiveShell();
311                         if (activeShell != editorShell) {
312                             fRenameLinkedMode.cancel();
313                         }
314                     }
315                 });
316             }
317         });
318         
319         if (! CARBON) { // carbon draws its own border...
320
fPopup.addPaintListener(new PaintListener() {
321                 public void paintControl(PaintEvent pe) {
322                     pe.gc.drawPolygon(getPolygon(true));
323                 }
324             });
325         }
326         
327 // fPopup.moveBelow(null); // make sure hovers are on top of the info popup
328
// XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
329
// fPopup.moveBelow(workbenchShell.getShells()[0]);
330

331         UIJob delayJob= new UIJob(display, ReorgMessages.RenameInformationPopup_delayJobName) {
332             public IStatus runInUIThread(IProgressMonitor monitor) {
333                 fDelayJobFinished= true;
334                 if (fPopup != null && ! fPopup.isDisposed()) {
335                     updateVisibility();
336                 }
337                 return Status.OK_STATUS;
338             }
339         };
340         delayJob.setSystem(true);
341         delayJob.setPriority(Job.INTERACTIVE);
342         delayJob.schedule(POPUP_VISIBILITY_DELAY);
343     }
344
345     public void close() {
346         if (fPopup != null) {
347             if (!fPopup.isDisposed()) {
348                 fPopup.close();
349             }
350             fPopup= null;
351         }
352         releaseWidgetToken();
353         if (fRegion != null) {
354             if (! fRegion.isDisposed()) {
355                 fRegion.dispose();
356             }
357         }
358     }
359     
360     public Shell getShell() {
361         return fPopup;
362     }
363     
364     private void updatePopupLocation(boolean force) {
365         if (! force && fSnapPosition == SNAP_POSITION_LOWER_RIGHT)
366             return;
367         
368         packPopup();
369         Point loc= computePopupLocation(fSnapPosition);
370         if (loc != null) {
371             fPopup.setLocation(loc);
372             // XXX workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=170774
373
// fPopup.moveBelow(fEditor.getSite().getShell().getShells()[0]);
374
}
375     }
376
377     private void updateVisibility() {
378         if (fPopup != null && !fPopup.isDisposed() && fDelayJobFinished) {
379             boolean visible= false;
380             //TODO: Check for visibility of linked position, not whether popup is outside of editor?
381
if (fRenameLinkedMode.isCaretInLinkedPosition()) {
382                 StyledText textWidget= fEditor.getViewer().getTextWidget();
383                 Rectangle eArea= Geometry.toDisplay(textWidget, textWidget.getClientArea());
384                 Rectangle pBounds= fPopup.getBounds();
385                 pBounds.x-= GAP;
386                 pBounds.y-= GAP;
387                 pBounds.width+= 2 * GAP;
388                 pBounds.height+= 2 * GAP;
389                 if (eArea.intersects(pBounds)) {
390                     visible= true;
391                 }
392             }
393             if (visible && ! fPopup.isVisible()) {
394                 ISourceViewer viewer= fEditor.getViewer();
395                 if (viewer instanceof IWidgetTokenOwnerExtension) {
396                     IWidgetTokenOwnerExtension widgetTokenOwnerExtension= (IWidgetTokenOwnerExtension) viewer;
397                     widgetTokenOwnerExtension.requestWidgetToken(this, WIDGET_PRIORITY);
398                 }
399             } else if (! visible && fPopup.isVisible()) {
400                 releaseWidgetToken();
401             }
402             fPopup.setVisible(visible);
403         }
404     }
405
406     private void releaseWidgetToken() {
407         ISourceViewer viewer= fEditor.getViewer();
408         if (viewer instanceof IWidgetTokenOwner) {
409             IWidgetTokenOwner widgetTokenOwner= (IWidgetTokenOwner) viewer;
410             widgetTokenOwner.releaseWidgetToken(this);
411         }
412     }
413
414     /**
415      * @param snapPosition one of the SNAP_POSITION_* constants
416      * @return the location in display coordinates or <code>null</code> iff not visible
417      */

418     private Point computePopupLocation(int snapPosition) {
419         if (fPopup == null || fPopup.isDisposed())
420             return null;
421         
422         switch (snapPosition) {
423             case SNAP_POSITION_LOWER_RIGHT:
424             {
425                 StyledText eWidget= fEditor.getViewer().getTextWidget();
426                 Rectangle eBounds= eWidget.getClientArea();
427                 Point eLowerRight= eWidget.toDisplay(eBounds.x + eBounds.width, eBounds.y + eBounds.height);
428                 Point pSize= getExtent();
429                 return new Point(eLowerRight.x - pSize.x - 5, eLowerRight.y - pSize.y - 5);
430             }
431             
432             case SNAP_POSITION_UNDER_RIGHT_FIELD:
433             case SNAP_POSITION_OVER_RIGHT_FIELD:
434             {
435                 LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
436                 if (position == null)
437                     return null;
438                 ISourceViewer viewer= fEditor.getViewer();
439                 ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
440                 int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset + position.length);
441                 
442                 StyledText textWidget= viewer.getTextWidget();
443                 Point pos= textWidget.getLocationAtOffset(widgetOffset);
444                 Point pSize= getExtent();
445                 if (snapPosition == SNAP_POSITION_OVER_RIGHT_FIELD) {
446                     pos.y-= pSize.y + GAP;
447                 } else {
448                     pos.y+= textWidget.getLineHeight(widgetOffset) + GAP;
449                 }
450                 pos.x+= GAP;
451                 Point dPos= textWidget.toDisplay(pos);
452                 Rectangle displayBounds= textWidget.getDisplay().getClientArea();
453                 Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
454                 Geometry.moveInside(dPopupRect, displayBounds);
455                 return new Point(dPopupRect.x, dPopupRect.y);
456             }
457             
458             case SNAP_POSITION_UNDER_LEFT_FIELD:
459             case SNAP_POSITION_OVER_LEFT_FIELD:
460             default: // same as SNAP_POSITION_UNDER_LEFT_FIELD
461
{
462                 LinkedPosition position= fRenameLinkedMode.getCurrentLinkedPosition();
463                 if (position == null)
464                     return null;
465                 ISourceViewer viewer= fEditor.getViewer();
466                 ITextViewerExtension5 viewer5= (ITextViewerExtension5) viewer;
467                 int widgetOffset= viewer5.modelOffset2WidgetOffset(position.offset/* + position.length*/);
468                 
469                 StyledText textWidget= viewer.getTextWidget();
470                 Point pos= textWidget.getLocationAtOffset(widgetOffset);
471                 Point pSize= getExtent();
472                 pSize.y+= HAH + 1;
473                 pos.x-= HAO;
474                 if (snapPosition == SNAP_POSITION_OVER_LEFT_FIELD) {
475                     pos.y-= pSize.y;
476                 } else {
477                     pos.y+= textWidget.getLineHeight(widgetOffset);
478                 }
479                 Point dPos= textWidget.toDisplay(pos);
480                 Rectangle displayBounds= textWidget.getDisplay().getClientArea();
481                 Rectangle dPopupRect= Geometry.createRectangle(dPos, pSize);
482                 Geometry.moveInside(dPopupRect, displayBounds);
483                 return new Point(dPopupRect.x, dPopupRect.y);
484             }
485             
486         }
487     }
488
489     private void addMoveSupport(final Shell popupShell, final Control movedControl) {
490         movedControl.addMouseListener(new MouseAdapter() {
491
492             public void mouseDown(final MouseEvent downEvent) {
493                 if (downEvent.button != 1) {
494                     return;
495                 }
496                 
497                 final Point POPUP_SOURCE= popupShell.getLocation();
498                 final StyledText textWidget= fEditor.getViewer().getTextWidget();
499                 Point pSize= getExtent();
500                 int originalSnapPosition= fSnapPosition;
501                 
502                 /*
503                  * Feature in Tracker: it is not possible to directly control the feedback,
504                  * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121300
505                  * and https://bugs.eclipse.org/bugs/show_bug.cgi?id=121298#c1 .
506                  *
507                  * Workaround is to have an offscreen rectangle for tracking mouse movement
508                  * and a manually updated rectangle for the actual drop target.
509                  */

510                 final Tracker tracker= new Tracker(textWidget, SWT.NONE);
511                 
512                 final Point[] LOCATIONS= {
513                         textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_RIGHT_FIELD)),
514                         textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_RIGHT_FIELD)),
515                         textWidget.toControl(computePopupLocation(SNAP_POSITION_UNDER_LEFT_FIELD)),
516                         textWidget.toControl(computePopupLocation(SNAP_POSITION_OVER_LEFT_FIELD)),
517                         textWidget.toControl(computePopupLocation(SNAP_POSITION_LOWER_RIGHT))
518                 };
519                 
520                 final Rectangle[] DROP_TARGETS= {
521                     Geometry.createRectangle(LOCATIONS[0], pSize),
522                     Geometry.createRectangle(LOCATIONS[1], pSize),
523                     new Rectangle(LOCATIONS[2].x, LOCATIONS[2].y + HAH, pSize.x, pSize.y),
524                     Geometry.createRectangle(LOCATIONS[3], pSize),
525                     Geometry.createRectangle(LOCATIONS[4], pSize)
526                 };
527                 final Rectangle MOUSE_MOVE_SOURCE= new Rectangle(1000000, 0, 0, 0);
528                 tracker.setRectangles(new Rectangle[] { MOUSE_MOVE_SOURCE, DROP_TARGETS[fSnapPosition] });
529                 tracker.setStippled(true);
530                 
531                 ControlListener moveListener= new ControlAdapter() {
532                     /*
533                      * @see org.eclipse.swt.events.ControlAdapter#controlMoved(org.eclipse.swt.events.ControlEvent)
534                      */

535                     public void controlMoved(ControlEvent moveEvent) {
536                         Rectangle[] currentRects= tracker.getRectangles();
537                         final Rectangle mouseMoveCurrent= currentRects[0];
538                         Point popupLoc= new Point(
539                                 POPUP_SOURCE.x + mouseMoveCurrent.x - MOUSE_MOVE_SOURCE.x,
540                                 POPUP_SOURCE.y + mouseMoveCurrent.y - MOUSE_MOVE_SOURCE.y);
541                         
542                         popupShell.setLocation(popupLoc);
543                         
544                         Point ePopupLoc= textWidget.toControl(popupLoc);
545                         int minDist= Integer.MAX_VALUE;
546                         for (int snapPos= 0; snapPos < DROP_TARGETS.length; snapPos++) {
547                             int dist= Geometry.distanceSquared(ePopupLoc, LOCATIONS[snapPos]);
548                             if (dist < minDist) {
549                                 minDist= dist;
550                                 fSnapPosition= snapPos;
551                                 currentRects[1]= DROP_TARGETS[snapPos];
552                             }
553                         }
554                         tracker.setRectangles(currentRects);
555                     }
556                 };
557                 tracker.addControlListener(moveListener);
558                 boolean committed= tracker.open();
559                 tracker.close();
560                 tracker.dispose();
561                 if (committed) {
562                     getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
563                 } else {
564                     fSnapPosition= originalSnapPosition;
565                 }
566                 updatePopupLocation(true);
567                 activateEditor();
568             }
569         });
570     }
571         
572     private void packPopup() {
573         boolean isUnderLeft= fSnapPosition == SNAP_POSITION_UNDER_LEFT_FIELD;
574         boolean isOverLeft= fSnapPosition == SNAP_POSITION_OVER_LEFT_FIELD;
575         fPopupLayout.marginTop= isUnderLeft ? HAH : 0;
576         fPopupLayout.marginBottom= isOverLeft ? HAH + 1 : 0;
577         fPopup.pack();
578         
579         Region oldRegion= fRegion;
580         if (isUnderLeft || isOverLeft) {
581             fRegion= new Region();
582             fRegion.add(getPolygon(false));
583             fPopup.setRegion(fRegion);
584             Rectangle bounds= fRegion.getBounds();
585             fPopup.setSize(bounds.width, bounds.height + 1);
586         } else {
587             fRegion= null;
588             fPopup.setRegion(null);
589         }
590         
591         if (oldRegion != null) {
592             oldRegion.dispose();
593         }
594     }
595     
596     private Point getExtent() {
597         Point e = fPopup.getSize();
598         switch (fSnapPosition) {
599             case SNAP_POSITION_UNDER_LEFT_FIELD:
600                 e.y -= HAH;
601                 break;
602             case SNAP_POSITION_OVER_LEFT_FIELD:
603                 e.y -= HAH + 1;
604                 break;
605         }
606         return e;
607     }
608     
609     private int[] getPolygon(boolean border) {
610         Point e = getExtent();
611         int b = border ? 1 : 0;
612         if (true /*arrowOnLeft*/) {
613             switch (fSnapPosition) {
614                 case SNAP_POSITION_OVER_LEFT_FIELD:
615                     return new int[] {
616                             0, 0,
617                             e.x - b, 0,
618                             e.x - b, e.y - b,
619                             HAO + HAW, e.y - b,
620                             HAO + HAW / 2, e.y + HAH - b,
621                             HAO, e.y - b,
622                             0, e.y - b,
623                             0, 0 };
624
625                 case SNAP_POSITION_UNDER_LEFT_FIELD:
626                     return new int[] {
627                             0, HAH,
628                             HAO + b, HAH,
629                             HAO + HAW / 2, b,
630                             HAO + HAW - b, HAH,
631                             e.x - b, HAH,
632                             e.x - b, e.y + HAH - b,
633                             0, e.y + HAH - b,
634                             0, HAH };
635                     
636                 default:
637                     return new int[] {
638                             0, 0,
639                             e.x - b, 0,
640                             e.x - b, e.y - b,
641                             0, e.y - b,
642                             0, 0 };
643             }
644         }
645         //TODO: BiDi?
646
return new int[] { 0, 0, e.x - b, 0, e.x - b, e.y - b,
647                 e.x - HAO - b, e.y - b, e.x - HAO - HAW / 2, e.y + HAH - b,
648                 e.x - HAO - HAW, e.y - b, 0, e.y - b, 0, 0 };
649     }
650     
651     private void createContent(Composite parent) {
652         Display display= parent.getDisplay();
653         Color foreground= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
654         Color background= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
655         addMoveSupport(fPopup, parent);
656         
657         StyledText hint= new StyledText(fPopup, SWT.READ_ONLY | SWT.SINGLE);
658         String JavaDoc enterKeyName= getEnterBinding();
659         String JavaDoc hintTemplate= ReorgMessages.RenameInformationPopup_EnterNewName;
660         hint.setText(Messages.format(hintTemplate, enterKeyName));
661         hint.setForeground(foreground);
662         hint.setStyleRange(new StyleRange(hintTemplate.indexOf("{0}"), enterKeyName.length(), null, null, SWT.BOLD)); //$NON-NLS-1$
663
hint.setEnabled(false); // text must not be selectable
664
addMoveSupport(fPopup, hint);
665         
666         addViewMenu(parent);
667         
668         recursiveSetBackgroundColor(parent, background);
669         
670     }
671
672     private ToolBar addViewMenu(final Composite parent) {
673         fToolBar= new ToolBar(parent, SWT.FLAT);
674         final ToolItem menuButton = new ToolItem(fToolBar, SWT.PUSH, 0);
675         fMenuImage= JavaPluginImages.DESC_ELCL_VIEW_MENU.createImage();
676         menuButton.setImage(fMenuImage);
677         menuButton.setToolTipText(ReorgMessages.RenameInformationPopup_menu);
678         fToolBar.addMouseListener(new MouseAdapter() {
679             public void mouseDown(MouseEvent e) {
680                 showMenu(fToolBar);
681             }
682         });
683         menuButton.addSelectionListener(new SelectionAdapter() {
684             public void widgetSelected(SelectionEvent e) {
685                 showMenu(fToolBar);
686             }
687         });
688         fToolBar.pack();
689         return fToolBar;
690     }
691
692     private void showMenu(ToolBar toolBar) {
693         Menu menu= getMenuManager().createContextMenu(toolBar);
694         menu.setLocation(toolBar.toDisplay(0, toolBar.getSize().y));
695         fIsMenuUp= true;
696         menu.setVisible(true);
697     }
698
699     private MenuManager getMenuManager() {
700         if (fMenuManager != null) {
701             return fMenuManager;
702         }
703         
704         fMenuManager= new MenuManager();
705         fMenuManager.setRemoveAllWhenShown(true);
706
707         fMenuManager.addMenuListener(new IMenuListener2() {
708             public void menuAboutToHide(IMenuManager manager) {
709                 fIsMenuUp= false;
710             }
711             public void menuAboutToShow(IMenuManager manager) {
712                 IAction refactorAction= new Action(ReorgMessages.RenameInformationPopup_RenameInWorkspace) {
713                     public void run() {
714                         activateEditor();
715                         fRenameLinkedMode.doRename(false);
716                     }
717                 };
718                 refactorAction.setAccelerator(SWT.CR);
719                 manager.add(refactorAction);
720                 
721                 IAction previewAction= new Action(ReorgMessages.RenameInformationPopup_Preview) {
722                     public void run() {
723                         activateEditor();
724                         fRenameLinkedMode.doRename(true);
725                     }
726                 };
727                 previewAction.setAccelerator(SWT.CTRL | SWT.CR);
728                 manager.add(previewAction);
729                 
730                 IAction openDialogAction= new Action(ReorgMessages.RenameInformationPopup_OpenDialog + '\t' + fOpenDialogBinding) {
731                     public void run() {
732                         activateEditor();
733                         fRenameLinkedMode.startFullDialog();
734                     }
735                 };
736                 manager.add(openDialogAction);
737                                 
738                 manager.add(new Separator());
739                 
740                 MenuManager subMenuManager= new MenuManager(ReorgMessages.RenameInformationPopup_SnapTo);
741                 addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_LEFT_FIELD, ReorgMessages.RenameInformationPopup_snap_under_left);
742                 addMoveMenuItem(subMenuManager, SNAP_POSITION_UNDER_RIGHT_FIELD, ReorgMessages.RenameInformationPopup_snap_under_right);
743                 addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_LEFT_FIELD, ReorgMessages.RenameInformationPopup_snap_over_left);
744                 addMoveMenuItem(subMenuManager, SNAP_POSITION_OVER_RIGHT_FIELD, ReorgMessages.RenameInformationPopup_snap_over_right);
745                 addMoveMenuItem(subMenuManager, SNAP_POSITION_LOWER_RIGHT, ReorgMessages.RenameInformationPopup_snap_bottom_right);
746                 manager.add(subMenuManager);
747                 
748                 IAction prefsAction= new Action(ReorgMessages.RenameInformationPopup_preferences) {
749                     public void run() {
750                         fRenameLinkedMode.cancel();
751                         String JavaDoc linkedModePrefPageID= "org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage"; //$NON-NLS-1$
752
String JavaDoc refactoringPrefPageID= JavaBasePreferencePage.JAVA_BASE_PREF_PAGE_ID;
753                         PreferencesUtil.createPreferenceDialogOn(fEditor.getSite().getShell(), refactoringPrefPageID, new String JavaDoc[] { linkedModePrefPageID, refactoringPrefPageID }, null).open();
754                     }
755                 };
756                 manager.add(prefsAction);
757             }
758         });
759         return fMenuManager;
760     }
761
762     private void addMoveMenuItem(IMenuManager manager, final int snapPosition, String JavaDoc text) {
763         IAction action= new Action(text, IAction.AS_RADIO_BUTTON) {
764             public void run() {
765                 fSnapPosition= snapPosition;
766                 getDialogSettings().put(SNAP_POSITION_KEY, fSnapPosition);
767                 updatePopupLocation(true);
768                 activateEditor();
769             }
770         };
771         action.setChecked(fSnapPosition == snapPosition);
772         manager.add(action);
773     }
774     
775     private static String JavaDoc getEnterBinding() {
776         return KeyStroke.getInstance(KeyLookupFactory.getDefault().formalKeyLookup(IKeyLookup.CR_NAME)).format();
777     }
778
779     /**
780      * WARNING: only works in workbench window context!
781      * @return the keybinding for Refactor &gt; Rename
782      */

783     private static String JavaDoc getOpenDialogBinding() {
784         IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
785         if (bindingService == null)
786             return ""; //$NON-NLS-1$
787
String JavaDoc binding= bindingService.getBestActiveBindingFormattedFor(IJavaEditorActionDefinitionIds.RENAME_ELEMENT);
788         return binding == null ? "" : binding; //$NON-NLS-1$
789
}
790     
791     private static void recursiveSetBackgroundColor(Control control, Color color) {
792         control.setBackground(color);
793         if (control instanceof Composite) {
794             Control[] children= ((Composite) control).getChildren();
795             for (int i= 0; i < children.length; i++) {
796                 recursiveSetBackgroundColor(children[i], color);
797             }
798         }
799     }
800
801     public boolean ownsFocusShell() {
802         if (fIsMenuUp)
803             return true;
804         if (fPopup == null || fPopup.isDisposed())
805             return false;
806         Shell activeShell= fPopup.getDisplay().getActiveShell();
807         if (fPopup == activeShell)
808             return true;
809         return false;
810     }
811
812     private void activateEditor() {
813         fEditor.getSite().getShell().setActive();
814     }
815     
816     public boolean requestWidgetToken(IWidgetTokenOwner owner) {
817         return false;
818     }
819     
820     public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
821         return false;
822     }
823     
824     public boolean setFocus(IWidgetTokenOwner owner) {
825         if (fToolBar != null && ! fToolBar.isDisposed())
826             showMenu(fToolBar);
827         return true;
828     }
829 }
830
Popular Tags