### Eclipse Workspace Patch 1.0 #P org.eclipse.jface.text Index: src/org/eclipse/jface/text/AbstractInformationControl.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControl.java,v retrieving revision 1.1 diff -u -r1.1 AbstractInformationControl.java --- src/org/eclipse/jface/text/AbstractInformationControl.java 20 Feb 2008 15:22:27 -0000 1.1 +++ src/org/eclipse/jface/text/AbstractInformationControl.java 21 Feb 2008 14:48:36 -0000 @@ -10,8 +10,11 @@ *******************************************************************************/ package org.eclipse.jface.text; -import java.util.List; - +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.internal.text.html.BrowserInformationControl; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.Geometry; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusEvent; @@ -19,7 +22,10 @@ import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; @@ -27,26 +33,21 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Slider; import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.core.runtime.ListenerList; - -import org.eclipse.jface.action.ToolBarManager; -import org.eclipse.jface.dialogs.PopupDialog; -import org.eclipse.jface.internal.text.html.BrowserInformationControl; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.util.Geometry; - /** - * The abstract information control can show any content inside a popup window. + * The abstract information control can show any content inside a shell. * Additionally it can present either a status line containing a status text or * a toolbar containing toolbar buttons. *

@@ -62,13 +63,14 @@ */ public abstract class AbstractInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension3, IInformationControlExtension5 { + private static final int BORDER= 1; - /** The control's popup dialog. */ - private PopupDialog fPopupDialog; + /** The information controls shell. */ + private final Shell fShell; /** Composite containing the content created by subclasses. */ - private Composite fContentComposite; + private final Composite fContentComposite; /** Composite containing the status line content or null if none. */ - private Composite fStatusComposite; + private final Composite fStatusComposite; /** Separator between content and status line or null if none. */ private Label fSeparator; /** Label in the status line or null if none. */ @@ -83,7 +85,8 @@ private Point fSizeConstaints; /** The toolbar manager used by the toolbar or null if none. */ private final ToolBarManager fToolBarManager; - + /** The size of the resize handle if already set, -1 otherwise */ + private int fResizeHandleSize; /** * Creates an abstract information control with the given shell as parent. @@ -122,78 +125,53 @@ * @param toolBarManager the manager of the popup tool bar, if any */ private AbstractInformationControl(Shell parentShell, int shellStyle, final String statusFieldText, final ToolBarManager toolBarManager) { + fResizeHandleSize= -1; fToolBarManager= toolBarManager; - fPopupDialog= new PopupDialog(parentShell, shellStyle | SWT.NO_FOCUS | SWT.ON_TOP, false, false, false, false, null, null) { - - /* - * @see org.eclipse.jface.dialogs.PopupDialog#createDialogArea(org.eclipse.swt.widgets.Composite) - */ - protected Control createDialogArea(Composite parent) { - Composite composite= new Composite(parent, SWT.NONE); - - composite.setLayoutData(new GridData(GridData.BEGINNING | GridData.FILL_BOTH)); - - GridLayout layout= new GridLayout(); - layout.marginHeight= 0; - layout.marginWidth= 0; - layout.verticalSpacing= 0; - composite.setLayout(layout); - - fContentComposite= new Composite(composite, SWT.NONE); - fContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - GridLayout contentLayout= new GridLayout(1, false); - contentLayout.marginHeight= 0; - contentLayout.marginWidth= 0; - fContentComposite.setLayout(contentLayout); - createContent(fContentComposite); - - if (toolBarManager != null || statusFieldText != null) { - fStatusComposite= new Composite(composite, SWT.NONE); - GridData gridData= new GridData(SWT.FILL, SWT.BOTTOM, true, false); - fStatusComposite.setLayoutData(gridData); - GridLayout gridLayout= new GridLayout(1, false); - gridLayout.marginHeight= 0; - gridLayout.marginWidth= 0; - gridLayout.verticalSpacing= 0; - fStatusComposite.setLayout(gridLayout); - - createStatusLine(fStatusComposite, statusFieldText, toolBarManager); - } - - return composite; - } - - /* - * @see org.eclipse.jface.dialogs.PopupDialog#getBackgroundColorExclusions() - */ - protected List getBackgroundColorExclusions() { - List result= super.getBackgroundColorExclusions(); - - if (fToolBar != null) { - result.add(fStatusComposite); - result.add(fSeparator); - result.add(fToolBar); - } - - return result; - } - - /* - * @see org.eclipse.jface.dialogs.PopupDialog#getForegroundColorExclusions() - */ - protected List getForegroundColorExclusions() { - List result= super.getForegroundColorExclusions(); - - if (fStatusLabel != null) { - result.add(fStatusLabel); - } - - return result; + + fShell= new Shell(parentShell, SWT.ON_TOP | shellStyle); + Display display= fShell.getDisplay(); + + GridLayout layout= new GridLayout(1, false); + int border; + if ((shellStyle & SWT.NO_TRIM) == 0) { + border= 0; + } else { + border= BORDER; + fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + } + layout.marginHeight= border; + layout.marginWidth= border; + layout.verticalSpacing= 0; + fShell.setLayout(layout); + + fContentComposite= new Composite(fShell, SWT.NONE); + fContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + GridLayout contentLayout= new GridLayout(1, false); + contentLayout.marginHeight= 0; + contentLayout.marginWidth= 0; + fContentComposite.setLayout(contentLayout); + createContent(fContentComposite); + + setColor(fContentComposite, display.getSystemColor(SWT.COLOR_INFO_FOREGROUND), display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + + if (toolBarManager != null || statusFieldText != null) { + fStatusComposite= new Composite(fShell, SWT.NONE); + GridData gridData= new GridData(SWT.FILL, SWT.BOTTOM, true, false); + fStatusComposite.setLayoutData(gridData); + GridLayout statusLayout= new GridLayout(1, false); + statusLayout.marginHeight= 0; + statusLayout.marginWidth= 0; + statusLayout.verticalSpacing= 0; + fStatusComposite.setLayout(statusLayout); + + createStatusLine(fStatusComposite, statusFieldText, toolBarManager); + + if (statusFieldText != null) { + setColor(fStatusComposite, display.getSystemColor(SWT.COLOR_INFO_FOREGROUND), display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } - }; - - // Force create early so that listeners can be added at all times with API. - fPopupDialog.create(); + } else { + fStatusComposite= null; + } } /** @@ -202,7 +180,7 @@ * @return the shell used for the popup window */ protected Shell getShell() { - return fPopupDialog.getShell(); + return fShell; } /** @@ -226,32 +204,32 @@ * @see IInformationControl#setVisible(boolean) */ public void setVisible(boolean visible) { - if (visible) - fPopupDialog.open(); - else - fPopupDialog.getShell().setVisible(false); + if (getShell().isVisible() == visible) + return; + + getShell().setVisible(visible); } /* * @see IInformationControl#dispose() */ public void dispose() { - fPopupDialog.close(); - fPopupDialog= null; + if (fShell != null && !fShell.isDisposed()) + fShell.dispose(); } /* * @see IInformationControl#setSize(int, int) */ public void setSize(int width, int height) { - fPopupDialog.getShell().setSize(width, height); + getShell().setSize(width, height); } /* * @see IInformationControl#setLocation(Point) */ public void setLocation(Point location) { - fPopupDialog.getShell().setLocation(location); + getShell().setLocation(location); } /* @@ -277,17 +255,23 @@ public Point computeSizeHint() { Point constrains= getSizeConstraints(); if (constrains == null) - return fPopupDialog.getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + return getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); - return fPopupDialog.getShell().computeSize(constrains.x, constrains.y, true); + return getShell().computeSize(constrains.x, constrains.y, true); } /* * @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim() */ public Rectangle computeTrim() { - Shell shell= fPopupDialog.getShell(); - Rectangle trim= shell.computeTrim(0, 0, 0, 0); + Rectangle trim= getShell().computeTrim(0, 0, 0, 0); + + if ((getShell().getStyle() & SWT.NO_TRIM) != 0) { + trim.x-= BORDER; + trim.y-= BORDER; + trim.width+= 2 * BORDER; + trim.height+= 2 * BORDER; + } if (fToolBar != null) { trim.height+= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; @@ -298,7 +282,7 @@ } // Popup dialog adds a 1 pixel border when SWT.NO_TRIM is set: - Layout layout= shell.getLayout(); + Layout layout= getShell().getLayout(); if (layout instanceof GridLayout) { GridLayout gridLayout= (GridLayout) layout; int left= gridLayout.marginLeft + gridLayout.marginWidth; @@ -332,7 +316,7 @@ * @see org.eclipse.jface.text.IInformationControlExtension3#getBounds() */ public Rectangle getBounds() { - return fPopupDialog.getShell().getBounds(); + return getShell().getBounds(); } /* @@ -353,14 +337,14 @@ * @see IInformationControl#addDisposeListener(DisposeListener) */ public void addDisposeListener(DisposeListener listener) { - fPopupDialog.getShell().addDisposeListener(listener); + getShell().addDisposeListener(listener); } /* * @see IInformationControl#removeDisposeListener(DisposeListener) */ public void removeDisposeListener(DisposeListener listener) { - fPopupDialog.getShell().removeDisposeListener(listener); + getShell().removeDisposeListener(listener); } /* @@ -381,15 +365,14 @@ * @see IInformationControl#isFocusControl() */ public boolean isFocusControl() { - Shell shell= fPopupDialog.getShell(); - return shell.getDisplay().getActiveShell() == shell; + return getShell().getDisplay().getActiveShell() == getShell(); } /* * @see IInformationControl#setFocus() */ public void setFocus() { - fPopupDialog.getShell().forceFocus(); + getShell().forceFocus(); } /* @@ -441,8 +424,7 @@ */ public boolean containsControl(Control control) { do { - Shell popupShell= fPopupDialog.getShell(); - if (control == popupShell) + if (control == getShell()) return true; if (control instanceof Shell) return false; @@ -455,8 +437,8 @@ * @see org.eclipse.jface.text.IInformationControlExtension5#isVisible() */ public boolean isVisible() { - Shell popupShell= fPopupDialog.getShell(); - return popupShell != null && !popupShell.isDisposed() && popupShell.isVisible(); + Shell shell= getShell(); + return shell != null && !shell.isDisposed() && shell.isVisible(); } /* @@ -484,10 +466,7 @@ fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if (toolBarManager != null) { - fToolBar= toolBarManager.createControl(parent); - fToolBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); - - addMoveSupport(parent); + createToolBar(parent, toolBarManager); } else { fStatusLabel= new Label(parent, SWT.RIGHT); fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); @@ -502,6 +481,93 @@ } } + private void createToolBar(Composite parent, ToolBarManager toolBarManager) { + final Composite bars= new Composite(parent, SWT.NONE); + bars.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + + GridLayout layout= new GridLayout(3, false); + layout.marginHeight= 0; + layout.marginWidth= 0; + layout.horizontalSpacing= 0; + layout.verticalSpacing= 0; + bars.setLayout(layout); + + fToolBar= toolBarManager.createControl(bars); + GridData gd= new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false); + fToolBar.setLayoutData(gd); + + Composite spacer= new Composite(bars, SWT.NONE); + gd= new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint= 0; + gd.heightHint= 0; + spacer.setLayoutData(gd); + + addMoveSupport(spacer); + + // XXX: workaround for + // - https://bugs.eclipse.org/bugs/show_bug.cgi?id=219139 : API to add resize grip / grow box in lower right corner of shell + // - https://bugs.eclipse.org/bugs/show_bug.cgi?id=23980 : platform specific shell resize behavior + String platform= SWT.getPlatform(); + final boolean isWin= platform.equals("win32"); //$NON-NLS-1$ + if (isWin || platform.equals("gtk")) { //$NON-NLS-1$ + final Canvas resizer= new Canvas(bars, SWT.NONE); + + int size= getResizeHandleSize(bars); + + GridData data= new GridData(SWT.END, SWT.END, false, true); + data.widthHint= size; + data.heightHint= size; + resizer.setLayoutData(data); + resizer.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + Point s= resizer.getSize(); + int x= s.x - 2; + int y= s.y - 2; + int min= Math.min(x, y); + if (isWin) { + // draw dots + e.gc.setBackground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); + int end= min - 1; + for (int i= 0; i <= 2; i++) + for (int j= 0; j <= 2 - i; j++) + e.gc.fillRectangle(end - 4 * i, end - 4 * j, 2, 2); + end--; + e.gc.setBackground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); + for (int i= 0; i <= 2; i++) + for (int j= 0; j <= 2 - i; j++) + e.gc.fillRectangle(end - 4 * i, end - 4 * j, 2, 2); + + } else { + // draw diagonal lines + e.gc.setForeground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); + for (int i= 1; i < min; i+= 4) { + e.gc.drawLine(i, y, x, i); + } + e.gc.setForeground(resizer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); + for (int i= 2; i < min; i+= 4) { + e.gc.drawLine(i, y, x, i); + } + } + } + }); + addResizeSupport(resizer); + } + } + + private int getResizeHandleSize(Composite parent) { + if (fResizeHandleSize == -1) { + Slider sliderV= new Slider(parent, SWT.VERTICAL); + Slider sliderH= new Slider(parent, SWT.HORIZONTAL); + int width= sliderV.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; + int height= sliderH.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; + sliderV.dispose(); + sliderH.dispose(); + fResizeHandleSize= Math.min(width, height); + } + + return fResizeHandleSize; + } + /** * Adds support to move the shell by dragging the given control. * @@ -512,7 +578,7 @@ private MouseMoveListener fMoveListener; public void mouseDown(MouseEvent e) { - Point shellLoc= fPopupDialog.getShell().getLocation(); + Point shellLoc= getShell().getLocation(); final int shellX= shellLoc.x; final int shellY= shellLoc.y; Point mouseLoc= control.toDisplay(e.x, e.y); @@ -523,7 +589,7 @@ Point mouseLoc2= control.toDisplay(e2.x, e2.y); int dx= mouseLoc2.x - mouseX; int dy= mouseLoc2.y - mouseY; - fPopupDialog.getShell().setLocation(shellX + dx, shellY + dy); + getShell().setLocation(shellX + dx, shellY + dy); } }; control.addMouseMoveListener(fMoveListener); @@ -537,4 +603,61 @@ control.addMouseListener(moveSupport); } + /** + * Adds support to resize the shell by dragging the given control. + * + * @param control the control that can be used to resize the shell + * @since 3.4 + */ + private void addResizeSupport(final Control control) { + control.setCursor(new Cursor(control.getDisplay(), SWT.CURSOR_SIZESE)); + MouseAdapter resizeSupport= new MouseAdapter() { + private MouseMoveListener fResizeListener; + + public void mouseDown(MouseEvent e) { + Point shellSize= fShell.getSize(); + final int shellX= shellSize.x; + final int shellY= shellSize.y; + Point mouseLoc= control.toDisplay(e.x, e.y); + final int mouseX= mouseLoc.x; + final int mouseY= mouseLoc.y; + fResizeListener= new MouseMoveListener() { + public void mouseMove(MouseEvent e2) { + Point mouseLoc2= control.toDisplay(e2.x, e2.y); + int dx= mouseLoc2.x - mouseX; + int dy= mouseLoc2.y - mouseY; + setSize(shellX + dx, shellY + dy); + } + }; + control.addMouseMoveListener(fResizeListener); + } + + public void mouseUp(MouseEvent e) { + control.removeMouseMoveListener(fResizeListener); + fResizeListener= null; + } + }; + control.addMouseListener(resizeSupport); + } + + /** + * Utility to set the foreground and the background color of the given + * control and of all its children. + * + * @param control the control to modify + * @param foreground the color to use for the foreground + * @param background the color to use for the background + */ + private static void setColor(Control control, Color foreground, Color background) { + control.setForeground(foreground); + control.setBackground(background); + + if (control instanceof Composite) { + Control[] children= ((Composite) control).getChildren(); + for (int i= 0; i < children.length; i++) { + setColor(children[i], foreground, background); + } + } + } + }