OmegaT の背景に画像を表示します。
change package names
| @@ -23,7 +23,7 @@ | ||
| 23 | 23 | <taskdef name="groovyc" classpath="${javac.classpath}" classname="org.codehaus.groovy.ant.Groovyc"/> |
| 24 | 24 | <property name="empty.dir" location="${build.dir}/empty"/> |
| 25 | 25 | <mkdir dir="${empty.dir}"/> |
| 26 | - <groovyc srcdir="@{srcdir}" sourcepath="@{sourcepath}" destdir="@{destdir}" encoding="${source.encoding}" includes="@{includes}" excludes="@{excludes}" includeAntRuntime="false" fork="true"> | |
| 26 | + <groovyc srcdir="@{srcdir}" sourcepath="@{sourcepath}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeAntRuntime="false" fork="true"> | |
| 27 | 27 | <src> |
| 28 | 28 | <dirset dir="@{gensrcdir}" erroronmissingdir="false"> |
| 29 | 29 | <include name="*"/> |
| @@ -55,6 +55,7 @@ | ||
| 55 | 55 | <property file="nbproject/project.properties"/> |
| 56 | 56 | </target> |
| 57 | 57 | <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init"> |
| 58 | + <property name="platform.java" value="${java.home}/bin/java"/> | |
| 58 | 59 | <available file="${manifest.file}" property="manifest.available"/> |
| 59 | 60 | <condition property="splashscreen.available"> |
| 60 | 61 | <and> |
| @@ -72,16 +73,20 @@ | ||
| 72 | 73 | </not> |
| 73 | 74 | </and> |
| 74 | 75 | </condition> |
| 75 | - <condition property="manifest.available+main.class"> | |
| 76 | + <condition property="profile.available"> | |
| 76 | 77 | <and> |
| 77 | - <isset property="manifest.available"/> | |
| 78 | - <isset property="main.class.available"/> | |
| 78 | + <isset property="javac.profile"/> | |
| 79 | + <length length="0" string="${javac.profile}" when="greater"/> | |
| 80 | + <matches pattern="1\.[89](\..*)?" string="${javac.source}"/> | |
| 79 | 81 | </and> |
| 80 | 82 | </condition> |
| 81 | 83 | <condition property="do.archive"> |
| 82 | - <not> | |
| 83 | - <istrue value="${jar.archive.disabled}"/> | |
| 84 | - </not> | |
| 84 | + <or> | |
| 85 | + <not> | |
| 86 | + <istrue value="${jar.archive.disabled}"/> | |
| 87 | + </not> | |
| 88 | + <istrue value="${not.archive.disabled}"/> | |
| 89 | + </or> | |
| 85 | 90 | </condition> |
| 86 | 91 | <condition property="do.mkdist"> |
| 87 | 92 | <and> |
| @@ -92,12 +97,6 @@ | ||
| 92 | 97 | </not> |
| 93 | 98 | </and> |
| 94 | 99 | </condition> |
| 95 | - <condition property="manifest.available+main.class+mkdist.available"> | |
| 96 | - <and> | |
| 97 | - <istrue value="${manifest.available+main.class}"/> | |
| 98 | - <isset property="do.mkdist"/> | |
| 99 | - </and> | |
| 100 | - </condition> | |
| 101 | 100 | <condition property="do.archive+manifest.available"> |
| 102 | 101 | <and> |
| 103 | 102 | <isset property="manifest.available"/> |
| @@ -116,24 +115,12 @@ | ||
| 116 | 115 | <istrue value="${do.archive}"/> |
| 117 | 116 | </and> |
| 118 | 117 | </condition> |
| 119 | - <condition property="do.archive+manifest.available+main.class"> | |
| 118 | + <condition property="do.archive+profile.available"> | |
| 120 | 119 | <and> |
| 121 | - <istrue value="${manifest.available+main.class}"/> | |
| 120 | + <isset property="profile.available"/> | |
| 122 | 121 | <istrue value="${do.archive}"/> |
| 123 | 122 | </and> |
| 124 | 123 | </condition> |
| 125 | - <condition property="manifest.available-mkdist.available"> | |
| 126 | - <or> | |
| 127 | - <istrue value="${manifest.available}"/> | |
| 128 | - <isset property="do.mkdist"/> | |
| 129 | - </or> | |
| 130 | - </condition> | |
| 131 | - <condition property="manifest.available+main.class-mkdist.available"> | |
| 132 | - <or> | |
| 133 | - <istrue value="${manifest.available+main.class}"/> | |
| 134 | - <isset property="do.mkdist"/> | |
| 135 | - </or> | |
| 136 | - </condition> | |
| 137 | 124 | <condition property="have.tests"> |
| 138 | 125 | <or> |
| 139 | 126 | <available file="${test.src.dir}"/> |
| @@ -187,8 +174,16 @@ | ||
| 187 | 174 | </condition> |
| 188 | 175 | <path id="endorsed.classpath.path" path="${endorsed.classpath}"/> |
| 189 | 176 | <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'"> |
| 190 | - <length length="0" string="${endorsed.classpath}" when="greater"/> | |
| 177 | + <and> | |
| 178 | + <isset property="endorsed.classpath"/> | |
| 179 | + <not> | |
| 180 | + <equals arg1="${endorsed.classpath}" arg2="" trim="true"/> | |
| 181 | + </not> | |
| 182 | + </and> | |
| 191 | 183 | </condition> |
| 184 | + <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}"> | |
| 185 | + <isset property="profile.available"/> | |
| 186 | + </condition> | |
| 192 | 187 | <condition else="false" property="jdkBug6558476"> |
| 193 | 188 | <and> |
| 194 | 189 | <matches pattern="1\.[56]" string="${java.specification.version}"/> |
| @@ -276,6 +271,7 @@ | ||
| 276 | 271 | <path path="@{classpath}"/> |
| 277 | 272 | </classpath> |
| 278 | 273 | <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> |
| 274 | + <compilerarg line="${javac.profile.cmd.line.arg}"/> | |
| 279 | 275 | <compilerarg line="${javac.compilerargs}"/> |
| 280 | 276 | <compilerarg value="-processorpath"/> |
| 281 | 277 | <compilerarg path="@{processorpath}:${empty.dir}"/> |
| @@ -315,6 +311,7 @@ | ||
| 315 | 311 | <path path="@{classpath}"/> |
| 316 | 312 | </classpath> |
| 317 | 313 | <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> |
| 314 | + <compilerarg line="${javac.profile.cmd.line.arg}"/> | |
| 318 | 315 | <compilerarg line="${javac.compilerargs}"/> |
| 319 | 316 | <customize/> |
| 320 | 317 | </javac> |
| @@ -447,7 +444,7 @@ | ||
| 447 | 444 | </fileset> |
| 448 | 445 | </union> |
| 449 | 446 | <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/> |
| 450 | - <testng classfilesetref="test.set" failureProperty="tests.failed" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Moenizer" testname="TestNG tests" workingDir="${work.dir}"> | |
| 447 | + <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Moenizer" testname="TestNG tests" workingDir="${work.dir}"> | |
| 451 | 448 | <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/> |
| 452 | 449 | <propertyset> |
| 453 | 450 | <propertyref prefix="test-sys-prop."/> |
| @@ -838,8 +835,8 @@ | ||
| 838 | 835 | </chainedmapper> |
| 839 | 836 | </pathconvert> |
| 840 | 837 | <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/> |
| 841 | - <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> | |
| 842 | - <fileset dir="${build.classes.dir}"/> | |
| 838 | + <copylibs compress="${jar.compress}" excludeFromCopy="${copylibs.excludes}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> | |
| 839 | + <fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/> | |
| 843 | 840 | <manifest> |
| 844 | 841 | <attribute name="Class-Path" value="${jar.classpath}"/> |
| 845 | 842 | <customize/> |
| @@ -851,7 +848,7 @@ | ||
| 851 | 848 | <target name="-init-presetdef-jar"> |
| 852 | 849 | <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> |
| 853 | 850 | <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}"> |
| 854 | - <j2seproject1:fileset dir="${build.classes.dir}"/> | |
| 851 | + <j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/> | |
| 855 | 852 | </jar> |
| 856 | 853 | </presetdef> |
| 857 | 854 | </target> |
| @@ -967,41 +964,25 @@ | ||
| 967 | 964 | <!-- Empty placeholder for easier customization. --> |
| 968 | 965 | <!-- You can override this target in the ../build.xml file. --> |
| 969 | 966 | </target> |
| 970 | - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available"> | |
| 971 | - <j2seproject1:jar/> | |
| 972 | - </target> | |
| 973 | - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available"> | |
| 974 | - <j2seproject1:jar manifest="${manifest.file}"/> | |
| 975 | - </target> | |
| 976 | - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available"> | |
| 977 | - <j2seproject1:jar manifest="${manifest.file}"> | |
| 978 | - <j2seproject1:manifest> | |
| 979 | - <j2seproject1:attribute name="Main-Class" value="${main.class}"/> | |
| 980 | - </j2seproject1:manifest> | |
| 981 | - </j2seproject1:jar> | |
| 982 | - <echo level="info">To run this application from the command line without Ant, try:</echo> | |
| 983 | - <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> | |
| 984 | - <property location="${dist.jar}" name="dist.jar.resolved"/> | |
| 985 | - <pathconvert property="run.classpath.with.dist.jar"> | |
| 986 | - <path path="${run.classpath}"/> | |
| 987 | - <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> | |
| 988 | - </pathconvert> | |
| 989 | - <echo level="info">java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> | |
| 990 | - </target> | |
| 991 | - <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available"> | |
| 967 | + <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available"> | |
| 992 | 968 | <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> |
| 993 | 969 | <touch file="${tmp.manifest.file}" verbose="false"/> |
| 994 | 970 | </target> |
| 995 | - <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest"> | |
| 971 | + <target depends="init" if="do.archive+manifest.available" name="-do-jar-copy-manifest"> | |
| 996 | 972 | <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> |
| 997 | 973 | <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/> |
| 998 | 974 | </target> |
| 999 | - <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main"> | |
| 975 | + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+main.class.available" name="-do-jar-set-mainclass"> | |
| 1000 | 976 | <manifest file="${tmp.manifest.file}" mode="update"> |
| 1001 | 977 | <attribute name="Main-Class" value="${main.class}"/> |
| 1002 | 978 | </manifest> |
| 1003 | 979 | </target> |
| 1004 | - <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen"> | |
| 980 | + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+profile.available" name="-do-jar-set-profile"> | |
| 981 | + <manifest file="${tmp.manifest.file}" mode="update"> | |
| 982 | + <attribute name="Profile" value="${javac.profile}"/> | |
| 983 | + </manifest> | |
| 984 | + </target> | |
| 985 | + <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-set-splashscreen"> | |
| 1005 | 986 | <basename file="${application.splash}" property="splashscreen.basename"/> |
| 1006 | 987 | <mkdir dir="${build.classes.dir}/META-INF"/> |
| 1007 | 988 | <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/> |
| @@ -1009,23 +990,41 @@ | ||
| 1009 | 990 | <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/> |
| 1010 | 991 | </manifest> |
| 1011 | 992 | </target> |
| 1012 | - <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack"> | |
| 993 | + <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.mkdist" name="-do-jar-copylibs"> | |
| 1013 | 994 | <j2seproject3:copylibs manifest="${tmp.manifest.file}"/> |
| 1014 | 995 | <echo level="info">To run this application from the command line without Ant, try:</echo> |
| 1015 | 996 | <property location="${dist.jar}" name="dist.jar.resolved"/> |
| 1016 | 997 | <echo level="info">java -jar "${dist.jar.resolved}"</echo> |
| 1017 | 998 | </target> |
| 1018 | - <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest"> | |
| 999 | + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.archive" name="-do-jar-jar" unless="do.mkdist"> | |
| 1000 | + <j2seproject1:jar manifest="${tmp.manifest.file}"/> | |
| 1001 | + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> | |
| 1002 | + <property location="${dist.jar}" name="dist.jar.resolved"/> | |
| 1003 | + <pathconvert property="run.classpath.with.dist.jar"> | |
| 1004 | + <path path="${run.classpath}"/> | |
| 1005 | + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> | |
| 1006 | + </pathconvert> | |
| 1007 | + <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java} -cp ${run.classpath.with.dist.jar} ${main.class}"> | |
| 1008 | + <isset property="main.class.available"/> | |
| 1009 | + </condition> | |
| 1010 | + <condition else="debug" property="jar.usage.level" value="info"> | |
| 1011 | + <isset property="main.class.available"/> | |
| 1012 | + </condition> | |
| 1013 | + <echo level="${jar.usage.level}" message="${jar.usage.message}"/> | |
| 1014 | + </target> | |
| 1015 | + <target depends="-do-jar-copylibs" if="do.archive" name="-do-jar-delete-manifest"> | |
| 1019 | 1016 | <delete> |
| 1020 | 1017 | <fileset file="${tmp.manifest.file}"/> |
| 1021 | 1018 | </delete> |
| 1022 | 1019 | </target> |
| 1023 | - <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/> | |
| 1020 | + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-jar,-do-jar-delete-manifest" name="-do-jar-without-libraries"/> | |
| 1021 | + <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-copylibs,-do-jar-delete-manifest" name="-do-jar-with-libraries"/> | |
| 1024 | 1022 | <target name="-post-jar"> |
| 1025 | 1023 | <!-- Empty placeholder for easier customization. --> |
| 1026 | 1024 | <!-- You can override this target in the ../build.xml file. --> |
| 1027 | 1025 | </target> |
| 1028 | - <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/> | |
| 1026 | + <target depends="init,compile,-pre-jar,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/> | |
| 1027 | + <target depends="init,compile,-pre-jar,-do-jar,-post-jar" description="Build JAR." name="jar"/> | |
| 1029 | 1028 | <!-- |
| 1030 | 1029 | ================= |
| 1031 | 1030 | EXECUTION SECTION |
| @@ -1204,11 +1203,14 @@ | ||
| 1204 | 1203 | </not> |
| 1205 | 1204 | </and> |
| 1206 | 1205 | </condition> |
| 1207 | - <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> | |
| 1206 | + <condition else="" property="bug5101868workaround" value="*.java"> | |
| 1207 | + <matches pattern="1\.[56](\..*)?" string="${java.version}"/> | |
| 1208 | + </condition> | |
| 1209 | + <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> | |
| 1208 | 1210 | <classpath> |
| 1209 | 1211 | <path path="${javac.classpath}"/> |
| 1210 | 1212 | </classpath> |
| 1211 | - <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}"> | |
| 1213 | + <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}"> | |
| 1212 | 1214 | <filename name="**/*.java"/> |
| 1213 | 1215 | </fileset> |
| 1214 | 1216 | <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> |
| @@ -1282,7 +1284,7 @@ | ||
| 1282 | 1284 | <mkdir dir="${build.test.results.dir}"/> |
| 1283 | 1285 | </target> |
| 1284 | 1286 | <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run"> |
| 1285 | - <j2seproject3:test testincludes="**/*Test.java"/> | |
| 1287 | + <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/> | |
| 1286 | 1288 | </target> |
| 1287 | 1289 | <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run"> |
| 1288 | 1290 | <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> |
| @@ -1,135 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import java.awt.image.BufferedImage; | |
| 20 | -import java.io.IOException; | |
| 21 | -import java.util.concurrent.TimeUnit; | |
| 22 | -import java.util.logging.Level; | |
| 23 | -import java.util.logging.Logger; | |
| 24 | -import javax.swing.SwingUtilities; | |
| 25 | -import javax.swing.SwingWorker; | |
| 26 | -import org.omegat.core.CoreEvents; | |
| 27 | -import org.omegat.core.events.IApplicationEventListener; | |
| 28 | -import org.omegat.core.events.IProjectEventListener; | |
| 29 | -import org.omegat.plugin.moenizer.imageloader.IImageLoader; | |
| 30 | -import org.omegat.plugin.moenizer.imageloader.ImageLoader; | |
| 31 | -import org.omegat.util.Log; | |
| 32 | -import org.omegat.util.StaticUtils; | |
| 33 | - | |
| 34 | -/** | |
| 35 | - * allow to set background image | |
| 36 | - * | |
| 37 | - * @author Yu-Tang | |
| 38 | - */ | |
| 39 | -public class Moenizer implements IApplicationEventListener, IProjectEventListener { | |
| 40 | - | |
| 41 | - private IImageLoader imageLoader; | |
| 42 | - private MoeUI ui; | |
| 43 | - | |
| 44 | - | |
| 45 | - @SuppressWarnings("LeakingThisInConstructor") | |
| 46 | - public Moenizer() { | |
| 47 | - CoreEvents.registerApplicationEventListener(this); | |
| 48 | - CoreEvents.registerProjectChangeListener(this); | |
| 49 | - | |
| 50 | - ui = null; | |
| 51 | - imageLoader = ImageLoader.getInstance(); | |
| 52 | - // この時点ではまだウィンドウがインスタンス化されていないので、 | |
| 53 | - // ウィンドウに対する処理は少し待つ。 | |
| 54 | - | |
| 55 | - (new SlideShow()).execute(); | |
| 56 | - } | |
| 57 | - | |
| 58 | - @Override | |
| 59 | - public void onApplicationStartup() { | |
| 60 | - try { | |
| 61 | - ui = MoeUI.getMoeUI(); | |
| 62 | - | |
| 63 | - // この時点でコンポーネントの透過設定をしても反映されない(タイミング?)。 | |
| 64 | - // Workaround として、invokeLater でキューに突っ込んで、後で処理する。 | |
| 65 | - SwingUtilities.invokeLater(new Runnable() { | |
| 66 | - @Override | |
| 67 | - public void run() { | |
| 68 | - CoreEvents.unregisterApplicationEventListener(Moenizer.this); | |
| 69 | - ui.transparent(); | |
| 70 | - } | |
| 71 | - }); | |
| 72 | - //CoreEvents.unregisterApplicationEventListener(this); // ここで発行すると、スレッドエラーになるので注意 | |
| 73 | - } catch(Exception e) { | |
| 74 | - Log.log("Error raised at " + this.getClass().getCanonicalName() + ".onApplicationStartup()\n" + e); | |
| 75 | - } | |
| 76 | - } | |
| 77 | - | |
| 78 | - @Override | |
| 79 | - public void onApplicationShutdown() { | |
| 80 | - // not used. | |
| 81 | - } | |
| 82 | - | |
| 83 | - @Override | |
| 84 | - public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
| 85 | - switch (eventType) { | |
| 86 | - case CREATE: | |
| 87 | - case LOAD: | |
| 88 | - // ここですぐ透過処理をしてもうまく適用されないので、後まわしにする。 | |
| 89 | - SwingUtilities.invokeLater(new Runnable() { | |
| 90 | - @Override | |
| 91 | - public void run() { | |
| 92 | - CoreEvents.unregisterProjectChangeListener(Moenizer.this); | |
| 93 | - ui.transparentEditor(); | |
| 94 | - } | |
| 95 | - }); | |
| 96 | - | |
| 97 | - // 一回 Editor の透過処理をしたら、透過状態が維持されるので、二回目 | |
| 98 | - // 以降は、透過処理は不要。 | |
| 99 | - //CoreEvents.unregisterProjectChangeListener(this); // ここで発行すると、スレッドエラーになるので注意 | |
| 100 | - break; | |
| 101 | - case CLOSE: | |
| 102 | - break; | |
| 103 | - } | |
| 104 | - } | |
| 105 | - | |
| 106 | - private class SlideShow extends SwingWorker<Object, Void> { | |
| 107 | - private long interval = -1; | |
| 108 | - | |
| 109 | - @Override | |
| 110 | - protected Object doInBackground() throws Exception { | |
| 111 | - while (imageLoader.availableNext()) { | |
| 112 | - imageLoader.readyForNextImage(); | |
| 113 | - interval = interval < 0 ? 0 : imageLoader.getNextInterval(); | |
| 114 | - if (interval > 0) { | |
| 115 | - try { | |
| 116 | - TimeUnit.MILLISECONDS.sleep(interval); | |
| 117 | - } catch (InterruptedException e) { /* ignore */ } | |
| 118 | - } | |
| 119 | - BufferedImage image = imageLoader.getNextImage(); | |
| 120 | - | |
| 121 | - if (image != null) { | |
| 122 | - // 初期化直後に、まだ MoeUI がインスタンス化されていない | |
| 123 | - // 空白時間に遭遇する可能性があるため、その場合は 0.1 秒 | |
| 124 | - // 単位で MoeUI のインスタンス化を待機する。 | |
| 125 | - while (ui == null) { | |
| 126 | - TimeUnit.MILLISECONDS.sleep(100); | |
| 127 | - } | |
| 128 | - ui.setBackground(image); | |
| 129 | - } | |
| 130 | - } | |
| 131 | - return null; | |
| 132 | - } | |
| 133 | - } | |
| 134 | - | |
| 135 | -} |
| @@ -1,162 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | - | |
| 19 | -import java.awt.image.BufferedImage; | |
| 20 | -import java.io.File; | |
| 21 | -import java.net.URL; | |
| 22 | -import java.util.regex.Pattern; | |
| 23 | -import javax.imageio.ImageIO; | |
| 24 | -import static org.omegat.plugin.moenizer.MoeConfig.*; | |
| 25 | -import org.omegat.util.Log; | |
| 26 | - | |
| 27 | -/** | |
| 28 | - * Default image loader. | |
| 29 | - * | |
| 30 | - * calling order is: | |
| 31 | - * 1. availableNext() ... exit if returned false | |
| 32 | - * 2. readyForNextImage() | |
| 33 | - * 3. getNextInterval() ... skipped first time | |
| 34 | - * 4. getNextImage() | |
| 35 | - * ... loop back to step 1 | |
| 36 | - * | |
| 37 | - * @author Yu-Tang | |
| 38 | - */ | |
| 39 | -public class DefaultImageLoader implements IImageLoader { | |
| 40 | - | |
| 41 | - private static final Pattern RE_HAS_IMAGE_EXTENSION = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif)"); | |
| 42 | - private long interval; | |
| 43 | - private Object[] sources; | |
| 44 | - private Object currentSource; | |
| 45 | - private int sourceIndex; | |
| 46 | - | |
| 47 | - protected BufferedImage image; | |
| 48 | - | |
| 49 | - public DefaultImageLoader() { | |
| 50 | - interval = getInterval(); | |
| 51 | - sources = getSources(); | |
| 52 | - currentSource = null; | |
| 53 | - image = null; | |
| 54 | - sourceIndex = -1; | |
| 55 | - } | |
| 56 | - | |
| 57 | - /** | |
| 58 | - * get if source is acceptable. | |
| 59 | - * @return bool. | |
| 60 | - */ | |
| 61 | - public static boolean isAcceptable(Object source) { | |
| 62 | - if (source instanceof URL) { | |
| 63 | - return true; | |
| 64 | - } else if (source instanceof File) { | |
| 65 | - String name = ((File) source).getName().toLowerCase(); | |
| 66 | - if (RE_HAS_IMAGE_EXTENSION.matcher(name).matches()) { | |
| 67 | - return true; | |
| 68 | - } | |
| 69 | - } | |
| 70 | - return false; | |
| 71 | - } | |
| 72 | - | |
| 73 | - @Override | |
| 74 | - public boolean availableNext() { | |
| 75 | - boolean ret = false; | |
| 76 | - if (sources.length == 0) { | |
| 77 | - // it's over! | |
| 78 | - } else if (sources.length == 1) { | |
| 79 | - if (currentSource == null || interval > 0) { // first time or refresh | |
| 80 | - currentSource = sources[0]; | |
| 81 | - ret = true; | |
| 82 | - } | |
| 83 | - } else { | |
| 84 | - currentSource = getCircularNextSource(); | |
| 85 | - ret = true; | |
| 86 | - } | |
| 87 | - return ret; | |
| 88 | - } | |
| 89 | - | |
| 90 | - /** | |
| 91 | - * get next image. | |
| 92 | - * @return BufferedImage object. Can be null if image is not available. | |
| 93 | - */ | |
| 94 | - @Override | |
| 95 | - public BufferedImage getNextImage() { | |
| 96 | - return image; | |
| 97 | - } | |
| 98 | - | |
| 99 | - /** | |
| 100 | - * Do anything should be done for the next image. | |
| 101 | - * Calling before getNextImage(). | |
| 102 | - */ | |
| 103 | - @Override | |
| 104 | - public void readyForNextImage() { | |
| 105 | - //TODO use cache | |
| 106 | - image = null; | |
| 107 | - try { | |
| 108 | - if (currentSource != null) { | |
| 109 | - if (currentSource instanceof File) { | |
| 110 | - image = ImageIO.read((File) currentSource); | |
| 111 | - } else if (currentSource instanceof URL) { | |
| 112 | - image = ImageIO.read((URL) currentSource); | |
| 113 | - } else { | |
| 114 | - removeCurrentSource(); | |
| 115 | - } | |
| 116 | - } | |
| 117 | - } catch (Exception ex) { | |
| 118 | - Log.log(ex); | |
| 119 | - removeCurrentSource(); | |
| 120 | - } | |
| 121 | - } | |
| 122 | - | |
| 123 | - /** | |
| 124 | - * get next interval. | |
| 125 | - * This method is not called at first time loop. | |
| 126 | - * @return long by milliseconds | |
| 127 | - */ | |
| 128 | - @Override | |
| 129 | - public long getNextInterval() { | |
| 130 | - return interval; | |
| 131 | - } | |
| 132 | - | |
| 133 | - private Object getCircularNextSource() { | |
| 134 | - sourceIndex++; | |
| 135 | - if (sourceIndex >= sources.length) { | |
| 136 | - sourceIndex = 0; | |
| 137 | - } | |
| 138 | - return sources[sourceIndex]; | |
| 139 | - } | |
| 140 | - | |
| 141 | - private void removeCurrentSource() { | |
| 142 | - if (sourceIndex >= 0 && sourceIndex < sources.length) { | |
| 143 | - sourceIndex = 0; // something is wrong. rewind index. | |
| 144 | - } else { | |
| 145 | - Object[] newSources = new Object[sources.length - 1]; | |
| 146 | - for (int i = 0; i < sources.length; i++) { | |
| 147 | - if ( i == sourceIndex ) { | |
| 148 | - // skip | |
| 149 | - } else if ( i < sourceIndex ) { | |
| 150 | - newSources[i] = sources[i]; | |
| 151 | - } else { | |
| 152 | - newSources[i - 1] = sources[i]; | |
| 153 | - } | |
| 154 | - } | |
| 155 | - sources = newSources; | |
| 156 | - if (sourceIndex >= sources.length) { | |
| 157 | - sourceIndex = 0; | |
| 158 | - } | |
| 159 | - } | |
| 160 | - } | |
| 161 | - | |
| 162 | -} |
| @@ -1,60 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | - | |
| 19 | -import java.awt.image.BufferedImage; | |
| 20 | - | |
| 21 | -/** | |
| 22 | - * Interface for Image Loader | |
| 23 | - * | |
| 24 | - * calling order is: | |
| 25 | - * 1. availableNext() ... exit from loop if returned false | |
| 26 | - * 2. readyForNextImage() | |
| 27 | - * 3. getNextInterval() ... skiped first time | |
| 28 | - * 4. getNextImage() | |
| 29 | - * ... loop back to step 1 | |
| 30 | - * | |
| 31 | - * @author Yu-Tang | |
| 32 | - */ | |
| 33 | -public interface IImageLoader { | |
| 34 | - | |
| 35 | - /** | |
| 36 | - * get if next image available. | |
| 37 | - * @return bool. | |
| 38 | - */ | |
| 39 | - boolean availableNext(); | |
| 40 | - | |
| 41 | - /** | |
| 42 | - * get next interval. | |
| 43 | - * This method is not called at first time loop. | |
| 44 | - * @return long by milliseconds | |
| 45 | - */ | |
| 46 | - long getNextInterval(); | |
| 47 | - | |
| 48 | - /** | |
| 49 | - * Do anything should be done for the next image. | |
| 50 | - * Calling before getNextImage(). | |
| 51 | - */ | |
| 52 | - void readyForNextImage(); | |
| 53 | - | |
| 54 | - /** | |
| 55 | - * get next image. | |
| 56 | - * @return BufferedImage object. Can be null if image is not available. | |
| 57 | - */ | |
| 58 | - BufferedImage getNextImage(); | |
| 59 | - | |
| 60 | -} |
| @@ -1,56 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | - | |
| 19 | -import java.lang.reflect.Method; | |
| 20 | -import java.net.URL; | |
| 21 | -import static org.omegat.plugin.moenizer.MoeConfig.*; | |
| 22 | -import org.omegat.util.Log; | |
| 23 | - | |
| 24 | -/** | |
| 25 | - * | |
| 26 | - * @author Yu-Tang | |
| 27 | - */ | |
| 28 | -public class ImageLoader { | |
| 29 | - | |
| 30 | - public static IImageLoader getInstance() { | |
| 31 | - Object[] sources = getSources(); | |
| 32 | - | |
| 33 | - if (sources.length == 0) { | |
| 34 | - return null; // no source, no need loader | |
| 35 | - } | |
| 36 | - | |
| 37 | - // default | |
| 38 | - return new DefaultImageLoader(); | |
| 39 | - } | |
| 40 | - | |
| 41 | - private static Object getAcceptableSource(Class<?> c, Object[] sources) { | |
| 42 | - for (Object source: sources) { | |
| 43 | - try { | |
| 44 | - Method method = c.getDeclaredMethod("isAcceptable", new Class[]{ Object.class }); | |
| 45 | - boolean isAcceptable = (Boolean) method.invoke(null, source); | |
| 46 | - if (isAcceptable) { | |
| 47 | - return source; | |
| 48 | - } | |
| 49 | - } catch (Exception ex) { | |
| 50 | - Log.log(ex); | |
| 51 | - } | |
| 52 | - } | |
| 53 | - return null; | |
| 54 | - } | |
| 55 | - | |
| 56 | -} |
| @@ -1,88 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import java.awt.AlphaComposite; | |
| 20 | -import java.awt.Graphics; | |
| 21 | -import java.awt.Graphics2D; | |
| 22 | -import java.awt.Rectangle; | |
| 23 | -import java.awt.TexturePaint; | |
| 24 | -import java.awt.image.BufferedImage; | |
| 25 | -import javax.swing.JLayeredPane; | |
| 26 | - | |
| 27 | -/** | |
| 28 | - * | |
| 29 | - * @author Yu-Tang | |
| 30 | - */ | |
| 31 | -public class MoeLayeredPane extends JLayeredPane { | |
| 32 | - | |
| 33 | - private BufferedImage image; | |
| 34 | - private TexturePaint paint; | |
| 35 | - private float alpha; | |
| 36 | - | |
| 37 | - public MoeLayeredPane() { | |
| 38 | - super(); | |
| 39 | - this.image = null; | |
| 40 | - this.paint = null; | |
| 41 | - this.alpha = MoeConfig.getOpacity(); | |
| 42 | - } | |
| 43 | - | |
| 44 | - public MoeLayeredPane(BufferedImage image) { | |
| 45 | - super(); | |
| 46 | - setPicture(image); | |
| 47 | - this.alpha = MoeConfig.getOpacity(); | |
| 48 | - } | |
| 49 | - | |
| 50 | - public void setBackground(BufferedImage image) { | |
| 51 | - setPicture(image); | |
| 52 | - this.repaint(); | |
| 53 | - } | |
| 54 | - | |
| 55 | - @Override | |
| 56 | - protected void paintComponent(Graphics g) { | |
| 57 | - if (image != null) { | |
| 58 | - Graphics2D g2 = (Graphics2D)g.create(); | |
| 59 | - g2.setComposite(makeComposite(alpha)); | |
| 60 | - | |
| 61 | - if (getWidth() > image.getWidth() || getHeight() > image.getHeight()) { | |
| 62 | - g2.setPaint(paint); | |
| 63 | - g2.fillRect(0, 0, getWidth(), getHeight()); | |
| 64 | - } else { | |
| 65 | - g2.drawImage(image, 0, 0, this); | |
| 66 | - } | |
| 67 | - | |
| 68 | - g2.dispose(); | |
| 69 | - } | |
| 70 | - super.paintComponent(g); | |
| 71 | - } | |
| 72 | - | |
| 73 | - private AlphaComposite makeComposite(float alpha) { | |
| 74 | - int type = AlphaComposite.SRC_OVER; | |
| 75 | - return(AlphaComposite.getInstance(type, alpha)); | |
| 76 | - } | |
| 77 | - | |
| 78 | - private void setPicture(BufferedImage image) { | |
| 79 | - this.image = image; | |
| 80 | - | |
| 81 | - if (image == null) { | |
| 82 | - this.paint = null; | |
| 83 | - } else { | |
| 84 | - Rectangle rect = new Rectangle(image.getWidth(), image.getHeight()); | |
| 85 | - this.paint = new TexturePaint(image, rect); | |
| 86 | - } | |
| 87 | - } | |
| 88 | -} |
| @@ -1,287 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import com.sun.java.swing.plaf.windows.WindowsMenuBarUI; | |
| 20 | -import com.vlsolutions.swing.docking.DockView; | |
| 21 | -import com.vlsolutions.swing.docking.DockViewTitleBar; | |
| 22 | -import com.vlsolutions.swing.docking.Dockable; | |
| 23 | -import com.vlsolutions.swing.docking.DockableState; | |
| 24 | -import com.vlsolutions.swing.docking.DockingDesktop; | |
| 25 | -import com.vlsolutions.swing.docking.SplitContainer; | |
| 26 | -import java.awt.Color; | |
| 27 | -import java.awt.Component; | |
| 28 | -import java.awt.Container; | |
| 29 | -import java.awt.Graphics; | |
| 30 | -import java.awt.SystemColor; | |
| 31 | -import java.awt.image.BufferedImage; | |
| 32 | -import javax.swing.JComponent; | |
| 33 | -import javax.swing.JEditorPane; | |
| 34 | -import javax.swing.JFrame; | |
| 35 | -import javax.swing.JMenuBar; | |
| 36 | -import javax.swing.JScrollPane; | |
| 37 | -import javax.swing.JTextPane; | |
| 38 | -//import javax.swing.plaf.basic.BasicMenuBarUI; | |
| 39 | -import org.omegat.core.Core; | |
| 40 | -import org.omegat.util.gui.UIThreadsUtil; | |
| 41 | - | |
| 42 | -/** | |
| 43 | - * | |
| 44 | - * @author Yu-Tang | |
| 45 | - */ | |
| 46 | -public class MoeUI { | |
| 47 | - | |
| 48 | - private static MoeUI moeUI; | |
| 49 | - | |
| 50 | - private JFrame frame; | |
| 51 | - private MoeLayeredPane layeredPane; | |
| 52 | - private Container contentPane; | |
| 53 | - private JMenuBar menuBar; | |
| 54 | - private DockingDesktop desktop; | |
| 55 | - | |
| 56 | - static { | |
| 57 | - moeUI = null; | |
| 58 | - } | |
| 59 | - | |
| 60 | - // Singleton. Not allow to Instanciate from outside. Use getMoeUI() to get instance. | |
| 61 | - private MoeUI(BufferedImage image) { | |
| 62 | - UIThreadsUtil.mustBeSwingThread(); | |
| 63 | - | |
| 64 | - initUI(image); | |
| 65 | - } | |
| 66 | - | |
| 67 | - private MoeUI() { | |
| 68 | - UIThreadsUtil.mustBeSwingThread(); | |
| 69 | - | |
| 70 | - initUI(null); | |
| 71 | - } | |
| 72 | - | |
| 73 | - public static MoeUI getMoeUI(BufferedImage image) { | |
| 74 | - if (moeUI == null) { | |
| 75 | - moeUI = new MoeUI(image); | |
| 76 | - } | |
| 77 | - return moeUI; | |
| 78 | - } | |
| 79 | - | |
| 80 | - public static MoeUI getMoeUI() { | |
| 81 | - if (moeUI == null) { | |
| 82 | - moeUI = new MoeUI(); | |
| 83 | - } | |
| 84 | - return moeUI; | |
| 85 | - } | |
| 86 | - | |
| 87 | - public void transparent() { | |
| 88 | - UIThreadsUtil.mustBeSwingThread(); | |
| 89 | - | |
| 90 | - transparent(menuBar); | |
| 91 | - transparentRecursive(contentPane); | |
| 92 | - transparentInstantStart(desktop); | |
| 93 | - | |
| 94 | - frame.repaint(); | |
| 95 | - } | |
| 96 | - | |
| 97 | - public void transparentEditor() { | |
| 98 | - // Editor に表示されるドキュメントは、以下のケースでまったく異なる。 | |
| 99 | - // | |
| 100 | - // 1. インスタントスタートガイドが表示されている場合(初期状態) | |
| 101 | - // -> view = JTextPane, HTMLDocument | |
| 102 | - // 2. プロジェクトをロードまたは新規作成して、分節編集画面が表示されている場合 | |
| 103 | - // -> view = JEditorPane, DefaultStyledDocument | |
| 104 | - // | |
| 105 | - // そのため、2 のタイミングで透過処理をやり直す必要がある。 | |
| 106 | - // このメソッドは、2 の透過処理専用。 | |
| 107 | - | |
| 108 | - UIThreadsUtil.mustBeSwingThread(); | |
| 109 | - | |
| 110 | - JEditorPane editor = getJEditorPaneFromEditor(desktop); | |
| 111 | - if (editor == null) { | |
| 112 | - return; | |
| 113 | - } | |
| 114 | - | |
| 115 | - /* ここで JEditorPane に半透明の背景色を設定すると、テキストの選択(反転) | |
| 116 | - * などの色の変化が正常に更新されず色残りしてしまう。 | |
| 117 | - * そのため、JEditorPane への処理では単純に背景を透明にして、元画像自体で | |
| 118 | - * 色味を調整しておく方針とする。 | |
| 119 | - * | |
| 120 | - int alpha = 100; // transparent <- 0...255 -> opaque | |
| 121 | - Color color = SystemColor.menu; | |
| 122 | - editor.setBackground(new Color( color.getRGB() & 0xffffff | 100 << 24, true)); | |
| 123 | - * */ | |
| 124 | - editor.setOpaque(false); | |
| 125 | - frame.repaint(); | |
| 126 | - } | |
| 127 | - | |
| 128 | - public void setBackground(final BufferedImage image) { | |
| 129 | - UIThreadsUtil.executeInSwingThread(new Runnable() { | |
| 130 | - @Override | |
| 131 | - public void run() { | |
| 132 | - layeredPane.setBackground(image); | |
| 133 | - } | |
| 134 | - }); | |
| 135 | - } | |
| 136 | - | |
| 137 | - private void initUI(BufferedImage image) { | |
| 138 | - frame = Core.getMainWindow().getApplicationFrame(); | |
| 139 | - if (image == null) { | |
| 140 | - layeredPane = new MoeLayeredPane(); | |
| 141 | - } else { | |
| 142 | - layeredPane = new MoeLayeredPane(image); | |
| 143 | - } | |
| 144 | - contentPane = frame.getContentPane(); | |
| 145 | - menuBar = frame.getJMenuBar(); | |
| 146 | - desktop = getDockingDesktop(contentPane); | |
| 147 | - | |
| 148 | - // replace LayeredPane with MoeLayeredPane | |
| 149 | - frame.setLayeredPane(layeredPane); | |
| 150 | - frame.setContentPane(contentPane); | |
| 151 | - frame.setJMenuBar(menuBar); | |
| 152 | - | |
| 153 | - frame.validate(); | |
| 154 | - } | |
| 155 | - | |
| 156 | - private void transparent(JMenuBar menuBar) { | |
| 157 | -// menuBar.setUI ( new BasicMenuBarUI () { | |
| 158 | -// 上記だと初期表示時に、アクティブメニューがアクティブで描画されない。 | |
| 159 | -// マウス通過などのタイミングで再描画された際にアクティブカラーになるが、 | |
| 160 | -// 見栄えが悪いので、Windows 用の UI を指定する。 | |
| 161 | -// アクティブメニューがアクティブで描画されない問題はこれで解決するが、 | |
| 162 | -// 変わりに Mac や *nix など別 L&F 環境下では違和感があるかもしれない。 | |
| 163 | - menuBar.setUI ( new WindowsMenuBarUI () { | |
| 164 | - @Override | |
| 165 | - public void paint ( Graphics g, JComponent c ) { | |
| 166 | - int alpha = 100; // transparent <- 0...255 -> opaque | |
| 167 | - Color oldColor = g.getColor(); | |
| 168 | - Color color = SystemColor.menu; | |
| 169 | - g.setColor ( new Color( color.getRGB() & 0xffffff | alpha << 24, true)); | |
| 170 | - g.fillRect ( 0, 0, c.getWidth (), c.getHeight () ); | |
| 171 | - g.setColor ( oldColor ); // restore | |
| 172 | - } | |
| 173 | - } ); | |
| 174 | - menuBar.setOpaque(false); | |
| 175 | - } | |
| 176 | - | |
| 177 | - private void transparentRecursive(Component component) { | |
| 178 | - if (component instanceof JComponent) { | |
| 179 | - JComponent c = (JComponent) component; | |
| 180 | - if (c.isOpaque()) { | |
| 181 | - c.setOpaque(false); | |
| 182 | - } | |
| 183 | - } | |
| 184 | - | |
| 185 | - if (component instanceof Container) { | |
| 186 | - Container container = (Container) component; | |
| 187 | - for (Component c: container.getComponents()) { | |
| 188 | - transparentRecursive(c); | |
| 189 | - } | |
| 190 | - } | |
| 191 | - | |
| 192 | - if (component instanceof DockingDesktop) { | |
| 193 | - transparentRecursive((DockingDesktop) component); | |
| 194 | - } | |
| 195 | - } | |
| 196 | - | |
| 197 | - private void transparentRecursive(DockingDesktop desktop) { | |
| 198 | - //DockingPanel dockingPanel = dockingDesktop.getDockingPanel(); // Scoping NG | |
| 199 | - // DockingPanel にアクセスできないので、下位要素から上にさかのぼって処理する。 | |
| 200 | - // 階層的には、こんな感じになっている。 | |
| 201 | - // ----------------------- | |
| 202 | - // DockingDesktop | |
| 203 | - // + DockingPanel <-- splitContainer.getParent() | |
| 204 | - // + splitContainer(HORIZONTAL) <-- splitContainer.getParent() | |
| 205 | - // + splitContainer(VERTICAL) <-- DockView.getParent() | |
| 206 | - // + DockView <-- Dockable.getParent() | |
| 207 | - // + Dockable <-- DockableState.getDockable() | |
| 208 | - for (DockableState d: desktop.getDockables()) { | |
| 209 | - double width = d.getPosition().getWidth(); | |
| 210 | - // width (height や x, y でも可) が 0.0 以外の場合はアイコン化されているので、透過処理不要 | |
| 211 | - // 他に適切な判定方法がありそうだけれども、分からなかったので、とりあえずこれで。 | |
| 212 | - if (width == 0.0) { | |
| 213 | - transparentRecursive(d); | |
| 214 | - } | |
| 215 | - } | |
| 216 | - } | |
| 217 | - | |
| 218 | - private void transparentRecursive(DockableState dockableState) { | |
| 219 | - Dockable dockable = dockableState.getDockable(); | |
| 220 | - | |
| 221 | - // DockView | |
| 222 | - Container container = dockable.getComponent().getParent(); | |
| 223 | - DockView view = (DockView) container; | |
| 224 | - if (view.isOpaque()) { | |
| 225 | - view.setOpaque(false); | |
| 226 | - } | |
| 227 | - DockViewTitleBar titleBar = view.getTitleBar(); | |
| 228 | - if (titleBar.isOpaque()) { | |
| 229 | - titleBar.setOpaque(false); | |
| 230 | - } | |
| 231 | - titleBar.setUI(new MoeDockViewTitleBarUI(titleBar)); | |
| 232 | - | |
| 233 | - // SplitContainer(VERTICAL) | |
| 234 | - container = container.getParent(); | |
| 235 | - if (container == null) { | |
| 236 | - return; | |
| 237 | - } else if (container.isOpaque()) { | |
| 238 | - ((SplitContainer) container).setOpaque(false); | |
| 239 | - } | |
| 240 | - | |
| 241 | - // SplitContainer(HORIZONTAL) | |
| 242 | - container = container.getParent(); | |
| 243 | - if (container == null) { | |
| 244 | - return; | |
| 245 | - } else if (container.isOpaque()) { | |
| 246 | - ((SplitContainer) container).setOpaque(false); | |
| 247 | - } | |
| 248 | - } | |
| 249 | - | |
| 250 | - private void transparentInstantStart(DockingDesktop desktop) { | |
| 251 | - // お手軽スタートは、以下のような HTML で背景色が指定されている。 | |
| 252 | - // <body ... bgcolor="white" ...> | |
| 253 | - // そのため、コンポーネント自体を透過にしても、HTML Body 背景色の | |
| 254 | - // 白指定が効いて透過にならない。そこで、背景色指定を削除する。 | |
| 255 | - for (DockableState d: desktop.getDockables()) { | |
| 256 | - Dockable dockable = d.getDockable(); | |
| 257 | - String key = dockable.getDockKey().getKey(); | |
| 258 | - if (key.equalsIgnoreCase("EDITOR")) { // found InstantStartGuide | |
| 259 | - JScrollPane sp = (JScrollPane) dockable.getComponent(); | |
| 260 | - JTextPane tp = (JTextPane) sp.getViewport().getView(); | |
| 261 | - tp.setText(tp.getText().replace(" bgcolor=\"white\"", "")); | |
| 262 | - tp.setCaretPosition(0); | |
| 263 | - return; | |
| 264 | - } | |
| 265 | - } | |
| 266 | - } | |
| 267 | - | |
| 268 | - private DockingDesktop getDockingDesktop(Container container) { | |
| 269 | - for (Component c: container.getComponents()) { | |
| 270 | - if (c instanceof DockingDesktop) { | |
| 271 | - return (DockingDesktop) c; | |
| 272 | - } | |
| 273 | - } | |
| 274 | - return null; | |
| 275 | - } | |
| 276 | - | |
| 277 | - private JEditorPane getJEditorPaneFromEditor(DockingDesktop desktop) { | |
| 278 | - for (DockableState d: desktop.getDockables()) { | |
| 279 | - Dockable dockable = d.getDockable(); | |
| 280 | - if (dockable.getDockKey().getKey().equalsIgnoreCase("EDITOR")) { | |
| 281 | - JScrollPane sp = (JScrollPane) dockable.getComponent(); | |
| 282 | - return (JEditorPane) sp.getViewport().getView(); | |
| 283 | - } | |
| 284 | - } | |
| 285 | - return null; | |
| 286 | - } | |
| 287 | -} |
| @@ -1,111 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import java.io.BufferedReader; | |
| 20 | -import java.io.File; | |
| 21 | -import java.io.FileInputStream; | |
| 22 | -import java.io.IOException; | |
| 23 | -import java.io.InputStreamReader; | |
| 24 | -import java.io.StringWriter; | |
| 25 | -import java.net.URISyntaxException; | |
| 26 | -import java.net.URL; | |
| 27 | -import java.security.CodeSource; | |
| 28 | -import java.util.regex.Matcher; | |
| 29 | -import java.util.regex.Pattern; | |
| 30 | -import org.omegat.util.LFileCopy; | |
| 31 | -import org.omegat.util.Log; | |
| 32 | -import org.omegat.util.OConsts; | |
| 33 | - | |
| 34 | -/** | |
| 35 | - * | |
| 36 | - * @author Yu-Tang | |
| 37 | - */ | |
| 38 | -public class MoeUtil { | |
| 39 | - | |
| 40 | - private static final Pattern RE_URL_IN_SHORTCUT = Pattern.compile("\\[InternetShortcut\\]\\s+URL=(.+)\\b"); | |
| 41 | - private static final Pattern RE_URL_IN_WEBLOC = Pattern.compile("<key>URL</key>\\s+<string>(.+)</string>"); | |
| 42 | - private static File pluginJarFile; | |
| 43 | - | |
| 44 | - static { | |
| 45 | - pluginJarFile = null; | |
| 46 | - } | |
| 47 | - | |
| 48 | - public static File getPluginJarFile() throws URISyntaxException { | |
| 49 | - if (pluginJarFile == null) { | |
| 50 | - CodeSource codeSource = MoeUtil.class.getProtectionDomain().getCodeSource(); | |
| 51 | - pluginJarFile = new File(codeSource.getLocation().toURI().getPath()); | |
| 52 | - } | |
| 53 | - return pluginJarFile; | |
| 54 | - } | |
| 55 | - | |
| 56 | - public static File getPluginJarDir() throws URISyntaxException { | |
| 57 | - File jarFile = getPluginJarFile(); | |
| 58 | - return new File(jarFile.getParentFile().getPath()); | |
| 59 | - } | |
| 60 | - | |
| 61 | - public static URL getURL(File file) { | |
| 62 | - String fileName = file.getName().toLowerCase(); | |
| 63 | - try { | |
| 64 | - if (fileName.endsWith(".url") || fileName.endsWith(".website")) { | |
| 65 | - // .url is Internet ShortCut file for IE8 or earlier, Firefox | |
| 66 | - // .website is Pinned Site ShortCut file for IE9 or later | |
| 67 | - | |
| 68 | - // Windows 日本語環境で作成すると Shift-JIS 文字列が含まれること | |
| 69 | - // があるため、文字コードはその OS の既定文字コードを想定した方 | |
| 70 | - // が望ましいと思われる。 | |
| 71 | - String text = readTextFile(file, System.getProperty("sun.jnu.encoding")); | |
| 72 | - Matcher matcher = RE_URL_IN_SHORTCUT.matcher(text); | |
| 73 | - if (matcher.find()) { | |
| 74 | - return new URL(matcher.group(1)); | |
| 75 | - } else { | |
| 76 | - Log.log("Could not find valid URL in internet shortcut file '" + file.getCanonicalPath() + "'"); | |
| 77 | - } | |
| 78 | - | |
| 79 | - } else if (fileName.endsWith(".webloc")) { | |
| 80 | - // .webloc is Mac OS X Website Location file for safari | |
| 81 | - String text = readTextFile(file, OConsts.UTF8); | |
| 82 | - Matcher matcher = RE_URL_IN_WEBLOC.matcher(text); | |
| 83 | - if (matcher.find()) { | |
| 84 | - return new URL(matcher.group(1)); | |
| 85 | - } else { | |
| 86 | - Log.log("Could not find valid URL in website location file '" + file.getCanonicalPath() + "'"); | |
| 87 | - } | |
| 88 | - | |
| 89 | - } else { // unknown | |
| 90 | - // ignore | |
| 91 | - } | |
| 92 | - } catch (IOException ex) { | |
| 93 | - Log.log(ex); | |
| 94 | - } | |
| 95 | - return null; | |
| 96 | - } | |
| 97 | - | |
| 98 | - /** | |
| 99 | - * Read file as platform dependent encoding text. | |
| 100 | - */ | |
| 101 | - public static String readTextFile(File file, String encoding) throws IOException { | |
| 102 | - BufferedReader rd = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding)); | |
| 103 | - try { | |
| 104 | - StringWriter out = new StringWriter(); | |
| 105 | - LFileCopy.copy(rd, out); | |
| 106 | - return out.toString(); | |
| 107 | - } finally { | |
| 108 | - rd.close(); | |
| 109 | - } | |
| 110 | - } | |
| 111 | -} |
| @@ -1,70 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import com.vlsolutions.swing.docking.DockViewTitleBar; | |
| 20 | -import com.vlsolutions.swing.docking.ui.DockViewTitleBarUI; | |
| 21 | -import java.awt.Color; | |
| 22 | -import java.awt.Graphics; | |
| 23 | -import java.awt.Graphics2D; | |
| 24 | -import javax.swing.JComponent; | |
| 25 | -import javax.swing.UIManager; | |
| 26 | - | |
| 27 | -/** | |
| 28 | - * | |
| 29 | - * @author Yu-Tang | |
| 30 | - */ | |
| 31 | -public class MoeDockViewTitleBarUI extends DockViewTitleBarUI { | |
| 32 | - | |
| 33 | - /* hack to use custom painting except on mac os (ugly opacity effects) */ | |
| 34 | - private static boolean useCustomPaint = System.getProperty("os.name"). | |
| 35 | - toLowerCase().indexOf("mac os") < 0; | |
| 36 | - | |
| 37 | - /* Alpha value for transparency (0-255) */ | |
| 38 | - private static int activeAlpha = 150; // transparent 0 <- ... -> 255 opaque | |
| 39 | - private static int inactiveAlpha = 100; // transparent 0 <- ... -> 255 opaque | |
| 40 | - | |
| 41 | - private Color activePanelColor = MoeDockViewTitleBarUI.makeTranslucentColor( | |
| 42 | - UIManager.getColor("Panel.background"), activeAlpha); | |
| 43 | - private Color inactivePanelColor = MoeDockViewTitleBarUI.makeTranslucentColor( | |
| 44 | - UIManager.getColor("Panel.background"), inactiveAlpha); | |
| 45 | - //private Color highlight = makeTranslucent(UIManager.getColor("controlLtHighlight")); | |
| 46 | - | |
| 47 | - | |
| 48 | - public MoeDockViewTitleBarUI(DockViewTitleBar tb) { | |
| 49 | - super(tb); | |
| 50 | - } | |
| 51 | - | |
| 52 | - @Override | |
| 53 | - public void paint(Graphics g, JComponent c) { | |
| 54 | - if (MoeDockViewTitleBarUI.useCustomPaint) { | |
| 55 | - DockViewTitleBar tb = (DockViewTitleBar)c; | |
| 56 | - | |
| 57 | - Graphics2D g2 = (Graphics2D) g.create(); | |
| 58 | - g2.setColor(tb.isActive() ? activePanelColor : inactivePanelColor); | |
| 59 | - g2.fillRect(0, 0, tb.getWidth(), tb.getHeight()); // emptyborder doesnt repaint | |
| 60 | - g2.dispose(); | |
| 61 | - } else { | |
| 62 | - super.paint(g, c); | |
| 63 | - } | |
| 64 | - } | |
| 65 | - | |
| 66 | - private static Color makeTranslucentColor(Color color, int alpha) { | |
| 67 | - return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); | |
| 68 | - } | |
| 69 | - | |
| 70 | -} |
| @@ -1,36 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import javax.swing.JOptionPane; | |
| 20 | - | |
| 21 | -/** | |
| 22 | - * | |
| 23 | - * @author Yu-Tang | |
| 24 | - */ | |
| 25 | -public class MoeVersionInfo { | |
| 26 | - | |
| 27 | - private static final String APP_NAME = "Moenizer"; | |
| 28 | - private static final String APP_VERSION = "0.1"; | |
| 29 | - private static final String APP_BUILD = "20130806"; | |
| 30 | - private static final String APP_AUTHOR = "Yu-Tang"; | |
| 31 | - | |
| 32 | - public static void main(String[] args) { | |
| 33 | - JOptionPane.showMessageDialog(null, | |
| 34 | - APP_NAME + " ver." + APP_VERSION + "." + APP_BUILD + "\nby " + APP_AUTHOR); | |
| 35 | - } | |
| 36 | -} |
| @@ -1,326 +0,0 @@ | ||
| 1 | -/************************************************************************** | |
| 2 | - Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | - | |
| 19 | -import java.io.File; | |
| 20 | -import java.io.FileFilter; | |
| 21 | -import java.net.URL; | |
| 22 | -import java.util.HashSet; | |
| 23 | -import java.util.Set; | |
| 24 | -import java.util.regex.Matcher; | |
| 25 | -import java.util.regex.Pattern; | |
| 26 | -import org.omegat.util.FileUtil; | |
| 27 | -import org.omegat.util.Log; | |
| 28 | - | |
| 29 | -/** | |
| 30 | - * | |
| 31 | - * @author Yu-Tang | |
| 32 | - */ | |
| 33 | -public class MoeConfig { | |
| 34 | - private static final String CONFIG_FILE_NAME = "moenizer.conf"; | |
| 35 | - private static final String SCRIPT_FILE_NAME = "moenizer.groovy"; | |
| 36 | - | |
| 37 | - private static final float DEFAULT_OPACITY = 0.5f; | |
| 38 | - private static final int MAX_OPACITY_IN_PERCENTAGE = 100; // Opaque | |
| 39 | - private static final int MIN_OPACITY_IN_PERCENTAGE = 0; // Transparent | |
| 40 | - | |
| 41 | - private static final long DEFAULT_INTERVAL = 60L * 1000L; // 1 minute in milliseconds | |
| 42 | - private static final long MAX_INTERVAL = 86400L * 1000L; // 24 hours | |
| 43 | - private static final long MIN_INTERVAL = 3L * 1000L; // 3 seconds | |
| 44 | - | |
| 45 | - private static final Pattern RE_LINEBREAK = Pattern.compile("[\\n\\r]+"); | |
| 46 | - private static final Pattern RE_OPACITY = Pattern.compile("(\\d+)\\s*%$"); | |
| 47 | - private static final Pattern RE_INTERVAL = Pattern.compile("(\\d+)\\s*([msh])", Pattern.CASE_INSENSITIVE); | |
| 48 | - private static final Pattern RE_SCRIPT = Pattern.compile("(?:/|\\\\\\\\[^\\\\]|[a-zA-Z]:\\\\).+\\.groovy"); | |
| 49 | - private static final Pattern RE_SOURCE = Pattern.compile("(?:http://|https://|/|\\\\\\\\[^\\\\]|[a-zA-Z]:\\\\).+"); | |
| 50 | - private static final Pattern RE_HAS_IMAGE_EXTENSION = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif)"); | |
| 51 | - private static final Pattern RE_HAS_INTERNET_SHORTCUT_EXTENSION = Pattern.compile(".+\\.(?:url|website|webloc)"); | |
| 52 | - private static final Pattern RE_HTTP_OR_HTTPS_PROTOCOL = Pattern.compile("(?:http://|https://).+"); | |
| 53 | - private static final Pattern RE_SOURCE_IN_PLUGIN_DIR = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif|url|website|webloc)"); | |
| 54 | - | |
| 55 | - private static ConfigData data; | |
| 56 | - private static HashSet<Object> sources; | |
| 57 | - | |
| 58 | - static { | |
| 59 | - // load config from file | |
| 60 | - ConfigData cd = loadConfig(); | |
| 61 | - | |
| 62 | - // flatten source dir to files (images only) | |
| 63 | - HashSet<Object> flattenSources = getFlattenSources(cd.source); | |
| 64 | - | |
| 65 | - // scan plugin dir if both sources and script are empty | |
| 66 | - if (flattenSources.isEmpty() && cd.script.isEmpty()) { | |
| 67 | - cd.script = getScriptInPluginDir(); | |
| 68 | - flattenSources = getSourcesInPluginDir(); | |
| 69 | - } | |
| 70 | - | |
| 71 | - // set default interval if current interval is 0 and has multiple sources | |
| 72 | - if (cd.interval == 0 && flattenSources.size() > 1) { | |
| 73 | - cd.interval = DEFAULT_INTERVAL; | |
| 74 | - } | |
| 75 | - | |
| 76 | - data = cd; | |
| 77 | - sources = flattenSources; | |
| 78 | - } | |
| 79 | - | |
| 80 | - public static long getInterval() { | |
| 81 | - return data.interval; | |
| 82 | - } | |
| 83 | - | |
| 84 | - public static float getOpacity() { | |
| 85 | - return data.opacity; | |
| 86 | - } | |
| 87 | - | |
| 88 | - public static File getScript() { | |
| 89 | - return data.script.isEmpty() ? null : new File(data.script); | |
| 90 | - } | |
| 91 | - | |
| 92 | - public static Object[] getSources() { | |
| 93 | - return sources.toArray(); | |
| 94 | - } | |
| 95 | - | |
| 96 | - | |
| 97 | - private static ConfigData loadConfig() { | |
| 98 | - ConfigData data = getDefaultConfig(); | |
| 99 | - try { | |
| 100 | - File file = new File(MoeUtil.getPluginJarDir(), CONFIG_FILE_NAME); | |
| 101 | - if ( file.isFile() ) { | |
| 102 | - String text = FileUtil.readTextFile(file); | |
| 103 | - String[] lines = RE_LINEBREAK.split(text); | |
| 104 | - for (String line: lines) { | |
| 105 | - if ( ! line.isEmpty() ) { | |
| 106 | - if (setOpacity(data, line) == true) { | |
| 107 | - // probably opacity value is changed from default | |
| 108 | - } else if (setInterval(data, line) == true) { | |
| 109 | - // probably interval value is changed from default | |
| 110 | - } else if (setScript(data, line) == true) { | |
| 111 | - // script URI | |
| 112 | - } else if (addSource(data, line) == true) { | |
| 113 | - // source URI (image) | |
| 114 | - } else { | |
| 115 | - // ignore | |
| 116 | - } | |
| 117 | - } | |
| 118 | - } | |
| 119 | - } else { | |
| 120 | - } | |
| 121 | - } catch (Exception ex) { | |
| 122 | - Log.log(ex); | |
| 123 | - } | |
| 124 | - return data; | |
| 125 | - } | |
| 126 | - | |
| 127 | - private static ConfigData getDefaultConfig() { | |
| 128 | - ConfigData cd = new ConfigData(); | |
| 129 | - cd.opacity = DEFAULT_OPACITY; | |
| 130 | - cd.interval = 0L; | |
| 131 | - cd.script = ""; | |
| 132 | - cd.source = new HashSet<String>(); // should be unique | |
| 133 | - return cd; | |
| 134 | - } | |
| 135 | - | |
| 136 | - /** | |
| 137 | - * set new opacity value to ConfigData | |
| 138 | - * @param data | |
| 139 | - * @param line | |
| 140 | - * @return true if line contains opacity value | |
| 141 | - */ | |
| 142 | - private static boolean setOpacity(ConfigData data, String line) { | |
| 143 | - Matcher matcher = RE_OPACITY.matcher(line); | |
| 144 | - if ( matcher.matches() ) { | |
| 145 | - String num = matcher.group(1); | |
| 146 | - int i = Integer.parseInt(num); // in percent | |
| 147 | - if (i > MAX_OPACITY_IN_PERCENTAGE) { | |
| 148 | - data.opacity = MAX_OPACITY_IN_PERCENTAGE; | |
| 149 | - } else if (i < MIN_OPACITY_IN_PERCENTAGE) { | |
| 150 | - data.opacity = MIN_OPACITY_IN_PERCENTAGE; | |
| 151 | - } else { | |
| 152 | - float f = ((float) i / MAX_OPACITY_IN_PERCENTAGE); | |
| 153 | - data.opacity = f; | |
| 154 | - } | |
| 155 | - return true; | |
| 156 | - } | |
| 157 | - return false; | |
| 158 | - } | |
| 159 | - | |
| 160 | - /** | |
| 161 | - * set new interval value to ConfigData | |
| 162 | - * @param data | |
| 163 | - * @param line | |
| 164 | - * @return true if line contains interval value | |
| 165 | - */ | |
| 166 | - private static boolean setInterval(ConfigData data, String line) { | |
| 167 | - Matcher matcher = RE_INTERVAL.matcher(line); | |
| 168 | - if ( matcher.matches() ) { | |
| 169 | - String num = matcher.group(1); | |
| 170 | - String unit = matcher.group(2).toLowerCase(); // s | m | h | |
| 171 | - | |
| 172 | - long i = Long.parseLong(num); | |
| 173 | - if (unit.equals("s")) { | |
| 174 | - i = i * 1000; | |
| 175 | - } else if (unit.equals("m")) { | |
| 176 | - i = i * 60 * 1000; | |
| 177 | - } else if (unit.equals("h")) { | |
| 178 | - i = i * 60 * 60 * 1000; | |
| 179 | - } | |
| 180 | - | |
| 181 | - // validate range | |
| 182 | - if (i > MAX_INTERVAL) { | |
| 183 | - data.interval = MAX_INTERVAL; | |
| 184 | - } else if (i < MIN_INTERVAL) { | |
| 185 | - data.interval = MIN_INTERVAL; | |
| 186 | - } else { | |
| 187 | - data.interval = i; | |
| 188 | - } | |
| 189 | - return true; | |
| 190 | - } | |
| 191 | - return false; | |
| 192 | - } | |
| 193 | - | |
| 194 | - /** | |
| 195 | - * set new script URI to ConfigData | |
| 196 | - * @param data | |
| 197 | - * @param line | |
| 198 | - * @return true if line contains script URI | |
| 199 | - */ | |
| 200 | - private static boolean setScript(ConfigData data, String line) { | |
| 201 | - Matcher matcher = RE_SCRIPT.matcher(line); | |
| 202 | - if ( matcher.matches() ) { | |
| 203 | - data.script = line; | |
| 204 | - return true; | |
| 205 | - } | |
| 206 | - return false; | |
| 207 | - } | |
| 208 | - | |
| 209 | - /** | |
| 210 | - * add new source URI to ConfigData | |
| 211 | - * @param data | |
| 212 | - * @param line | |
| 213 | - * @return true if line contains source URI | |
| 214 | - */ | |
| 215 | - private static boolean addSource(ConfigData data, String line) { | |
| 216 | - Matcher matcher = RE_SOURCE.matcher(line); | |
| 217 | - if ( matcher.matches() ) { | |
| 218 | - data.source.add(line); | |
| 219 | - return true; | |
| 220 | - } | |
| 221 | - return false; | |
| 222 | - } | |
| 223 | - | |
| 224 | - /** | |
| 225 | - * | |
| 226 | - * @param source | |
| 227 | - * @return URL object or File object (file only) | |
| 228 | - */ | |
| 229 | - private static HashSet<Object> getFlattenSources(Set<String> source) { | |
| 230 | - HashSet<Object> newSource = new HashSet<Object>(); // should be unique | |
| 231 | - for (String s: source) { | |
| 232 | - try { | |
| 233 | - if (RE_HTTP_OR_HTTPS_PROTOCOL.matcher(s.toLowerCase()).matches()) { | |
| 234 | - newSource.add(new URL(s)); | |
| 235 | - } else { | |
| 236 | - File file = new File(s); | |
| 237 | - // Single file and image file ? | |
| 238 | - if (file.isFile() && RE_HAS_IMAGE_EXTENSION.matcher(s.toLowerCase()).matches()) { | |
| 239 | - newSource.add(file); | |
| 240 | - } else if (file.isDirectory()) { | |
| 241 | - File[] listFiles = file.listFiles(new FileFilter() { | |
| 242 | - @Override | |
| 243 | - public boolean accept(File f) { | |
| 244 | - if (f.isFile()) { | |
| 245 | - String fileName = f.getName().toLowerCase(); | |
| 246 | - if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches() || | |
| 247 | - RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 248 | - return true; | |
| 249 | - } | |
| 250 | - } | |
| 251 | - return false; | |
| 252 | - } | |
| 253 | - }); | |
| 254 | - for (File f: listFiles) { | |
| 255 | - String fileName = f.getName().toLowerCase(); | |
| 256 | - // image file | |
| 257 | - if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches()) { | |
| 258 | - newSource.add(file); | |
| 259 | - // internet shortcut | |
| 260 | - } else if (RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 261 | - URL url = MoeUtil.getURL(file); | |
| 262 | - if (url != null) { | |
| 263 | - newSource.add(url); | |
| 264 | - } | |
| 265 | - } | |
| 266 | - } | |
| 267 | - } | |
| 268 | - } | |
| 269 | - } catch (Exception ex) { | |
| 270 | - Log.log(ex); | |
| 271 | - } | |
| 272 | - } | |
| 273 | - return newSource; | |
| 274 | - } | |
| 275 | - | |
| 276 | - private static String getScriptInPluginDir() { | |
| 277 | - try { | |
| 278 | - File file = new File(MoeUtil.getPluginJarDir(), SCRIPT_FILE_NAME); | |
| 279 | - if (file.isFile()) { | |
| 280 | - return file.getCanonicalPath(); | |
| 281 | - } | |
| 282 | - } catch (Exception ex) { /* ignore */ } | |
| 283 | - return ""; | |
| 284 | - } | |
| 285 | - | |
| 286 | - private static HashSet<Object> getSourcesInPluginDir() { | |
| 287 | - HashSet<Object> newSource = new HashSet<Object>(); // should be unique | |
| 288 | - try { | |
| 289 | - File dir = MoeUtil.getPluginJarDir(); | |
| 290 | - File[] listFiles = dir.listFiles(new FileFilter() { | |
| 291 | - @Override | |
| 292 | - public boolean accept(File f) { | |
| 293 | - if (f.isFile()) { | |
| 294 | - String fileName = f.getName().toLowerCase(); | |
| 295 | - if (RE_SOURCE_IN_PLUGIN_DIR.matcher(fileName).matches()) { | |
| 296 | - return true; | |
| 297 | - } | |
| 298 | - } | |
| 299 | - return false; | |
| 300 | - } | |
| 301 | - }); | |
| 302 | - for (File f: listFiles) { | |
| 303 | - String fileName = f.getName().toLowerCase(); | |
| 304 | - // image file | |
| 305 | - if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches()) { | |
| 306 | - newSource.add(f); | |
| 307 | - // internet shortcut | |
| 308 | - } else if (RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 309 | - URL url = MoeUtil.getURL(f); | |
| 310 | - if (url != null) { | |
| 311 | - newSource.add(url); | |
| 312 | - } | |
| 313 | - } | |
| 314 | - } | |
| 315 | - } catch (Exception ex) { /* ignore */ } | |
| 316 | - return newSource; | |
| 317 | - } | |
| 318 | - | |
| 319 | - private static class ConfigData { | |
| 320 | - protected float opacity; // 0.0f <--> 1.0f | |
| 321 | - protected long interval; // by milliseconds | |
| 322 | - protected String script; | |
| 323 | - protected Set<String> source; | |
| 324 | - } | |
| 325 | -} | |
| 326 | - |
| @@ -0,0 +1,70 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import com.vlsolutions.swing.docking.DockViewTitleBar; | |
| 20 | +import com.vlsolutions.swing.docking.ui.DockViewTitleBarUI; | |
| 21 | +import java.awt.Color; | |
| 22 | +import java.awt.Graphics; | |
| 23 | +import java.awt.Graphics2D; | |
| 24 | +import javax.swing.JComponent; | |
| 25 | +import javax.swing.UIManager; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * | |
| 29 | + * @author Yu-Tang | |
| 30 | + */ | |
| 31 | +public class MoeDockViewTitleBarUI extends DockViewTitleBarUI { | |
| 32 | + | |
| 33 | + /* hack to use custom painting except on mac os (ugly opacity effects) */ | |
| 34 | + private static boolean useCustomPaint = System.getProperty("os.name"). | |
| 35 | + toLowerCase().indexOf("mac os") < 0; | |
| 36 | + | |
| 37 | + /* Alpha value for transparency (0-255) */ | |
| 38 | + private static int activeAlpha = 150; // transparent 0 <- ... -> 255 opaque | |
| 39 | + private static int inactiveAlpha = 100; // transparent 0 <- ... -> 255 opaque | |
| 40 | + | |
| 41 | + private Color activePanelColor = MoeDockViewTitleBarUI.makeTranslucentColor( | |
| 42 | + UIManager.getColor("Panel.background"), activeAlpha); | |
| 43 | + private Color inactivePanelColor = MoeDockViewTitleBarUI.makeTranslucentColor( | |
| 44 | + UIManager.getColor("Panel.background"), inactiveAlpha); | |
| 45 | + //private Color highlight = makeTranslucent(UIManager.getColor("controlLtHighlight")); | |
| 46 | + | |
| 47 | + | |
| 48 | + public MoeDockViewTitleBarUI(DockViewTitleBar tb) { | |
| 49 | + super(tb); | |
| 50 | + } | |
| 51 | + | |
| 52 | + @Override | |
| 53 | + public void paint(Graphics g, JComponent c) { | |
| 54 | + if (MoeDockViewTitleBarUI.useCustomPaint) { | |
| 55 | + DockViewTitleBar tb = (DockViewTitleBar)c; | |
| 56 | + | |
| 57 | + Graphics2D g2 = (Graphics2D) g.create(); | |
| 58 | + g2.setColor(tb.isActive() ? activePanelColor : inactivePanelColor); | |
| 59 | + g2.fillRect(0, 0, tb.getWidth(), tb.getHeight()); // emptyborder doesnt repaint | |
| 60 | + g2.dispose(); | |
| 61 | + } else { | |
| 62 | + super.paint(g, c); | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + private static Color makeTranslucentColor(Color color, int alpha) { | |
| 67 | + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); | |
| 68 | + } | |
| 69 | + | |
| 70 | +} |
| @@ -0,0 +1,36 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import javax.swing.JOptionPane; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * | |
| 23 | + * @author Yu-Tang | |
| 24 | + */ | |
| 25 | +public class MoeVersionInfo { | |
| 26 | + | |
| 27 | + private static final String APP_NAME = "Moenizer"; | |
| 28 | + private static final String APP_VERSION = "0.1"; | |
| 29 | + private static final String APP_BUILD = "20130806"; | |
| 30 | + private static final String APP_AUTHOR = "Yu-Tang"; | |
| 31 | + | |
| 32 | + public static void main(String[] args) { | |
| 33 | + JOptionPane.showMessageDialog(null, | |
| 34 | + APP_NAME + " ver." + APP_VERSION + "." + APP_BUILD + "\nby " + APP_AUTHOR); | |
| 35 | + } | |
| 36 | +} |
| @@ -0,0 +1,326 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import java.io.File; | |
| 20 | +import java.io.FileFilter; | |
| 21 | +import java.net.URL; | |
| 22 | +import java.util.HashSet; | |
| 23 | +import java.util.Set; | |
| 24 | +import java.util.regex.Matcher; | |
| 25 | +import java.util.regex.Pattern; | |
| 26 | +import org.omegat.util.FileUtil; | |
| 27 | +import org.omegat.util.Log; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * | |
| 31 | + * @author Yu-Tang | |
| 32 | + */ | |
| 33 | +public class MoeConfig { | |
| 34 | + private static final String CONFIG_FILE_NAME = "moenizer.conf"; | |
| 35 | + private static final String SCRIPT_FILE_NAME = "moenizer.groovy"; | |
| 36 | + | |
| 37 | + private static final float DEFAULT_OPACITY = 0.5f; | |
| 38 | + private static final int MAX_OPACITY_IN_PERCENTAGE = 100; // Opaque | |
| 39 | + private static final int MIN_OPACITY_IN_PERCENTAGE = 0; // Transparent | |
| 40 | + | |
| 41 | + private static final long DEFAULT_INTERVAL = 60L * 1000L; // 1 minute in milliseconds | |
| 42 | + private static final long MAX_INTERVAL = 86400L * 1000L; // 24 hours | |
| 43 | + private static final long MIN_INTERVAL = 3L * 1000L; // 3 seconds | |
| 44 | + | |
| 45 | + private static final Pattern RE_LINEBREAK = Pattern.compile("[\\n\\r]+"); | |
| 46 | + private static final Pattern RE_OPACITY = Pattern.compile("(\\d+)\\s*%$"); | |
| 47 | + private static final Pattern RE_INTERVAL = Pattern.compile("(\\d+)\\s*([msh])", Pattern.CASE_INSENSITIVE); | |
| 48 | + private static final Pattern RE_SCRIPT = Pattern.compile("(?:/|\\\\\\\\[^\\\\]|[a-zA-Z]:\\\\).+\\.groovy"); | |
| 49 | + private static final Pattern RE_SOURCE = Pattern.compile("(?:http://|https://|/|\\\\\\\\[^\\\\]|[a-zA-Z]:\\\\).+"); | |
| 50 | + private static final Pattern RE_HAS_IMAGE_EXTENSION = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif)"); | |
| 51 | + private static final Pattern RE_HAS_INTERNET_SHORTCUT_EXTENSION = Pattern.compile(".+\\.(?:url|website|webloc)"); | |
| 52 | + private static final Pattern RE_HTTP_OR_HTTPS_PROTOCOL = Pattern.compile("(?:http://|https://).+"); | |
| 53 | + private static final Pattern RE_SOURCE_IN_PLUGIN_DIR = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif|url|website|webloc)"); | |
| 54 | + | |
| 55 | + private static ConfigData data; | |
| 56 | + private static HashSet<Object> sources; | |
| 57 | + | |
| 58 | + static { | |
| 59 | + // load config from file | |
| 60 | + ConfigData cd = loadConfig(); | |
| 61 | + | |
| 62 | + // flatten source dir to files (images only) | |
| 63 | + HashSet<Object> flattenSources = getFlattenSources(cd.source); | |
| 64 | + | |
| 65 | + // scan plugin dir if both sources and script are empty | |
| 66 | + if (flattenSources.isEmpty() && cd.script.isEmpty()) { | |
| 67 | + cd.script = getScriptInPluginDir(); | |
| 68 | + flattenSources = getSourcesInPluginDir(); | |
| 69 | + } | |
| 70 | + | |
| 71 | + // set default interval if current interval is 0 and has multiple sources | |
| 72 | + if (cd.interval == 0 && flattenSources.size() > 1) { | |
| 73 | + cd.interval = DEFAULT_INTERVAL; | |
| 74 | + } | |
| 75 | + | |
| 76 | + data = cd; | |
| 77 | + sources = flattenSources; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public static long getInterval() { | |
| 81 | + return data.interval; | |
| 82 | + } | |
| 83 | + | |
| 84 | + public static float getOpacity() { | |
| 85 | + return data.opacity; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public static File getScript() { | |
| 89 | + return data.script.isEmpty() ? null : new File(data.script); | |
| 90 | + } | |
| 91 | + | |
| 92 | + public static Object[] getSources() { | |
| 93 | + return sources.toArray(); | |
| 94 | + } | |
| 95 | + | |
| 96 | + | |
| 97 | + private static ConfigData loadConfig() { | |
| 98 | + ConfigData data = getDefaultConfig(); | |
| 99 | + try { | |
| 100 | + File file = new File(MoeUtil.getPluginJarDir(), CONFIG_FILE_NAME); | |
| 101 | + if ( file.isFile() ) { | |
| 102 | + String text = FileUtil.readTextFile(file); | |
| 103 | + String[] lines = RE_LINEBREAK.split(text); | |
| 104 | + for (String line: lines) { | |
| 105 | + if ( ! line.isEmpty() ) { | |
| 106 | + if (setOpacity(data, line) == true) { | |
| 107 | + // probably opacity value is changed from default | |
| 108 | + } else if (setInterval(data, line) == true) { | |
| 109 | + // probably interval value is changed from default | |
| 110 | + } else if (setScript(data, line) == true) { | |
| 111 | + // script URI | |
| 112 | + } else if (addSource(data, line) == true) { | |
| 113 | + // source URI (image) | |
| 114 | + } else { | |
| 115 | + // ignore | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + } else { | |
| 120 | + } | |
| 121 | + } catch (Exception ex) { | |
| 122 | + Log.log(ex); | |
| 123 | + } | |
| 124 | + return data; | |
| 125 | + } | |
| 126 | + | |
| 127 | + private static ConfigData getDefaultConfig() { | |
| 128 | + ConfigData cd = new ConfigData(); | |
| 129 | + cd.opacity = DEFAULT_OPACITY; | |
| 130 | + cd.interval = 0L; | |
| 131 | + cd.script = ""; | |
| 132 | + cd.source = new HashSet<String>(); // should be unique | |
| 133 | + return cd; | |
| 134 | + } | |
| 135 | + | |
| 136 | + /** | |
| 137 | + * set new opacity value to ConfigData | |
| 138 | + * @param data | |
| 139 | + * @param line | |
| 140 | + * @return true if line contains opacity value | |
| 141 | + */ | |
| 142 | + private static boolean setOpacity(ConfigData data, String line) { | |
| 143 | + Matcher matcher = RE_OPACITY.matcher(line); | |
| 144 | + if ( matcher.matches() ) { | |
| 145 | + String num = matcher.group(1); | |
| 146 | + int i = Integer.parseInt(num); // in percent | |
| 147 | + if (i > MAX_OPACITY_IN_PERCENTAGE) { | |
| 148 | + data.opacity = MAX_OPACITY_IN_PERCENTAGE; | |
| 149 | + } else if (i < MIN_OPACITY_IN_PERCENTAGE) { | |
| 150 | + data.opacity = MIN_OPACITY_IN_PERCENTAGE; | |
| 151 | + } else { | |
| 152 | + float f = ((float) i / MAX_OPACITY_IN_PERCENTAGE); | |
| 153 | + data.opacity = f; | |
| 154 | + } | |
| 155 | + return true; | |
| 156 | + } | |
| 157 | + return false; | |
| 158 | + } | |
| 159 | + | |
| 160 | + /** | |
| 161 | + * set new interval value to ConfigData | |
| 162 | + * @param data | |
| 163 | + * @param line | |
| 164 | + * @return true if line contains interval value | |
| 165 | + */ | |
| 166 | + private static boolean setInterval(ConfigData data, String line) { | |
| 167 | + Matcher matcher = RE_INTERVAL.matcher(line); | |
| 168 | + if ( matcher.matches() ) { | |
| 169 | + String num = matcher.group(1); | |
| 170 | + String unit = matcher.group(2).toLowerCase(); // s | m | h | |
| 171 | + | |
| 172 | + long i = Long.parseLong(num); | |
| 173 | + if (unit.equals("s")) { | |
| 174 | + i = i * 1000; | |
| 175 | + } else if (unit.equals("m")) { | |
| 176 | + i = i * 60 * 1000; | |
| 177 | + } else if (unit.equals("h")) { | |
| 178 | + i = i * 60 * 60 * 1000; | |
| 179 | + } | |
| 180 | + | |
| 181 | + // validate range | |
| 182 | + if (i > MAX_INTERVAL) { | |
| 183 | + data.interval = MAX_INTERVAL; | |
| 184 | + } else if (i < MIN_INTERVAL) { | |
| 185 | + data.interval = MIN_INTERVAL; | |
| 186 | + } else { | |
| 187 | + data.interval = i; | |
| 188 | + } | |
| 189 | + return true; | |
| 190 | + } | |
| 191 | + return false; | |
| 192 | + } | |
| 193 | + | |
| 194 | + /** | |
| 195 | + * set new script URI to ConfigData | |
| 196 | + * @param data | |
| 197 | + * @param line | |
| 198 | + * @return true if line contains script URI | |
| 199 | + */ | |
| 200 | + private static boolean setScript(ConfigData data, String line) { | |
| 201 | + Matcher matcher = RE_SCRIPT.matcher(line); | |
| 202 | + if ( matcher.matches() ) { | |
| 203 | + data.script = line; | |
| 204 | + return true; | |
| 205 | + } | |
| 206 | + return false; | |
| 207 | + } | |
| 208 | + | |
| 209 | + /** | |
| 210 | + * add new source URI to ConfigData | |
| 211 | + * @param data | |
| 212 | + * @param line | |
| 213 | + * @return true if line contains source URI | |
| 214 | + */ | |
| 215 | + private static boolean addSource(ConfigData data, String line) { | |
| 216 | + Matcher matcher = RE_SOURCE.matcher(line); | |
| 217 | + if ( matcher.matches() ) { | |
| 218 | + data.source.add(line); | |
| 219 | + return true; | |
| 220 | + } | |
| 221 | + return false; | |
| 222 | + } | |
| 223 | + | |
| 224 | + /** | |
| 225 | + * | |
| 226 | + * @param source | |
| 227 | + * @return URL object or File object (file only) | |
| 228 | + */ | |
| 229 | + private static HashSet<Object> getFlattenSources(Set<String> source) { | |
| 230 | + HashSet<Object> newSource = new HashSet<Object>(); // should be unique | |
| 231 | + for (String s: source) { | |
| 232 | + try { | |
| 233 | + if (RE_HTTP_OR_HTTPS_PROTOCOL.matcher(s.toLowerCase()).matches()) { | |
| 234 | + newSource.add(new URL(s)); | |
| 235 | + } else { | |
| 236 | + File file = new File(s); | |
| 237 | + // Single file and image file ? | |
| 238 | + if (file.isFile() && RE_HAS_IMAGE_EXTENSION.matcher(s.toLowerCase()).matches()) { | |
| 239 | + newSource.add(file); | |
| 240 | + } else if (file.isDirectory()) { | |
| 241 | + File[] listFiles = file.listFiles(new FileFilter() { | |
| 242 | + @Override | |
| 243 | + public boolean accept(File f) { | |
| 244 | + if (f.isFile()) { | |
| 245 | + String fileName = f.getName().toLowerCase(); | |
| 246 | + if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches() || | |
| 247 | + RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 248 | + return true; | |
| 249 | + } | |
| 250 | + } | |
| 251 | + return false; | |
| 252 | + } | |
| 253 | + }); | |
| 254 | + for (File f: listFiles) { | |
| 255 | + String fileName = f.getName().toLowerCase(); | |
| 256 | + // image file | |
| 257 | + if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches()) { | |
| 258 | + newSource.add(file); | |
| 259 | + // internet shortcut | |
| 260 | + } else if (RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 261 | + URL url = MoeUtil.getURL(file); | |
| 262 | + if (url != null) { | |
| 263 | + newSource.add(url); | |
| 264 | + } | |
| 265 | + } | |
| 266 | + } | |
| 267 | + } | |
| 268 | + } | |
| 269 | + } catch (Exception ex) { | |
| 270 | + Log.log(ex); | |
| 271 | + } | |
| 272 | + } | |
| 273 | + return newSource; | |
| 274 | + } | |
| 275 | + | |
| 276 | + private static String getScriptInPluginDir() { | |
| 277 | + try { | |
| 278 | + File file = new File(MoeUtil.getPluginJarDir(), SCRIPT_FILE_NAME); | |
| 279 | + if (file.isFile()) { | |
| 280 | + return file.getCanonicalPath(); | |
| 281 | + } | |
| 282 | + } catch (Exception ex) { /* ignore */ } | |
| 283 | + return ""; | |
| 284 | + } | |
| 285 | + | |
| 286 | + private static HashSet<Object> getSourcesInPluginDir() { | |
| 287 | + HashSet<Object> newSource = new HashSet<Object>(); // should be unique | |
| 288 | + try { | |
| 289 | + File dir = MoeUtil.getPluginJarDir(); | |
| 290 | + File[] listFiles = dir.listFiles(new FileFilter() { | |
| 291 | + @Override | |
| 292 | + public boolean accept(File f) { | |
| 293 | + if (f.isFile()) { | |
| 294 | + String fileName = f.getName().toLowerCase(); | |
| 295 | + if (RE_SOURCE_IN_PLUGIN_DIR.matcher(fileName).matches()) { | |
| 296 | + return true; | |
| 297 | + } | |
| 298 | + } | |
| 299 | + return false; | |
| 300 | + } | |
| 301 | + }); | |
| 302 | + for (File f: listFiles) { | |
| 303 | + String fileName = f.getName().toLowerCase(); | |
| 304 | + // image file | |
| 305 | + if (RE_HAS_IMAGE_EXTENSION.matcher(fileName).matches()) { | |
| 306 | + newSource.add(f); | |
| 307 | + // internet shortcut | |
| 308 | + } else if (RE_HAS_INTERNET_SHORTCUT_EXTENSION.matcher(fileName).matches()) { | |
| 309 | + URL url = MoeUtil.getURL(f); | |
| 310 | + if (url != null) { | |
| 311 | + newSource.add(url); | |
| 312 | + } | |
| 313 | + } | |
| 314 | + } | |
| 315 | + } catch (Exception ex) { /* ignore */ } | |
| 316 | + return newSource; | |
| 317 | + } | |
| 318 | + | |
| 319 | + private static class ConfigData { | |
| 320 | + protected float opacity; // 0.0f <--> 1.0f | |
| 321 | + protected long interval; // by milliseconds | |
| 322 | + protected String script; | |
| 323 | + protected Set<String> source; | |
| 324 | + } | |
| 325 | +} | |
| 326 | + |
| @@ -0,0 +1,135 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import java.awt.image.BufferedImage; | |
| 20 | +import java.io.IOException; | |
| 21 | +import java.util.concurrent.TimeUnit; | |
| 22 | +import java.util.logging.Level; | |
| 23 | +import java.util.logging.Logger; | |
| 24 | +import javax.swing.SwingUtilities; | |
| 25 | +import javax.swing.SwingWorker; | |
| 26 | +import org.omegat.core.CoreEvents; | |
| 27 | +import org.omegat.core.events.IApplicationEventListener; | |
| 28 | +import org.omegat.core.events.IProjectEventListener; | |
| 29 | +import jp.sourceforge.users.yutang.omegat.plugin.moenizer.imageloader.IImageLoader; | |
| 30 | +import jp.sourceforge.users.yutang.omegat.plugin.moenizer.imageloader.ImageLoader; | |
| 31 | +import org.omegat.util.Log; | |
| 32 | +import org.omegat.util.StaticUtils; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * allow to set background image | |
| 36 | + * | |
| 37 | + * @author Yu-Tang | |
| 38 | + */ | |
| 39 | +public class Moenizer implements IApplicationEventListener, IProjectEventListener { | |
| 40 | + | |
| 41 | + private IImageLoader imageLoader; | |
| 42 | + private MoeUI ui; | |
| 43 | + | |
| 44 | + | |
| 45 | + @SuppressWarnings("LeakingThisInConstructor") | |
| 46 | + public Moenizer() { | |
| 47 | + CoreEvents.registerApplicationEventListener(this); | |
| 48 | + CoreEvents.registerProjectChangeListener(this); | |
| 49 | + | |
| 50 | + ui = null; | |
| 51 | + imageLoader = ImageLoader.getInstance(); | |
| 52 | + // この時点ではまだウィンドウがインスタンス化されていないので、 | |
| 53 | + // ウィンドウに対する処理は少し待つ。 | |
| 54 | + | |
| 55 | + (new SlideShow()).execute(); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public void onApplicationStartup() { | |
| 60 | + try { | |
| 61 | + ui = MoeUI.getMoeUI(); | |
| 62 | + | |
| 63 | + // この時点でコンポーネントの透過設定をしても反映されない(タイミング?)。 | |
| 64 | + // Workaround として、invokeLater でキューに突っ込んで、後で処理する。 | |
| 65 | + SwingUtilities.invokeLater(new Runnable() { | |
| 66 | + @Override | |
| 67 | + public void run() { | |
| 68 | + CoreEvents.unregisterApplicationEventListener(Moenizer.this); | |
| 69 | + ui.transparent(); | |
| 70 | + } | |
| 71 | + }); | |
| 72 | + //CoreEvents.unregisterApplicationEventListener(this); // ここで発行すると、スレッドエラーになるので注意 | |
| 73 | + } catch(Exception e) { | |
| 74 | + Log.log("Error raised at " + this.getClass().getCanonicalName() + ".onApplicationStartup()\n" + e); | |
| 75 | + } | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 79 | + public void onApplicationShutdown() { | |
| 80 | + // not used. | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 84 | + public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
| 85 | + switch (eventType) { | |
| 86 | + case CREATE: | |
| 87 | + case LOAD: | |
| 88 | + // ここですぐ透過処理をしてもうまく適用されないので、後まわしにする。 | |
| 89 | + SwingUtilities.invokeLater(new Runnable() { | |
| 90 | + @Override | |
| 91 | + public void run() { | |
| 92 | + CoreEvents.unregisterProjectChangeListener(Moenizer.this); | |
| 93 | + ui.transparentEditor(); | |
| 94 | + } | |
| 95 | + }); | |
| 96 | + | |
| 97 | + // 一回 Editor の透過処理をしたら、透過状態が維持されるので、二回目 | |
| 98 | + // 以降は、透過処理は不要。 | |
| 99 | + //CoreEvents.unregisterProjectChangeListener(this); // ここで発行すると、スレッドエラーになるので注意 | |
| 100 | + break; | |
| 101 | + case CLOSE: | |
| 102 | + break; | |
| 103 | + } | |
| 104 | + } | |
| 105 | + | |
| 106 | + private class SlideShow extends SwingWorker<Object, Void> { | |
| 107 | + private long interval = -1; | |
| 108 | + | |
| 109 | + @Override | |
| 110 | + protected Object doInBackground() throws Exception { | |
| 111 | + while (imageLoader.availableNext()) { | |
| 112 | + imageLoader.readyForNextImage(); | |
| 113 | + interval = interval < 0 ? 0 : imageLoader.getNextInterval(); | |
| 114 | + if (interval > 0) { | |
| 115 | + try { | |
| 116 | + TimeUnit.MILLISECONDS.sleep(interval); | |
| 117 | + } catch (InterruptedException e) { /* ignore */ } | |
| 118 | + } | |
| 119 | + BufferedImage image = imageLoader.getNextImage(); | |
| 120 | + | |
| 121 | + if (image != null) { | |
| 122 | + // 初期化直後に、まだ MoeUI がインスタンス化されていない | |
| 123 | + // 空白時間に遭遇する可能性があるため、その場合は 0.1 秒 | |
| 124 | + // 単位で MoeUI のインスタンス化を待機する。 | |
| 125 | + while (ui == null) { | |
| 126 | + TimeUnit.MILLISECONDS.sleep(100); | |
| 127 | + } | |
| 128 | + ui.setBackground(image); | |
| 129 | + } | |
| 130 | + } | |
| 131 | + return null; | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 135 | +} |
| @@ -0,0 +1,60 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | + | |
| 19 | +import java.awt.image.BufferedImage; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * Interface for Image Loader | |
| 23 | + * | |
| 24 | + * calling order is: | |
| 25 | + * 1. availableNext() ... exit from loop if returned false | |
| 26 | + * 2. readyForNextImage() | |
| 27 | + * 3. getNextInterval() ... skiped first time | |
| 28 | + * 4. getNextImage() | |
| 29 | + * ... loop back to step 1 | |
| 30 | + * | |
| 31 | + * @author Yu-Tang | |
| 32 | + */ | |
| 33 | +public interface IImageLoader { | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * get if next image available. | |
| 37 | + * @return bool. | |
| 38 | + */ | |
| 39 | + boolean availableNext(); | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * get next interval. | |
| 43 | + * This method is not called at first time loop. | |
| 44 | + * @return long by milliseconds | |
| 45 | + */ | |
| 46 | + long getNextInterval(); | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Do anything should be done for the next image. | |
| 50 | + * Calling before getNextImage(). | |
| 51 | + */ | |
| 52 | + void readyForNextImage(); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * get next image. | |
| 56 | + * @return BufferedImage object. Can be null if image is not available. | |
| 57 | + */ | |
| 58 | + BufferedImage getNextImage(); | |
| 59 | + | |
| 60 | +} |
| @@ -0,0 +1,56 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | + | |
| 19 | +import java.lang.reflect.Method; | |
| 20 | +import java.net.URL; | |
| 21 | +import static jp.sourceforge.users.yutang.omegat.plugin.moenizer.MoeConfig.*; | |
| 22 | +import org.omegat.util.Log; | |
| 23 | + | |
| 24 | +/** | |
| 25 | + * | |
| 26 | + * @author Yu-Tang | |
| 27 | + */ | |
| 28 | +public class ImageLoader { | |
| 29 | + | |
| 30 | + public static IImageLoader getInstance() { | |
| 31 | + Object[] sources = getSources(); | |
| 32 | + | |
| 33 | + if (sources.length == 0) { | |
| 34 | + return null; // no source, no need loader | |
| 35 | + } | |
| 36 | + | |
| 37 | + // default | |
| 38 | + return new DefaultImageLoader(); | |
| 39 | + } | |
| 40 | + | |
| 41 | + private static Object getAcceptableSource(Class<?> c, Object[] sources) { | |
| 42 | + for (Object source: sources) { | |
| 43 | + try { | |
| 44 | + Method method = c.getDeclaredMethod("isAcceptable", new Class[]{ Object.class }); | |
| 45 | + boolean isAcceptable = (Boolean) method.invoke(null, source); | |
| 46 | + if (isAcceptable) { | |
| 47 | + return source; | |
| 48 | + } | |
| 49 | + } catch (Exception ex) { | |
| 50 | + Log.log(ex); | |
| 51 | + } | |
| 52 | + } | |
| 53 | + return null; | |
| 54 | + } | |
| 55 | + | |
| 56 | +} |
| @@ -0,0 +1,162 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer.imageloader; | |
| 18 | + | |
| 19 | +import java.awt.image.BufferedImage; | |
| 20 | +import java.io.File; | |
| 21 | +import java.net.URL; | |
| 22 | +import java.util.regex.Pattern; | |
| 23 | +import javax.imageio.ImageIO; | |
| 24 | +import static jp.sourceforge.users.yutang.omegat.plugin.moenizer.MoeConfig.*; | |
| 25 | +import org.omegat.util.Log; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * Default image loader. | |
| 29 | + * | |
| 30 | + * calling order is: | |
| 31 | + * 1. availableNext() ... exit if returned false | |
| 32 | + * 2. readyForNextImage() | |
| 33 | + * 3. getNextInterval() ... skipped first time | |
| 34 | + * 4. getNextImage() | |
| 35 | + * ... loop back to step 1 | |
| 36 | + * | |
| 37 | + * @author Yu-Tang | |
| 38 | + */ | |
| 39 | +public class DefaultImageLoader implements IImageLoader { | |
| 40 | + | |
| 41 | + private static final Pattern RE_HAS_IMAGE_EXTENSION = Pattern.compile(".+\\.(?:bmp|png|jpg|jpeg|gif)"); | |
| 42 | + private long interval; | |
| 43 | + private Object[] sources; | |
| 44 | + private Object currentSource; | |
| 45 | + private int sourceIndex; | |
| 46 | + | |
| 47 | + protected BufferedImage image; | |
| 48 | + | |
| 49 | + public DefaultImageLoader() { | |
| 50 | + interval = getInterval(); | |
| 51 | + sources = getSources(); | |
| 52 | + currentSource = null; | |
| 53 | + image = null; | |
| 54 | + sourceIndex = -1; | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * get if source is acceptable. | |
| 59 | + * @return bool. | |
| 60 | + */ | |
| 61 | + public static boolean isAcceptable(Object source) { | |
| 62 | + if (source instanceof URL) { | |
| 63 | + return true; | |
| 64 | + } else if (source instanceof File) { | |
| 65 | + String name = ((File) source).getName().toLowerCase(); | |
| 66 | + if (RE_HAS_IMAGE_EXTENSION.matcher(name).matches()) { | |
| 67 | + return true; | |
| 68 | + } | |
| 69 | + } | |
| 70 | + return false; | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public boolean availableNext() { | |
| 75 | + boolean ret = false; | |
| 76 | + if (sources.length == 0) { | |
| 77 | + // it's over! | |
| 78 | + } else if (sources.length == 1) { | |
| 79 | + if (currentSource == null || interval > 0) { // first time or refresh | |
| 80 | + currentSource = sources[0]; | |
| 81 | + ret = true; | |
| 82 | + } | |
| 83 | + } else { | |
| 84 | + currentSource = getCircularNextSource(); | |
| 85 | + ret = true; | |
| 86 | + } | |
| 87 | + return ret; | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * get next image. | |
| 92 | + * @return BufferedImage object. Can be null if image is not available. | |
| 93 | + */ | |
| 94 | + @Override | |
| 95 | + public BufferedImage getNextImage() { | |
| 96 | + return image; | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * Do anything should be done for the next image. | |
| 101 | + * Calling before getNextImage(). | |
| 102 | + */ | |
| 103 | + @Override | |
| 104 | + public void readyForNextImage() { | |
| 105 | + //TODO use cache | |
| 106 | + image = null; | |
| 107 | + try { | |
| 108 | + if (currentSource != null) { | |
| 109 | + if (currentSource instanceof File) { | |
| 110 | + image = ImageIO.read((File) currentSource); | |
| 111 | + } else if (currentSource instanceof URL) { | |
| 112 | + image = ImageIO.read((URL) currentSource); | |
| 113 | + } else { | |
| 114 | + removeCurrentSource(); | |
| 115 | + } | |
| 116 | + } | |
| 117 | + } catch (Exception ex) { | |
| 118 | + Log.log(ex); | |
| 119 | + removeCurrentSource(); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + /** | |
| 124 | + * get next interval. | |
| 125 | + * This method is not called at first time loop. | |
| 126 | + * @return long by milliseconds | |
| 127 | + */ | |
| 128 | + @Override | |
| 129 | + public long getNextInterval() { | |
| 130 | + return interval; | |
| 131 | + } | |
| 132 | + | |
| 133 | + private Object getCircularNextSource() { | |
| 134 | + sourceIndex++; | |
| 135 | + if (sourceIndex >= sources.length) { | |
| 136 | + sourceIndex = 0; | |
| 137 | + } | |
| 138 | + return sources[sourceIndex]; | |
| 139 | + } | |
| 140 | + | |
| 141 | + private void removeCurrentSource() { | |
| 142 | + if (sourceIndex >= 0 && sourceIndex < sources.length) { | |
| 143 | + sourceIndex = 0; // something is wrong. rewind index. | |
| 144 | + } else { | |
| 145 | + Object[] newSources = new Object[sources.length - 1]; | |
| 146 | + for (int i = 0; i < sources.length; i++) { | |
| 147 | + if ( i == sourceIndex ) { | |
| 148 | + // skip | |
| 149 | + } else if ( i < sourceIndex ) { | |
| 150 | + newSources[i] = sources[i]; | |
| 151 | + } else { | |
| 152 | + newSources[i - 1] = sources[i]; | |
| 153 | + } | |
| 154 | + } | |
| 155 | + sources = newSources; | |
| 156 | + if (sourceIndex >= sources.length) { | |
| 157 | + sourceIndex = 0; | |
| 158 | + } | |
| 159 | + } | |
| 160 | + } | |
| 161 | + | |
| 162 | +} |
| @@ -0,0 +1,88 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import java.awt.AlphaComposite; | |
| 20 | +import java.awt.Graphics; | |
| 21 | +import java.awt.Graphics2D; | |
| 22 | +import java.awt.Rectangle; | |
| 23 | +import java.awt.TexturePaint; | |
| 24 | +import java.awt.image.BufferedImage; | |
| 25 | +import javax.swing.JLayeredPane; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * | |
| 29 | + * @author Yu-Tang | |
| 30 | + */ | |
| 31 | +public class MoeLayeredPane extends JLayeredPane { | |
| 32 | + | |
| 33 | + private BufferedImage image; | |
| 34 | + private TexturePaint paint; | |
| 35 | + private float alpha; | |
| 36 | + | |
| 37 | + public MoeLayeredPane() { | |
| 38 | + super(); | |
| 39 | + this.image = null; | |
| 40 | + this.paint = null; | |
| 41 | + this.alpha = MoeConfig.getOpacity(); | |
| 42 | + } | |
| 43 | + | |
| 44 | + public MoeLayeredPane(BufferedImage image) { | |
| 45 | + super(); | |
| 46 | + setPicture(image); | |
| 47 | + this.alpha = MoeConfig.getOpacity(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + public void setBackground(BufferedImage image) { | |
| 51 | + setPicture(image); | |
| 52 | + this.repaint(); | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Override | |
| 56 | + protected void paintComponent(Graphics g) { | |
| 57 | + if (image != null) { | |
| 58 | + Graphics2D g2 = (Graphics2D)g.create(); | |
| 59 | + g2.setComposite(makeComposite(alpha)); | |
| 60 | + | |
| 61 | + if (getWidth() > image.getWidth() || getHeight() > image.getHeight()) { | |
| 62 | + g2.setPaint(paint); | |
| 63 | + g2.fillRect(0, 0, getWidth(), getHeight()); | |
| 64 | + } else { | |
| 65 | + g2.drawImage(image, 0, 0, this); | |
| 66 | + } | |
| 67 | + | |
| 68 | + g2.dispose(); | |
| 69 | + } | |
| 70 | + super.paintComponent(g); | |
| 71 | + } | |
| 72 | + | |
| 73 | + private AlphaComposite makeComposite(float alpha) { | |
| 74 | + int type = AlphaComposite.SRC_OVER; | |
| 75 | + return(AlphaComposite.getInstance(type, alpha)); | |
| 76 | + } | |
| 77 | + | |
| 78 | + private void setPicture(BufferedImage image) { | |
| 79 | + this.image = image; | |
| 80 | + | |
| 81 | + if (image == null) { | |
| 82 | + this.paint = null; | |
| 83 | + } else { | |
| 84 | + Rectangle rect = new Rectangle(image.getWidth(), image.getHeight()); | |
| 85 | + this.paint = new TexturePaint(image, rect); | |
| 86 | + } | |
| 87 | + } | |
| 88 | +} |
| @@ -0,0 +1,287 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import com.sun.java.swing.plaf.windows.WindowsMenuBarUI; | |
| 20 | +import com.vlsolutions.swing.docking.DockView; | |
| 21 | +import com.vlsolutions.swing.docking.DockViewTitleBar; | |
| 22 | +import com.vlsolutions.swing.docking.Dockable; | |
| 23 | +import com.vlsolutions.swing.docking.DockableState; | |
| 24 | +import com.vlsolutions.swing.docking.DockingDesktop; | |
| 25 | +import com.vlsolutions.swing.docking.SplitContainer; | |
| 26 | +import java.awt.Color; | |
| 27 | +import java.awt.Component; | |
| 28 | +import java.awt.Container; | |
| 29 | +import java.awt.Graphics; | |
| 30 | +import java.awt.SystemColor; | |
| 31 | +import java.awt.image.BufferedImage; | |
| 32 | +import javax.swing.JComponent; | |
| 33 | +import javax.swing.JEditorPane; | |
| 34 | +import javax.swing.JFrame; | |
| 35 | +import javax.swing.JMenuBar; | |
| 36 | +import javax.swing.JScrollPane; | |
| 37 | +import javax.swing.JTextPane; | |
| 38 | +//import javax.swing.plaf.basic.BasicMenuBarUI; | |
| 39 | +import org.omegat.core.Core; | |
| 40 | +import org.omegat.util.gui.UIThreadsUtil; | |
| 41 | + | |
| 42 | +/** | |
| 43 | + * | |
| 44 | + * @author Yu-Tang | |
| 45 | + */ | |
| 46 | +public class MoeUI { | |
| 47 | + | |
| 48 | + private static MoeUI moeUI; | |
| 49 | + | |
| 50 | + private JFrame frame; | |
| 51 | + private MoeLayeredPane layeredPane; | |
| 52 | + private Container contentPane; | |
| 53 | + private JMenuBar menuBar; | |
| 54 | + private DockingDesktop desktop; | |
| 55 | + | |
| 56 | + static { | |
| 57 | + moeUI = null; | |
| 58 | + } | |
| 59 | + | |
| 60 | + // Singleton. Not allow to Instanciate from outside. Use getMoeUI() to get instance. | |
| 61 | + private MoeUI(BufferedImage image) { | |
| 62 | + UIThreadsUtil.mustBeSwingThread(); | |
| 63 | + | |
| 64 | + initUI(image); | |
| 65 | + } | |
| 66 | + | |
| 67 | + private MoeUI() { | |
| 68 | + UIThreadsUtil.mustBeSwingThread(); | |
| 69 | + | |
| 70 | + initUI(null); | |
| 71 | + } | |
| 72 | + | |
| 73 | + public static MoeUI getMoeUI(BufferedImage image) { | |
| 74 | + if (moeUI == null) { | |
| 75 | + moeUI = new MoeUI(image); | |
| 76 | + } | |
| 77 | + return moeUI; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public static MoeUI getMoeUI() { | |
| 81 | + if (moeUI == null) { | |
| 82 | + moeUI = new MoeUI(); | |
| 83 | + } | |
| 84 | + return moeUI; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public void transparent() { | |
| 88 | + UIThreadsUtil.mustBeSwingThread(); | |
| 89 | + | |
| 90 | + transparent(menuBar); | |
| 91 | + transparentRecursive(contentPane); | |
| 92 | + transparentInstantStart(desktop); | |
| 93 | + | |
| 94 | + frame.repaint(); | |
| 95 | + } | |
| 96 | + | |
| 97 | + public void transparentEditor() { | |
| 98 | + // Editor に表示されるドキュメントは、以下のケースでまったく異なる。 | |
| 99 | + // | |
| 100 | + // 1. インスタントスタートガイドが表示されている場合(初期状態) | |
| 101 | + // -> view = JTextPane, HTMLDocument | |
| 102 | + // 2. プロジェクトをロードまたは新規作成して、分節編集画面が表示されている場合 | |
| 103 | + // -> view = JEditorPane, DefaultStyledDocument | |
| 104 | + // | |
| 105 | + // そのため、2 のタイミングで透過処理をやり直す必要がある。 | |
| 106 | + // このメソッドは、2 の透過処理専用。 | |
| 107 | + | |
| 108 | + UIThreadsUtil.mustBeSwingThread(); | |
| 109 | + | |
| 110 | + JEditorPane editor = getJEditorPaneFromEditor(desktop); | |
| 111 | + if (editor == null) { | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + | |
| 115 | + /* ここで JEditorPane に半透明の背景色を設定すると、テキストの選択(反転) | |
| 116 | + * などの色の変化が正常に更新されず色残りしてしまう。 | |
| 117 | + * そのため、JEditorPane への処理では単純に背景を透明にして、元画像自体で | |
| 118 | + * 色味を調整しておく方針とする。 | |
| 119 | + * | |
| 120 | + int alpha = 100; // transparent <- 0...255 -> opaque | |
| 121 | + Color color = SystemColor.menu; | |
| 122 | + editor.setBackground(new Color( color.getRGB() & 0xffffff | 100 << 24, true)); | |
| 123 | + * */ | |
| 124 | + editor.setOpaque(false); | |
| 125 | + frame.repaint(); | |
| 126 | + } | |
| 127 | + | |
| 128 | + public void setBackground(final BufferedImage image) { | |
| 129 | + UIThreadsUtil.executeInSwingThread(new Runnable() { | |
| 130 | + @Override | |
| 131 | + public void run() { | |
| 132 | + layeredPane.setBackground(image); | |
| 133 | + } | |
| 134 | + }); | |
| 135 | + } | |
| 136 | + | |
| 137 | + private void initUI(BufferedImage image) { | |
| 138 | + frame = Core.getMainWindow().getApplicationFrame(); | |
| 139 | + if (image == null) { | |
| 140 | + layeredPane = new MoeLayeredPane(); | |
| 141 | + } else { | |
| 142 | + layeredPane = new MoeLayeredPane(image); | |
| 143 | + } | |
| 144 | + contentPane = frame.getContentPane(); | |
| 145 | + menuBar = frame.getJMenuBar(); | |
| 146 | + desktop = getDockingDesktop(contentPane); | |
| 147 | + | |
| 148 | + // replace LayeredPane with MoeLayeredPane | |
| 149 | + frame.setLayeredPane(layeredPane); | |
| 150 | + frame.setContentPane(contentPane); | |
| 151 | + frame.setJMenuBar(menuBar); | |
| 152 | + | |
| 153 | + frame.validate(); | |
| 154 | + } | |
| 155 | + | |
| 156 | + private void transparent(JMenuBar menuBar) { | |
| 157 | +// menuBar.setUI ( new BasicMenuBarUI () { | |
| 158 | +// 上記だと初期表示時に、アクティブメニューがアクティブで描画されない。 | |
| 159 | +// マウス通過などのタイミングで再描画された際にアクティブカラーになるが、 | |
| 160 | +// 見栄えが悪いので、Windows 用の UI を指定する。 | |
| 161 | +// アクティブメニューがアクティブで描画されない問題はこれで解決するが、 | |
| 162 | +// 変わりに Mac や *nix など別 L&F 環境下では違和感があるかもしれない。 | |
| 163 | + menuBar.setUI ( new WindowsMenuBarUI () { | |
| 164 | + @Override | |
| 165 | + public void paint ( Graphics g, JComponent c ) { | |
| 166 | + int alpha = 100; // transparent <- 0...255 -> opaque | |
| 167 | + Color oldColor = g.getColor(); | |
| 168 | + Color color = SystemColor.menu; | |
| 169 | + g.setColor ( new Color( color.getRGB() & 0xffffff | alpha << 24, true)); | |
| 170 | + g.fillRect ( 0, 0, c.getWidth (), c.getHeight () ); | |
| 171 | + g.setColor ( oldColor ); // restore | |
| 172 | + } | |
| 173 | + } ); | |
| 174 | + menuBar.setOpaque(false); | |
| 175 | + } | |
| 176 | + | |
| 177 | + private void transparentRecursive(Component component) { | |
| 178 | + if (component instanceof JComponent) { | |
| 179 | + JComponent c = (JComponent) component; | |
| 180 | + if (c.isOpaque()) { | |
| 181 | + c.setOpaque(false); | |
| 182 | + } | |
| 183 | + } | |
| 184 | + | |
| 185 | + if (component instanceof Container) { | |
| 186 | + Container container = (Container) component; | |
| 187 | + for (Component c: container.getComponents()) { | |
| 188 | + transparentRecursive(c); | |
| 189 | + } | |
| 190 | + } | |
| 191 | + | |
| 192 | + if (component instanceof DockingDesktop) { | |
| 193 | + transparentRecursive((DockingDesktop) component); | |
| 194 | + } | |
| 195 | + } | |
| 196 | + | |
| 197 | + private void transparentRecursive(DockingDesktop desktop) { | |
| 198 | + //DockingPanel dockingPanel = dockingDesktop.getDockingPanel(); // Scoping NG | |
| 199 | + // DockingPanel にアクセスできないので、下位要素から上にさかのぼって処理する。 | |
| 200 | + // 階層的には、こんな感じになっている。 | |
| 201 | + // ----------------------- | |
| 202 | + // DockingDesktop | |
| 203 | + // + DockingPanel <-- splitContainer.getParent() | |
| 204 | + // + splitContainer(HORIZONTAL) <-- splitContainer.getParent() | |
| 205 | + // + splitContainer(VERTICAL) <-- DockView.getParent() | |
| 206 | + // + DockView <-- Dockable.getParent() | |
| 207 | + // + Dockable <-- DockableState.getDockable() | |
| 208 | + for (DockableState d: desktop.getDockables()) { | |
| 209 | + double width = d.getPosition().getWidth(); | |
| 210 | + // width (height や x, y でも可) が 0.0 以外の場合はアイコン化されているので、透過処理不要 | |
| 211 | + // 他に適切な判定方法がありそうだけれども、分からなかったので、とりあえずこれで。 | |
| 212 | + if (width == 0.0) { | |
| 213 | + transparentRecursive(d); | |
| 214 | + } | |
| 215 | + } | |
| 216 | + } | |
| 217 | + | |
| 218 | + private void transparentRecursive(DockableState dockableState) { | |
| 219 | + Dockable dockable = dockableState.getDockable(); | |
| 220 | + | |
| 221 | + // DockView | |
| 222 | + Container container = dockable.getComponent().getParent(); | |
| 223 | + DockView view = (DockView) container; | |
| 224 | + if (view.isOpaque()) { | |
| 225 | + view.setOpaque(false); | |
| 226 | + } | |
| 227 | + DockViewTitleBar titleBar = view.getTitleBar(); | |
| 228 | + if (titleBar.isOpaque()) { | |
| 229 | + titleBar.setOpaque(false); | |
| 230 | + } | |
| 231 | + titleBar.setUI(new MoeDockViewTitleBarUI(titleBar)); | |
| 232 | + | |
| 233 | + // SplitContainer(VERTICAL) | |
| 234 | + container = container.getParent(); | |
| 235 | + if (container == null) { | |
| 236 | + return; | |
| 237 | + } else if (container.isOpaque()) { | |
| 238 | + ((SplitContainer) container).setOpaque(false); | |
| 239 | + } | |
| 240 | + | |
| 241 | + // SplitContainer(HORIZONTAL) | |
| 242 | + container = container.getParent(); | |
| 243 | + if (container == null) { | |
| 244 | + return; | |
| 245 | + } else if (container.isOpaque()) { | |
| 246 | + ((SplitContainer) container).setOpaque(false); | |
| 247 | + } | |
| 248 | + } | |
| 249 | + | |
| 250 | + private void transparentInstantStart(DockingDesktop desktop) { | |
| 251 | + // お手軽スタートは、以下のような HTML で背景色が指定されている。 | |
| 252 | + // <body ... bgcolor="white" ...> | |
| 253 | + // そのため、コンポーネント自体を透過にしても、HTML Body 背景色の | |
| 254 | + // 白指定が効いて透過にならない。そこで、背景色指定を削除する。 | |
| 255 | + for (DockableState d: desktop.getDockables()) { | |
| 256 | + Dockable dockable = d.getDockable(); | |
| 257 | + String key = dockable.getDockKey().getKey(); | |
| 258 | + if (key.equalsIgnoreCase("EDITOR")) { // found InstantStartGuide | |
| 259 | + JScrollPane sp = (JScrollPane) dockable.getComponent(); | |
| 260 | + JTextPane tp = (JTextPane) sp.getViewport().getView(); | |
| 261 | + tp.setText(tp.getText().replace(" bgcolor=\"white\"", "")); | |
| 262 | + tp.setCaretPosition(0); | |
| 263 | + return; | |
| 264 | + } | |
| 265 | + } | |
| 266 | + } | |
| 267 | + | |
| 268 | + private DockingDesktop getDockingDesktop(Container container) { | |
| 269 | + for (Component c: container.getComponents()) { | |
| 270 | + if (c instanceof DockingDesktop) { | |
| 271 | + return (DockingDesktop) c; | |
| 272 | + } | |
| 273 | + } | |
| 274 | + return null; | |
| 275 | + } | |
| 276 | + | |
| 277 | + private JEditorPane getJEditorPaneFromEditor(DockingDesktop desktop) { | |
| 278 | + for (DockableState d: desktop.getDockables()) { | |
| 279 | + Dockable dockable = d.getDockable(); | |
| 280 | + if (dockable.getDockKey().getKey().equalsIgnoreCase("EDITOR")) { | |
| 281 | + JScrollPane sp = (JScrollPane) dockable.getComponent(); | |
| 282 | + return (JEditorPane) sp.getViewport().getView(); | |
| 283 | + } | |
| 284 | + } | |
| 285 | + return null; | |
| 286 | + } | |
| 287 | +} |
| @@ -0,0 +1,111 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 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.moenizer; | |
| 18 | + | |
| 19 | +import java.io.BufferedReader; | |
| 20 | +import java.io.File; | |
| 21 | +import java.io.FileInputStream; | |
| 22 | +import java.io.IOException; | |
| 23 | +import java.io.InputStreamReader; | |
| 24 | +import java.io.StringWriter; | |
| 25 | +import java.net.URISyntaxException; | |
| 26 | +import java.net.URL; | |
| 27 | +import java.security.CodeSource; | |
| 28 | +import java.util.regex.Matcher; | |
| 29 | +import java.util.regex.Pattern; | |
| 30 | +import org.omegat.util.LFileCopy; | |
| 31 | +import org.omegat.util.Log; | |
| 32 | +import org.omegat.util.OConsts; | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * | |
| 36 | + * @author Yu-Tang | |
| 37 | + */ | |
| 38 | +public class MoeUtil { | |
| 39 | + | |
| 40 | + private static final Pattern RE_URL_IN_SHORTCUT = Pattern.compile("\\[InternetShortcut\\]\\s+URL=(.+)\\b"); | |
| 41 | + private static final Pattern RE_URL_IN_WEBLOC = Pattern.compile("<key>URL</key>\\s+<string>(.+)</string>"); | |
| 42 | + private static File pluginJarFile; | |
| 43 | + | |
| 44 | + static { | |
| 45 | + pluginJarFile = null; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public static File getPluginJarFile() throws URISyntaxException { | |
| 49 | + if (pluginJarFile == null) { | |
| 50 | + CodeSource codeSource = MoeUtil.class.getProtectionDomain().getCodeSource(); | |
| 51 | + pluginJarFile = new File(codeSource.getLocation().toURI().getPath()); | |
| 52 | + } | |
| 53 | + return pluginJarFile; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public static File getPluginJarDir() throws URISyntaxException { | |
| 57 | + File jarFile = getPluginJarFile(); | |
| 58 | + return new File(jarFile.getParentFile().getPath()); | |
| 59 | + } | |
| 60 | + | |
| 61 | + public static URL getURL(File file) { | |
| 62 | + String fileName = file.getName().toLowerCase(); | |
| 63 | + try { | |
| 64 | + if (fileName.endsWith(".url") || fileName.endsWith(".website")) { | |
| 65 | + // .url is Internet ShortCut file for IE8 or earlier, Firefox | |
| 66 | + // .website is Pinned Site ShortCut file for IE9 or later | |
| 67 | + | |
| 68 | + // Windows 日本語環境で作成すると Shift-JIS 文字列が含まれること | |
| 69 | + // があるため、文字コードはその OS の既定文字コードを想定した方 | |
| 70 | + // が望ましいと思われる。 | |
| 71 | + String text = readTextFile(file, System.getProperty("sun.jnu.encoding")); | |
| 72 | + Matcher matcher = RE_URL_IN_SHORTCUT.matcher(text); | |
| 73 | + if (matcher.find()) { | |
| 74 | + return new URL(matcher.group(1)); | |
| 75 | + } else { | |
| 76 | + Log.log("Could not find valid URL in internet shortcut file '" + file.getCanonicalPath() + "'"); | |
| 77 | + } | |
| 78 | + | |
| 79 | + } else if (fileName.endsWith(".webloc")) { | |
| 80 | + // .webloc is Mac OS X Website Location file for safari | |
| 81 | + String text = readTextFile(file, OConsts.UTF8); | |
| 82 | + Matcher matcher = RE_URL_IN_WEBLOC.matcher(text); | |
| 83 | + if (matcher.find()) { | |
| 84 | + return new URL(matcher.group(1)); | |
| 85 | + } else { | |
| 86 | + Log.log("Could not find valid URL in website location file '" + file.getCanonicalPath() + "'"); | |
| 87 | + } | |
| 88 | + | |
| 89 | + } else { // unknown | |
| 90 | + // ignore | |
| 91 | + } | |
| 92 | + } catch (IOException ex) { | |
| 93 | + Log.log(ex); | |
| 94 | + } | |
| 95 | + return null; | |
| 96 | + } | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * Read file as platform dependent encoding text. | |
| 100 | + */ | |
| 101 | + public static String readTextFile(File file, String encoding) throws IOException { | |
| 102 | + BufferedReader rd = new BufferedReader(new InputStreamReader(new FileInputStream(file), encoding)); | |
| 103 | + try { | |
| 104 | + StringWriter out = new StringWriter(); | |
| 105 | + LFileCopy.copy(rd, out); | |
| 106 | + return out.toString(); | |
| 107 | + } finally { | |
| 108 | + rd.close(); | |
| 109 | + } | |
| 110 | + } | |
| 111 | +} |