001 ///////////////////////////////////////////////// 002 // This file is part of Sears project. 003 // Subtitle Editor And Re-Synch 004 // A tool to easily modify and resynch movies subtitles. 005 ///////////////////////////////////////////////// 006 //This program is free software; 007 //you can redistribute it and/or modify it under the terms 008 //of the GNU General Public License 009 //as published by the Free Software Foundation; 010 //either version 2 of the License, or (at your option) any later version. 011 ///////////////////////////////////////////////// 012 //Sears project is available under sourceforge 013 // at adress: http://sourceforge.net/projects/sears/ 014 //Copyright (C) 2005 Booba Skaya 015 //Mail: booba.skaya@gmail.com 016 //////////////////////////////////////////////// 017 018 package sears.gui.resources; 019 020 import java.awt.Toolkit; 021 import java.awt.event.InputEvent; 022 import java.awt.event.KeyEvent; 023 import java.io.File; 024 import java.net.URL; 025 import java.util.HashMap; 026 027 import javax.swing.ImageIcon; 028 import javax.swing.KeyStroke; 029 030 import sears.gui.JDialogOptions; 031 import sears.gui.MainWindow; 032 import sears.tools.JarResources; 033 import sears.tools.SearsProperties; 034 import sears.tools.Trace; 035 import sears.tools.Utils; 036 037 /** 038 * Class SearsResourceBundle. 039 * <br><b>Summary:</b><br> 040 * This class contains resources for Sears GUI. 041 */ 042 public class SearsResources { 043 private static Object[][] resources = { 044 //General stuff 045 // 'favicon' :) displayed by Windows and Linux OS 046 // [ 20x20 size is good for a nice icon view ] 047 { "SearsGUIFavicon", "searsFavicon.png" }, 048 { "SearsGUIIcon", "sears.png" }, 049 { "SearsGUITitle", "Sears Beta V" }, 050 { "BrowseIcon", "browse.png" }, 051 // used by ArrowButton class 052 { "ArrowDown", "arrowDown.png" }, 053 { "ArrowUp", "arrowUp.png" }, 054 055 //Open Action 056 { "OpenIcon", "open.png"}, 057 { "OpenKey" , KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)}, 058 { "OpenKeyMac", KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_MASK)}, 059 060 //Save Action 061 { "SaveIcon", "save.png"}, 062 { "SaveKey" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)}, 063 { "SaveKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_MASK)}, 064 065 //SaveAs Action 066 { "SaveAsIcon", "saveAs.png"}, 067 { "SaveAsKey" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_MASK)}, 068 { "SaveAsKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_MASK | InputEvent.SHIFT_MASK)}, 069 070 //Quit Action 071 { "QuitIcon", "quit.png"}, 072 //{ "QuitKey" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)}, 073 //{ "QuitKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_MASK)}, 074 075 //Delay Action 076 { "DelayIcon", "delay.png"}, 077 { "DelayKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F1, InputEvent.CTRL_DOWN_MASK)}, 078 { "DelayKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.META_MASK | InputEvent.ALT_DOWN_MASK)}, 079 080 //Resynch Action 081 { "ResynchIcon", "resynch.png"}, 082 { "ResynchKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_DOWN_MASK)}, 083 { "ResynchKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.META_MASK | InputEvent.ALT_DOWN_MASK)}, 084 085 //Split Action 086 { "SplitIcon", "split.png"}, 087 { "SplitKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.CTRL_DOWN_MASK)}, 088 { "SplitKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_MASK | InputEvent.ALT_DOWN_MASK)}, 089 090 //Append Action 091 { "AppendIcon", "append.png"}, 092 { "AppendKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.CTRL_DOWN_MASK)}, 093 { "AppendKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.META_MASK | InputEvent.ALT_DOWN_MASK)}, 094 095 //ChainRepair Action 096 { "ChainRepairIcon", "chainRepair.png"}, 097 { "ChainRepairKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F5, InputEvent.CTRL_DOWN_MASK)}, 098 { "ChainRepairKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_MASK | InputEvent.ALT_DOWN_MASK)}, 099 100 //AccentRepair Action 101 { "AccentRepairIcon", "accentRepair.png"}, 102 { "AccentRepairKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK)}, 103 { "AccentRepairKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 104 105 //HtmlRepair Action 106 { "HtmlRepairIcon", "htmlRepair.png"}, 107 { "HtmlRepairKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F7, InputEvent.CTRL_DOWN_MASK)}, 108 { "HtmlRepairKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 109 110 //OrderRepair Action 111 { "OrderRepairIcon", "orderRepair.png"}, 112 { "OrderRepairKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F8, InputEvent.CTRL_DOWN_MASK)}, 113 { "OrderRepairKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 114 115 //TimeRepair Action 116 { "TimeRepairIcon", "timeRepair.png"}, 117 { "TimeRepairKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F9, InputEvent.CTRL_DOWN_MASK)}, 118 { "TimeRepairKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 119 120 //Undo Action 121 { "UndoIcon", "undo.png"}, 122 { "UndoKey" , KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK)}, 123 { "UndoKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 124 125 //Redo Action 126 { "RedoIcon", "redo.png"}, 127 { "RedoKey" , KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK)}, 128 { "RedoKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.META_MASK | InputEvent.SHIFT_DOWN_MASK)}, 129 130 131 //NormalizeDuration Action 132 { "NormalizeDurationIcon", "normalizeDuration.png"}, 133 { "NormalizeDurationKey" , null}, 134 135 //Split GUI stuff 136 { "SplitGUIBanner", "splitBanner.png"}, 137 138 //SelectVideo Action 139 { "SelectVideoIcon", "openVideo.png"}, 140 { "SelectVideoKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.CTRL_DOWN_MASK)}, 141 { "SelectVideoKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_DOWN_MASK | InputEvent.SHIFT_MASK)}, 142 143 //Options Action 144 { "OptionsIcon", "options.png"}, 145 { "OptionsKey" , KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK)}, 146 { "OptionsKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, InputEvent.META_MASK)}, 147 148 //Play Action 149 { "PlayIcon", "play.png"}, 150 { "PlayKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F11, InputEvent.CTRL_DOWN_MASK)}, 151 { "PlayKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.META_DOWN_MASK | InputEvent.SHIFT_MASK)}, 152 153 //Pause Action 154 { "PauseIcon", "pause.png"}, 155 156 //Stop Action 157 { "StopIcon", "stop.png"}, 158 159 //Previous Action 160 { "PreviousIcon", "reward.png"}, 161 162 //Next Action 163 { "NextIcon", "forward.png"}, 164 165 //GotoSub Action 166 { "GotoSubIcon", "gotoSub.png"}, 167 168 //MagicResynchro Action 169 { "MagicResynchroIcon", "magicResynchro.png"}, 170 171 //RemoveAllAnchors Action 172 { "RemoveAllAnchorsIcon", "removeAllAnchors.png"}, 173 174 //RecentFile Action 175 { "RecentFileIcon", "openRecent.png"}, 176 177 //Anchor icon 178 { "AnchorIcon", "anchor.png"}, 179 180 //Dot icon 181 { "DotIcon", "dot.png"}, 182 183 //About Action 184 { "AboutIcon", "about.png"}, 185 186 //Help 187 { "HelpIcon", "help.png"}, 188 // no question_mark keyEvent... 189 190 //Find Action 191 { "FindIcon", "find.png"}, 192 { "FindKey" , KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_DOWN_MASK)}, 193 { "FindKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.META_DOWN_MASK)}, 194 195 { "TinyFindIcon", "tinyFind.png" }, 196 197 //Mix Action 198 { "MixIcon", "mix.png"}, 199 { "MixKey" , KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.CTRL_DOWN_MASK)}, 200 { "MixKeyMac" , KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.META_DOWN_MASK | InputEvent.ALT_DOWN_MASK)}, 201 202 // Error icon, use in JDialogErrorMessage 203 { "ErrorIcon", "error.png" }, 204 205 // Flag: 206 { "fr", "flag/fr.png" }, 207 { "en", "flag/us.png" }, 208 { "it", "flag/it.png" }, 209 { "es", "flag/es.png" }, 210 { "nl", "flag/nl.png" }, 211 212 { "delete", "s_delete.png"}, 213 { "deletePressed", "s_delete_pressed.png"}, 214 215 { "blank","blank.png"} 216 217 }; 218 219 private static HashMap<String, Object> resourcesMap; 220 221 private static JarResources jarResources; 222 223 private static String iconFolder; 224 225 226 /** 227 * Method getString. 228 * <br><b>Summary:</b><br> 229 * This method return the value that correspond to the given key. 230 * @param key The key to search. 231 * @return The <b>String</b> searched value, or "" if does not found. 232 */ 233 public static String getString(String key) { 234 //the result of the method. 235 String result = ""; 236 if (resourcesMap == null) { 237 constructMap(); 238 } 239 String value = (String) resourcesMap.get(key); 240 //return value only if non null 241 if (value != null) { 242 result = value; 243 } 244 //return the result 245 return result; 246 } 247 248 /** 249 * Method getIcon. 250 * <br><b>Summary:</b><br> 251 * This method return the icon that correspond to the given key. 252 * @param key The key to search. 253 * @return The <b>ImageIcon</b> searched icon, or blankIcon if does not found. 254 */ 255 public static ImageIcon getIcon(String key) { 256 //the result of the method. 257 ImageIcon result = null; 258 String iconFile = getString(key); 259 if (!iconFile.equals("")) { 260 //retrieve icon URL. 261 //check if a skin is precised. 262 String iconSetFile = SearsProperties.getProperty(SearsProperties.ICON_SET); 263 if(iconSetFile != null && !iconSetFile.equals("")){ 264 //We have to reach the icon in the jar file using the jarResources. 265 //create the jarResources if not already set. 266 if(jarResources == null){ 267 jarResources = new JarResources(getIconFolder()+File.separator+iconSetFile); 268 } 269 //Reach the icon in it. 270 byte[] byteImage = jarResources.getResource(iconFile); 271 if(byteImage != null){ 272 result = new ImageIcon(Toolkit.getDefaultToolkit().createImage(byteImage)); 273 }else{ 274 Trace.warning("Can't find resource "+iconFile+" in jar resources "+iconSetFile+". Using default icon."); 275 } 276 } 277 //If can not find resource, use default icon. 278 if(result == null){ 279 URL url = MainWindow.instance.getClass().getResource("/sears/gui/resources/" + iconFile); 280 if(url != null){ 281 result = new ImageIcon(url); 282 } 283 } 284 } 285 //if could not find icon, return blank icon 286 if(result == null){ 287 result = new ImageIcon(MainWindow.instance.getClass().getResource("/sears/gui/resources/blank.png")); 288 } 289 //return the result 290 return result; 291 } 292 293 /** 294 * Method getKey. 295 * <br><b>Summary:</b><br> 296 * This method return the Key accelerator that correspond to the given key. 297 * @param key The key to search. 298 * @return The <b>KeyStroke</b> searched key, or null if does not found. 299 */ 300 public static KeyStroke getKey(String key) { 301 // if we are running on Mac OS: 302 if(Utils.isMacPlatform){ 303 key = key + "Mac"; 304 } 305 //the result of the method. 306 KeyStroke result = (KeyStroke) resourcesMap.get(key); 307 //return the result 308 return result; 309 } 310 311 /** 312 * Method constructMap. 313 * <br><b>Summary:</b><br> 314 * This contruct the HashMap of resources. 315 */ 316 private static void constructMap() { 317 resourcesMap = new HashMap<String, Object>(); 318 for (int i = 0; i < resources.length; i++) { 319 resourcesMap.put((String) resources[i][0], resources[i][1]); 320 } 321 } 322 323 /** 324 * Method getIconFolder. 325 * <br><b>Summary:</b><br> 326 * This method return the Icon folder. 327 * @return (<b>String</b>) the Icon folder. 328 */ 329 public static String getIconFolder() { 330 if (iconFolder == null) { 331 // To do that retrieve the location of the JDialogOption class 332 String classResource = JDialogOptions.class.getResource( 333 "JDialogOptions.class").getFile(); 334 // DEVELOPER: 335 // spaces are not allowed in URL and replaced by %20 336 // there's a maybe a better solution to correct this 337 // than the one under: 338 classResource = classResource.replace("%20", " "); 339 // Then retrieve the index of the "file:" string, which indicate we 340 // are executing from a jar file. 341 int indexOfFile = classResource.indexOf("file:"); 342 // the beginning of the jar file contain, if it exists: 343 int indexOfJar = classResource.indexOf("!"); 344 // if we are in a jar file: 345 if (indexOfFile != -1 && indexOfJar != -1) { 346 // we get the parent file of the jar file: 347 File parent = new File(classResource.substring(0, indexOfJar)).getParentFile(); 348 // and with the parent of the parent, we get back the icon directory path: 349 iconFolder = new File(parent.getParent()) + System.getProperty("file.separator") + "icons"; 350 //remove begining "file:" pattern 351 iconFolder = iconFolder.substring(5); 352 } else { 353 // we are not in a jar file, let's assume we are in eclipse. 354 // And eclipse project does export the icons folder. 355 // search for the last sears pattern, which is the root for the 356 // sears class. 357 int indexOfSearsPackage = classResource.lastIndexOf("sears"); 358 if (indexOfSearsPackage != -1) { 359 // we have retrieved the sears folder, go up, and find the 360 // icon folder. 361 iconFolder = classResource 362 .substring(0, indexOfSearsPackage); 363 iconFolder += "icons"; 364 } 365 } 366 } 367 return iconFolder; 368 } 369 370 /** 371 * Sets to null all utilized variables 372 * <br>Useful when an icon change request is launched 373 */ 374 public static void dispose() { 375 //resourcesMap = null; 376 jarResources = null; 377 //iconFolder = null; 378 } 379 }