1 /*
   2  * Copyright (c) 1996, 2013, 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         File[] jFiles = null;
 143 
 144         if (multiple) {
 145             jDirectory = wFiles[0];
 146             int filesNumber = wFiles.length - 1;
 147             jFiles = new File[filesNumber];
 148             for (int i = 0; i < filesNumber; i++) {
 149                 jFiles[i] = new File(jDirectory, wFiles[i + 1]);
 150         }
 151             jFile = wFiles[1]; // choose any file
 152         } else {
 153             int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
 154             if (index == -1) {
 155                 jDirectory = "."+java.io.File.separator;
 156                 jFile = wFiles[0];
 157             } else {
 158                 jDirectory = wFiles[0].substring(0, index + 1);
 159                 jFile = wFiles[0].substring(index + 1);
 160             }
 161             jFiles = new File[] { new File(jDirectory, jFile) };
 162         }
 163 
 164         final FileDialog fileDialog = (FileDialog)target;
 165         AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
 166 
 167         fileDialogAccessor.setDirectory(fileDialog, jDirectory);
 168         fileDialogAccessor.setFile(fileDialog, jFile);
 169         fileDialogAccessor.setFiles(fileDialog, jFiles);
 170 
 171         WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
 172              public void run() {
 173                  fileDialog.setVisible(false);
 174              }
 175         });
 176     } // handleSelected()
 177 
 178     // NOTE: This method is called by privileged threads.
 179     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 180     void handleCancel() {
 181         final FileDialog fileDialog = (FileDialog)target;
 182 
 183         AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
 184         AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null);
 185         AWTAccessor.getFileDialogAccessor().setDirectory(fileDialog, null);
 186 
 187         WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
 188              public void run() {
 189                  fileDialog.setVisible(false);
 190              }
 191         });
 192     } // handleCancel()
 193 
 194     //This whole static block is a part of 4152317 fix
 195     static {
 196         String filterString = AccessController.doPrivileged(
 197             new PrivilegedAction<String>() {
 198                 public String run() {
 199                     try {
 200                         ResourceBundle rb = ResourceBundle.getBundle("sun.awt.windows.awtLocalization");
 201                         return rb.getString("allFiles");
 202                     } catch (MissingResourceException e) {
 203                         return "All Files";
 204                     }
 205                 }
 206             });
 207         setFilterString(filterString);
 208     }
 209 
 210     void blockWindow(WWindowPeer window) {
 211         blockedWindows.add(window);
 212         // if this dialog hasn't got an HWND, notification is
 213         // postponed until setHWnd() is called
 214         if (hwnd != 0) {
 215             window.modalDisable((Dialog)target, hwnd);
 216         }
 217     }
 218     void unblockWindow(WWindowPeer window) {
 219         blockedWindows.remove(window);
 220         // if this dialog hasn't got an HWND or has been already
 221         // closed, don't send notification
 222         if (hwnd != 0) {
 223             window.modalEnable((Dialog)target);
 224         }
 225     }
 226 
 227     public void blockWindows(java.util.List<Window> toBlock) {
 228         for (Window w : toBlock) {
 229             WWindowPeer wp = (WWindowPeer)AWTAccessor.getComponentAccessor().getPeer(w);
 230             if (wp != null) {
 231                 blockWindow(wp);
 232             }
 233         }
 234     }
 235 
 236     public native void toFront();
 237     public native void toBack();
 238 
 239     // unused methods.  Overridden to disable this functionality as
 240     // it requires HWND which is not available for FileDialog
 241     public void updateAlwaysOnTopState() {}
 242     public void setDirectory(String dir) {}
 243     public void setFile(String file) {}
 244     public void setTitle(String title) {}
 245 
 246     public void setResizable(boolean resizable) {}
 247     public void enable() {}
 248     public void disable() {}
 249     public void reshape(int x, int y, int width, int height) {}
 250     public boolean handleEvent(Event e) { return false; }
 251     public void setForeground(Color c) {}
 252     public void setBackground(Color c) {}
 253     public void setFont(Font f) {}
 254     public void updateMinimumSize() {}
 255     public void updateIconImages() {}
 256     public boolean requestFocus(boolean temporary,
 257                                 boolean focusedWindowChangeAllowed) {
 258         return false;
 259     }
 260 
 261     public boolean requestFocus
 262          (Component lightweightChild, boolean temporary,
 263           boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
 264     {
 265         return false;
 266     }
 267 
 268     void start() {}
 269     public void beginValidate() {}
 270     public void endValidate() {}
 271     void invalidate(int x, int y, int width, int height) {}
 272     public void addDropTarget(DropTarget dt) {}
 273     public void removeDropTarget(DropTarget dt) {}
 274     public void updateFocusableWindowState() {}
 275     public void setZOrder(ComponentPeer above) {}
 276 
 277     /**
 278      * Initialize JNI field and method ids
 279      */
 280     private static native void initIDs();
 281 
 282     // The effects are not supported for system dialogs.
 283     public void applyShape(sun.java2d.pipe.Region shape) {}
 284     public void setOpacity(float opacity) {}
 285     public void setOpaque(boolean isOpaque) {}
 286     public void updateWindow(java.awt.image.BufferedImage backBuffer) {}
 287 
 288     // the file/print dialogs are native dialogs and
 289     // the native system does their own rendering
 290     @Override
 291     public void createScreenSurface(boolean isResize) {}
 292     @Override
 293     public void replaceSurfaceData() {}
 294 
 295     public boolean isMultipleMode() {
 296         FileDialog fileDialog = (FileDialog)target;
 297         return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog);
 298     }
 299 }