org.eclipse.swt.widgets.TaskBar.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.swt.widgets.TaskBar.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;

import java.io.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.ole.win32.*;
import org.eclipse.swt.internal.win32.*;

/**
 * Instances of this class represent the system task bar.
 *
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 *
 * @see Display#getSystemTaskBar
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 *
 * @since 3.6
 *
 * @noextend This class is not intended to be subclassed by clients.
 */
public class TaskBar extends Widget {
    int itemCount;
    TaskItem[] items = new TaskItem[4];
    ITaskbarList3 mTaskbarList3;
    String iconsDir;

    static final char[] EXE_PATH;
    static final PROPERTYKEY PKEY_Title = new PROPERTYKEY();
    static final PROPERTYKEY PKEY_AppUserModel_IsDestListSeparator = new PROPERTYKEY();
    static final String EXE_PATH_KEY = "org.eclipse.swt.win32.taskbar.executable"; //$NON-NLS-1$
    static final String EXE_ARGS_KEY = "org.eclipse.swt.win32.taskbar.arguments"; //$NON-NLS-1$
    static final String ICON_KEY = "org.eclipse.swt.win32.taskbar.icon"; //$NON-NLS-1$
    static final String ICON_INDEX_KEY = "org.eclipse.swt.win32.taskbar.icon.index"; //$NON-NLS-1$
    static {
        OS.PSPropertyKeyFromString("{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2\0".toCharArray(), PKEY_Title); //$NON-NLS-1$
        OS.PSPropertyKeyFromString("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 6\0".toCharArray(), //$NON-NLS-1$
                PKEY_AppUserModel_IsDestListSeparator);
        char[] buffer = new char[OS.MAX_PATH];
        while (OS.GetModuleFileName(0, buffer, buffer.length) == buffer.length) {
            buffer = new char[buffer.length + OS.MAX_PATH];
        }
        EXE_PATH = buffer;
    }

    TaskBar(Display display, int style) {
        this.display = display;
        createHandle();
        reskinWidget();
    }

    void createHandle() {
        long[] ppv = new long[1];
        int hr = COM.CoCreateInstance(COM.CLSID_TaskbarList, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_ITaskbarList3,
                ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        mTaskbarList3 = new ITaskbarList3(ppv[0]);
    }

    void createItem(TaskItem item, int index) {
        if (index == -1)
            index = itemCount;
        if (!(0 <= index && index <= itemCount))
            error(SWT.ERROR_INVALID_RANGE);
        if (itemCount == items.length) {
            TaskItem[] newItems = new TaskItem[items.length + 4];
            System.arraycopy(items, 0, newItems, 0, items.length);
            items = newItems;
        }
        System.arraycopy(items, index, items, index + 1, itemCount++ - index);
        items[index] = item;
    }

    void createItems() {
        Shell[] shells = display.getShells();
        for (int i = 0; i < shells.length; i++) {
            getItem(shells[i]);
        }
        getItem(null);
    }

    IShellLink createShellLink(MenuItem item) {
        int style = item.getStyle();
        if ((style & SWT.CASCADE) != 0)
            return null;
        long[] ppv = new long[1];
        int hr = COM.CoCreateInstance(COM.CLSID_ShellLink, 0, COM.CLSCTX_INPROC_SERVER, COM.IID_IShellLinkW, ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        IShellLink pLink = new IShellLink(ppv[0]);

        long hHeap = OS.GetProcessHeap();
        long pv = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, OS.PROPVARIANT_sizeof());
        long titlePtr = 0;
        PROPERTYKEY key;
        if ((style & SWT.SEPARATOR) != 0) {
            OS.MoveMemory(pv, new short[] { OS.VT_BOOL }, 2);
            OS.MoveMemory(pv + 8, new short[] { OS.VARIANT_TRUE }, 2);
            key = PKEY_AppUserModel_IsDestListSeparator;
        } else {
            String text = item.getText();
            int length = text.length();
            char[] buffer = new char[length + 1];
            text.getChars(0, length, buffer, 0);
            titlePtr = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length * 2);
            OS.MoveMemory(titlePtr, buffer, buffer.length * 2);
            OS.MoveMemory(pv, new short[] { OS.VT_LPWSTR }, 2);
            OS.MoveMemory(pv + 8, new long[] { titlePtr }, C.PTR_SIZEOF);
            key = PKEY_Title;

            String exePath = (String) item.getData(EXE_PATH_KEY);
            if (exePath != null) {
                length = exePath.length();
                buffer = new char[length + 1];
                exePath.getChars(0, length, buffer, 0);
            } else {
                buffer = EXE_PATH;
            }
            hr = pLink.SetPath(buffer);
            if (hr != OS.S_OK)
                error(SWT.ERROR_INVALID_ARGUMENT);

            text = (String) item.getData(EXE_ARGS_KEY);
            if (text == null)
                text = Display.LAUNCHER_PREFIX + Display.TASKBAR_EVENT + item.id;
            length = text.length();
            buffer = new char[length + 1];
            text.getChars(0, length, buffer, 0);
            hr = pLink.SetArguments(buffer);
            if (hr != OS.S_OK)
                error(SWT.ERROR_INVALID_ARGUMENT);

            /* This code is intentionally commented */
            //      String tooltip = item.tooltip;
            //      if (tooltip != null) {
            //         length = tooltip.length ();
            //         buffer = new char [length + 1];
            //         tooltip.getChars (0, length, buffer, 0);
            //         hr = pLink.SetDescription (buffer);
            //         if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
            //      }

            String icon = (String) item.getData(ICON_KEY);
            int index = 0;
            if (icon != null) {
                text = (String) item.getData(ICON_INDEX_KEY);
                if (text != null)
                    index = Integer.parseInt(text);
            } else {
                String directory = null;
                Image image = item.getImage();
                if (image != null)
                    directory = getIconsDir();
                if (directory != null) {
                    icon = directory + "\\" + "menu" + item.id + ".ico";
                    ImageData data;
                    if (item.hBitmap != 0) {
                        Image image2 = Image.win32_new(display, SWT.BITMAP, item.hBitmap);
                        data = image2.getImageData(DPIUtil.getDeviceZoom());
                    } else {
                        data = image.getImageData(DPIUtil.getDeviceZoom());
                    }
                    ImageLoader loader = new ImageLoader();
                    loader.data = new ImageData[] { data };
                    loader.save(icon, SWT.IMAGE_ICO);
                }
            }
            if (icon != null) {
                length = icon.length();
                buffer = new char[length + 1];
                icon.getChars(0, length, buffer, 0);
                hr = pLink.SetIconLocation(buffer, index);
                if (hr != OS.S_OK)
                    error(SWT.ERROR_INVALID_ARGUMENT);
            }
        }

        hr = pLink.QueryInterface(COM.IID_IPropertyStore, ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        IPropertyStore pPropStore = new IPropertyStore(ppv[0]);
        hr = pPropStore.SetValue(key, pv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_INVALID_ARGUMENT);
        pPropStore.Commit();
        pPropStore.Release();

        OS.HeapFree(hHeap, 0, pv);
        if (titlePtr != 0)
            OS.HeapFree(hHeap, 0, titlePtr);
        return pLink;
    }

    IObjectArray createShellLinkArray(MenuItem[] items) {
        if (items == null)
            return null;
        if (items.length == 0)
            return null;
        long[] ppv = new long[1];
        int hr = COM.CoCreateInstance(COM.CLSID_EnumerableObjectCollection, 0, COM.CLSCTX_INPROC_SERVER,
                COM.IID_IObjectCollection, ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        IObjectCollection pObjColl = new IObjectCollection(ppv[0]);
        for (int i = 0; i < items.length; i++) {
            IShellLink pLink = createShellLink(items[i]);
            if (pLink != null) {
                /*IObjectCollection::AddObject*/
                pObjColl.AddObject(pLink);
                if (hr != OS.S_OK)
                    error(SWT.ERROR_INVALID_ARGUMENT);
                pLink.Release();
            }
        }
        /*IUnknown::QueryInterface*/
        hr = pObjColl.QueryInterface(COM.IID_IObjectArray, ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        IObjectArray poa = new IObjectArray(ppv[0]);
        pObjColl.Release();
        return poa;
    }

    void destroyItem(TaskItem item) {
        int index = 0;
        while (index < itemCount) {
            if (items[index] == item)
                break;
            index++;
        }
        if (index == itemCount)
            return;
        System.arraycopy(items, index + 1, items, index, --itemCount - index);
        items[itemCount] = null;
    }

    String getIconsDir() {
        if (iconsDir != null)
            return iconsDir;
        String appData = System.getenv("LOCALAPPDATA");
        String appName = Display.APP_NAME;
        if (appData == null || appName == null)
            return null;
        appName = appName.replaceAll("[\\\\/:*?\"<>|]", "_");
        File dir = new File(appData + "\\" + appName + "\\ico_dir");
        if (dir.exists()) {
            // remove old icons
            for (File file : dir.listFiles())
                file.delete();
        } else if (!dir.mkdirs()) {
            return null;
        }
        return iconsDir = dir.getPath();
    }

    /**
     * Returns the item at the given, zero-relative index in the
     * receiver. Throws an exception if the index is out of range.
     *
     * @param index the index of the item to return
     * @return the item at the given index
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     * </ul>
     */
    public TaskItem getItem(int index) {
        checkWidget();
        createItems();
        if (!(0 <= index && index < itemCount))
            error(SWT.ERROR_INVALID_RANGE);
        return items[index];
    }

    /**
     * Returns the <code>TaskItem</code> for the given <code>Shell</code> or the <code>TaskItem</code>
     * for the application if the <code>Shell</code> parameter is <code>null</code>.
     * If the requested item is not supported by the platform it returns <code>null</code>.
     *
     * @param shell the shell for which the task item is requested, or null to request the application item
     * @return the task item for the given shell or the application
     *
     * @exception SWTException <ul>
     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     * </ul>
     */
    public TaskItem getItem(Shell shell) {
        checkWidget();
        for (int i = 0; i < items.length; i++) {
            if (items[i] != null && items[i].shell == shell) {
                return items[i];
            }
        }
        TaskItem item = new TaskItem(this, SWT.NONE);
        if (shell != null)
            item.setShell(shell);
        return item;
    }

    /**
     * Returns the number of items contained in the receiver.
     *
     * @return the number of items
     *
     * @exception SWTException <ul>
     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     * </ul>
     */
    public int getItemCount() {
        checkWidget();
        createItems();
        return itemCount;
    }

    /**
     * Returns an array of <code>TaskItem</code>s which are the items
     * in the receiver.
     * <p>
     * Note: This is not the actual structure used by the receiver
     * to maintain its list of items, so modifying the array will
     * not affect the receiver.
     * </p>
     *
     * @return the items in the receiver
     *
     * @exception SWTException <ul>
     *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     * </ul>
     */
    public TaskItem[] getItems() {
        checkWidget();
        createItems();
        TaskItem[] result = new TaskItem[itemCount];
        System.arraycopy(items, 0, result, 0, result.length);
        return result;
    }

    @Override
    void releaseChildren(boolean destroy) {
        if (items != null) {
            for (int i = 0; i < items.length; i++) {
                TaskItem item = items[i];
                if (item != null && !item.isDisposed()) {
                    item.release(false);
                }
            }
            items = null;
        }
        super.releaseChildren(destroy);
    }

    @Override
    void releaseParent() {
        super.releaseParent();
        if (display.taskBar == this)
            display.taskBar = null;
    }

    @Override
    void releaseWidget() {
        super.releaseWidget();
        mTaskbarList3.Release();
        mTaskbarList3 = null;
    }

    @Override
    void reskinChildren(int flags) {
        if (items != null) {
            for (int i = 0; i < items.length; i++) {
                TaskItem item = items[i];
                if (item != null)
                    item.reskin(flags);
            }
        }
        super.reskinChildren(flags);
    }

    void setMenu(Menu menu) {
        long[] ppv = new long[1];
        int hr = COM.CoCreateInstance(COM.CLSID_DestinationList, 0, COM.CLSCTX_INPROC_SERVER,
                COM.IID_ICustomDestinationList, ppv);
        if (hr != OS.S_OK)
            error(SWT.ERROR_NO_HANDLES);
        ICustomDestinationList pDestList = new ICustomDestinationList(ppv[0]);
        String appName = Display.APP_NAME;
        char[] buffer = { 'S', 'W', 'T', '\0' };
        if (appName != null && appName.length() > 0) {
            int length = appName.length();
            buffer = new char[length + 1];
            appName.getChars(0, length, buffer, 0);
        }
        MenuItem[] items = null;
        if (menu != null && (items = menu.getItems()).length != 0) {
            IObjectArray poa = createShellLinkArray(items);
            if (poa != null) {
                hr = pDestList.SetAppID(buffer);
                if (hr != OS.S_OK)
                    error(SWT.ERROR_INVALID_ARGUMENT);

                int[] cMaxSlots = new int[1];
                pDestList.BeginList(cMaxSlots, COM.IID_IObjectArray, ppv);
                if (hr != OS.S_OK)
                    error(SWT.ERROR_INVALID_ARGUMENT);
                IObjectArray pRemovedItems = new IObjectArray(ppv[0]);

                int[] count = new int[1];
                poa.GetCount(count);
                if (count[0] != 0) {
                    hr = pDestList.AddUserTasks(poa);
                    if (hr != OS.S_OK)
                        error(SWT.ERROR_INVALID_ARGUMENT);
                }

                for (int i = 0; i < items.length; i++) {
                    MenuItem item = items[i];
                    if ((item.getStyle() & SWT.CASCADE) != 0) {
                        Menu subMenu = item.getMenu();
                        if (subMenu != null) {
                            MenuItem[] subItems = subMenu.getItems();
                            IObjectArray poa2 = createShellLinkArray(subItems);
                            if (poa2 != null) {
                                poa2.GetCount(count);
                                if (count[0] != 0) {
                                    String text = item.getText();
                                    int length = text.length();
                                    char[] buffer2 = new char[length + 1];
                                    text.getChars(0, length, buffer2, 0);
                                    hr = pDestList.AppendCategory(buffer2, poa2);
                                    if (hr != OS.S_OK)
                                        error(SWT.ERROR_INVALID_ARGUMENT);
                                }
                                /*IUnknown::Release*/
                                poa2.Release();
                            }
                        }
                    }
                    poa.Release();
                }
                hr = pDestList.CommitList();
                if (hr != OS.S_OK)
                    error(SWT.ERROR_INVALID_ARGUMENT);
                pRemovedItems.Release();
            }
        } else {
            hr = pDestList.DeleteList(buffer);
            if (hr != OS.S_OK)
                error(SWT.ERROR_INVALID_ARGUMENT);
        }
        pDestList.Release();
    }

}