/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2014 Briac Pilpre 2015 Aaron Madlon-Kay Home page: http://www.omegat.org/ Support center: http://groups.yahoo.com/group/OmegaT/ This file is part of OmegaT. OmegaT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmegaT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.omegat.gui.scripting; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import org.apache.commons.io.FilenameUtils; import org.omegat.core.CoreEvents; import org.omegat.core.data.SourceTextEntry; import org.omegat.core.events.IApplicationEventListener; import org.omegat.core.events.IEditorEventListener; import org.omegat.core.events.IEntryEventListener; import org.omegat.core.events.IProjectEventListener; import org.omegat.util.DirectoryMonitor; /** * Monitor to check changes in the script directory. * * @author Briac Pilpre */ public class ScriptsMonitor implements DirectoryMonitor.DirectoryCallback, DirectoryMonitor.Callback { private static final boolean SCRIPTING_EVENTS = true; private static boolean applicationStartupEventScriptsExecuted = false; private static final FilenameFilter FILTER; static { List<String> extensions = ScriptRunner.getAvailableScriptExtensions(); FILTER = (dir, name) -> extensions.contains(FilenameUtils.getExtension(name).toLowerCase()); } public ScriptsMonitor(final ScriptingWindow scriptingWindow) { this.m_scriptingWindow = scriptingWindow; if (SCRIPTING_EVENTS) { // Initialize the events script list for all the events for (EventType t : EventType.values()) { m_eventsScript.put(t, new ArrayList<ScriptItem>()); } } } public void start(final File scriptDir) { this.m_scriptDir = scriptDir; m_monitor = new DirectoryMonitor(scriptDir, this, this); m_monitor.start(); // Immediately execute APPLICATION_STARTUP event scripts if (!applicationStartupEventScriptsExecuted) { // first-time only applicationStartupEventScriptsExecuted = true; addEventScripts(EventType.APPLICATION_STARTUP); ArrayList<ScriptItem> scripts = m_eventsScript.get(EventType.APPLICATION_STARTUP); for (ScriptItem si : scripts) { m_scriptingWindow.executeScriptFile(si); } scripts.clear(); } } public void stop() { if (m_monitor != null) { m_monitor.fin(); } } /** * Executed on file changed. */ @Override public void fileChanged(File file) { } @Override public void directoryChanged(File file) { if (!m_scriptDir.isDirectory()) { // No script directory. return; } // Plain Scripts // Only display files with an extension supported by the engines // currently installed. ArrayList<ScriptItem> scriptsList = new ArrayList<ScriptItem>(); // Replace the script filename by its description, if available for (File script : m_scriptDir.listFiles(FILTER)) { scriptsList.add(new ScriptItem(script)); } Collections.sort(scriptsList); m_scriptingWindow.setScriptItems(scriptsList); if (SCRIPTING_EVENTS) { hookApplicationEvent(); hookEntryEvent(); hookProjectEvent(); hookEditorEvent(); } } private void hookEntryEvent() { if (m_entryEventListener != null) { CoreEvents.unregisterEntryEventListener(m_entryEventListener); } addEventScripts(EventType.ENTRY_ACTIVATED); addEventScripts(EventType.NEW_FILE); m_entryEventListener = new IEntryEventListener() { @Override public void onNewFile(String activeFileName) { HashMap<String, Object> binding = new HashMap<String, Object>(); binding.put("activeFileName", activeFileName); for (ScriptItem si : m_eventsScript.get(EventType.NEW_FILE)) { m_scriptingWindow.executeScriptFile(si, binding); } } @Override public void onEntryActivated(SourceTextEntry newEntry) { HashMap<String, Object> binding = new HashMap<String, Object>(); binding.put("newEntry", newEntry); for (ScriptItem si : m_eventsScript.get(EventType.ENTRY_ACTIVATED)) { m_scriptingWindow.executeScriptFile(si, binding); } } }; CoreEvents.registerEntryEventListener(m_entryEventListener); } private void hookProjectEvent() { if (m_projectEventListener != null) { CoreEvents.unregisterProjectChangeListener(m_projectEventListener); } addEventScripts(EventType.PROJECT_CHANGED); m_projectEventListener = new IProjectEventListener() { @Override public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { HashMap<String, Object> binding = new HashMap<String, Object>(); binding.put("eventType", eventType); for (ScriptItem si : m_eventsScript.get(EventType.PROJECT_CHANGED)) { m_scriptingWindow.executeScriptFile(si, binding); } } }; CoreEvents.registerProjectChangeListener(m_projectEventListener); } private void hookApplicationEvent() { if (m_applicationEventListener != null) { CoreEvents.unregisterApplicationEventListener(m_applicationEventListener); } // APPLICATION_STARTUP is not working because it is registered too late. // addEventScripts(EventType.APPLICATION_STARTUP); addEventScripts(EventType.APPLICATION_SHUTDOWN); m_applicationEventListener = new IApplicationEventListener() { @Override public void onApplicationStartup() { // for (ScriptItem si : m_eventsScript.get(EventType.APPLICATION_STARTUP)) { // m_scriptingWindow.executeScriptFile(si, true); // } } @Override public void onApplicationShutdown() { for (ScriptItem si : m_eventsScript.get(EventType.APPLICATION_SHUTDOWN)) { m_scriptingWindow.executeScriptFile(si); } } }; CoreEvents.registerApplicationEventListener(m_applicationEventListener); } private void hookEditorEvent() { if (m_editorEventListener != null) { CoreEvents.unregisterEditorEventListener(m_editorEventListener); } addEventScripts(EventType.NEW_WORD); m_editorEventListener = new IEditorEventListener() { @Override public void onNewWord(String newWord) { HashMap<String, Object> binding = new HashMap<String, Object>(); binding.put("newWord", newWord); for (ScriptItem si : m_eventsScript.get(EventType.NEW_WORD)) { m_scriptingWindow.executeScriptFile(si, binding); } } }; CoreEvents.registerEditorEventListener(m_editorEventListener); } private void addEventScripts(EventType eventType) { String entryDirName = eventType.name().toLowerCase(); File entryActivatedDir = new File(m_scriptDir, entryDirName); if (!entryActivatedDir.isDirectory()) { return; } ArrayList<ScriptItem> eventScripts = m_eventsScript.get(eventType); // Avoid executing scripts that may be deleted during the directory change. eventScripts.clear(); for (File script : entryActivatedDir.listFiles(FILTER)) { ScriptItem scriptItem = new ScriptItem(script); if (!eventScripts.contains(scriptItem)) { eventScripts.add(scriptItem); } } } private enum EventType { // ApplicationEvent APPLICATION_STARTUP, APPLICATION_SHUTDOWN, // EditorEvent NEW_WORD, // FontEvent //FONT_CHANGED, // ProjectEvent PROJECT_CHANGED, // EntryEvent ENTRY_ACTIVATED, NEW_FILE } private File m_scriptDir; protected DirectoryMonitor m_monitor; private ScriptingWindow m_scriptingWindow; // Event listeners. private IEntryEventListener m_entryEventListener; private IProjectEventListener m_projectEventListener; private IApplicationEventListener m_applicationEventListener; private IEditorEventListener m_editorEventListener; // Map holding the script fired for the different event listeners. private HashMap<EventType, ArrayList<ScriptItem>> m_eventsScript = new HashMap<EventType, ArrayList<ScriptItem>>(); }