Package org.apache.harmony.awt.theme.windows

Source Code of org.apache.harmony.awt.theme.windows.WinFileDialog$OFNHookHandler

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
/**
* @author Dmitry A. Durnev
* @version $Revision$
*/
package org.apache.harmony.awt.theme.windows;

import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.util.HashMap;
import java.util.Map;

import org.apache.harmony.awt.ComponentInternals;
import org.apache.harmony.awt.nativebridge.Int16Pointer;
import org.apache.harmony.awt.nativebridge.NativeBridge;
import org.apache.harmony.awt.nativebridge.PointerPointer;
import org.apache.harmony.awt.nativebridge.VoidPointer;
import org.apache.harmony.awt.nativebridge.windows.Callback;
import org.apache.harmony.awt.nativebridge.windows.Win32;
import org.apache.harmony.awt.nativebridge.windows.WindowsConsts;
import org.apache.harmony.awt.nativebridge.windows.Callback.Handler;


public class WinFileDialog extends WinStyle {
   
    // windows defs from CommDlg.h
    private static final int CDN_FIRST = -601;
    private static final int CDN_INCLUDEITEM = CDN_FIRST - 0x0007;
   
    private static class OFNHookHandler implements Handler {
       
        public long windowProc(long hwnd, int msg, long wParam, long lParam) {
            FileDialog fd = thread2fd.get(Thread.currentThread());
            if (fd == null) {
                return 0l;
            }
            FilenameFilter ff = fd.getFilenameFilter();
           
            if (msg == WM_INITDIALOG) {
                WinFileDialog.getInstance(fd).hwnd = win32.GetParent(hwnd);
            }
            if (msg != WM_NOTIFY) {
                return 0l;
            }           
            if (win32.createNMHDR(lParam).get_code() != CDN_INCLUDEITEM) {
                return 0l;
            }
           
            if (ff == null) {
                return 1l;
            }
            Win32.OFNOTIFYEXW ofnotify = win32.createOFNOTIFYEXW(lParam);
            Win32.IShellFolder psf = getIShellFolder(ofnotify.get_psf());
           
            int flags = (WindowsConsts.SHGDN_FORPARSING);           
            Win32.ITEMIDLIST item = win32.createITEMIDLIST(ofnotify.get_pidl());
            String fullName = getDisplayNameOf(item, psf, flags);
            File file = new File(fullName);
            String fName = file.getName();
            boolean res = true;
            if (!"".equals(fName)) {
                res = ff.accept(file.getParentFile(), fName);
            }           
            return (res ? 1 : 0);
        }
       
        private Win32.IShellFolder getIShellFolder(VoidPointer ptr) {
            PointerPointer ptrPtr = nb.createPointerPointer(ptr, false);
            return win32.createIShellFolder(ptrPtr.getAddress(0));
        }
       
        private String getDisplayNameOf(Win32.ITEMIDLIST item,
                                        Win32.IShellFolder parent,
                                        int flags) {
           
            Win32.STRRET strret = win32.createSTRRET(false);
            parent.GetDisplayNameOf(item, flags, strret);
            int bufLen = 2048;           
            Int16Pointer bufPtr = nb.createInt16Pointer(bufLen, false);
            win32.StrRetToBufW(strret, null, bufPtr, bufLen);
            return bufPtr.getString();
        }
       
    }
   
    private static final Win32 win32 = Win32.getInstance();
    private static final NativeBridge nb = NativeBridge.getInstance();
    private static final ComponentInternals ci = ComponentInternals.
    getComponentInternals();
    private static final Map<Thread, FileDialog> thread2fd = new HashMap<Thread, FileDialog>();
    private static final Map<FileDialog, WinFileDialog> fd2win = new HashMap<FileDialog, WinFileDialog>();
    private static final OFNHookHandler handler = new OFNHookHandler();
    private static final long ofnHookPtr = Callback.registerCallbackOFN(handler);
    private final FileDialog fileDialog;
    private final boolean modal;
    private final Win32.OPENFILENAMEW ofn;
    private long hwnd;
   
    public static WinFileDialog getInstance(FileDialog fd) {
        return fd2win.get(fd);
    }
   
    public WinFileDialog(FileDialog fd) {
        fileDialog = fd;
        fd2win.put(fd, this);
        modal = fd.isModal();
        ofn = win32.createOPENFILENAMEW(false);
        ofn.set_lStructSize(ofn.size());       
    }
   
    private void show(int mode) {
        synchronized (handler) {
            if (!fileDialog.isDisplayable()) {
                // make displayable together with owner
                fileDialog.addNotify();
            }
            ci.setVisibleFlag(fileDialog, true);
            postEvent(new ComponentEvent(fileDialog,
                                         ComponentEvent.COMPONENT_SHOWN));
            initOFN();
            boolean ok = false;
            Thread thread = Thread.currentThread();
            thread2fd.put(thread, fileDialog);

            switch (mode) {
            case FileDialog.LOAD:
                ok = (win32.GetOpenFileNameW(ofn) != 0);
                break;
            case FileDialog.SAVE:
                ok = (win32.GetSaveFileNameW(ofn) != 0);
                break;
            default:
                return;

            }
            setValues(ok);
            thread2fd.remove(thread);
            fd2win.remove(fileDialog);
            ci.setVisibleFlag(fileDialog, false);
            postEvent(new ComponentEvent(fileDialog,
                    ComponentEvent.COMPONENT_HIDDEN));
        }
    }

    private void setValues(boolean ok) {
        String error = null;
        if (ok) {
            String fullName = ofn.get_lpstrFile().getString();
            File file = new File(fullName);
            fileDialog.setFile(ofn.get_lpstrFileTitle().getString());
            fileDialog.setDirectory(file.getParent() + File.separator);

        } else {
            fileDialog.setFile(null);
            fileDialog.setDirectory(null);
            int code = win32.CommDlgExtendedError();
            if (code != 0) {
                error = getExtendedError(code);
            }
        }
        if (error != null) {
            System.err.println("file dialog " + error + " error!");
        }
    }

    private void initOFN() {       
        setOwner(fileDialog.getOwner());
       
        setFile(fileDialog.getFile());
        setDir(fileDialog.getDirectory());       
        setTitle(fileDialog.getTitle());
        setFilter("All Files (*.*)\0*.*\0");
       
        ofn.set_Flags(OFN_ENABLEHOOK | OFN_ENABLEINCLUDENOTIFY | OFN_EXPLORER |
                      OFN_ENABLESIZING);
        ofn.set_lpfnHook(ofnHookPtr);
    }

    private void setOwner(Window w) {
        if ((w == null) || !w.isDisplayable()) {
            return;
        }
        // this also makes file dialog modal:
        ofn.set_hwndOwner(ci.getNativeWindow(w).getId());
    }

    private void setFilter(String filter) {
        if (filter == null) {
            return;
        }
        ofn.set_lpstrFilter(nb.createInt16Pointer(filter, false));
    }

    private void setTitle(String title) {
        if (title == null) {
            return;
        }
        ofn.set_lpstrTitle(nb.createInt16Pointer(title, false));
    }

    private void setDir(String dirName) {
        if (dirName == null) {
            dirName = System.getProperty("user.dir");
        }
        ofn.set_lpstrInitialDir(nb.createInt16Pointer(dirName, false));
    }

    private void setFile(String fileName) {
        int bufSize = 255;
        Int16Pointer bufferPtr = nb.createInt16Pointer(bufSize, false);
        if (fileName != null) {
            bufferPtr.setString(fileName);
        }
        ofn.set_nMaxFileTitle(bufSize);
        ofn.set_lpstrFileTitle(nb.createInt16Pointer(bufSize, false));
        ofn.set_lpstrFile(bufferPtr);
        ofn.set_nMaxFile(bufSize); // mandatory!
    }
   
    public boolean show() {       
        if (modal) {
            if (EventQueue.isDispatchThread()) {
                // need to continue dispatching events
                // so start inner modal loop:
                new Thread() {
                    @Override
                    public void run() {
                        show(fileDialog.getMode());
                        ci.endModalLoop(fileDialog);
                    }
                }.start();
                ci.runModalLoop(fileDialog);
            } else {
                // just block the calling thread:
                show(fileDialog.getMode());
            }
        } else {
            // start new thread here and
            // return immediately(return value is useless)
            new Thread() {
                @Override
                public void run() {
                    show(fileDialog.getMode());
                }
            }.start();
        }
       
        return false; // don't call super(Dialog).show()
    }

    private String getExtendedError(int code) {
        switch (code) {
        case CDERR_GENERALCODES:
            return "general";
        case CDERR_STRUCTSIZE:
            return "structure size";
        case CDERR_INITIALIZATION:
            return "init";
        case CDERR_NOTEMPLATE:
            return "no template";
        case CDERR_NOHINSTANCE:
            return "no hInstance";
        case CDERR_LOADSTRFAILURE:
            return "load string failure";
        case CDERR_FINDRESFAILURE:
            return "find resource failure";
        case CDERR_LOADRESFAILURE:
            return "load resource failure";
        case CDERR_LOCKRESFAILURE:
            return "lock resource failure";
        case CDERR_MEMALLOCFAILURE:
            return "mem alloc failure";
        case CDERR_MEMLOCKFAILURE:
            return "mem lock failure";
        case CDERR_NOHOOK:
            return "no hook";
        }
        return "unknown";
    }
   
    private void postEvent(AWTEvent e) {
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
    }
   
    public long close() {
        ci.setVisibleFlag(fileDialog, false);
        fd2win.remove(fileDialog);
        // should post IDABORT, but it doesn't work for some reason
        // so use IDCANCEL as a workaround
        long res = win32.PostMessageW(hwnd, WM_COMMAND, IDCANCEL, 0);
       
        if (res == 0) {
            System.err.println("error:" + win32.GetLastError());
        }
        return res;
    }
}
TOP

Related Classes of org.apache.harmony.awt.theme.windows.WinFileDialog$OFNHookHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.