OmegaT のメニューバーにフォルダーツリー参照用のメニューを追加します。
change package name
@@ -1,82 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import java.io.File; | |
20 | -import java.io.IOException; | |
21 | -import javax.swing.JMenu; | |
22 | -import javax.swing.JMenuBar; | |
23 | -import org.omegat.core.Core; | |
24 | -import org.omegat.util.Log; | |
25 | -import org.omegat.util.StaticUtils; | |
26 | -import org.openide.awt.Mnemonics; | |
27 | - | |
28 | -/** | |
29 | - * | |
30 | - * @author Yu-Tang | |
31 | - */ | |
32 | -public class MenuManager { | |
33 | - | |
34 | - private JMenu root; | |
35 | - private JMenu currentProject; | |
36 | - private JMenu userConfig; | |
37 | - | |
38 | - public MenuManager() { | |
39 | - root = createLocalizedMenu(L10n.getFoldersMenuLabel()); // Folders menu | |
40 | - root.addMenuKeyListener(MenuHelper.getMenuKeyListener()); // for opening folder with enter key | |
41 | - root.addMenuListener(MenuHelper.getRootMenuListener()); | |
42 | - | |
43 | - // ProjectRoot | |
44 | - try { | |
45 | - root.add(currentProject = new ShellLinkMenu(L10n.getProjectRootMenuLabel()).getMenu()); | |
46 | - } catch (IOException ex) { | |
47 | - Log.log(ex); | |
48 | - return; | |
49 | - } | |
50 | - | |
51 | - // User Config | |
52 | - try { | |
53 | - File confDir = new File(StaticUtils.getConfigDir()); | |
54 | - root.add(userConfig = new ShellLinkMenu(confDir, L10n.getUserConfigMenuLabel()).getMenu()); | |
55 | - } catch (IOException ex) { | |
56 | - Log.log(ex); | |
57 | - } | |
58 | - | |
59 | - // insert Files menu before the last menu (Help menu.) | |
60 | - JMenuBar mainMenuBar = (JMenuBar) Core.getMainWindow().getMainMenu().getOptionsMenu().getParent(); | |
61 | - mainMenuBar.add(root, mainMenuBar.getMenuCount() - 1); | |
62 | - } | |
63 | - | |
64 | - public void createProjectItems() { | |
65 | - File rootDir = new File(Core.getProject().getProjectProperties().getProjectRoot()); | |
66 | - try { | |
67 | - new ShellLinkMenu(currentProject).link(rootDir); | |
68 | - } catch (IOException ex) { | |
69 | - Log.log(ex); | |
70 | - } | |
71 | - } | |
72 | - | |
73 | - public void removeAllProjectItems() { | |
74 | - new ShellLinkMenu(currentProject).unlink(); | |
75 | - } | |
76 | - | |
77 | - private JMenu createLocalizedMenu(String labelString) { | |
78 | - JMenu m = new JMenu(); | |
79 | - Mnemonics.setLocalizedText(m, labelString); | |
80 | - return m; | |
81 | - } | |
82 | -} | |
\ No newline at end of file |
@@ -1,62 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import org.omegat.core.CoreEvents; | |
20 | -import org.omegat.core.events.IApplicationEventListener; | |
21 | -import org.omegat.core.events.IProjectEventListener; | |
22 | -import org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.*; | |
23 | -import org.omegat.plugin.foldermenu.filepreview.FilePreview; | |
24 | - | |
25 | -/** | |
26 | - * easy access to project folders from menu | |
27 | - * | |
28 | - * @author Yu Tang | |
29 | - */ | |
30 | -public class FolderMenu implements IApplicationEventListener, IProjectEventListener { | |
31 | - | |
32 | - private MenuManager menuManager; | |
33 | - | |
34 | - @SuppressWarnings("LeakingThisInConstructor") | |
35 | - public FolderMenu() { | |
36 | - CoreEvents.registerApplicationEventListener(this); | |
37 | - CoreEvents.registerProjectChangeListener(this); | |
38 | - } | |
39 | - | |
40 | - @Override | |
41 | - public void onApplicationStartup() { | |
42 | - menuManager = new MenuManager(); | |
43 | - FilePreview.init(); | |
44 | - } | |
45 | - | |
46 | - @Override | |
47 | - public void onApplicationShutdown() { /* do nothing */ } | |
48 | - | |
49 | - @Override | |
50 | - public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
51 | - switch (eventType) { | |
52 | - case CREATE: | |
53 | - case LOAD: | |
54 | - menuManager.createProjectItems(); | |
55 | - break; | |
56 | - case CLOSE: | |
57 | - menuManager.removeAllProjectItems(); | |
58 | - break; | |
59 | - } | |
60 | - } | |
61 | - | |
62 | -} | |
\ No newline at end of file |
@@ -1,390 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu.filepreview; | |
18 | - | |
19 | -import java.io.File; | |
20 | -import java.io.IOException; | |
21 | -import java.io.InputStream; | |
22 | -import java.util.ArrayList; | |
23 | -import java.util.Arrays; | |
24 | -import java.util.List; | |
25 | -import org.omegat.plugin.foldermenu.L10n; | |
26 | -import org.omegat.util.LFileCopy; | |
27 | -import org.omegat.util.Log; | |
28 | -import static org.omegat.util.Platform.OsType.WIN32; | |
29 | -import static org.omegat.util.Platform.OsType.WIN64; | |
30 | -import static org.omegat.util.Platform.getOsType; | |
31 | -import org.omegat.util.StaticUtils; | |
32 | - | |
33 | -/** | |
34 | - * Word 文書をプレビュー用に開きます。 | |
35 | - * | |
36 | - * | |
37 | - * @author Yu-Tang | |
38 | - */ | |
39 | -public class WordPreview implements IPreview { | |
40 | - | |
41 | - private static final String WSF_NAME = "WordPreview.wsf"; | |
42 | - private static boolean _isMSWordAvailable; | |
43 | - private static File _wsf; | |
44 | - | |
45 | - private final File originalFile; | |
46 | - private long originalFileLastModified; // will update at each every time compiling target docs | |
47 | - private final String windowTitle; | |
48 | - private final File temporaryFile; // Primary temp file | |
49 | - private final File temporaryFile2; // Secondary temp file | |
50 | - | |
51 | - public WordPreview(final File originalFile) throws IOException { | |
52 | - this.originalFile = originalFile; | |
53 | - this.originalFileLastModified = originalFile.lastModified(); | |
54 | - this.temporaryFile = getTempFile(originalFile); | |
55 | - this.windowTitle = StaticUtils.format( | |
56 | - L10n.getWordWindowCaption(), | |
57 | - originalFile.getName()); | |
58 | - this.temporaryFile2 = getTempFile2(this.temporaryFile); | |
59 | - } | |
60 | - | |
61 | - static { | |
62 | - // _isMSWordAvailable | |
63 | - switch (getOsType()) { | |
64 | - case WIN64: | |
65 | - case WIN32: | |
66 | - new Thread() { | |
67 | - @Override | |
68 | - public void run() { | |
69 | - _isMSWordAvailable = getMSWordAvailable(); | |
70 | - Log.log("_isMSWordAvailable = " + _isMSWordAvailable); | |
71 | - } | |
72 | - }.start(); | |
73 | - break; | |
74 | - default: // Mac, Linux and others | |
75 | - _isMSWordAvailable = false; | |
76 | - break; | |
77 | - } | |
78 | - | |
79 | - // _wsf | |
80 | - File tempDir = new File(System.getProperty("java.io.tmpdir")); | |
81 | - _wsf = new File(tempDir, WSF_NAME); | |
82 | - } | |
83 | - | |
84 | - public static boolean isAvailable(File file) { | |
85 | - return isAvailable() && | |
86 | - file.isFile() && | |
87 | - file.getName().toLowerCase().endsWith(".docx"); | |
88 | - } | |
89 | - | |
90 | - public static boolean isAvailable() { | |
91 | - return _isMSWordAvailable; | |
92 | - } | |
93 | - | |
94 | - public static void init() { | |
95 | - // force executing static initializer | |
96 | - } | |
97 | - | |
98 | - private static boolean getMSWordAvailable() { | |
99 | - final int RET_OK = 0; | |
100 | - try { | |
101 | - Command command = new Command(); | |
102 | - String s; | |
103 | - if (RET_OK == command.execDOS("assoc", ".docx")) { | |
104 | - s = command.getStdout(); | |
105 | - // s's data example) | |
106 | - // ----------------------------------------------------- | |
107 | - //.docx=Word.Document.12 | |
108 | - //<-(\r\n) | |
109 | - // ----------------------------------------------------- | |
110 | - // 末尾に空行が入るので注意。 | |
111 | - if (s.toLowerCase().startsWith(".docx=word.document.")) { | |
112 | - String classString = s.substring(".docx=".length()).replaceAll("\\r\\n", ""); | |
113 | - if (RET_OK == command.exec("reg", "query", "HKCR\\" + classString + "\\shell\\open\\command", "/ve")) { | |
114 | - s = command.getStdout(); | |
115 | - // s's data example) | |
116 | - // ----------------------------------------------------- | |
117 | - //<-(\r\n) | |
118 | - //HKEY_CLASSES_ROOT\Word.document.12\shell\open\command | |
119 | - //(既定) REG_SZ "C:\PROGRA~2\MICROS~4\OFFICE11\WINWORD.EXE" /n /dde | |
120 | - //<-(\r\n) | |
121 | - // ----------------------------------------------------- | |
122 | - // 前後に空行が入るので注意。 | |
123 | - return s.toUpperCase().indexOf("\\WINWORD.EXE") > -1; | |
124 | - } | |
125 | - } | |
126 | - } | |
127 | - } catch (Exception ex) { | |
128 | - Log.log(ex); | |
129 | - } | |
130 | - return false; | |
131 | - } | |
132 | - | |
133 | - private static File getWSF() throws IOException { | |
134 | - if (! _wsf.exists()) { | |
135 | - InputStream in = WordPreview.class.getResourceAsStream(WSF_NAME); | |
136 | - try { | |
137 | - LFileCopy.copy(in, _wsf); | |
138 | - } finally { | |
139 | - in.close(); | |
140 | - } | |
141 | - _wsf.deleteOnExit(); | |
142 | - } | |
143 | - return _wsf; | |
144 | - } | |
145 | - | |
146 | - @Override | |
147 | - public String[] getTempFiles() { | |
148 | - // ここでは、残留する可能性のある一時ファイルをすべて申告します。 | |
149 | - String[] paths = new String[3]; | |
150 | - try { | |
151 | - paths[0] = this.temporaryFile.getCanonicalPath(); | |
152 | - paths[1] = this.temporaryFile2.getCanonicalPath(); | |
153 | - | |
154 | - // MS Word が作成する(プレビュー用ファイルの)一時ファイルも、強制 | |
155 | - // 終了時などには残留する可能性があるため、ここで申告しておきます。 | |
156 | - final String PREFIX = "~$"; | |
157 | - String parent = this.temporaryFile.getParent(); | |
158 | - String name = this.temporaryFile.getName(); | |
159 | - paths[2] = (new File(parent, PREFIX + name.substring(2))).getCanonicalPath(); | |
160 | - } catch (IOException ex) { | |
161 | - Log.log(ex); | |
162 | - } | |
163 | - return paths; | |
164 | - } | |
165 | - | |
166 | - @Override | |
167 | - public void activate() { | |
168 | - try { | |
169 | - final Command command = new Command(); | |
170 | - final String job = "activate"; | |
171 | - final int ret = command.execWSF(job, this.windowTitle); | |
172 | - } catch (IOException ex) { | |
173 | - Log.log(ex); | |
174 | - } catch (InterruptedException ex) { | |
175 | - Log.log(ex); | |
176 | - } | |
177 | - } | |
178 | - | |
179 | - @Override | |
180 | - public void open() { | |
181 | - | |
182 | - // 以下の処理は少し時間がかかるため、別スレッドに処理を委譲します。 | |
183 | - new Thread() { | |
184 | - @Override | |
185 | - public void run() { | |
186 | - try { | |
187 | - // 起動前にファイルをコピーする。 | |
188 | - // OmegaT は訳文ファイルの作成時に、既存の訳文ファイルを上書きする。 | |
189 | - // そのため、オリジナルのファイルをそのまま開くとファイルがロックされ、 | |
190 | - // 次回のコンパイル時に上書きできずに失敗する。それを避けるために、 | |
191 | - // プレビュー専用の一時ファイルをコピーして、そちらを開く。 | |
192 | - // コピー先は、temp フォルダーではなく、オリジナルと同じフォルダー内に | |
193 | - // コピーする。文書に相対パスで画像リンクなどが張られている場合のリンク | |
194 | - // 切れを防ぐため。 | |
195 | - // そのままコピーすると FolderMenu プラグインのメニュー上で一時ファイル | |
196 | - // が見えてしまうため、hidden 属性を付けておく。 | |
197 | - LFileCopy.copy(originalFile, temporaryFile); | |
198 | - | |
199 | - // make temp file hidden on Windows | |
200 | - addHiddenFileAttribute(temporaryFile); | |
201 | - | |
202 | - // Desktop.getDesktop().open(temp); | |
203 | - // 上記のようにして一時ファイルを開くと、場合によっては Word | |
204 | - // の MRU に一時ファイルを開いた履歴が大量に残ってしまう。 | |
205 | - // これを回避するため、WSH を経由して COM オートメーションで | |
206 | - // 処理する。 | |
207 | - | |
208 | - // open the document | |
209 | - Command command = new Command(); | |
210 | - String document = temporaryFile.getCanonicalPath(); | |
211 | - String document2 = temporaryFile2.getCanonicalPath(); | |
212 | - String job = "open"; | |
213 | - int ret = command.execWSF(job, document, document2, windowTitle); | |
214 | - | |
215 | - if (! command.stderr.isEmpty()) { | |
216 | - Log.log("Word error(" + ret + "): " + command.stderr); | |
217 | - } | |
218 | - onWordApplicationQuit(ret); | |
219 | - } catch (IOException ex) { | |
220 | - Log.log(ex); | |
221 | - } catch (InterruptedException ex) { | |
222 | - Log.log(ex); | |
223 | - } | |
224 | - } | |
225 | - }.start(); | |
226 | - } | |
227 | - | |
228 | - private File getTempFile(final File originalFile) throws IOException { | |
229 | - String prefix = "_WordPreview"; | |
230 | - String name = originalFile.getName(); | |
231 | - String suffix = name.substring(name.lastIndexOf(".")); | |
232 | - File parentFolder = originalFile.getParentFile(); | |
233 | - File tempFile = File.createTempFile(prefix, suffix, parentFolder); | |
234 | - tempFile.deleteOnExit(); | |
235 | - return tempFile; | |
236 | - } | |
237 | - | |
238 | - // foo.ext => foo(2).ext | |
239 | - private File getTempFile2(final File primaryTempFile) throws IOException { | |
240 | - String name = primaryTempFile.getName(); | |
241 | - int lastDotPos = name.lastIndexOf("."); | |
242 | - String baseName = name.substring(0, lastDotPos); | |
243 | - String extension = name.substring(lastDotPos); | |
244 | - String fileName = baseName + "(2)" + extension; | |
245 | - File parentFolder = primaryTempFile.getParentFile(); | |
246 | - File tempFile2 = new File(parentFolder, fileName); | |
247 | - tempFile2.deleteOnExit(); | |
248 | - return tempFile2; | |
249 | - } | |
250 | - | |
251 | - private void addHiddenFileAttribute(File file) { | |
252 | - try { | |
253 | - new ProcessBuilder("attrib","+H", file.getCanonicalPath()).start(); | |
254 | - } catch (IOException ex) { | |
255 | - Log.log(ex); | |
256 | - } | |
257 | - } | |
258 | - | |
259 | - private void onWordApplicationQuit(final int returnCode) { | |
260 | - try { | |
261 | - // remove this from Previews collection | |
262 | - FilePreview.delete(originalFile); | |
263 | - | |
264 | - // try to delete temporary file | |
265 | - temporaryFile.delete(); | |
266 | - | |
267 | - // try to delete WSF file | |
268 | - if (FilePreview.size(WordPreview.class) == 0) | |
269 | - _wsf.delete(); | |
270 | - | |
271 | - } catch (IOException ex) { | |
272 | - Log.log(ex); | |
273 | - } | |
274 | - } | |
275 | - | |
276 | - @Override | |
277 | - public void close() { | |
278 | - try { | |
279 | - // close the document | |
280 | - final Command command = new Command(); | |
281 | - final String job = "close"; | |
282 | - final String document = temporaryFile.getCanonicalPath(); | |
283 | - command.execWSF(job, document); | |
284 | - } catch (IOException ex) { | |
285 | - Log.log(ex); | |
286 | - } catch (InterruptedException ex) { | |
287 | - Log.log(ex); | |
288 | - } | |
289 | - } | |
290 | - | |
291 | - @Override | |
292 | - public void reload() { | |
293 | - if (! isOriginalFileUpdated()) { | |
294 | - return; | |
295 | - } | |
296 | - | |
297 | - try { | |
298 | - File temp = getTempFile(originalFile); | |
299 | - | |
300 | - // copy the file to avoid locking the file unnecessarily | |
301 | - LFileCopy.copy(originalFile, temp); | |
302 | - | |
303 | - // rename to secondary temp file (and pass it to WSF) | |
304 | - temp.renameTo(temporaryFile2); | |
305 | - | |
306 | - // make temp file hidden on Windows | |
307 | - addHiddenFileAttribute(temporaryFile2); | |
308 | - | |
309 | - // update lastModified value | |
310 | - this.originalFileLastModified = originalFile.lastModified(); | |
311 | - } catch (IOException ex) { | |
312 | - Log.log(ex); | |
313 | - } | |
314 | - } | |
315 | - | |
316 | - private boolean isOriginalFileUpdated() { | |
317 | - return this.originalFileLastModified != this.originalFile.lastModified(); | |
318 | - } | |
319 | - | |
320 | - // バッファあふれ非対応のため、少量のテキスト(だいたい 500文字ていど)が | |
321 | - // 予想される場合のみ利用してください。 | |
322 | - // また同期実行です。プロセスの終了を待機してから制御を返します。 | |
323 | - protected static class Command { | |
324 | - | |
325 | - private int exitCode = 0; | |
326 | - private String stdout = ""; | |
327 | - private String stderr = ""; | |
328 | - | |
329 | - public int getExitCode() { | |
330 | - return exitCode; | |
331 | - } | |
332 | - | |
333 | - public String getStdout() { | |
334 | - return stdout; | |
335 | - } | |
336 | - | |
337 | - public String getStderr() { | |
338 | - return stderr; | |
339 | - } | |
340 | - | |
341 | - public int exec(String... command) | |
342 | - throws IOException, InterruptedException { | |
343 | - return startProcessAndWait(Arrays.asList(command)); | |
344 | - } | |
345 | - | |
346 | - public int execDOS(String... command) | |
347 | - throws IOException, InterruptedException { | |
348 | - List<String> commands = new ArrayList<String>(command.length + 2); | |
349 | - commands.add("cmd.exe"); | |
350 | - commands.add("/c"); | |
351 | - commands.addAll(Arrays.asList(command)); | |
352 | - | |
353 | - return startProcessAndWait(commands); | |
354 | - } | |
355 | - | |
356 | - public int execWSF(String job, String... command) | |
357 | - throws IOException, InterruptedException { | |
358 | - String script = getWSF().getCanonicalPath(); | |
359 | - List<String> commands = new ArrayList<String>(command.length + 4); | |
360 | - commands.add("cscript.exe"); | |
361 | - commands.add("//nologo"); | |
362 | - commands.add("//Job:" + job); | |
363 | - commands.add(script); | |
364 | - commands.addAll(Arrays.asList(command)); | |
365 | - | |
366 | - return startProcessAndWait(commands); | |
367 | - } | |
368 | - | |
369 | - private int startProcessAndWait(List<String> command) | |
370 | - throws IOException, InterruptedException { | |
371 | - ProcessBuilder pb = new ProcessBuilder(command); | |
372 | - Process process = pb.start(); | |
373 | - exitCode = process.waitFor(); // 0: succeed | |
374 | - stdout = getString(process.getInputStream()); | |
375 | - stderr = getString(process.getErrorStream()); | |
376 | - return exitCode; | |
377 | - } | |
378 | - | |
379 | - private String getString(InputStream is) throws IOException { | |
380 | - byte[] b = new byte[1024]; | |
381 | - int size = is.read(b); | |
382 | - if (size > 0) { | |
383 | - return new String(b, 0, size); | |
384 | - } else { | |
385 | - return ""; | |
386 | - } | |
387 | - } | |
388 | - | |
389 | - } | |
390 | -} |
@@ -1,102 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu.filepreview; | |
18 | - | |
19 | -import java.io.File; | |
20 | -import java.io.IOException; | |
21 | -import org.omegat.util.FileUtil; | |
22 | -import org.omegat.util.Log; | |
23 | -import org.omegat.util.StaticUtils; | |
24 | - | |
25 | -/** | |
26 | - * Cleanup temp files | |
27 | - * | |
28 | - * @author Yu-Tang | |
29 | - */ | |
30 | -public class TempFileCleaner { | |
31 | - | |
32 | - private static final String LOG_FILE_NAME = "FilePreviewTempFiles.log"; | |
33 | - private static final File logFile; | |
34 | - | |
35 | - private TempFileCleaner() { /* not allow instanciation. static only. */ } | |
36 | - | |
37 | - static { | |
38 | - logFile = new File(StaticUtils.getConfigDir(), LOG_FILE_NAME); | |
39 | - } | |
40 | - | |
41 | - public static void cleanup() { | |
42 | - // load temp file list from log file | |
43 | - String[] list = readTempFileList().split("\\n"); | |
44 | - String content = ""; | |
45 | - | |
46 | - // try to delete them | |
47 | - for (String path: list) { | |
48 | - if (! path.isEmpty()) { | |
49 | - File f = new File(path); | |
50 | - if (f.isFile()) { | |
51 | - if (! f.delete()) { | |
52 | - f.deleteOnExit(); | |
53 | - content += path + "\n"; | |
54 | - } | |
55 | - } | |
56 | - } | |
57 | - } | |
58 | - | |
59 | - // save back to log file or delete log if empty | |
60 | - writeTempFileList(content); | |
61 | - } | |
62 | - | |
63 | - public static void addToList(String[] filePaths) { | |
64 | - // load temp file list from log file | |
65 | - String list = readTempFileList(); | |
66 | - | |
67 | - // add the file to the list | |
68 | - for (String path: filePaths) | |
69 | - list += path + "\n"; | |
70 | - | |
71 | - // save back to log file or delete log if empty | |
72 | - writeTempFileList(list); | |
73 | - } | |
74 | - | |
75 | - // 末尾改行付きのリストを返します。 | |
76 | - private static String readTempFileList() { | |
77 | - String ret = ""; | |
78 | - if (logFile.isFile()) { | |
79 | - try { | |
80 | - ret = FileUtil.readTextFile(logFile); | |
81 | - if (!ret.isEmpty() && !ret.endsWith("\n")) | |
82 | - ret += "\n"; | |
83 | - } catch (IOException ex) { | |
84 | - Log.log(ex); | |
85 | - } | |
86 | - } | |
87 | - return ret; | |
88 | - } | |
89 | - | |
90 | - private static void writeTempFileList(final String content) { | |
91 | - if (content.isEmpty()) { | |
92 | - if (logFile.isFile()) | |
93 | - logFile.delete(); | |
94 | - } else { | |
95 | - try { | |
96 | - FileUtil.writeTextFile(logFile, content); | |
97 | - } catch (IOException ex) { | |
98 | - Log.log(ex); | |
99 | - } | |
100 | - } | |
101 | - } | |
102 | -} |
@@ -1,221 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu.filepreview; | |
18 | - | |
19 | -import java.io.File; | |
20 | -import java.io.IOException; | |
21 | -import java.util.HashMap; | |
22 | -import javax.swing.SwingUtilities; | |
23 | -import org.omegat.core.Core; | |
24 | -import org.omegat.core.CoreEvents; | |
25 | -import org.omegat.core.events.IApplicationEventListener; | |
26 | -import org.omegat.core.events.IProjectEventListener; | |
27 | -import org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE; | |
28 | -import static org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.CLOSE; | |
29 | -import static org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.COMPILE; | |
30 | - | |
31 | -/** | |
32 | - * must call init() before using this class. | |
33 | - * | |
34 | - * @author Yu-Tang | |
35 | - */ | |
36 | - | |
37 | -public class FilePreview { | |
38 | - | |
39 | - // key = target file's canonical path | |
40 | - private static final HashMap<String, IPreview> previews = new HashMap<String, IPreview>(); | |
41 | - | |
42 | - private static IProjectEventListener projectEventListener = null; | |
43 | - private static IApplicationEventListener applicationEventListener = null; | |
44 | - | |
45 | - static { | |
46 | - // cleanup left temp files if they exists | |
47 | - TempFileCleaner.cleanup(); | |
48 | - | |
49 | - // call each Preview#init() | |
50 | - WordPreview.init(); | |
51 | - | |
52 | - //@@TODO WSF reload 時にselectionがテキストボックスの場合、restore に失敗するバグ | |
53 | - } | |
54 | - | |
55 | - public static boolean delete(final File originalFile) throws IOException { | |
56 | - String key = originalFile.getCanonicalPath(); | |
57 | - IPreview deleted = previews.remove(key); | |
58 | - if (previews.isEmpty()) | |
59 | - unhookProjectChangeEvent(); | |
60 | - return (deleted != null); | |
61 | - } | |
62 | - | |
63 | - public static void init() { | |
64 | - // force executing static initializer | |
65 | - } | |
66 | - | |
67 | - public static boolean open(File file) throws IOException { | |
68 | - // not available for directory | |
69 | - if (! file.isFile()) | |
70 | - return false; | |
71 | - | |
72 | - // does file exists inside of the target folder? | |
73 | - if (! isUnderTargetFolder(file)) | |
74 | - return false; | |
75 | - | |
76 | - // file type or environment is not supported | |
77 | - if (! available(file)) | |
78 | - return false; | |
79 | - | |
80 | - // Preview instance is already there? | |
81 | - String key = file.getCanonicalPath(); | |
82 | - if (previews.containsKey(key)) { | |
83 | - previews.get(key).activate(); | |
84 | - return true; | |
85 | - } | |
86 | - | |
87 | - // open it | |
88 | - IPreview p = new WordPreview(file); | |
89 | - p.open(); | |
90 | - hookProjectChangeEvent(); | |
91 | - hookApplicationChangeEvent(); | |
92 | - previews.put(key, p); | |
93 | - | |
94 | - // add temp files to cleaner list | |
95 | - TempFileCleaner.addToList(p.getTempFiles()); | |
96 | - | |
97 | - return true; | |
98 | - } | |
99 | - | |
100 | - public static int size(Class<?> classObj) { | |
101 | - if (classObj == null) { | |
102 | - return previews.size(); | |
103 | - } else { | |
104 | - int i = 0; | |
105 | - for (Object o: previews.values()) { | |
106 | - if (classObj.isInstance(o)) | |
107 | - i++; | |
108 | - } | |
109 | - return i; | |
110 | - } | |
111 | - } | |
112 | - | |
113 | - private static boolean available(File file) { | |
114 | - return WordPreview.isAvailable(file); | |
115 | - } | |
116 | - | |
117 | - /** hook project change event */ | |
118 | - private static void hookProjectChangeEvent() { | |
119 | - if (projectEventListener != null) | |
120 | - return; | |
121 | - | |
122 | - projectEventListener= new IProjectEventListener() { | |
123 | - | |
124 | - @Override | |
125 | - public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
126 | - switch (eventType) { | |
127 | - case CLOSE: | |
128 | - onProjectClose(); | |
129 | - break; | |
130 | - case COMPILE: | |
131 | - onProjectCompile(); | |
132 | - break; | |
133 | - } | |
134 | - } | |
135 | - | |
136 | - }; | |
137 | - | |
138 | - CoreEvents.registerProjectChangeListener(projectEventListener); | |
139 | - } | |
140 | - | |
141 | - /** unhook project change event */ | |
142 | - private static void unhookProjectChangeEvent() { | |
143 | - if (projectEventListener == null) | |
144 | - return; | |
145 | - | |
146 | - CoreEvents.unregisterProjectChangeListener(projectEventListener); | |
147 | - projectEventListener= null; | |
148 | - } | |
149 | - | |
150 | - /** hook application change event */ | |
151 | - private static void hookApplicationChangeEvent() { | |
152 | - if (applicationEventListener != null) | |
153 | - return; | |
154 | - | |
155 | - applicationEventListener= new IApplicationEventListener() { | |
156 | - | |
157 | - @Override | |
158 | - public void onApplicationStartup() { | |
159 | - /* do nothing */ | |
160 | - } | |
161 | - | |
162 | - @Override | |
163 | - public void onApplicationShutdown() { | |
164 | - closeAllPreviews(); | |
165 | - } | |
166 | - | |
167 | - }; | |
168 | - | |
169 | - CoreEvents.registerApplicationEventListener(applicationEventListener); | |
170 | - } | |
171 | - | |
172 | - /** unhook project change event */ | |
173 | - private static void unhookApplicationChangeEvent() { | |
174 | - if (applicationEventListener == null) | |
175 | - return; | |
176 | - | |
177 | - CoreEvents.unregisterApplicationEventListener(applicationEventListener); | |
178 | - applicationEventListener= null; | |
179 | - } | |
180 | - | |
181 | - private static void onProjectClose() { | |
182 | - closeAllPreviews(); | |
183 | - | |
184 | - // イベントリスナーの登録解除をここで発行するとスレッドエラーになるので | |
185 | - // 後で実行する。 | |
186 | - SwingUtilities.invokeLater(new Runnable() { | |
187 | - @Override | |
188 | - public void run() { | |
189 | - unhookProjectChangeEvent(); | |
190 | - unhookApplicationChangeEvent(); | |
191 | - } | |
192 | - }); | |
193 | - } | |
194 | - | |
195 | - private static void onProjectCompile() { | |
196 | - reloadAllPreviews(); | |
197 | - } | |
198 | - | |
199 | - private static boolean isUnderTargetFolder(final File file) throws IOException { | |
200 | - // does file exists inside of the target folder? | |
201 | - String targetRoot = Core.getProject().getProjectProperties().getTargetRoot(); | |
202 | - return file.getCanonicalPath().startsWith(targetRoot); | |
203 | - } | |
204 | - | |
205 | - private static void closeAllPreviews() { | |
206 | - if (! previews.isEmpty()) { | |
207 | - for (IPreview preview: previews.values()) { | |
208 | - preview.close(); | |
209 | - } | |
210 | - } | |
211 | - } | |
212 | - | |
213 | - private static void reloadAllPreviews() { | |
214 | - if (! previews.isEmpty()) { | |
215 | - for (IPreview preview: previews.values()) { | |
216 | - preview.reload(); | |
217 | - } | |
218 | - } | |
219 | - } | |
220 | - | |
221 | -} |
@@ -1,41 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu.filepreview; | |
18 | - | |
19 | -import java.io.File; | |
20 | - | |
21 | -/** | |
22 | - * | |
23 | - * @author Yu-Tang | |
24 | - */ | |
25 | -public interface IPreview { | |
26 | - | |
27 | - /** activate preview window */ | |
28 | - public void activate(); | |
29 | - | |
30 | - /** get temporary files for preview */ | |
31 | - public String[] getTempFiles(); | |
32 | - | |
33 | - /** open preview window */ | |
34 | - public void open(); | |
35 | - | |
36 | - /** close preview window */ | |
37 | - public void close(); | |
38 | - | |
39 | - /** reload document */ | |
40 | - public void reload(); | |
41 | - } |
@@ -1,36 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import javax.swing.JOptionPane; | |
20 | - | |
21 | -/** | |
22 | - * | |
23 | - * @author Yu-Tang | |
24 | - */ | |
25 | -public class VersionInfo { | |
26 | - | |
27 | - private static final String APP_NAME = "FolderMenu"; | |
28 | - private static final String APP_VERSION = "0.3"; | |
29 | - private static final String APP_BUILD = "20131024"; | |
30 | - private static final String APP_AUTHOR = "Yu-Tang"; | |
31 | - | |
32 | - public static void main(String[] args) { | |
33 | - JOptionPane.showMessageDialog(null, | |
34 | - APP_NAME + " ver." + APP_VERSION + "." + APP_BUILD + "\nby " + APP_AUTHOR); | |
35 | - } | |
36 | -} |
@@ -1,226 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import java.awt.Component; | |
20 | -import java.awt.event.ActionEvent; | |
21 | -import java.awt.event.ActionListener; | |
22 | -import java.awt.event.KeyEvent; | |
23 | -import java.awt.event.MouseEvent; | |
24 | -import java.awt.event.MouseListener; | |
25 | -import java.io.File; | |
26 | -import java.io.FileFilter; | |
27 | -import java.util.Comparator; | |
28 | -import javax.swing.Icon; | |
29 | -import javax.swing.JMenu; | |
30 | -import javax.swing.JMenuItem; | |
31 | -import javax.swing.MenuElement; | |
32 | -import javax.swing.MenuSelectionManager; | |
33 | -import javax.swing.event.MenuEvent; | |
34 | -import javax.swing.event.MenuKeyEvent; | |
35 | -import javax.swing.event.MenuKeyListener; | |
36 | -import javax.swing.event.MenuListener; | |
37 | -import javax.swing.filechooser.FileSystemView; | |
38 | - | |
39 | -/** | |
40 | - * | |
41 | - * @author Yu-Tang | |
42 | - */ | |
43 | -public class MenuHelper { | |
44 | - | |
45 | - static { | |
46 | - fs = FileSystemView.getFileSystemView(); | |
47 | - ff = new FileFilter() { | |
48 | - | |
49 | - @Override | |
50 | - public boolean accept(File file) { | |
51 | - // except dot started named files (i.e. ".svn") and hidden files | |
52 | - return !file.getName().startsWith(".") && !file.isHidden(); | |
53 | - } | |
54 | - | |
55 | - }; | |
56 | - | |
57 | - al = new ActionListener() { | |
58 | - | |
59 | - @Override | |
60 | - public void actionPerformed(ActionEvent e) { $(e).open(); } | |
61 | - | |
62 | - }; | |
63 | - | |
64 | - mkl = new MenuKeyListener() { | |
65 | - | |
66 | - @Override | |
67 | - public void menuKeyTyped(MenuKeyEvent e) { /* do nothing */ } | |
68 | - | |
69 | - @Override | |
70 | - public void menuKeyPressed(MenuKeyEvent e) { | |
71 | - if (e.getKeyCode() == KeyEvent.VK_ENTER) { | |
72 | - MenuSelectionManager manager = e.getMenuSelectionManager(); | |
73 | - MenuElement[] selectedPath = manager.getSelectedPath(); | |
74 | - MenuElement selection = selectedPath[selectedPath.length-1]; | |
75 | - if (selection instanceof JMenu) { | |
76 | - JMenu menu = (JMenu) selection; | |
77 | - if (menu.isEnabled()) { | |
78 | - manager.clearSelectedPath(); | |
79 | - $(menu).open(); | |
80 | - } | |
81 | - } | |
82 | - } | |
83 | - } | |
84 | - | |
85 | - @Override | |
86 | - public void menuKeyReleased(MenuKeyEvent e) { /* do nothing */ } | |
87 | - | |
88 | - }; | |
89 | - | |
90 | - mol = new MouseListener() { | |
91 | - | |
92 | - @Override | |
93 | - public void mouseClicked(MouseEvent e) { $(e).open(); } | |
94 | - | |
95 | - @Override | |
96 | - public void mousePressed(MouseEvent e) { /* do nothing */ } | |
97 | - | |
98 | - @Override | |
99 | - public void mouseReleased(MouseEvent e) { /* do nothing */ } | |
100 | - | |
101 | - @Override | |
102 | - public void mouseEntered(MouseEvent e) { /* do nothing */ } | |
103 | - | |
104 | - @Override | |
105 | - public void mouseExited(MouseEvent e) { /* do nothing */ } | |
106 | - | |
107 | - }; | |
108 | - | |
109 | - mel = new MenuListener() { | |
110 | - | |
111 | - @Override | |
112 | - public void menuSelected(MenuEvent e) { | |
113 | - // Lazy create submenus | |
114 | - $(e).createChildren(); | |
115 | - } | |
116 | - | |
117 | - @Override | |
118 | - public void menuDeselected(MenuEvent e) { /* do nothing */ } | |
119 | - | |
120 | - @Override | |
121 | - public void menuCanceled(MenuEvent e) { /* do nothing */ } | |
122 | - | |
123 | - }; | |
124 | - | |
125 | - /* for Folders root menu only */ | |
126 | - melRoot = new MenuListener() { | |
127 | - | |
128 | - @Override | |
129 | - public void menuSelected(MenuEvent e) { /* do nothing */ } | |
130 | - | |
131 | - @Override | |
132 | - public void menuDeselected(MenuEvent e) { | |
133 | - // remove children's all menuitems | |
134 | - JMenu menu = (JMenu) e.getSource(); | |
135 | - for (Component c: menu.getMenuComponents()) { | |
136 | - if (c instanceof JMenu) { | |
137 | - JMenu m = (JMenu) c; | |
138 | - if (m.isEnabled()) | |
139 | - m.removeAll(); | |
140 | - } | |
141 | - } | |
142 | - } | |
143 | - | |
144 | - @Override | |
145 | - public void menuCanceled(MenuEvent e) { /* do nothing */ } | |
146 | - | |
147 | - }; | |
148 | - | |
149 | - comp = new Comparator<File>() { | |
150 | - | |
151 | - @Override | |
152 | - public int compare(File f1, File f2) { | |
153 | - if (f1.isFile() == f2.isFile()) { | |
154 | - return f1.getName().compareToIgnoreCase(f2.getName()); | |
155 | - } else { | |
156 | - return f1.isFile() ? 1 : -1; | |
157 | - } | |
158 | - } | |
159 | - | |
160 | - }; | |
161 | - } | |
162 | - | |
163 | - private MenuHelper() {} // no instanciation, static only. | |
164 | - | |
165 | - public static Icon getIcon(File file) { | |
166 | - return fs.getSystemIcon(file); | |
167 | - } | |
168 | - | |
169 | - public static File[] getFilteredListFiles(File folder) { | |
170 | - return folder.listFiles(ff); | |
171 | - } | |
172 | - | |
173 | - public static ActionListener getActionListener() { | |
174 | - return al; | |
175 | - } | |
176 | - | |
177 | - public static MenuKeyListener getMenuKeyListener() { | |
178 | - return mkl; | |
179 | - } | |
180 | - | |
181 | - public static MouseListener getMouseListener() { | |
182 | - return mol; | |
183 | - } | |
184 | - | |
185 | - public static MenuListener getMenuListener() { | |
186 | - return mel; | |
187 | - } | |
188 | - | |
189 | - public static MenuListener getRootMenuListener() { | |
190 | - return melRoot; | |
191 | - } | |
192 | - | |
193 | - public static Comparator<File> getComparator() { | |
194 | - return comp; | |
195 | - } | |
196 | - | |
197 | - private static ShellLinkMenuItem $(JMenuItem mi) { | |
198 | - return new ShellLinkMenuItem(mi); | |
199 | - } | |
200 | - | |
201 | - private static ShellLinkMenu $(JMenu m) { | |
202 | - return new ShellLinkMenu(m); | |
203 | - } | |
204 | - | |
205 | - private static ShellLinkMenuItem $(ActionEvent e) { | |
206 | - return new ShellLinkMenuItem((JMenuItem) e.getSource()); | |
207 | - } | |
208 | - | |
209 | - private static ShellLinkMenu $(MouseEvent e) { | |
210 | - return new ShellLinkMenu((JMenu) e.getSource()); | |
211 | - } | |
212 | - | |
213 | - private static ShellLinkMenu $(MenuEvent e) { | |
214 | - return new ShellLinkMenu((JMenu) e.getSource()); | |
215 | - } | |
216 | - | |
217 | - private static final FileSystemView fs; | |
218 | - private static final FileFilter ff; | |
219 | - private static final ActionListener al; | |
220 | - private static final MenuKeyListener mkl; | |
221 | - private static final MouseListener mol; | |
222 | - private static final MenuListener mel; | |
223 | - private static final MenuListener melRoot; | |
224 | - private static final Comparator<File> comp; | |
225 | - | |
226 | -} |
@@ -1,94 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import java.awt.Desktop; | |
20 | -import java.io.File; | |
21 | -import java.io.IOException; | |
22 | -import javax.swing.JMenuItem; | |
23 | -import org.omegat.core.Core; | |
24 | -import static org.omegat.plugin.foldermenu.MenuHelper.getActionListener; | |
25 | -import static org.omegat.plugin.foldermenu.MenuHelper.getIcon; | |
26 | -import org.omegat.plugin.foldermenu.filepreview.FilePreview; | |
27 | -import org.omegat.util.Log; | |
28 | -import static org.omegat.util.Platform.OsType.MAC32; | |
29 | -import static org.omegat.util.Platform.OsType.MAC64; | |
30 | -import static org.omegat.util.Platform.OsType.WIN32; | |
31 | -import static org.omegat.util.Platform.OsType.WIN64; | |
32 | -import static org.omegat.util.Platform.getOsType; | |
33 | -import org.omegat.util.StaticUtils; | |
34 | - | |
35 | -/** | |
36 | - * | |
37 | - * @author Yu-Tang | |
38 | - */ | |
39 | -public class ShellLinkMenuItem { | |
40 | - | |
41 | - protected JMenuItem menuItem; | |
42 | - | |
43 | - public ShellLinkMenuItem() { | |
44 | - menuItem = new JMenuItem(); | |
45 | - } | |
46 | - | |
47 | - public ShellLinkMenuItem(JMenuItem mi) { | |
48 | - menuItem = mi; | |
49 | - } | |
50 | - | |
51 | - public ShellLinkMenuItem(File file) throws IOException { | |
52 | - JMenuItem m = new JMenuItem(file.getName(), getIcon(file)); | |
53 | - m.setActionCommand(file.getCanonicalPath()); | |
54 | - m.addActionListener(getActionListener()); | |
55 | - menuItem = m; | |
56 | - } | |
57 | - | |
58 | - public boolean isEnabled() { | |
59 | - return menuItem.isEnabled(); | |
60 | - } | |
61 | - | |
62 | - public JMenuItem getMenuItem() { | |
63 | - return menuItem; | |
64 | - } | |
65 | - | |
66 | - public void open() { | |
67 | - if (! menuItem.isEnabled()) | |
68 | - return; | |
69 | - | |
70 | - String path = menuItem.getActionCommand(); | |
71 | - try { | |
72 | - switch (getOsType()) { | |
73 | - case WIN64: | |
74 | - case WIN32: | |
75 | - File file = new File(path); | |
76 | - if (! FilePreview.open(file)) { | |
77 | - Desktop.getDesktop().open(file); | |
78 | - } | |
79 | - break; | |
80 | - case MAC64: | |
81 | - case MAC32: | |
82 | - new ProcessBuilder("open", path).start(); | |
83 | - break; | |
84 | - default: // Linux and others | |
85 | - new ProcessBuilder("xdg-open", path).start(); | |
86 | - break; | |
87 | - } | |
88 | - } catch (IOException ex) { | |
89 | - Log.log(ex); | |
90 | - Core.getMainWindow().showMessageDialog(StaticUtils.format( | |
91 | - L10n.getErrMsgFileHasNoAssoc(), path)); | |
92 | - } | |
93 | - } | |
94 | -} |
@@ -1,59 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import java.util.ResourceBundle; | |
20 | - | |
21 | -/** | |
22 | - * | |
23 | - * @author Yu-Tang | |
24 | - */ | |
25 | -public class L10n { | |
26 | - | |
27 | - private static final ResourceBundle bundle; | |
28 | - | |
29 | - static { | |
30 | - bundle = ResourceBundle.getBundle("org/omegat/plugin/foldermenu/Bundle"); | |
31 | - } | |
32 | - | |
33 | - // for menu | |
34 | - | |
35 | - public static String getFoldersMenuLabel() { | |
36 | - return bundle.getString("FOLDERS_MENU_LABEL"); | |
37 | - } | |
38 | - | |
39 | - public static String getProjectRootMenuLabel() { | |
40 | - return bundle.getString("PROJECT_ROOT_MENU_LABEL"); | |
41 | - } | |
42 | - | |
43 | - public static String getUserConfigMenuLabel() { | |
44 | - return bundle.getString("USER_CONFIG_MENU_LABEL"); | |
45 | - } | |
46 | - | |
47 | - // for Word | |
48 | - | |
49 | - public static String getWordWindowCaption() { | |
50 | - return bundle.getString("WORD_WINDOW_CAPTION"); | |
51 | - } | |
52 | - | |
53 | - // for error | |
54 | - | |
55 | - public static String getErrMsgFileHasNoAssoc() { | |
56 | - return bundle.getString("ERROR_FILE_HAS_NO_ASSOC"); | |
57 | - } | |
58 | - | |
59 | -} |
@@ -1,114 +0,0 @@ | ||
1 | -/************************************************************************** | |
2 | - FolderMenu - easy access to project folders from menu. | |
3 | - | |
4 | - Copyright (C) 2013 Yu Tang | |
5 | - Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | - Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | - | |
8 | - This file is part of plugin for OmegaT. | |
9 | - http://www.omegat.org/ | |
10 | - | |
11 | - License: GNU GPL version 3 or (at your option) any later version. | |
12 | - | |
13 | - You should have received a copy of the GNU General Public License | |
14 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | - **************************************************************************/ | |
16 | - | |
17 | -package org.omegat.plugin.foldermenu; | |
18 | - | |
19 | -import java.io.File; | |
20 | -import java.io.IOException; | |
21 | -import java.util.Arrays; | |
22 | -import javax.swing.JMenu; | |
23 | -import static org.omegat.plugin.foldermenu.MenuHelper.getComparator; | |
24 | -import static org.omegat.plugin.foldermenu.MenuHelper.getFilteredListFiles; | |
25 | -import static org.omegat.plugin.foldermenu.MenuHelper.getIcon; | |
26 | -import static org.omegat.plugin.foldermenu.MenuHelper.getMenuListener; | |
27 | -import static org.omegat.plugin.foldermenu.MenuHelper.getMouseListener; | |
28 | -import org.omegat.util.Log; | |
29 | -import org.openide.awt.Mnemonics; | |
30 | - | |
31 | -/** | |
32 | - * | |
33 | - * @author Yu-Tang | |
34 | - */ | |
35 | -public class ShellLinkMenu extends ShellLinkMenuItem { | |
36 | - | |
37 | - public ShellLinkMenu(JMenu m) { | |
38 | - super(m); | |
39 | - } | |
40 | - | |
41 | - public ShellLinkMenu(File folder) throws IOException { | |
42 | - this(folder, null); | |
43 | - } | |
44 | - | |
45 | - public ShellLinkMenu(String label) throws IOException { | |
46 | - this(null, label); | |
47 | - } | |
48 | - | |
49 | - public ShellLinkMenu(File folder, String label) throws IOException { | |
50 | - JMenu m; | |
51 | - if (label == null) { | |
52 | - m = new JMenu(folder.getName()); | |
53 | - } else { | |
54 | - m = new JMenu(); | |
55 | - Mnemonics.setLocalizedText(m, label); | |
56 | - } | |
57 | - | |
58 | - m.addMenuListener(getMenuListener()); | |
59 | - m.addMouseListener(getMouseListener()); | |
60 | - | |
61 | - if (folder != null) { | |
62 | - m.setIcon(getIcon(folder)); | |
63 | - m.setActionCommand(folder.getCanonicalPath()); | |
64 | - } else { | |
65 | - m.setEnabled(false); | |
66 | - } | |
67 | - | |
68 | - menuItem = m; | |
69 | - } | |
70 | - | |
71 | - public void createChildren() { | |
72 | - JMenu menu = (JMenu) menuItem; | |
73 | - if (menu.isEnabled() && menu.getItemCount() == 0) { | |
74 | - File folder = new File(menu.getActionCommand()); | |
75 | - File[] filteredListFiles = getFilteredListFiles(folder); | |
76 | - Arrays.sort(filteredListFiles, getComparator()); | |
77 | - | |
78 | - for (File file : filteredListFiles) { | |
79 | - try { | |
80 | - if (file.isDirectory() && hasChildren(file)) { | |
81 | - menu.add(new ShellLinkMenu(file).getMenuItem()); | |
82 | - } else { | |
83 | - menu.add(new ShellLinkMenuItem(file).getMenuItem()); | |
84 | - } | |
85 | - } catch (IOException ex) { | |
86 | - Log.log(ex); | |
87 | - } | |
88 | - } | |
89 | - } | |
90 | - } | |
91 | - | |
92 | - public JMenu getMenu() { | |
93 | - return (JMenu) menuItem; | |
94 | - } | |
95 | - | |
96 | - public void link(File folder) throws IOException { | |
97 | - JMenu menu = (JMenu) menuItem; | |
98 | - menu.setActionCommand(folder.getCanonicalPath()); | |
99 | - menu.setIcon(getIcon(folder)); | |
100 | - menu.setEnabled(true); | |
101 | - } | |
102 | - | |
103 | - public void unlink() { | |
104 | - JMenu menu = (JMenu) menuItem; | |
105 | - menu.setEnabled(false); | |
106 | - menu.removeAll(); | |
107 | - menu.setActionCommand(""); | |
108 | - menu.setIcon(null); | |
109 | - } | |
110 | - | |
111 | - private boolean hasChildren(File folder) { | |
112 | - return getFilteredListFiles(folder).length > 0; | |
113 | - } | |
114 | -} |
@@ -0,0 +1,82 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import javax.swing.JMenu; | |
22 | +import javax.swing.JMenuBar; | |
23 | +import org.omegat.core.Core; | |
24 | +import org.omegat.util.Log; | |
25 | +import org.omegat.util.StaticUtils; | |
26 | +import org.openide.awt.Mnemonics; | |
27 | + | |
28 | +/** | |
29 | + * | |
30 | + * @author Yu-Tang | |
31 | + */ | |
32 | +public class MenuManager { | |
33 | + | |
34 | + private JMenu root; | |
35 | + private JMenu currentProject; | |
36 | + private JMenu userConfig; | |
37 | + | |
38 | + public MenuManager() { | |
39 | + root = createLocalizedMenu(L10n.getFoldersMenuLabel()); // Folders menu | |
40 | + root.addMenuKeyListener(MenuHelper.getMenuKeyListener()); // for opening folder with enter key | |
41 | + root.addMenuListener(MenuHelper.getRootMenuListener()); | |
42 | + | |
43 | + // ProjectRoot | |
44 | + try { | |
45 | + root.add(currentProject = new ShellLinkMenu(L10n.getProjectRootMenuLabel()).getMenu()); | |
46 | + } catch (IOException ex) { | |
47 | + Log.log(ex); | |
48 | + return; | |
49 | + } | |
50 | + | |
51 | + // User Config | |
52 | + try { | |
53 | + File confDir = new File(StaticUtils.getConfigDir()); | |
54 | + root.add(userConfig = new ShellLinkMenu(confDir, L10n.getUserConfigMenuLabel()).getMenu()); | |
55 | + } catch (IOException ex) { | |
56 | + Log.log(ex); | |
57 | + } | |
58 | + | |
59 | + // insert Files menu before the last menu (Help menu.) | |
60 | + JMenuBar mainMenuBar = (JMenuBar) Core.getMainWindow().getMainMenu().getOptionsMenu().getParent(); | |
61 | + mainMenuBar.add(root, mainMenuBar.getMenuCount() - 1); | |
62 | + } | |
63 | + | |
64 | + public void createProjectItems() { | |
65 | + File rootDir = new File(Core.getProject().getProjectProperties().getProjectRoot()); | |
66 | + try { | |
67 | + new ShellLinkMenu(currentProject).link(rootDir); | |
68 | + } catch (IOException ex) { | |
69 | + Log.log(ex); | |
70 | + } | |
71 | + } | |
72 | + | |
73 | + public void removeAllProjectItems() { | |
74 | + new ShellLinkMenu(currentProject).unlink(); | |
75 | + } | |
76 | + | |
77 | + private JMenu createLocalizedMenu(String labelString) { | |
78 | + JMenu m = new JMenu(); | |
79 | + Mnemonics.setLocalizedText(m, labelString); | |
80 | + return m; | |
81 | + } | |
82 | +} | |
\ No newline at end of file |
@@ -0,0 +1,62 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import org.omegat.core.CoreEvents; | |
20 | +import org.omegat.core.events.IApplicationEventListener; | |
21 | +import org.omegat.core.events.IProjectEventListener; | |
22 | +import org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.*; | |
23 | +import jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview.FilePreview; | |
24 | + | |
25 | +/** | |
26 | + * easy access to project folders from menu | |
27 | + * | |
28 | + * @author Yu Tang | |
29 | + */ | |
30 | +public class FolderMenu implements IApplicationEventListener, IProjectEventListener { | |
31 | + | |
32 | + private MenuManager menuManager; | |
33 | + | |
34 | + @SuppressWarnings("LeakingThisInConstructor") | |
35 | + public FolderMenu() { | |
36 | + CoreEvents.registerApplicationEventListener(this); | |
37 | + CoreEvents.registerProjectChangeListener(this); | |
38 | + } | |
39 | + | |
40 | + @Override | |
41 | + public void onApplicationStartup() { | |
42 | + menuManager = new MenuManager(); | |
43 | + FilePreview.init(); | |
44 | + } | |
45 | + | |
46 | + @Override | |
47 | + public void onApplicationShutdown() { /* do nothing */ } | |
48 | + | |
49 | + @Override | |
50 | + public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
51 | + switch (eventType) { | |
52 | + case CREATE: | |
53 | + case LOAD: | |
54 | + menuManager.createProjectItems(); | |
55 | + break; | |
56 | + case CLOSE: | |
57 | + menuManager.removeAllProjectItems(); | |
58 | + break; | |
59 | + } | |
60 | + } | |
61 | + | |
62 | +} | |
\ No newline at end of file |
@@ -0,0 +1,36 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import javax.swing.JOptionPane; | |
20 | + | |
21 | +/** | |
22 | + * | |
23 | + * @author Yu-Tang | |
24 | + */ | |
25 | +public class VersionInfo { | |
26 | + | |
27 | + private static final String APP_NAME = "FolderMenu"; | |
28 | + private static final String APP_VERSION = "0.3"; | |
29 | + private static final String APP_BUILD = "20131024"; | |
30 | + private static final String APP_AUTHOR = "Yu-Tang"; | |
31 | + | |
32 | + public static void main(String[] args) { | |
33 | + JOptionPane.showMessageDialog(null, | |
34 | + APP_NAME + " ver." + APP_VERSION + "." + APP_BUILD + "\nby " + APP_AUTHOR); | |
35 | + } | |
36 | +} |
@@ -0,0 +1,102 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import org.omegat.util.FileUtil; | |
22 | +import org.omegat.util.Log; | |
23 | +import org.omegat.util.StaticUtils; | |
24 | + | |
25 | +/** | |
26 | + * Cleanup temp files | |
27 | + * | |
28 | + * @author Yu-Tang | |
29 | + */ | |
30 | +public class TempFileCleaner { | |
31 | + | |
32 | + private static final String LOG_FILE_NAME = "FilePreviewTempFiles.log"; | |
33 | + private static final File logFile; | |
34 | + | |
35 | + private TempFileCleaner() { /* not allow instanciation. static only. */ } | |
36 | + | |
37 | + static { | |
38 | + logFile = new File(StaticUtils.getConfigDir(), LOG_FILE_NAME); | |
39 | + } | |
40 | + | |
41 | + public static void cleanup() { | |
42 | + // load temp file list from log file | |
43 | + String[] list = readTempFileList().split("\\n"); | |
44 | + String content = ""; | |
45 | + | |
46 | + // try to delete them | |
47 | + for (String path: list) { | |
48 | + if (! path.isEmpty()) { | |
49 | + File f = new File(path); | |
50 | + if (f.isFile()) { | |
51 | + if (! f.delete()) { | |
52 | + f.deleteOnExit(); | |
53 | + content += path + "\n"; | |
54 | + } | |
55 | + } | |
56 | + } | |
57 | + } | |
58 | + | |
59 | + // save back to log file or delete log if empty | |
60 | + writeTempFileList(content); | |
61 | + } | |
62 | + | |
63 | + public static void addToList(String[] filePaths) { | |
64 | + // load temp file list from log file | |
65 | + String list = readTempFileList(); | |
66 | + | |
67 | + // add the file to the list | |
68 | + for (String path: filePaths) | |
69 | + list += path + "\n"; | |
70 | + | |
71 | + // save back to log file or delete log if empty | |
72 | + writeTempFileList(list); | |
73 | + } | |
74 | + | |
75 | + // 末尾改行付きのリストを返します。 | |
76 | + private static String readTempFileList() { | |
77 | + String ret = ""; | |
78 | + if (logFile.isFile()) { | |
79 | + try { | |
80 | + ret = FileUtil.readTextFile(logFile); | |
81 | + if (!ret.isEmpty() && !ret.endsWith("\n")) | |
82 | + ret += "\n"; | |
83 | + } catch (IOException ex) { | |
84 | + Log.log(ex); | |
85 | + } | |
86 | + } | |
87 | + return ret; | |
88 | + } | |
89 | + | |
90 | + private static void writeTempFileList(final String content) { | |
91 | + if (content.isEmpty()) { | |
92 | + if (logFile.isFile()) | |
93 | + logFile.delete(); | |
94 | + } else { | |
95 | + try { | |
96 | + FileUtil.writeTextFile(logFile, content); | |
97 | + } catch (IOException ex) { | |
98 | + Log.log(ex); | |
99 | + } | |
100 | + } | |
101 | + } | |
102 | +} |
@@ -0,0 +1,221 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import java.util.HashMap; | |
22 | +import javax.swing.SwingUtilities; | |
23 | +import org.omegat.core.Core; | |
24 | +import org.omegat.core.CoreEvents; | |
25 | +import org.omegat.core.events.IApplicationEventListener; | |
26 | +import org.omegat.core.events.IProjectEventListener; | |
27 | +import org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE; | |
28 | +import static org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.CLOSE; | |
29 | +import static org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE.COMPILE; | |
30 | + | |
31 | +/** | |
32 | + * must call init() before using this class. | |
33 | + * | |
34 | + * @author Yu-Tang | |
35 | + */ | |
36 | + | |
37 | +public class FilePreview { | |
38 | + | |
39 | + // key = target file's canonical path | |
40 | + private static final HashMap<String, IPreview> previews = new HashMap<String, IPreview>(); | |
41 | + | |
42 | + private static IProjectEventListener projectEventListener = null; | |
43 | + private static IApplicationEventListener applicationEventListener = null; | |
44 | + | |
45 | + static { | |
46 | + // cleanup left temp files if they exists | |
47 | + TempFileCleaner.cleanup(); | |
48 | + | |
49 | + // call each Preview#init() | |
50 | + WordPreview.init(); | |
51 | + | |
52 | + //@@TODO WSF reload 時にselectionがテキストボックスの場合、restore に失敗するバグ | |
53 | + } | |
54 | + | |
55 | + public static boolean delete(final File originalFile) throws IOException { | |
56 | + String key = originalFile.getCanonicalPath(); | |
57 | + IPreview deleted = previews.remove(key); | |
58 | + if (previews.isEmpty()) | |
59 | + unhookProjectChangeEvent(); | |
60 | + return (deleted != null); | |
61 | + } | |
62 | + | |
63 | + public static void init() { | |
64 | + // force executing static initializer | |
65 | + } | |
66 | + | |
67 | + public static boolean open(File file) throws IOException { | |
68 | + // not available for directory | |
69 | + if (! file.isFile()) | |
70 | + return false; | |
71 | + | |
72 | + // does file exists inside of the target folder? | |
73 | + if (! isUnderTargetFolder(file)) | |
74 | + return false; | |
75 | + | |
76 | + // file type or environment is not supported | |
77 | + if (! available(file)) | |
78 | + return false; | |
79 | + | |
80 | + // Preview instance is already there? | |
81 | + String key = file.getCanonicalPath(); | |
82 | + if (previews.containsKey(key)) { | |
83 | + previews.get(key).activate(); | |
84 | + return true; | |
85 | + } | |
86 | + | |
87 | + // open it | |
88 | + IPreview p = new WordPreview(file); | |
89 | + p.open(); | |
90 | + hookProjectChangeEvent(); | |
91 | + hookApplicationChangeEvent(); | |
92 | + previews.put(key, p); | |
93 | + | |
94 | + // add temp files to cleaner list | |
95 | + TempFileCleaner.addToList(p.getTempFiles()); | |
96 | + | |
97 | + return true; | |
98 | + } | |
99 | + | |
100 | + public static int size(Class<?> classObj) { | |
101 | + if (classObj == null) { | |
102 | + return previews.size(); | |
103 | + } else { | |
104 | + int i = 0; | |
105 | + for (Object o: previews.values()) { | |
106 | + if (classObj.isInstance(o)) | |
107 | + i++; | |
108 | + } | |
109 | + return i; | |
110 | + } | |
111 | + } | |
112 | + | |
113 | + private static boolean available(File file) { | |
114 | + return WordPreview.isAvailable(file); | |
115 | + } | |
116 | + | |
117 | + /** hook project change event */ | |
118 | + private static void hookProjectChangeEvent() { | |
119 | + if (projectEventListener != null) | |
120 | + return; | |
121 | + | |
122 | + projectEventListener= new IProjectEventListener() { | |
123 | + | |
124 | + @Override | |
125 | + public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
126 | + switch (eventType) { | |
127 | + case CLOSE: | |
128 | + onProjectClose(); | |
129 | + break; | |
130 | + case COMPILE: | |
131 | + onProjectCompile(); | |
132 | + break; | |
133 | + } | |
134 | + } | |
135 | + | |
136 | + }; | |
137 | + | |
138 | + CoreEvents.registerProjectChangeListener(projectEventListener); | |
139 | + } | |
140 | + | |
141 | + /** unhook project change event */ | |
142 | + private static void unhookProjectChangeEvent() { | |
143 | + if (projectEventListener == null) | |
144 | + return; | |
145 | + | |
146 | + CoreEvents.unregisterProjectChangeListener(projectEventListener); | |
147 | + projectEventListener= null; | |
148 | + } | |
149 | + | |
150 | + /** hook application change event */ | |
151 | + private static void hookApplicationChangeEvent() { | |
152 | + if (applicationEventListener != null) | |
153 | + return; | |
154 | + | |
155 | + applicationEventListener= new IApplicationEventListener() { | |
156 | + | |
157 | + @Override | |
158 | + public void onApplicationStartup() { | |
159 | + /* do nothing */ | |
160 | + } | |
161 | + | |
162 | + @Override | |
163 | + public void onApplicationShutdown() { | |
164 | + closeAllPreviews(); | |
165 | + } | |
166 | + | |
167 | + }; | |
168 | + | |
169 | + CoreEvents.registerApplicationEventListener(applicationEventListener); | |
170 | + } | |
171 | + | |
172 | + /** unhook project change event */ | |
173 | + private static void unhookApplicationChangeEvent() { | |
174 | + if (applicationEventListener == null) | |
175 | + return; | |
176 | + | |
177 | + CoreEvents.unregisterApplicationEventListener(applicationEventListener); | |
178 | + applicationEventListener= null; | |
179 | + } | |
180 | + | |
181 | + private static void onProjectClose() { | |
182 | + closeAllPreviews(); | |
183 | + | |
184 | + // イベントリスナーの登録解除をここで発行するとスレッドエラーになるので | |
185 | + // 後で実行する。 | |
186 | + SwingUtilities.invokeLater(new Runnable() { | |
187 | + @Override | |
188 | + public void run() { | |
189 | + unhookProjectChangeEvent(); | |
190 | + unhookApplicationChangeEvent(); | |
191 | + } | |
192 | + }); | |
193 | + } | |
194 | + | |
195 | + private static void onProjectCompile() { | |
196 | + reloadAllPreviews(); | |
197 | + } | |
198 | + | |
199 | + private static boolean isUnderTargetFolder(final File file) throws IOException { | |
200 | + // does file exists inside of the target folder? | |
201 | + String targetRoot = Core.getProject().getProjectProperties().getTargetRoot(); | |
202 | + return file.getCanonicalPath().startsWith(targetRoot); | |
203 | + } | |
204 | + | |
205 | + private static void closeAllPreviews() { | |
206 | + if (! previews.isEmpty()) { | |
207 | + for (IPreview preview: previews.values()) { | |
208 | + preview.close(); | |
209 | + } | |
210 | + } | |
211 | + } | |
212 | + | |
213 | + private static void reloadAllPreviews() { | |
214 | + if (! previews.isEmpty()) { | |
215 | + for (IPreview preview: previews.values()) { | |
216 | + preview.reload(); | |
217 | + } | |
218 | + } | |
219 | + } | |
220 | + | |
221 | +} |
@@ -0,0 +1,41 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview; | |
18 | + | |
19 | +import java.io.File; | |
20 | + | |
21 | +/** | |
22 | + * | |
23 | + * @author Yu-Tang | |
24 | + */ | |
25 | +public interface IPreview { | |
26 | + | |
27 | + /** activate preview window */ | |
28 | + public void activate(); | |
29 | + | |
30 | + /** get temporary files for preview */ | |
31 | + public String[] getTempFiles(); | |
32 | + | |
33 | + /** open preview window */ | |
34 | + public void open(); | |
35 | + | |
36 | + /** close preview window */ | |
37 | + public void close(); | |
38 | + | |
39 | + /** reload document */ | |
40 | + public void reload(); | |
41 | + } |
@@ -0,0 +1,390 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import java.io.InputStream; | |
22 | +import java.util.ArrayList; | |
23 | +import java.util.Arrays; | |
24 | +import java.util.List; | |
25 | +import jp.sourceforge.users.yutang.omegat.plugin.foldermenu.L10n; | |
26 | +import org.omegat.util.LFileCopy; | |
27 | +import org.omegat.util.Log; | |
28 | +import static org.omegat.util.Platform.OsType.WIN32; | |
29 | +import static org.omegat.util.Platform.OsType.WIN64; | |
30 | +import static org.omegat.util.Platform.getOsType; | |
31 | +import org.omegat.util.StaticUtils; | |
32 | + | |
33 | +/** | |
34 | + * Word 文書をプレビュー用に開きます。 | |
35 | + * | |
36 | + * | |
37 | + * @author Yu-Tang | |
38 | + */ | |
39 | +public class WordPreview implements IPreview { | |
40 | + | |
41 | + private static final String WSF_NAME = "WordPreview.wsf"; | |
42 | + private static boolean _isMSWordAvailable; | |
43 | + private static File _wsf; | |
44 | + | |
45 | + private final File originalFile; | |
46 | + private long originalFileLastModified; // will update at each every time compiling target docs | |
47 | + private final String windowTitle; | |
48 | + private final File temporaryFile; // Primary temp file | |
49 | + private final File temporaryFile2; // Secondary temp file | |
50 | + | |
51 | + public WordPreview(final File originalFile) throws IOException { | |
52 | + this.originalFile = originalFile; | |
53 | + this.originalFileLastModified = originalFile.lastModified(); | |
54 | + this.temporaryFile = getTempFile(originalFile); | |
55 | + this.windowTitle = StaticUtils.format( | |
56 | + L10n.getWordWindowCaption(), | |
57 | + originalFile.getName()); | |
58 | + this.temporaryFile2 = getTempFile2(this.temporaryFile); | |
59 | + } | |
60 | + | |
61 | + static { | |
62 | + // _isMSWordAvailable | |
63 | + switch (getOsType()) { | |
64 | + case WIN64: | |
65 | + case WIN32: | |
66 | + new Thread() { | |
67 | + @Override | |
68 | + public void run() { | |
69 | + _isMSWordAvailable = getMSWordAvailable(); | |
70 | + Log.log("_isMSWordAvailable = " + _isMSWordAvailable); | |
71 | + } | |
72 | + }.start(); | |
73 | + break; | |
74 | + default: // Mac, Linux and others | |
75 | + _isMSWordAvailable = false; | |
76 | + break; | |
77 | + } | |
78 | + | |
79 | + // _wsf | |
80 | + File tempDir = new File(System.getProperty("java.io.tmpdir")); | |
81 | + _wsf = new File(tempDir, WSF_NAME); | |
82 | + } | |
83 | + | |
84 | + public static boolean isAvailable(File file) { | |
85 | + return isAvailable() && | |
86 | + file.isFile() && | |
87 | + file.getName().toLowerCase().endsWith(".docx"); | |
88 | + } | |
89 | + | |
90 | + public static boolean isAvailable() { | |
91 | + return _isMSWordAvailable; | |
92 | + } | |
93 | + | |
94 | + public static void init() { | |
95 | + // force executing static initializer | |
96 | + } | |
97 | + | |
98 | + private static boolean getMSWordAvailable() { | |
99 | + final int RET_OK = 0; | |
100 | + try { | |
101 | + Command command = new Command(); | |
102 | + String s; | |
103 | + if (RET_OK == command.execDOS("assoc", ".docx")) { | |
104 | + s = command.getStdout(); | |
105 | + // s's data example) | |
106 | + // ----------------------------------------------------- | |
107 | + //.docx=Word.Document.12 | |
108 | + //<-(\r\n) | |
109 | + // ----------------------------------------------------- | |
110 | + // 末尾に空行が入るので注意。 | |
111 | + if (s.toLowerCase().startsWith(".docx=word.document.")) { | |
112 | + String classString = s.substring(".docx=".length()).replaceAll("\\r\\n", ""); | |
113 | + if (RET_OK == command.exec("reg", "query", "HKCR\\" + classString + "\\shell\\open\\command", "/ve")) { | |
114 | + s = command.getStdout(); | |
115 | + // s's data example) | |
116 | + // ----------------------------------------------------- | |
117 | + //<-(\r\n) | |
118 | + //HKEY_CLASSES_ROOT\Word.document.12\shell\open\command | |
119 | + //(既定) REG_SZ "C:\PROGRA~2\MICROS~4\OFFICE11\WINWORD.EXE" /n /dde | |
120 | + //<-(\r\n) | |
121 | + // ----------------------------------------------------- | |
122 | + // 前後に空行が入るので注意。 | |
123 | + return s.toUpperCase().indexOf("\\WINWORD.EXE") > -1; | |
124 | + } | |
125 | + } | |
126 | + } | |
127 | + } catch (Exception ex) { | |
128 | + Log.log(ex); | |
129 | + } | |
130 | + return false; | |
131 | + } | |
132 | + | |
133 | + private static File getWSF() throws IOException { | |
134 | + if (! _wsf.exists()) { | |
135 | + InputStream in = WordPreview.class.getResourceAsStream(WSF_NAME); | |
136 | + try { | |
137 | + LFileCopy.copy(in, _wsf); | |
138 | + } finally { | |
139 | + in.close(); | |
140 | + } | |
141 | + _wsf.deleteOnExit(); | |
142 | + } | |
143 | + return _wsf; | |
144 | + } | |
145 | + | |
146 | + @Override | |
147 | + public String[] getTempFiles() { | |
148 | + // ここでは、残留する可能性のある一時ファイルをすべて申告します。 | |
149 | + String[] paths = new String[3]; | |
150 | + try { | |
151 | + paths[0] = this.temporaryFile.getCanonicalPath(); | |
152 | + paths[1] = this.temporaryFile2.getCanonicalPath(); | |
153 | + | |
154 | + // MS Word が作成する(プレビュー用ファイルの)一時ファイルも、強制 | |
155 | + // 終了時などには残留する可能性があるため、ここで申告しておきます。 | |
156 | + final String PREFIX = "~$"; | |
157 | + String parent = this.temporaryFile.getParent(); | |
158 | + String name = this.temporaryFile.getName(); | |
159 | + paths[2] = (new File(parent, PREFIX + name.substring(2))).getCanonicalPath(); | |
160 | + } catch (IOException ex) { | |
161 | + Log.log(ex); | |
162 | + } | |
163 | + return paths; | |
164 | + } | |
165 | + | |
166 | + @Override | |
167 | + public void activate() { | |
168 | + try { | |
169 | + final Command command = new Command(); | |
170 | + final String job = "activate"; | |
171 | + final int ret = command.execWSF(job, this.windowTitle); | |
172 | + } catch (IOException ex) { | |
173 | + Log.log(ex); | |
174 | + } catch (InterruptedException ex) { | |
175 | + Log.log(ex); | |
176 | + } | |
177 | + } | |
178 | + | |
179 | + @Override | |
180 | + public void open() { | |
181 | + | |
182 | + // 以下の処理は少し時間がかかるため、別スレッドに処理を委譲します。 | |
183 | + new Thread() { | |
184 | + @Override | |
185 | + public void run() { | |
186 | + try { | |
187 | + // 起動前にファイルをコピーする。 | |
188 | + // OmegaT は訳文ファイルの作成時に、既存の訳文ファイルを上書きする。 | |
189 | + // そのため、オリジナルのファイルをそのまま開くとファイルがロックされ、 | |
190 | + // 次回のコンパイル時に上書きできずに失敗する。それを避けるために、 | |
191 | + // プレビュー専用の一時ファイルをコピーして、そちらを開く。 | |
192 | + // コピー先は、temp フォルダーではなく、オリジナルと同じフォルダー内に | |
193 | + // コピーする。文書に相対パスで画像リンクなどが張られている場合のリンク | |
194 | + // 切れを防ぐため。 | |
195 | + // そのままコピーすると FolderMenu プラグインのメニュー上で一時ファイル | |
196 | + // が見えてしまうため、hidden 属性を付けておく。 | |
197 | + LFileCopy.copy(originalFile, temporaryFile); | |
198 | + | |
199 | + // make temp file hidden on Windows | |
200 | + addHiddenFileAttribute(temporaryFile); | |
201 | + | |
202 | + // Desktop.getDesktop().open(temp); | |
203 | + // 上記のようにして一時ファイルを開くと、場合によっては Word | |
204 | + // の MRU に一時ファイルを開いた履歴が大量に残ってしまう。 | |
205 | + // これを回避するため、WSH を経由して COM オートメーションで | |
206 | + // 処理する。 | |
207 | + | |
208 | + // open the document | |
209 | + Command command = new Command(); | |
210 | + String document = temporaryFile.getCanonicalPath(); | |
211 | + String document2 = temporaryFile2.getCanonicalPath(); | |
212 | + String job = "open"; | |
213 | + int ret = command.execWSF(job, document, document2, windowTitle); | |
214 | + | |
215 | + if (! command.stderr.isEmpty()) { | |
216 | + Log.log("Word error(" + ret + "): " + command.stderr); | |
217 | + } | |
218 | + onWordApplicationQuit(ret); | |
219 | + } catch (IOException ex) { | |
220 | + Log.log(ex); | |
221 | + } catch (InterruptedException ex) { | |
222 | + Log.log(ex); | |
223 | + } | |
224 | + } | |
225 | + }.start(); | |
226 | + } | |
227 | + | |
228 | + private File getTempFile(final File originalFile) throws IOException { | |
229 | + String prefix = "_WordPreview"; | |
230 | + String name = originalFile.getName(); | |
231 | + String suffix = name.substring(name.lastIndexOf(".")); | |
232 | + File parentFolder = originalFile.getParentFile(); | |
233 | + File tempFile = File.createTempFile(prefix, suffix, parentFolder); | |
234 | + tempFile.deleteOnExit(); | |
235 | + return tempFile; | |
236 | + } | |
237 | + | |
238 | + // foo.ext => foo(2).ext | |
239 | + private File getTempFile2(final File primaryTempFile) throws IOException { | |
240 | + String name = primaryTempFile.getName(); | |
241 | + int lastDotPos = name.lastIndexOf("."); | |
242 | + String baseName = name.substring(0, lastDotPos); | |
243 | + String extension = name.substring(lastDotPos); | |
244 | + String fileName = baseName + "(2)" + extension; | |
245 | + File parentFolder = primaryTempFile.getParentFile(); | |
246 | + File tempFile2 = new File(parentFolder, fileName); | |
247 | + tempFile2.deleteOnExit(); | |
248 | + return tempFile2; | |
249 | + } | |
250 | + | |
251 | + private void addHiddenFileAttribute(File file) { | |
252 | + try { | |
253 | + new ProcessBuilder("attrib","+H", file.getCanonicalPath()).start(); | |
254 | + } catch (IOException ex) { | |
255 | + Log.log(ex); | |
256 | + } | |
257 | + } | |
258 | + | |
259 | + private void onWordApplicationQuit(final int returnCode) { | |
260 | + try { | |
261 | + // remove this from Previews collection | |
262 | + FilePreview.delete(originalFile); | |
263 | + | |
264 | + // try to delete temporary file | |
265 | + temporaryFile.delete(); | |
266 | + | |
267 | + // try to delete WSF file | |
268 | + if (FilePreview.size(WordPreview.class) == 0) | |
269 | + _wsf.delete(); | |
270 | + | |
271 | + } catch (IOException ex) { | |
272 | + Log.log(ex); | |
273 | + } | |
274 | + } | |
275 | + | |
276 | + @Override | |
277 | + public void close() { | |
278 | + try { | |
279 | + // close the document | |
280 | + final Command command = new Command(); | |
281 | + final String job = "close"; | |
282 | + final String document = temporaryFile.getCanonicalPath(); | |
283 | + command.execWSF(job, document); | |
284 | + } catch (IOException ex) { | |
285 | + Log.log(ex); | |
286 | + } catch (InterruptedException ex) { | |
287 | + Log.log(ex); | |
288 | + } | |
289 | + } | |
290 | + | |
291 | + @Override | |
292 | + public void reload() { | |
293 | + if (! isOriginalFileUpdated()) { | |
294 | + return; | |
295 | + } | |
296 | + | |
297 | + try { | |
298 | + File temp = getTempFile(originalFile); | |
299 | + | |
300 | + // copy the file to avoid locking the file unnecessarily | |
301 | + LFileCopy.copy(originalFile, temp); | |
302 | + | |
303 | + // rename to secondary temp file (and pass it to WSF) | |
304 | + temp.renameTo(temporaryFile2); | |
305 | + | |
306 | + // make temp file hidden on Windows | |
307 | + addHiddenFileAttribute(temporaryFile2); | |
308 | + | |
309 | + // update lastModified value | |
310 | + this.originalFileLastModified = originalFile.lastModified(); | |
311 | + } catch (IOException ex) { | |
312 | + Log.log(ex); | |
313 | + } | |
314 | + } | |
315 | + | |
316 | + private boolean isOriginalFileUpdated() { | |
317 | + return this.originalFileLastModified != this.originalFile.lastModified(); | |
318 | + } | |
319 | + | |
320 | + // バッファあふれ非対応のため、少量のテキスト(だいたい 500文字ていど)が | |
321 | + // 予想される場合のみ利用してください。 | |
322 | + // また同期実行です。プロセスの終了を待機してから制御を返します。 | |
323 | + protected static class Command { | |
324 | + | |
325 | + private int exitCode = 0; | |
326 | + private String stdout = ""; | |
327 | + private String stderr = ""; | |
328 | + | |
329 | + public int getExitCode() { | |
330 | + return exitCode; | |
331 | + } | |
332 | + | |
333 | + public String getStdout() { | |
334 | + return stdout; | |
335 | + } | |
336 | + | |
337 | + public String getStderr() { | |
338 | + return stderr; | |
339 | + } | |
340 | + | |
341 | + public int exec(String... command) | |
342 | + throws IOException, InterruptedException { | |
343 | + return startProcessAndWait(Arrays.asList(command)); | |
344 | + } | |
345 | + | |
346 | + public int execDOS(String... command) | |
347 | + throws IOException, InterruptedException { | |
348 | + List<String> commands = new ArrayList<String>(command.length + 2); | |
349 | + commands.add("cmd.exe"); | |
350 | + commands.add("/c"); | |
351 | + commands.addAll(Arrays.asList(command)); | |
352 | + | |
353 | + return startProcessAndWait(commands); | |
354 | + } | |
355 | + | |
356 | + public int execWSF(String job, String... command) | |
357 | + throws IOException, InterruptedException { | |
358 | + String script = getWSF().getCanonicalPath(); | |
359 | + List<String> commands = new ArrayList<String>(command.length + 4); | |
360 | + commands.add("cscript.exe"); | |
361 | + commands.add("//nologo"); | |
362 | + commands.add("//Job:" + job); | |
363 | + commands.add(script); | |
364 | + commands.addAll(Arrays.asList(command)); | |
365 | + | |
366 | + return startProcessAndWait(commands); | |
367 | + } | |
368 | + | |
369 | + private int startProcessAndWait(List<String> command) | |
370 | + throws IOException, InterruptedException { | |
371 | + ProcessBuilder pb = new ProcessBuilder(command); | |
372 | + Process process = pb.start(); | |
373 | + exitCode = process.waitFor(); // 0: succeed | |
374 | + stdout = getString(process.getInputStream()); | |
375 | + stderr = getString(process.getErrorStream()); | |
376 | + return exitCode; | |
377 | + } | |
378 | + | |
379 | + private String getString(InputStream is) throws IOException { | |
380 | + byte[] b = new byte[1024]; | |
381 | + int size = is.read(b); | |
382 | + if (size > 0) { | |
383 | + return new String(b, 0, size); | |
384 | + } else { | |
385 | + return ""; | |
386 | + } | |
387 | + } | |
388 | + | |
389 | + } | |
390 | +} |
@@ -0,0 +1,226 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import java.awt.Component; | |
20 | +import java.awt.event.ActionEvent; | |
21 | +import java.awt.event.ActionListener; | |
22 | +import java.awt.event.KeyEvent; | |
23 | +import java.awt.event.MouseEvent; | |
24 | +import java.awt.event.MouseListener; | |
25 | +import java.io.File; | |
26 | +import java.io.FileFilter; | |
27 | +import java.util.Comparator; | |
28 | +import javax.swing.Icon; | |
29 | +import javax.swing.JMenu; | |
30 | +import javax.swing.JMenuItem; | |
31 | +import javax.swing.MenuElement; | |
32 | +import javax.swing.MenuSelectionManager; | |
33 | +import javax.swing.event.MenuEvent; | |
34 | +import javax.swing.event.MenuKeyEvent; | |
35 | +import javax.swing.event.MenuKeyListener; | |
36 | +import javax.swing.event.MenuListener; | |
37 | +import javax.swing.filechooser.FileSystemView; | |
38 | + | |
39 | +/** | |
40 | + * | |
41 | + * @author Yu-Tang | |
42 | + */ | |
43 | +public class MenuHelper { | |
44 | + | |
45 | + static { | |
46 | + fs = FileSystemView.getFileSystemView(); | |
47 | + ff = new FileFilter() { | |
48 | + | |
49 | + @Override | |
50 | + public boolean accept(File file) { | |
51 | + // except dot started named files (i.e. ".svn") and hidden files | |
52 | + return !file.getName().startsWith(".") && !file.isHidden(); | |
53 | + } | |
54 | + | |
55 | + }; | |
56 | + | |
57 | + al = new ActionListener() { | |
58 | + | |
59 | + @Override | |
60 | + public void actionPerformed(ActionEvent e) { $(e).open(); } | |
61 | + | |
62 | + }; | |
63 | + | |
64 | + mkl = new MenuKeyListener() { | |
65 | + | |
66 | + @Override | |
67 | + public void menuKeyTyped(MenuKeyEvent e) { /* do nothing */ } | |
68 | + | |
69 | + @Override | |
70 | + public void menuKeyPressed(MenuKeyEvent e) { | |
71 | + if (e.getKeyCode() == KeyEvent.VK_ENTER) { | |
72 | + MenuSelectionManager manager = e.getMenuSelectionManager(); | |
73 | + MenuElement[] selectedPath = manager.getSelectedPath(); | |
74 | + MenuElement selection = selectedPath[selectedPath.length-1]; | |
75 | + if (selection instanceof JMenu) { | |
76 | + JMenu menu = (JMenu) selection; | |
77 | + if (menu.isEnabled()) { | |
78 | + manager.clearSelectedPath(); | |
79 | + $(menu).open(); | |
80 | + } | |
81 | + } | |
82 | + } | |
83 | + } | |
84 | + | |
85 | + @Override | |
86 | + public void menuKeyReleased(MenuKeyEvent e) { /* do nothing */ } | |
87 | + | |
88 | + }; | |
89 | + | |
90 | + mol = new MouseListener() { | |
91 | + | |
92 | + @Override | |
93 | + public void mouseClicked(MouseEvent e) { $(e).open(); } | |
94 | + | |
95 | + @Override | |
96 | + public void mousePressed(MouseEvent e) { /* do nothing */ } | |
97 | + | |
98 | + @Override | |
99 | + public void mouseReleased(MouseEvent e) { /* do nothing */ } | |
100 | + | |
101 | + @Override | |
102 | + public void mouseEntered(MouseEvent e) { /* do nothing */ } | |
103 | + | |
104 | + @Override | |
105 | + public void mouseExited(MouseEvent e) { /* do nothing */ } | |
106 | + | |
107 | + }; | |
108 | + | |
109 | + mel = new MenuListener() { | |
110 | + | |
111 | + @Override | |
112 | + public void menuSelected(MenuEvent e) { | |
113 | + // Lazy create submenus | |
114 | + $(e).createChildren(); | |
115 | + } | |
116 | + | |
117 | + @Override | |
118 | + public void menuDeselected(MenuEvent e) { /* do nothing */ } | |
119 | + | |
120 | + @Override | |
121 | + public void menuCanceled(MenuEvent e) { /* do nothing */ } | |
122 | + | |
123 | + }; | |
124 | + | |
125 | + /* for Folders root menu only */ | |
126 | + melRoot = new MenuListener() { | |
127 | + | |
128 | + @Override | |
129 | + public void menuSelected(MenuEvent e) { /* do nothing */ } | |
130 | + | |
131 | + @Override | |
132 | + public void menuDeselected(MenuEvent e) { | |
133 | + // remove children's all menuitems | |
134 | + JMenu menu = (JMenu) e.getSource(); | |
135 | + for (Component c: menu.getMenuComponents()) { | |
136 | + if (c instanceof JMenu) { | |
137 | + JMenu m = (JMenu) c; | |
138 | + if (m.isEnabled()) | |
139 | + m.removeAll(); | |
140 | + } | |
141 | + } | |
142 | + } | |
143 | + | |
144 | + @Override | |
145 | + public void menuCanceled(MenuEvent e) { /* do nothing */ } | |
146 | + | |
147 | + }; | |
148 | + | |
149 | + comp = new Comparator<File>() { | |
150 | + | |
151 | + @Override | |
152 | + public int compare(File f1, File f2) { | |
153 | + if (f1.isFile() == f2.isFile()) { | |
154 | + return f1.getName().compareToIgnoreCase(f2.getName()); | |
155 | + } else { | |
156 | + return f1.isFile() ? 1 : -1; | |
157 | + } | |
158 | + } | |
159 | + | |
160 | + }; | |
161 | + } | |
162 | + | |
163 | + private MenuHelper() {} // no instanciation, static only. | |
164 | + | |
165 | + public static Icon getIcon(File file) { | |
166 | + return fs.getSystemIcon(file); | |
167 | + } | |
168 | + | |
169 | + public static File[] getFilteredListFiles(File folder) { | |
170 | + return folder.listFiles(ff); | |
171 | + } | |
172 | + | |
173 | + public static ActionListener getActionListener() { | |
174 | + return al; | |
175 | + } | |
176 | + | |
177 | + public static MenuKeyListener getMenuKeyListener() { | |
178 | + return mkl; | |
179 | + } | |
180 | + | |
181 | + public static MouseListener getMouseListener() { | |
182 | + return mol; | |
183 | + } | |
184 | + | |
185 | + public static MenuListener getMenuListener() { | |
186 | + return mel; | |
187 | + } | |
188 | + | |
189 | + public static MenuListener getRootMenuListener() { | |
190 | + return melRoot; | |
191 | + } | |
192 | + | |
193 | + public static Comparator<File> getComparator() { | |
194 | + return comp; | |
195 | + } | |
196 | + | |
197 | + private static ShellLinkMenuItem $(JMenuItem mi) { | |
198 | + return new ShellLinkMenuItem(mi); | |
199 | + } | |
200 | + | |
201 | + private static ShellLinkMenu $(JMenu m) { | |
202 | + return new ShellLinkMenu(m); | |
203 | + } | |
204 | + | |
205 | + private static ShellLinkMenuItem $(ActionEvent e) { | |
206 | + return new ShellLinkMenuItem((JMenuItem) e.getSource()); | |
207 | + } | |
208 | + | |
209 | + private static ShellLinkMenu $(MouseEvent e) { | |
210 | + return new ShellLinkMenu((JMenu) e.getSource()); | |
211 | + } | |
212 | + | |
213 | + private static ShellLinkMenu $(MenuEvent e) { | |
214 | + return new ShellLinkMenu((JMenu) e.getSource()); | |
215 | + } | |
216 | + | |
217 | + private static final FileSystemView fs; | |
218 | + private static final FileFilter ff; | |
219 | + private static final ActionListener al; | |
220 | + private static final MenuKeyListener mkl; | |
221 | + private static final MouseListener mol; | |
222 | + private static final MenuListener mel; | |
223 | + private static final MenuListener melRoot; | |
224 | + private static final Comparator<File> comp; | |
225 | + | |
226 | +} |
@@ -0,0 +1,94 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import java.awt.Desktop; | |
20 | +import java.io.File; | |
21 | +import java.io.IOException; | |
22 | +import javax.swing.JMenuItem; | |
23 | +import org.omegat.core.Core; | |
24 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getActionListener; | |
25 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getIcon; | |
26 | +import jp.sourceforge.users.yutang.omegat.plugin.foldermenu.filepreview.FilePreview; | |
27 | +import org.omegat.util.Log; | |
28 | +import static org.omegat.util.Platform.OsType.MAC32; | |
29 | +import static org.omegat.util.Platform.OsType.MAC64; | |
30 | +import static org.omegat.util.Platform.OsType.WIN32; | |
31 | +import static org.omegat.util.Platform.OsType.WIN64; | |
32 | +import static org.omegat.util.Platform.getOsType; | |
33 | +import org.omegat.util.StaticUtils; | |
34 | + | |
35 | +/** | |
36 | + * | |
37 | + * @author Yu-Tang | |
38 | + */ | |
39 | +public class ShellLinkMenuItem { | |
40 | + | |
41 | + protected JMenuItem menuItem; | |
42 | + | |
43 | + public ShellLinkMenuItem() { | |
44 | + menuItem = new JMenuItem(); | |
45 | + } | |
46 | + | |
47 | + public ShellLinkMenuItem(JMenuItem mi) { | |
48 | + menuItem = mi; | |
49 | + } | |
50 | + | |
51 | + public ShellLinkMenuItem(File file) throws IOException { | |
52 | + JMenuItem m = new JMenuItem(file.getName(), getIcon(file)); | |
53 | + m.setActionCommand(file.getCanonicalPath()); | |
54 | + m.addActionListener(getActionListener()); | |
55 | + menuItem = m; | |
56 | + } | |
57 | + | |
58 | + public boolean isEnabled() { | |
59 | + return menuItem.isEnabled(); | |
60 | + } | |
61 | + | |
62 | + public JMenuItem getMenuItem() { | |
63 | + return menuItem; | |
64 | + } | |
65 | + | |
66 | + public void open() { | |
67 | + if (! menuItem.isEnabled()) | |
68 | + return; | |
69 | + | |
70 | + String path = menuItem.getActionCommand(); | |
71 | + try { | |
72 | + switch (getOsType()) { | |
73 | + case WIN64: | |
74 | + case WIN32: | |
75 | + File file = new File(path); | |
76 | + if (! FilePreview.open(file)) { | |
77 | + Desktop.getDesktop().open(file); | |
78 | + } | |
79 | + break; | |
80 | + case MAC64: | |
81 | + case MAC32: | |
82 | + new ProcessBuilder("open", path).start(); | |
83 | + break; | |
84 | + default: // Linux and others | |
85 | + new ProcessBuilder("xdg-open", path).start(); | |
86 | + break; | |
87 | + } | |
88 | + } catch (IOException ex) { | |
89 | + Log.log(ex); | |
90 | + Core.getMainWindow().showMessageDialog(StaticUtils.format( | |
91 | + L10n.getErrMsgFileHasNoAssoc(), path)); | |
92 | + } | |
93 | + } | |
94 | +} |
@@ -0,0 +1,59 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import java.util.ResourceBundle; | |
20 | + | |
21 | +/** | |
22 | + * | |
23 | + * @author Yu-Tang | |
24 | + */ | |
25 | +public class L10n { | |
26 | + | |
27 | + private static final ResourceBundle bundle; | |
28 | + | |
29 | + static { | |
30 | + bundle = ResourceBundle.getBundle("org/omegat/plugin/foldermenu/Bundle"); | |
31 | + } | |
32 | + | |
33 | + // for menu | |
34 | + | |
35 | + public static String getFoldersMenuLabel() { | |
36 | + return bundle.getString("FOLDERS_MENU_LABEL"); | |
37 | + } | |
38 | + | |
39 | + public static String getProjectRootMenuLabel() { | |
40 | + return bundle.getString("PROJECT_ROOT_MENU_LABEL"); | |
41 | + } | |
42 | + | |
43 | + public static String getUserConfigMenuLabel() { | |
44 | + return bundle.getString("USER_CONFIG_MENU_LABEL"); | |
45 | + } | |
46 | + | |
47 | + // for Word | |
48 | + | |
49 | + public static String getWordWindowCaption() { | |
50 | + return bundle.getString("WORD_WINDOW_CAPTION"); | |
51 | + } | |
52 | + | |
53 | + // for error | |
54 | + | |
55 | + public static String getErrMsgFileHasNoAssoc() { | |
56 | + return bundle.getString("ERROR_FILE_HAS_NO_ASSOC"); | |
57 | + } | |
58 | + | |
59 | +} |
@@ -0,0 +1,114 @@ | ||
1 | +/************************************************************************** | |
2 | + FolderMenu - easy access to project folders from menu. | |
3 | + | |
4 | + Copyright (C) 2013 Yu Tang | |
5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/ | |
7 | + | |
8 | + This file is part of plugin for OmegaT. | |
9 | + http://www.omegat.org/ | |
10 | + | |
11 | + License: GNU GPL version 3 or (at your option) any later version. | |
12 | + | |
13 | + You should have received a copy of the GNU General Public License | |
14 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | + **************************************************************************/ | |
16 | + | |
17 | +package jp.sourceforge.users.yutang.omegat.plugin.foldermenu; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import java.util.Arrays; | |
22 | +import javax.swing.JMenu; | |
23 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getComparator; | |
24 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getFilteredListFiles; | |
25 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getIcon; | |
26 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getMenuListener; | |
27 | +import static jp.sourceforge.users.yutang.omegat.plugin.foldermenu.MenuHelper.getMouseListener; | |
28 | +import org.omegat.util.Log; | |
29 | +import org.openide.awt.Mnemonics; | |
30 | + | |
31 | +/** | |
32 | + * | |
33 | + * @author Yu-Tang | |
34 | + */ | |
35 | +public class ShellLinkMenu extends ShellLinkMenuItem { | |
36 | + | |
37 | + public ShellLinkMenu(JMenu m) { | |
38 | + super(m); | |
39 | + } | |
40 | + | |
41 | + public ShellLinkMenu(File folder) throws IOException { | |
42 | + this(folder, null); | |
43 | + } | |
44 | + | |
45 | + public ShellLinkMenu(String label) throws IOException { | |
46 | + this(null, label); | |
47 | + } | |
48 | + | |
49 | + public ShellLinkMenu(File folder, String label) throws IOException { | |
50 | + JMenu m; | |
51 | + if (label == null) { | |
52 | + m = new JMenu(folder.getName()); | |
53 | + } else { | |
54 | + m = new JMenu(); | |
55 | + Mnemonics.setLocalizedText(m, label); | |
56 | + } | |
57 | + | |
58 | + m.addMenuListener(getMenuListener()); | |
59 | + m.addMouseListener(getMouseListener()); | |
60 | + | |
61 | + if (folder != null) { | |
62 | + m.setIcon(getIcon(folder)); | |
63 | + m.setActionCommand(folder.getCanonicalPath()); | |
64 | + } else { | |
65 | + m.setEnabled(false); | |
66 | + } | |
67 | + | |
68 | + menuItem = m; | |
69 | + } | |
70 | + | |
71 | + public void createChildren() { | |
72 | + JMenu menu = (JMenu) menuItem; | |
73 | + if (menu.isEnabled() && menu.getItemCount() == 0) { | |
74 | + File folder = new File(menu.getActionCommand()); | |
75 | + File[] filteredListFiles = getFilteredListFiles(folder); | |
76 | + Arrays.sort(filteredListFiles, getComparator()); | |
77 | + | |
78 | + for (File file : filteredListFiles) { | |
79 | + try { | |
80 | + if (file.isDirectory() && hasChildren(file)) { | |
81 | + menu.add(new ShellLinkMenu(file).getMenuItem()); | |
82 | + } else { | |
83 | + menu.add(new ShellLinkMenuItem(file).getMenuItem()); | |
84 | + } | |
85 | + } catch (IOException ex) { | |
86 | + Log.log(ex); | |
87 | + } | |
88 | + } | |
89 | + } | |
90 | + } | |
91 | + | |
92 | + public JMenu getMenu() { | |
93 | + return (JMenu) menuItem; | |
94 | + } | |
95 | + | |
96 | + public void link(File folder) throws IOException { | |
97 | + JMenu menu = (JMenu) menuItem; | |
98 | + menu.setActionCommand(folder.getCanonicalPath()); | |
99 | + menu.setIcon(getIcon(folder)); | |
100 | + menu.setEnabled(true); | |
101 | + } | |
102 | + | |
103 | + public void unlink() { | |
104 | + JMenu menu = (JMenu) menuItem; | |
105 | + menu.setEnabled(false); | |
106 | + menu.removeAll(); | |
107 | + menu.setActionCommand(""); | |
108 | + menu.setIcon(null); | |
109 | + } | |
110 | + | |
111 | + private boolean hasChildren(File folder) { | |
112 | + return getFilteredListFiles(folder).length > 0; | |
113 | + } | |
114 | +} |