1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.platform.windows;
4 
5 import java.awt.color.ICC_Profile;
6 import java.io.File;
7 import java.io.InputStream;
8 import java.io.IOException;
9 import java.util.*;
10 import java.util.stream.Stream;
11 
12 import javax.swing.filechooser.FileSystemView;
13 import javax.swing.*;
14 
15 import sun.awt.shell.ShellFolder;
16 
17 import com.lightcrafts.platform.FileChooser;
18 import com.lightcrafts.platform.Platform;
19 import com.lightcrafts.platform.PrinterLayer;
20 import com.lightcrafts.utils.ColorProfileInfo;
21 import com.lightcrafts.utils.directory.DirectoryMonitor;
22 import com.lightcrafts.utils.directory.WindowsDirectoryMonitor;
23 import com.lightcrafts.utils.file.FileUtil;
24 import com.lightcrafts.utils.file.ICC_ProfileFileFilter;
25 import com.lightcrafts.utils.Version;
26 
27 import static com.lightcrafts.platform.windows.WindowsFileUtil.*;
28 
29 import com.lightcrafts.ui.LightZoneSkin;
30 import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
31 
32 public final class WindowsPlatform extends Platform {
33 
34     ////////// public /////////////////////////////////////////////////////////
35 
36     @Override
getDefaultImageDirectory()37     public File getDefaultImageDirectory() {
38         final String path =
39             WindowsFileUtil.getFolderPathOf( FOLDER_MY_PICTURES );
40         return path != null ? new File( path ) : null;
41     }
42 
43     @Override
getDirectoryMonitor()44     public DirectoryMonitor getDirectoryMonitor() {
45         return new WindowsDirectoryMonitor();
46     }
47 
48     @Override
getDisplayProfile()49     public ICC_Profile getDisplayProfile() {
50         final String path =
51             WindowsColorProfileManager.getSystemDisplayProfilePath();
52         if ( path == null )
53             return null;
54         try {
55             final InputStream in = new File( path ).toURL().openStream();
56             final ICC_Profile profile = ICC_Profile.getInstance( in );
57             System.out.println(
58                 "Display profile " + ColorProfileInfo.getNameOf( profile )
59             );
60             return profile;
61         }
62         catch ( IOException e ) {
63             return null;
64         }
65     }
66 
67     @Override
getExportProfiles()68     public Collection<ColorProfileInfo> getExportProfiles() {
69         return getColorProfiles();
70     }
71 
72     @Override
getFileChooser()73     public FileChooser getFileChooser() {
74         return super.getFileChooser();
75         // return new WindowsFileChooser();
76     }
77 
78     @Override
getDisplayNameOf( File file )79     public String getDisplayNameOf( File file ) {
80         String displayName;
81 
82         if ( file instanceof ShellFolder ) {
83             //
84             // This is a stupid hack fix when running on Vista that shows the
85             // GUID rather than the display name for the user's home directory
86             // (and a few other directories).
87             //
88             // See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6488082
89             //
90             // It's apparently fixed for ShellFolder, but still broken for
91             // FileSystemView.
92             //
93             displayName = ((ShellFolder)file).getDisplayName();
94         } else
95             displayName = getFileSystemView().getSystemDisplayName( file );
96 
97         if ( displayName.endsWith( ".lnk" ) ) {
98             //
99             // Windows shortcuts' display names sometimes incorrectly show the
100             // ".lnk" extension -- remove it.
101             //
102             displayName = FileUtil.trimExtensionOf( displayName );
103         }
104 
105         return displayName;
106     }
107 
108     @Override
getLightZoneDocumentsDirectory()109     public File getLightZoneDocumentsDirectory() {
110         final File myDocuments =
111             FileSystemView.getFileSystemView().getDefaultDirectory();
112         return new File( myDocuments, Version.getApplicationName() );
113     }
114 
115     @Override
getLookAndFeel()116     public LookAndFeel getLookAndFeel() {
117         LookAndFeel laf = LightZoneSkin.getLightZoneLookAndFeel();
118 
119         boolean addWindows = false;
120 
121         if (addWindows) {
122             WindowsLookAndFeel quaqua = new WindowsLookAndFeel();
123 
124             UIDefaults quaquaDefaults = quaqua.getDefaults();
125             Set<Object> quaquaKeys = quaquaDefaults.keySet();
126 
127             String[] fromQuaqua = new String[] {
128                     "FileChooser",
129             };
130 
131             Stream.of(fromQuaqua).forEach(qk -> {
132                 quaquaKeys.stream()
133                     .filter(key -> key instanceof String &&
134                             ((String) key).startsWith(qk))
135                     .forEach(key -> {
136                         Object value = quaquaDefaults.get(key);
137                         UIManager.put(key, value);
138                     });
139             });
140         }
141 
142         return laf;
143     }
144 
145     @Override
getPathComponentsToPicturesFolder()146     public String[] getPathComponentsToPicturesFolder() {
147         final File picturesDir =
148             Platform.getPlatform().getDefaultImageDirectory();
149         if ( picturesDir == null )
150             return null;
151         final String[] picturesComponents =
152             picturesDir.toString().split( "\\\\" );
153         if ( picturesComponents.length != 5 ) {
154             //
155             // We expect the components to be:
156             //
157             //      C:
158             //      Documents and Settings
159             //      {user}
160             //      My Documents
161             //      My Pictures
162             //
163             // If it isn't, forget it.
164             //
165             return null;
166         }
167         final String[] wantedComponents = new String[2];
168         System.arraycopy( picturesComponents, 3, wantedComponents, 0, 2 );
169         return wantedComponents;
170     }
171 
172     @Override
getPhysicalMemoryInMB()173     public int getPhysicalMemoryInMB() {
174         return WindowsMemory.getPhysicalMemoryInMB();
175     }
176 
177     @Override
getPrinterProfiles()178     public Collection<ColorProfileInfo> getPrinterProfiles() {
179         return getColorProfiles();
180     }
181 
182     @Override
hasInternetConnectionTo( String hostName )183     public boolean hasInternetConnectionTo( String hostName ) {
184         return WindowsInternetConnection.hasConnection();
185     }
186 
187     @Override
hideFile( File file )188     public void hideFile( File file ) throws IOException {
189         WindowsFileUtil.hideFile( file.getAbsolutePath() );
190     }
191 
192     @Override
isKeyPressed( int keyCode )193     public boolean isKeyPressed( int keyCode ) {
194         return WindowsKeyUtil.isKeyPressed( keyCode );
195     }
196 
197     @Override
isSpecialFile( File file )198     public File isSpecialFile( File file ) {
199         file = FileUtil.resolveAliasFile( file );
200         if ( !(file instanceof WindowsSavedSearch) &&
201              WindowsSavedSearch.isSavedSearch( file ) )
202             return new WindowsSavedSearch( file );
203         if ( isVista() )
204             return isSpecialFileOnVista( file );
205         return file;
206     }
207 
208     /**
209      * True if it's newer than Vista.
210      */
isVista()211     public static boolean isVista() {
212         String version = System.getProperty( "os.version" );
213         int majorVersion = Character.getNumericValue(version.charAt(0));
214         return majorVersion >= 6;
215     }
216 
217     @Override
loadLibraries()218     public void loadLibraries() throws UnsatisfiedLinkError {
219         // We may need clib_jiio and either mlib_jai or mlib_jai_mmx, but we
220         // don't load these explicitly so JAI can make up its own mind.
221         System.loadLibrary( "Windows" );
222     }
223 
224     @Override
moveFilesToTrash( String[] pathNames )225     public boolean moveFilesToTrash( String[] pathNames ) {
226         return WindowsFileUtil.moveToRecycleBin( pathNames );
227     }
228 
229     @Override
readyToOpenFiles()230     public void readyToOpenFiles() {
231         if ( System.getProperty( "IDE" ) == null )
232             WindowsLauncher.readyToOpenFiles();
233     }
234 
235     @Override
resolveAliasFile( File file )236     public String resolveAliasFile( File file ) {
237         return WindowsFileUtil.resolveShortcut( file.getAbsolutePath() );
238     }
239 
240     @Override
showFileInFolder( String path )241     public boolean showFileInFolder( String path ) {
242         return WindowsFileUtil.showInExplorer( path );
243     }
244 
245     @Override
showHelpTopic( String topic )246     public void showHelpTopic( String topic ) {
247         WindowsHelp.showHelpTopic( topic );
248     }
249 
250     private PrinterLayer printerLayer = new WindowsPrinterLayer();
251 
252     @Override
getPrinterLayer()253     public PrinterLayer getPrinterLayer() {
254         return printerLayer;
255     }
256 
257     ////////// private ////////////////////////////////////////////////////////
258 
getColorProfiles()259     private static synchronized Collection<ColorProfileInfo> getColorProfiles() {
260         if (m_profiles == null) {
261             String windir = System.getenv("WINDIR");
262             if (windir == null)
263                 windir = "C:\\WINDOWS";
264 
265             final File profileDir = new File(
266                     windir + "\\system32\\spool\\drivers\\color");
267             m_profiles = getColorProfiles(profileDir);
268         }
269         return m_profiles;
270     }
271 
272     /**
273      * Checks whether the given {@link File} is special in some way on Windows
274      * Vista to deal with Vista-specific quirks.
275      *
276      * @param file The {@link File} to check.
277      * @return If the file is special, returns a new {@link File} to deal with
278      * a Vista-specific quirk; otherwise returns the passed-in file.
279      */
isSpecialFileOnVista( File file )280     private File isSpecialFileOnVista( File file ) {
281         //
282         // Under Vista, the user's Desktop has a special folder that's some
283         // kind of "link" to the user's home folder, i.e., Desktop\{user}.
284         // Java correctly recognizes it as a folder, but listFiles() on it
285         // always returns an empty array -- it must be a bug.
286         //
287         // To work around this, we check to see if the given file has the path
288         // Desktop\{user}.  If so, we return a new File of the user's real home
289         // folder of C:\Users\{user} for which listFiles() works correctly.
290         //
291         final String displayName = getDisplayNameOf( file );
292         if ( !displayName.equals( System.getProperty( "user.name" ) ) )
293             return file;
294         final File parentDir = file.getParentFile();
295         if ( parentDir == null )
296             return file;
297         if ( parentDir.getName().equals( "Desktop" ) )
298             return new File( System.getProperty( "user.home" ) );
299         return file;
300     }
301 
302     /**
303      * The ICC profiles from
304      * <code>$WINDIR\system32\spool\drivers\color</code>.
305      */
306     private static Collection<ColorProfileInfo> m_profiles;
307 }
308 /* vim:set et sw=4 ts=4: */
309