1 /*
   2  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.awt.windows;
  26 
  27 import java.awt.*;
  28 import java.awt.dnd.DropTarget;
  29 import java.awt.peer.*;
  30 import java.io.File;
  31 import java.io.FilenameFilter;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import java.util.ResourceBundle;
  35 import java.util.MissingResourceException;
  36 import java.util.Vector;
  37 import sun.awt.AppContext;
  38 import sun.awt.CausedFocusEvent;
  39 import sun.awt.AWTAccessor;
  40 
  41 public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
  42 
  43     static {
  44         initIDs();
  45     }
  46 
  47     private WComponentPeer parent;
  48     private FilenameFilter fileFilter;
  49 
  50     private Vector<WWindowPeer> blockedWindows = new Vector<WWindowPeer>();
  51 
  52     //Needed to fix 4152317
  53     private static native void setFilterString(String allFilter);
  54 
  55     public void setFilenameFilter(FilenameFilter filter) {
  56         this.fileFilter = filter;
  57     }
  58 
  59     boolean checkFilenameFilter(String filename) {
  60         FileDialog fileDialog = (FileDialog)target;
  61         if (fileFilter == null) {
  62             return true;
  63         }
  64         File file = new File(filename);
  65         return fileFilter.accept(new File(file.getParent()), file.getName());
  66     }
  67 
  68     // Toolkit & peer internals
  69     WFileDialogPeer(FileDialog target) {
  70         super(target);
  71     }
  72 
  73     void create(WComponentPeer parent) {
  74         this.parent = parent;
  75     }
  76 
  77     // don't use checkCreation() from WComponentPeer to avoid hwnd check
  78     protected void checkCreation() {
  79     }
  80 
  81     void initialize() {
  82         setFilenameFilter(((FileDialog) target).getFilenameFilter());
  83     }
  84 
  85     private native void _dispose();
  86     protected void disposeImpl() {
  87         WToolkit.targetDisposedPeer(target, this);
  88         _dispose();
  89     }
  90 
  91     private native void _show();
  92     private native void _hide();
  93 
  94     public void show() {
  95         new Thread(new Runnable() {
  96             public void run() {
  97                 _show();
  98             }
  99         }).start();
 100     }
 101 
 102     public void hide() {
 103         _hide();
 104     }
 105 
 106     // called from native code when the dialog is shown or hidden
 107     void setHWnd(long hwnd) {
 108         if (this.hwnd == hwnd) {
 109             return;
 110         }
 111         this.hwnd = hwnd;
 112         for (WWindowPeer window : blockedWindows) {
 113             if (hwnd != 0) {
 114                 window.modalDisable((Dialog)target, hwnd);
 115             } else {
 116                 window.modalEnable((Dialog)target);
 117             }
 118         }
 119     }
 120 
 121     /*
 122      * The function converts the file names (the buffer parameter)
 123      * in the Windows format into the Java format and saves the results
 124      * into the FileDialog instance.
 125      *
 126      * If it's the multi-select mode, the buffer contains the current
 127      * directory followed by the short names of the files.
 128      * The directory and file name strings are NULL separated.
 129      * If it's the single-select mode, the buffer doesn't have the NULL
 130      * separator between the path and the file name.
 131      *
 132      * NOTE: This method is called by privileged threads.
 133      *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 134      */
 135     void handleSelected(final char[] buffer)
 136     {
 137         String[] wFiles = (new String(buffer)).split("\0"); // NULL is the delimiter
 138         boolean multiple = (wFiles.length > 1);
 139 
 140         String jDirectory = null;
 141         String jFile = null;
 142         String jFiles[] = null;
 143 
 144         if (multiple) {
 145             jDirectory = wFiles[0];
 146             jFiles = new String[wFiles.length - 1];
 147             System.arraycopy(wFiles, 1, jFiles, 0, jFiles.length);
 148             jFile = jFiles[1]; // choose any file
 149         } else {
 150             int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
 151             if (index == -1) {
 152                 jDirectory = "."+java.io.File.separator;
 153                 jFile = wFiles[0];
 154             } else {
 155                 jDirectory = wFiles[0].substring(0, index + 1);
 156                 jFile = wFiles[0].substring(index + 1);
 157             }
 158             jFiles = new String[] { jFile };
 159         }
 160 
 161         final FileDialog fileDialog = (FileDialog)target;
 162         AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
 163 
 164         fileDialogAccessor.setDirectory(fileDialog, jDirectory);
 165         fileDialogAccessor.setFile(fileDialog, jFile);
 166         fileDialogAccessor.setFiles(fileDialog, jDirectory, jFiles);
 167 
 168         WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
 169              public void run() {
 170                  fileDialog.hide();
 171              }
 172         });
 173     } // handleSelected()
 174 
 175     // NOTE: This method is called by privileged threads.
 176     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 177     void handleCancel() {
 178         final FileDialog fileDialog = (FileDialog)target;
 179 
 180         AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
 181         AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null, null);
 182 
 183         WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
 184              public void run() {
 185                  fileDialog.hide();
 186              }
 187         });
 188     } // handleCancel()
 189 
 190     //This whole static block is a part of 4152317 fix
 191     static {
 192         String filterString = (String) AccessController.doPrivileged(
 193             new PrivilegedAction() {
 194                 public Object run() {
 195                     try {
 196                         ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization");
 197                         return rb.getString("allFiles");
 198                     } catch (MissingResourceException e) {
 199                         return "All Files";
 200                     }
 201                 }
 202             });
 203         setFilterString(filterString);
 204     }
 205 
 206     void blockWindow(WWindowPeer window) {
 207         blockedWindows.add(window);
 208         // if this dialog hasn't got an HWND, notification is
 209         // postponed until setHWnd() is called
 210         if (hwnd != 0) {
 211             window.modalDisable((Dialog)target, hwnd);
 212         }
 213     }
 214     void unblockWindow(WWindowPeer window) {
 215         blockedWindows.remove(window);
 216         // if this dialog hasn't got an HWND or has been already
 217         // closed, don't send notification
 218         if (hwnd != 0) {
 219             window.modalEnable((Dialog)target);
 220         }
 221     }
 222 
 223     public void blockWindows(java.util.List<Window> toBlock) {
 224         for (Window w : toBlock) {
 225             WWindowPeer wp = (WWindowPeer)AWTAccessor.getComponentAccessor().getPeer(w);
 226             if (wp != null) {
 227                 blockWindow(wp);
 228             }
 229         }
 230     }
 231 
 232     public native void toFront();
 233     public native void toBack();
 234 
 235     // unused methods.  Overridden to disable this functionality as
 236     // it requires HWND which is not available for FileDialog
 237     public void setAlwaysOnTop(boolean value) {}
 238     public void setDirectory(String dir) {}
 239     public void setFile(String file) {}
 240     public void setTitle(String title) {}
 241 
 242     public void setResizable(boolean resizable) {}
 243     public void enable() {}
 244     public void disable() {}
 245     public void reshape(int x, int y, int width, int height) {}
 246     public boolean handleEvent(Event e) { return false; }
 247     public void setForeground(Color c) {}
 248     public void setBackground(Color c) {}
 249     public void setFont(Font f) {}
 250     public void updateMinimumSize() {}
 251     public void updateIconImages() {}
 252     public boolean requestFocus(boolean temporary,
 253                                 boolean focusedWindowChangeAllowed) {
 254         return false;
 255     }
 256 
 257     public boolean requestFocus
 258          (Component lightweightChild, boolean temporary,
 259           boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
 260     {
 261         return false;
 262     }
 263 
 264     void start() {}
 265     public void beginValidate() {}
 266     public void endValidate() {}
 267     void invalidate(int x, int y, int width, int height) {}
 268     public void addDropTarget(DropTarget dt) {}
 269     public void removeDropTarget(DropTarget dt) {}
 270     public void updateFocusableWindowState() {}
 271     public void setZOrder(ComponentPeer above) {}
 272 
 273     /**
 274      * Initialize JNI field and method ids
 275      */
 276     private static native void initIDs();
 277 
 278     // The effects are not supported for system dialogs.
 279     public void applyShape(sun.java2d.pipe.Region shape) {}
 280     public void setOpacity(float opacity) {}
 281     public void setOpaque(boolean isOpaque) {}
 282     public void updateWindow(java.awt.image.BufferedImage backBuffer) {}
 283 
 284     // the file/print dialogs are native dialogs and
 285     // the native system does their own rendering
 286     @Override
 287     public void createScreenSurface(boolean isResize) {}
 288     @Override
 289     public void replaceSurfaceData() {}
 290 
 291     public boolean isMultipleMode() {
 292         FileDialog fileDialog = (FileDialog)target;
 293         return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog);
 294     }
 295 }