分享

Eclipse RCP application - custom splash screen

 LibraryPKU 2014-04-29

I'm currently developing an Eclipse RCP application, in which I'm trying to implement a custom splash screen handler, sporting a progress bar (behavior similar to the default progress bar you can define in the .product definition) and multiple cycling background images.

After editing the extensions of the main application plugin this way:

[...]
<!-- install custom splash handler -->
<extension point="org.eclipse.ui.splashHandlers">
   <splashHandler
        class="com.example.application.splash.SlideShowSplashHandler"
        id="splash.slideshow">
   </splashHandler>
   <splashHandlerProductBinding
        productId="com.example.application.product"
        splashId="com.example.application.splash.slideshow">
   </splashHandlerProductBinding>
</extension>
<!-- define images (in plugin root directory) to be shown -->
<extension point="com.example.application.splashExtension">
     <splashExtension id="01" image="01_Splash2Ag.bmp"></splashExtension>
     <splashExtension id="02" image="02_Splash3Ag.bmp"></splashExtension>
     <splashExtension id="00" image="00_Splash1Ag.bmp"></splashExtension>         
</extension>
[...]

I'm trying to implement the custom splashscreen handler class:

public class SlideShowSplashHandler extends AbstractSplashHandler {

    private List<Image> fImageList;
    private ProgressBar fBar;
    private final static String F_SPLASH_EXTENSION_ID = "com.example.application.splashExtension"; //NON-NLS-1
    private final static String F_ELEMENT_IMAGE = "image"; //NON-NLS-1
    private int imageIdx = 0;

    public SlideShowSplashHandler() {
        fImageList = new ArrayList<Image>(5);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
     */
    public void init(Shell splash) {
        // Store the shell
        super.init(splash);
            // Force shell to inherit the splash background
            getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT); 
        // Load all splash extensions
        loadSplashExtensions();
        // If no splash extensions were loaded abort the splash handler
        if (hasSplashExtensions() == false) return;
        // Create UI
        createUI(splash);
    }

    private boolean hasSplashExtensions() {
        if (fImageList.isEmpty()) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public IProgressMonitor getBundleProgressMonitor() {
       return new NullProgressMonitor() {

          @Override
          public void beginTask(String name, final int totalWork) {
            getSplash().getDisplay().syncExec(new Runnable() {
              public void run() {
                  fBar.setSelection(50);
              }
            });
          }

          @Override
          public void subTask(String name) {
            getSplash().getDisplay().syncExec(new Runnable() {
              public void run() {
                  if (fBar.getSelection() < 100) fBar.setSelection(fBar.getSelection() + 10);
                  if (imageIdx >= fImageList.size()) imageIdx = 0;
                  Image image = fImageList.get(imageIdx++);
                  getSplash().setBackgroundImage(image);
                  getSplash().setRedraw(true);
                  getSplash().redraw();
              }
            });
          }
        };
    }

    private void createUI(Shell shell) {

        Composite container = new Composite(shell, SWT.NONE);
        container.setLayout(new GridLayout(1, false));
        container.setLocation(5, 374);
        container.setSize(480, 15);

        /* Progress Bar */
        fBar = new ProgressBar(container, SWT.HORIZONTAL);
        fBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
        ((GridData) fBar.getLayoutData()).heightHint = 13;
        fBar.setMaximum(100);
        fBar.setSelection(25);

        /* Version Label */
        Label versionLabel = new Label(container, SWT.NONE);
        versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
        //versionLabel.setFont(fVersionFont);
        //versionLabel.setForeground(fVersionColor);
        //versionLabel.setText(NLS.bind(Messages.SplashHandler_BUILD, "2.1 Nightly")); //$NON-NLS-1$

        /* Layout All */
        shell.layout(true, true);
    }   

    private void loadSplashExtensions() {
        // Get all splash handler extensions
        IExtension[] extensions = Platform.getExtensionRegistry()
                .getExtensionPoint(F_SPLASH_EXTENSION_ID).getExtensions();
        // Process all splash handler extensions
        for (int i = 0; i < extensions.length; i++) {
            processSplashExtension(extensions[i]);
        }
    }

    /**
     * Parse the extension points with the images filename.
     */
    private void processSplashExtension(IExtension extension) {
        // Get all splash handler configuration elements
        IConfigurationElement[] elements = extension.getConfigurationElements();
        // Process all splash handler configuration elements
        for (int j = 0; j < elements.length; j++) {
            processSplashElements(elements[j]);
        }
    }

    /**
     * Create the images defined as extension points
     */
    private void processSplashElements(IConfigurationElement configurationElement) {

        String name = configurationElement.getAttribute(F_ELEMENT_IMAGE);
        ImageDescriptor descriptor = Activator.getImageDescriptor("/"+name);
        if (descriptor != null) {
            Image image = descriptor.createImage();
            if (image !=null) {
                fImageList.add(image);
            }
        }
    }

    public void dispose() {
        super.dispose();
        // Check to see if any images were defined
        if ((fImageList == null) ||
                fImageList.isEmpty()) {
            return;
        }
        // Dispose of all the images
        Iterator<Image> iterator = fImageList.iterator();
        while (iterator.hasNext()) {
            Image image = iterator.next();
            image.dispose();
        }
    }
}

Problem is that the progress bar just works, while the images are not shown. While debugging I could verify that the images are actually found and loaded, and correctly set in the shell; the shell just seems to not being redrawn. Am i missing something?=

share|improve this question

add comment

2 Answers

up vote 1 down vote accepted

I could solve the problem on linux and windows, but it did not work on macos/cocoa (in which the splash screen is looking "scrambled" on each image slideshow iteration).

Is was very simple indeed, just attaching an extra Composite between the splash shell and the container containing the widgets; then change the background image on the newly create container object.

private void createUI(Shell shell) {
    Composite bgcontainer = new Composite(shell, SWT.NONE); // new
    [...]
    Composite container = new Composite(bgcontainer, SWT.NONE);
    [...]
    fBar = new ProgressBar(container, SWT.HORIZONTAL);
    [...]
    Label versionLabel = new Label(container, SWT.NONE);
    versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
    shell.layout(true, true);
}   

@Override public IProgressMonitor getBundleProgressMonitor() {
return new NullProgressMonitor() {
    @Override public void beginTask(String name, final int totalWork) {
        getSplash().getDisplay().syncExec(new Runnable() {
            public void run() {
                    if (fBar != null) fBar.setSelection(40);
                    Image image = fImageList.get(imageIdx++);
                    bgcontainer.setBackgroundImage(image);
                    bgcontainer.setRedraw(true);
                    bgcontainer.update();                 
                }
            });
        }

    @Override public void subTask(String name) {
        final String n = name;
        getSplash().getDisplay().syncExec(new Runnable() {
            String taskname = n;
            public void run() {
                    if (fBar != null && fBar.getSelection() < 100)
                        fBar.setSelection(fBar.getSelection() + 10);
                    if (fBar.getSelection() == 60 || fBar.getSelection() == 80) {
                        if (imageIdx >= fImageList.size()) imageIdx = 0;
                        Image image = fImageList.get(imageIdx++);
                        bgcontainer.setBackgroundImage(image);
                        bgcontainer.setRedraw(true);
                        bgcontainer.update();
                    }
                 }
             });
         }
    };
}
share|improve this answer

add comment

I haven't tried your code, but when you make changes to a Control, it is not enough to call Control.redraw(), but you must also call Control.update().

Control.redraw() requests that a control should be redrawn, Control.update() actually redraws it. The later is needed when your code runs on the UI thread!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多