| /*=============================================================================# |
| # Copyright (c) 2010, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.r.ui.rhelp; |
| |
| import static org.eclipse.debug.ui.IDebugUIConstants.PREF_DETAIL_PANE_FONT; |
| |
| import static org.eclipse.statet.ltk.ui.sourceediting.assist.InfoHover.MODE_FOCUS; |
| |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.IHandler2; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.internal.text.html.BrowserInformationControl; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.text.AbstractInformationControl; |
| import org.eclipse.jface.text.AbstractReusableInformationControlCreator; |
| import org.eclipse.jface.text.IInformationControl; |
| import org.eclipse.jface.text.IInformationControlCreator; |
| import org.eclipse.jface.text.IInformationControlExtension2; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.StyledString; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.browser.Browser; |
| import org.eclipse.swt.browser.LocationEvent; |
| import org.eclipse.swt.browser.LocationListener; |
| import org.eclipse.swt.browser.OpenWindowListener; |
| import org.eclipse.swt.browser.ProgressEvent; |
| import org.eclipse.swt.browser.ProgressListener; |
| import org.eclipse.swt.browser.TitleEvent; |
| import org.eclipse.swt.browser.TitleListener; |
| import org.eclipse.swt.browser.WindowEvent; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.FontMetrics; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.menus.CommandContributionItemParameter; |
| import org.eclipse.ui.services.IServiceLocator; |
| |
| import org.eclipse.statet.ecommons.ui.SharedUIResources; |
| import org.eclipse.statet.ecommons.ui.actions.HandlerCollection; |
| import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem; |
| import org.eclipse.statet.ecommons.ui.actions.SimpleContributionItem; |
| import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.IBrowserProvider; |
| import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.NavigateBackHandler; |
| import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.NavigateForwardHandler; |
| import org.eclipse.statet.ecommons.ui.util.InformationDispatchHandler; |
| import org.eclipse.statet.ecommons.ui.util.LayoutUtils; |
| import org.eclipse.statet.ecommons.ui.util.PixelConverter; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.r.core.RCore; |
| import org.eclipse.statet.r.ui.RUI; |
| import org.eclipse.statet.rhelp.core.http.RHelpHttpService; |
| |
| |
| public class RHelpInfoHoverCreator extends AbstractReusableInformationControlCreator { |
| |
| |
| public static final boolean isAvailable(final Composite parent) { |
| return BrowserInformationControl.isAvailable(parent); |
| } |
| |
| |
| public static class Data { |
| |
| private final Control control; |
| |
| final Object helpObject; |
| final URI httpUrl; |
| |
| public Data(final Control control, final Object helpObject, final URI httpUrl) { |
| this.control= control; |
| this.helpObject= helpObject; |
| this.httpUrl= httpUrl; |
| } |
| |
| |
| public Control getControl() { |
| return this.control; |
| } |
| |
| } |
| |
| |
| private final int mode; |
| |
| |
| public RHelpInfoHoverCreator(final int mode) { |
| this.mode= mode; |
| } |
| |
| |
| @Override |
| protected IInformationControl doCreateInformationControl(final Shell parent) { |
| return ((this.mode & MODE_FOCUS) != 0) ? |
| new RHelpInfoControl(parent, this.mode, true) : |
| new RHelpInfoControl(parent, this.mode); |
| } |
| |
| } |
| |
| class RHelpInfoControl extends AbstractInformationControl implements IInformationControlExtension2, |
| IPropertyChangeListener, OpenWindowListener, LocationListener, ProgressListener, TitleListener, |
| IBrowserProvider { |
| |
| |
| /** Action id (command) to navigate one page back. */ |
| protected static final String NAVIGATE_BACK_COMMAND_ID= IWorkbenchCommandConstants.NAVIGATE_BACK; |
| /** Action id (command) to navigate one page forward. */ |
| protected static final String NAVIGATE_FORWARD_COMMAND_ID= IWorkbenchCommandConstants.NAVIGATE_FORWARD; |
| |
| |
| /** |
| * Cached scroll bar width and height |
| */ |
| private static Point gScrollBarSize; |
| |
| |
| private final int mode; |
| |
| private RHelpLabelProvider labelProvider; |
| |
| private Composite contentComposite; |
| private Label titleImage; |
| private StyledText titleText; |
| private Browser infoBrowser; |
| |
| private final HandlerCollection handlerCollection= new HandlerCollection(); |
| |
| private boolean layoutWorkaround; |
| private boolean layoutHint; |
| |
| private RHelpInfoHoverCreator.Data input; |
| private boolean inputChanged; |
| |
| private boolean loadingCompleted; |
| private String browserTitle; |
| |
| private boolean hide; |
| |
| |
| RHelpInfoControl(final Shell shell, final int mode) { |
| super(shell, ""); //$NON-NLS-1$ |
| assert ((mode & MODE_FOCUS) == 0); |
| this.mode= mode; |
| |
| JFaceResources.getFontRegistry().addListener(this); |
| create(); |
| } |
| |
| RHelpInfoControl(final Shell shell, final int mode, final boolean dummy) { |
| super(shell, new ToolBarManager(SWT.FLAT)); |
| assert ((mode & MODE_FOCUS) != 0); |
| this.mode= mode; |
| |
| create(); |
| } |
| |
| |
| @Override |
| public void setInput(final Object input) { |
| this.inputChanged= true; |
| if (input instanceof RHelpInfoHoverCreator.Data) { |
| this.input= (RHelpInfoHoverCreator.Data) input; |
| } |
| else { |
| this.input= null; |
| } |
| } |
| |
| @Override |
| public boolean hasContents() { |
| return (this.input != null); |
| } |
| |
| @Override |
| protected void createContent(final Composite parent) { |
| this.contentComposite= new Composite(parent, SWT.NONE) { |
| @Override |
| public Point computeSize(final int width, final int height, final boolean changed) { |
| return super.computeSize(width, height, changed || width != getSize().x); |
| } |
| }; |
| this.contentComposite.setBackgroundMode(SWT.INHERIT_FORCE); |
| |
| final GridLayout gridLayout= LayoutUtils.newCompositeGrid(2); |
| gridLayout.horizontalSpacing= (int) ((gridLayout.horizontalSpacing) / 1.5); |
| this.contentComposite.setLayout(gridLayout); |
| |
| final int vIndent= Math.max(1, LayoutUtils.defaultVSpacing() / 4); |
| final int hIndent= Math.max(3, LayoutUtils.defaultHSpacing() / 3); |
| |
| { // Title image |
| this.titleImage= new Label(this.contentComposite, SWT.NULL); |
| final Image image= SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID); |
| this.titleImage.setImage(image); |
| |
| final GridData textGd= new GridData(SWT.FILL, SWT.TOP, false, false); |
| this.titleText= new StyledText(this.contentComposite, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP) { |
| @Override |
| public Point computeSize(int width, final int height, final boolean changed) { |
| if (!RHelpInfoControl.this.layoutHint && width <= 0 && RHelpInfoControl.this.contentComposite.getSize().x > 0) { |
| width= RHelpInfoControl.this.contentComposite.getSize().x - |
| LayoutUtils.defaultHMargin() - RHelpInfoControl.this.titleImage.getSize().x - LayoutUtils.defaultHSpacing() - 10; |
| } |
| |
| final Point size= super.computeSize(width, -1, true); |
| // if (width >= 0) { |
| // size.x= Math.min(size.x, width); |
| // } |
| return size; |
| } |
| }; |
| |
| this.titleText.setFont(JFaceResources.getDialogFont()); |
| final GC gc= new GC(this.titleText); |
| final FontMetrics fontMetrics= gc.getFontMetrics(); |
| final GridData imageGd= new GridData(SWT.FILL, SWT.TOP, false, false); |
| imageGd.horizontalIndent= hIndent - 2; |
| final int textHeight= fontMetrics.getAscent() + fontMetrics.getLeading(); |
| final int imageHeight= image.getBounds().height; |
| final int shift= Math.max(3, (int) ((fontMetrics.getDescent()) / 1.5)); |
| if (textHeight+shift < imageHeight) { |
| imageGd.verticalIndent= vIndent+shift; |
| textGd.verticalIndent= vIndent+(imageHeight-textHeight); |
| } |
| else { |
| imageGd.verticalIndent= vIndent+(textHeight-imageHeight)+shift; |
| textGd.verticalIndent= vIndent; |
| } |
| this.titleImage.setLayoutData(imageGd); |
| this.titleText.setLayoutData(textGd); |
| this.layoutWorkaround= true; |
| |
| gc.dispose(); |
| } |
| |
| this.infoBrowser= new Browser(this.contentComposite, SWT.NONE); |
| |
| this.infoBrowser.addOpenWindowListener(this); |
| this.infoBrowser.addLocationListener(this); |
| this.infoBrowser.addProgressListener(this); |
| this.infoBrowser.addTitleListener(this); |
| |
| this.infoBrowser.addOpenWindowListener(new OpenWindowListener() { |
| @Override |
| public void open(final WindowEvent event) { |
| event.required= true; |
| } |
| }); |
| // Disable context menu |
| this.infoBrowser.setMenu(new Menu(getShell(), SWT.NONE)); |
| |
| final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); |
| // gd.widthHint= LayoutUtils.hintWidth(fInfoText, INFO_FONT, 50); |
| this.infoBrowser.setLayoutData(gd); |
| |
| this.infoBrowser.addKeyListener(new KeyListener() { |
| @Override |
| public void keyPressed(final KeyEvent e) { |
| if (e.character == SWT.ESC) { |
| dispose(); |
| } |
| } |
| @Override |
| public void keyReleased(final KeyEvent e) {} |
| }); |
| |
| setBackgroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
| setForegroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); |
| |
| if ((this.mode & MODE_FOCUS) != 0) { |
| initActions(this.handlerCollection); |
| final ToolBarManager toolBarManager= getToolBarManager(); |
| contributeToActionBars(PlatformUI.getWorkbench(), toolBarManager, this.handlerCollection); |
| toolBarManager.update(true); |
| } |
| |
| updateInput(); |
| } |
| |
| protected void initActions(final HandlerCollection handlers) { |
| { final IHandler2 handler= new NavigateBackHandler(this); |
| handlers.add(NAVIGATE_BACK_COMMAND_ID, handler); |
| // handlerService.activateHandler(NAVIGATE_BACK_COMMAND_ID, handler); |
| // handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_BACKWARD_HISTORY, handler); |
| } |
| { final IHandler2 handler= new NavigateForwardHandler(this); |
| handlers.add(NAVIGATE_FORWARD_COMMAND_ID, handler); |
| // handlerService.activateHandler(NAVIGATE_FORWARD_COMMAND_ID, handler); |
| // handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_FORWARD_HISTORY, handler); |
| } |
| } |
| |
| protected void contributeToActionBars(final IServiceLocator serviceLocator, |
| final ToolBarManager toolBarManager, final HandlerCollection handlers) { |
| toolBarManager.add( |
| new HandlerContributionItem(new CommandContributionItemParameter( |
| serviceLocator, null, NAVIGATE_BACK_COMMAND_ID, HandlerContributionItem.STYLE_PUSH), |
| handlers.get(NAVIGATE_BACK_COMMAND_ID) )); |
| toolBarManager.add( |
| new HandlerContributionItem(new CommandContributionItemParameter( |
| serviceLocator, null, NAVIGATE_FORWARD_COMMAND_ID, HandlerContributionItem.STYLE_PUSH), |
| handlers.get(NAVIGATE_FORWARD_COMMAND_ID) )); |
| |
| toolBarManager.add(new Separator()); |
| toolBarManager.add(new SimpleContributionItem( |
| "Show in R Help View", "V", |
| RUI.getImageDescriptor(RUI.IMG_OBJ_R_HELP_SEARCH), null ) { |
| @Override |
| protected void execute() throws ExecutionException { |
| if (UIAccess.isOkToUse(RHelpInfoControl.this.infoBrowser)) { |
| try { |
| final String urlString= RHelpInfoControl.this.infoBrowser.getUrl(); |
| final IWorkbenchPage page= UIAccess.getActiveWorkbenchPage(true); |
| final RHelpView view= (RHelpView) page.showView(RUI.R_HELP_VIEW_ID); |
| final URI browseUrl= RCore.getRHelpHttpService().toHttpUrl(urlString, |
| null, RHelpHttpService.BROWSE_TARGET ); |
| if (browseUrl != null) { |
| view.openUrl(browseUrl, null); |
| } |
| else { |
| view.openUrl(urlString, null); |
| } |
| } |
| catch (final Exception e) {} |
| } |
| } |
| }); |
| } |
| |
| |
| @Override |
| public Browser getBrowser() { |
| return this.infoBrowser; |
| } |
| |
| @Override |
| public void showMessage(final IStatus status) { |
| } |
| |
| @Override |
| public void changing(final LocationEvent event) { |
| if (event.location.startsWith("http://")) { //$NON-NLS-1$ |
| try { |
| if (RCore.getRHelpHttpService().isDynamicUrl(new URI(event.location))) { |
| return; |
| } |
| } |
| catch (final Exception e) {} |
| } |
| if (event.location.equals("about:blank")) { //$NON-NLS-1$ |
| return; |
| } |
| event.doit= false; |
| } |
| |
| @Override |
| public void changed(final LocationEvent event) { |
| if (!event.top) { |
| return; |
| } |
| final String url= this.infoBrowser.getUrl(); |
| final Object obj= RCore.getRHelpHttpService().getContentOfUrl(url); |
| updateTitle(obj, this.browserTitle); |
| } |
| |
| @Override |
| public void changed(final ProgressEvent event) { |
| this.handlerCollection.update(null); |
| } |
| |
| @Override |
| public void completed(final ProgressEvent event) { |
| this.loadingCompleted= true; |
| this.handlerCollection.update(null); |
| } |
| |
| @Override |
| public void changed(final TitleEvent event) { |
| String title= event.title; |
| if (title == null) { |
| title= ""; //$NON-NLS-1$ |
| } |
| else if (title.startsWith("http://")) { //$NON-NLS-1$ |
| final int idx= title.lastIndexOf('/'); |
| if (idx >= 0) { |
| title= title.substring(idx+1); |
| } |
| } |
| this.browserTitle= title; |
| } |
| |
| @Override |
| public void open(final WindowEvent event) { |
| event.required= true; |
| } |
| |
| |
| @Override |
| public void setBackgroundColor(final Color background) { |
| super.setBackgroundColor(background); |
| this.contentComposite.setBackground(background); |
| this.infoBrowser.setBackground(background); |
| } |
| |
| @Override |
| public void setForegroundColor(final Color foreground) { |
| super.setForegroundColor(foreground); |
| this.contentComposite.setForeground(foreground); |
| this.titleText.setForeground(foreground); |
| this.infoBrowser.setForeground(foreground); |
| } |
| |
| @Override |
| public void setSize(final int width, final int height) { |
| this.infoBrowser.setRedraw(false); // avoid flickering |
| try { |
| super.setSize(width, height); |
| } |
| finally { |
| this.infoBrowser.setRedraw(true); |
| } |
| } |
| |
| |
| @Override |
| public Rectangle computeTrim() { |
| final Rectangle trim= super.computeTrim(); |
| |
| final Rectangle textTrim= this.infoBrowser.computeTrim(0, 0, 0, 0); |
| if ((this.mode & MODE_FOCUS) != 0 && textTrim.width == 0) { |
| if (gScrollBarSize == null) { |
| final Text text= new Text(this.contentComposite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); |
| gScrollBarSize= new Point( |
| text.getVerticalBar().getSize().x, |
| text.getHorizontalBar().getSize().y); |
| text.dispose(); |
| } |
| textTrim.x= 0; |
| textTrim.y= 0; |
| textTrim.width= gScrollBarSize.x; |
| textTrim.height= gScrollBarSize.y; |
| } |
| trim.x+= textTrim.x; |
| trim.y+= textTrim.y; |
| trim.width+= textTrim.width; |
| trim.height+= textTrim.height; |
| |
| return trim; |
| } |
| |
| @Override |
| public Point computeSizeHint() { |
| updateInput(); |
| final Point sizeConstraints= getSizeConstraints(); |
| final Rectangle trim= computeTrim(); |
| |
| this.titleText.setFont(JFaceResources.getDialogFont()); |
| final PixelConverter converter= new PixelConverter(this.titleText); |
| int widthHint= converter.convertWidthInCharsToPixels(60); |
| final GC gc= new GC(this.contentComposite); |
| gc.setFont(JFaceResources.getTextFont()); |
| widthHint= Math.max(widthHint, (int)(gc.getFontMetrics().getAverageCharacterWidth() * 60 + 0x0.FFFFFp0)); |
| gc.dispose(); |
| |
| final int heightHint= this.titleText.getLineHeight() * 12; |
| |
| final int widthMax= ((sizeConstraints != null && sizeConstraints.x != SWT.DEFAULT) ? |
| sizeConstraints.x : widthHint+100) - trim.width; |
| final int heightMax= ((sizeConstraints != null && sizeConstraints.y != SWT.DEFAULT) ? |
| sizeConstraints.y : this.titleText.getLineHeight()*12) - trim.height; |
| |
| final Point size= new Point(widthHint, heightHint); |
| size.y+= LayoutUtils.defaultVSpacing(); |
| size.x= Math.max(Math.min(size.x, widthMax), 200) + trim.width; |
| size.y= Math.max(Math.min(size.y, heightMax), 100) + trim.height; |
| return size; |
| } |
| |
| @Override |
| public Point computeSizeConstraints(final int widthInChars, final int heightInChars) { |
| final int width= LayoutUtils.hintWidth(this.titleText, JFaceResources.DIALOG_FONT, widthInChars); |
| final int lineHeight= this.titleText.getLineHeight(); |
| |
| return new Point(width, lineHeight * heightInChars + LayoutUtils.defaultVSpacing()); |
| } |
| |
| @Override |
| public void setVisible(final boolean visible) { |
| if (visible) { |
| this.hide= false; |
| updateInput(); |
| waitCompleted(); |
| final Shell shell; |
| if (this.hide || !UIAccess.isOkToUse(shell= getShell())) { |
| return; |
| } |
| |
| if (this.layoutWorkaround) { |
| this.contentComposite.layout(true, true); |
| this.layoutWorkaround= false; |
| } |
| |
| if (Platform.WS_WIN32.equals(SWT.getPlatform())) { |
| shell.moveAbove(null); |
| } |
| } |
| else { |
| this.hide= true; |
| } |
| super.setVisible(visible); |
| } |
| |
| private void waitCompleted() { |
| final Display display= Display.getCurrent(); |
| display.timerExec(200, new Runnable() { |
| @Override |
| public void run() { |
| RHelpInfoControl.this.loadingCompleted= true; |
| } |
| }); |
| while (!this.loadingCompleted) { |
| // Drive the event loop to process the events required to load the browser widget's contents: |
| if (!display.readAndDispatch()) { |
| display.sleep(); |
| } |
| } |
| } |
| |
| @Override |
| public void setFocus() { |
| this.infoBrowser.setFocus(); |
| } |
| |
| private void updateInput() { |
| if (this.infoBrowser == null || !this.inputChanged) { |
| return; |
| } |
| if (this.labelProvider == null) { |
| this.labelProvider= new RHelpLabelProvider(RHelpLabelProvider.WITH_TITLE | RHelpLabelProvider.WITH_QUALIFIER | RHelpLabelProvider.HEADER); |
| } |
| this.loadingCompleted= false; |
| this.inputChanged= false; |
| this.browserTitle= null; |
| updateTitle(this.input.helpObject, null); |
| if (this.input != null && this.input.httpUrl != null) { |
| URI url= this.input.httpUrl; |
| if ((this.mode & MODE_FOCUS) == 0) { // disable scrollbars |
| try { |
| url= new URI(url.toString() + |
| '?' + RHelpUIServlet.STYLE_PARAM + '=' + RHelpUIServlet.HOVER_STYLE ); |
| } |
| catch (final URISyntaxException e) {} |
| } |
| this.infoBrowser.setUrl(url.toString()); |
| } |
| else { |
| this.infoBrowser.setUrl("about:blank"); //$NON-NLS-1$ |
| } |
| if ((this.mode & MODE_FOCUS) == 0) { |
| setStatusText((this.input.getControl() != null |
| && this.input.getControl().isFocusControl() ) ? |
| InformationDispatchHandler.getAffordanceString(this.mode) : "" ); //$NON-NLS-1$ |
| } |
| } |
| |
| private void updateTitle(final Object helpObject, final String alt) { |
| if (helpObject != null) { |
| final Image image= this.labelProvider.getImage(helpObject); |
| this.titleImage.setImage((image != null) ? image : SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID)); |
| final StyledString styleString= this.labelProvider.getStyledText(helpObject); |
| this.titleText.setText(styleString.getString()); |
| this.titleText.setStyleRanges(styleString.getStyleRanges()); |
| } |
| else { |
| this.titleImage.setImage(SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID)); |
| this.titleText.setText((alt != null) ? alt : ""); //$NON-NLS-1$ |
| } |
| } |
| |
| |
| @Override |
| public IInformationControlCreator getInformationPresenterControlCreator() { |
| // enriched mode |
| return new RHelpInfoHoverCreator(this.mode | MODE_FOCUS); |
| } |
| |
| @Override |
| public void propertyChange(final PropertyChangeEvent event) { |
| final String property= event.getProperty(); |
| if (property.equals(PREF_DETAIL_PANE_FONT) || property.equals(JFaceResources.DEFAULT_FONT)) { |
| dispose(); |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| JFaceResources.getFontRegistry().removeListener(this); |
| this.handlerCollection.dispose(); |
| super.dispose(); |
| } |
| |
| } |