• R/O
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

OmegaT の背景に画像を表示します。


Commit MetaInfo

Revision6 (tree)
Time2014-05-05 20:53:20
Authoryu-tang

Log Message

change package names

Change Summary

Incremental Difference

--- trunk/nbproject/groovy-build.xml (revision 5)
+++ trunk/nbproject/groovy-build.xml (revision 6)
@@ -23,7 +23,7 @@
2323 <taskdef name="groovyc" classpath="${javac.classpath}" classname="org.codehaus.groovy.ant.Groovyc"/>
2424 <property name="empty.dir" location="${build.dir}/empty"/>
2525 <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">
2727 <src>
2828 <dirset dir="@{gensrcdir}" erroronmissingdir="false">
2929 <include name="*"/>
--- trunk/nbproject/build-impl.xml (revision 5)
+++ trunk/nbproject/build-impl.xml (revision 6)
@@ -55,6 +55,7 @@
5555 <property file="nbproject/project.properties"/>
5656 </target>
5757 <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"/>
5859 <available file="${manifest.file}" property="manifest.available"/>
5960 <condition property="splashscreen.available">
6061 <and>
@@ -72,16 +73,20 @@
7273 </not>
7374 </and>
7475 </condition>
75- <condition property="manifest.available+main.class">
76+ <condition property="profile.available">
7677 <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}"/>
7981 </and>
8082 </condition>
8183 <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>
8590 </condition>
8691 <condition property="do.mkdist">
8792 <and>
@@ -92,12 +97,6 @@
9297 </not>
9398 </and>
9499 </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>
101100 <condition property="do.archive+manifest.available">
102101 <and>
103102 <isset property="manifest.available"/>
@@ -116,24 +115,12 @@
116115 <istrue value="${do.archive}"/>
117116 </and>
118117 </condition>
119- <condition property="do.archive+manifest.available+main.class">
118+ <condition property="do.archive+profile.available">
120119 <and>
121- <istrue value="${manifest.available+main.class}"/>
120+ <isset property="profile.available"/>
122121 <istrue value="${do.archive}"/>
123122 </and>
124123 </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>
137124 <condition property="have.tests">
138125 <or>
139126 <available file="${test.src.dir}"/>
@@ -187,8 +174,16 @@
187174 </condition>
188175 <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
189176 <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>
191183 </condition>
184+ <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}">
185+ <isset property="profile.available"/>
186+ </condition>
192187 <condition else="false" property="jdkBug6558476">
193188 <and>
194189 <matches pattern="1\.[56]" string="${java.specification.version}"/>
@@ -276,6 +271,7 @@
276271 <path path="@{classpath}"/>
277272 </classpath>
278273 <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
274+ <compilerarg line="${javac.profile.cmd.line.arg}"/>
279275 <compilerarg line="${javac.compilerargs}"/>
280276 <compilerarg value="-processorpath"/>
281277 <compilerarg path="@{processorpath}:${empty.dir}"/>
@@ -315,6 +311,7 @@
315311 <path path="@{classpath}"/>
316312 </classpath>
317313 <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
314+ <compilerarg line="${javac.profile.cmd.line.arg}"/>
318315 <compilerarg line="${javac.compilerargs}"/>
319316 <customize/>
320317 </javac>
@@ -447,7 +444,7 @@
447444 </fileset>
448445 </union>
449446 <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}">
451448 <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
452449 <propertyset>
453450 <propertyref prefix="test-sys-prop."/>
@@ -838,8 +835,8 @@
838835 </chainedmapper>
839836 </pathconvert>
840837 <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}"/>
843840 <manifest>
844841 <attribute name="Class-Path" value="${jar.classpath}"/>
845842 <customize/>
@@ -851,7 +848,7 @@
851848 <target name="-init-presetdef-jar">
852849 <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
853850 <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}"/>
855852 </jar>
856853 </presetdef>
857854 </target>
@@ -967,41 +964,25 @@
967964 <!-- Empty placeholder for easier customization. -->
968965 <!-- You can override this target in the ../build.xml file. -->
969966 </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">
992968 <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
993969 <touch file="${tmp.manifest.file}" verbose="false"/>
994970 </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">
996972 <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
997973 <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
998974 </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">
1000976 <manifest file="${tmp.manifest.file}" mode="update">
1001977 <attribute name="Main-Class" value="${main.class}"/>
1002978 </manifest>
1003979 </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">
1005986 <basename file="${application.splash}" property="splashscreen.basename"/>
1006987 <mkdir dir="${build.classes.dir}/META-INF"/>
1007988 <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
@@ -1009,23 +990,41 @@
1009990 <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
1010991 </manifest>
1011992 </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">
1013994 <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
1014995 <echo level="info">To run this application from the command line without Ant, try:</echo>
1015996 <property location="${dist.jar}" name="dist.jar.resolved"/>
1016997 <echo level="info">java -jar "${dist.jar.resolved}"</echo>
1017998 </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">
10191016 <delete>
10201017 <fileset file="${tmp.manifest.file}"/>
10211018 </delete>
10221019 </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"/>
10241022 <target name="-post-jar">
10251023 <!-- Empty placeholder for easier customization. -->
10261024 <!-- You can override this target in the ../build.xml file. -->
10271025 </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"/>
10291028 <!--
10301029 =================
10311030 EXECUTION SECTION
@@ -1204,11 +1203,14 @@
12041203 </not>
12051204 </and>
12061205 </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}">
12081210 <classpath>
12091211 <path path="${javac.classpath}"/>
12101212 </classpath>
1211- <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">
1213+ <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
12121214 <filename name="**/*.java"/>
12131215 </fileset>
12141216 <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
@@ -1282,7 +1284,7 @@
12821284 <mkdir dir="${build.test.results.dir}"/>
12831285 </target>
12841286 <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"/>
12861288 </target>
12871289 <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
12881290 <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
--- trunk/src/org/omegat/plugin/moenizer/Moenizer.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/Moenizer.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/imageloader/DefaultImageLoader.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/imageloader/DefaultImageLoader.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/imageloader/IImageLoader.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/imageloader/IImageLoader.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/imageloader/ImageLoader.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/imageloader/ImageLoader.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeLayeredPane.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeLayeredPane.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeUI.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeUI.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeUtil.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeUtil.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeDockViewTitleBarUI.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeDockViewTitleBarUI.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeVersionInfo.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeVersionInfo.java (nonexistent)
@@ -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-}
--- trunk/src/org/omegat/plugin/moenizer/MoeConfig.java (revision 5)
+++ trunk/src/org/omegat/plugin/moenizer/MoeConfig.java (nonexistent)
@@ -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-
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeDockViewTitleBarUI.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeDockViewTitleBarUI.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeVersionInfo.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeVersionInfo.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeConfig.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeConfig.java (revision 6)
@@ -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+
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/Moenizer.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/Moenizer.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/IImageLoader.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/IImageLoader.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/ImageLoader.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/ImageLoader.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/DefaultImageLoader.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/imageloader/DefaultImageLoader.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeLayeredPane.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeLayeredPane.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeUI.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeUI.java (revision 6)
@@ -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+}
--- trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeUtil.java (nonexistent)
+++ trunk/src/jp/sourceforge/users/yutang/omegat/plugin/moenizer/MoeUtil.java (revision 6)
@@ -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+}