• R/O
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-cqtcocoa誰得pythonphprubygameguibathyscaphec翻訳計画中(planning stage)omegatframeworktwittertestdomvb.netdirectxbtronarduinopreviewerゲームエンジン

OmegaT のメニューバーにフォルダーツリー参照用のメニューを追加します。


Commit MetaInfo

Revision43 (tree)
Time2014-04-25 15:39:53
Authoryu-tang

Log Message

change package name

Change Summary

Incremental Difference

--- trunk/src/org/omegat/plugin/foldermenu/MenuHelper.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/MenuHelper.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/ShellLinkMenuItem.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/ShellLinkMenuItem.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/L10n.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/L10n.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/ShellLinkMenu.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/ShellLinkMenu.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/MenuManager.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/MenuManager.java (nonexistent)
@@ -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
--- trunk/src/org/omegat/plugin/foldermenu/FolderMenu.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/FolderMenu.java (nonexistent)
@@ -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
--- trunk/src/org/omegat/plugin/foldermenu/filepreview/TempFileCleaner.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/filepreview/TempFileCleaner.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/filepreview/FilePreview.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/filepreview/FilePreview.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/filepreview/IPreview.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/filepreview/IPreview.java (nonexistent)
@@ -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- }
--- trunk/src/org/omegat/plugin/foldermenu/filepreview/WordPreview.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/filepreview/WordPreview.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/foldermenu/VersionInfo.java (revision 42)
+++ trunk/src/org/omegat/plugin/foldermenu/VersionInfo.java (nonexistent)
@@ -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-}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/MenuManager.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/MenuManager.java (revision 43)
@@ -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
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/FolderMenu.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/FolderMenu.java (revision 43)
@@ -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
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/VersionInfo.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/VersionInfo.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/TempFileCleaner.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/TempFileCleaner.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/FilePreview.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/FilePreview.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/IPreview.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/IPreview.java (revision 43)
@@ -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+ }
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/WordPreview.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/filepreview/WordPreview.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/MenuHelper.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/MenuHelper.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/ShellLinkMenuItem.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/ShellLinkMenuItem.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/L10n.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/L10n.java (revision 43)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/ShellLinkMenu.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/foldermenu/ShellLinkMenu.java (revision 43)
@@ -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+}