OmegaT の背景に画像を表示します。
エフェクトの種類に SlideEffect を追加
| @@ -19,7 +19,6 @@ | ||
| 19 | 19 | import groovy.util.ConfigObject; |
| 20 | 20 | import java.util.List; |
| 21 | 21 | import java.util.Map; |
| 22 | -import java.util.concurrent.Executors; | |
| 23 | 22 | import java.util.concurrent.ScheduledThreadPoolExecutor; |
| 24 | 23 | import jp.sourceforge.users.yutang.omegat.plugin.moenizer.effect.Effect; |
| 25 | 24 | import org.omegat.util.Log; |
| @@ -33,11 +32,10 @@ | ||
| 33 | 32 | private final int THREAD_NUM = 2; |
| 34 | 33 | private final MoeUI model; |
| 35 | 34 | private ConfigObject theme = null; |
| 36 | - private final ScheduledThreadPoolExecutor service; | |
| 35 | + private ScheduledThreadPoolExecutor service = null; | |
| 37 | 36 | |
| 38 | 37 | public ThemeChanger(MoeUI ui) { |
| 39 | 38 | this.model = ui; |
| 40 | - this.service = new ScheduledThreadPoolExecutor(THREAD_NUM); | |
| 41 | 39 | } |
| 42 | 40 | |
| 43 | 41 | public void setTheme(ConfigObject theme) { |
| @@ -49,8 +47,11 @@ | ||
| 49 | 47 | } |
| 50 | 48 | |
| 51 | 49 | public void apply() { |
| 52 | - // shutdown old tasks | |
| 53 | - this.service.shutdown(); | |
| 50 | + // immediately shutdown old tasks | |
| 51 | + if (service != null) { | |
| 52 | + service.shutdownNow(); | |
| 53 | + service = null; | |
| 54 | + } | |
| 54 | 55 | |
| 55 | 56 | // no theme, no effects |
| 56 | 57 | if (theme == null || !theme.containsKey("effects")) { //@@TODO literal to const |
| @@ -63,6 +64,8 @@ | ||
| 63 | 64 | return; |
| 64 | 65 | } |
| 65 | 66 | |
| 67 | + service = new ScheduledThreadPoolExecutor(THREAD_NUM); | |
| 68 | + | |
| 66 | 69 | // apply effects |
| 67 | 70 | for (Map conf: effects) { |
| 68 | 71 | try { |
| @@ -69,7 +72,7 @@ | ||
| 69 | 72 | Effect.Type type = conf.containsKey("type") ? |
| 70 | 73 | (Effect.Type) conf.get("type") : Effect.Type.Basic; |
| 71 | 74 | Effect effect = Effect.create(type, conf); |
| 72 | - effect.invoke(this.model, this.service); | |
| 75 | + effect.invoke(model, service); | |
| 73 | 76 | } catch (Exception ex) { |
| 74 | 77 | ex.printStackTrace(); |
| 75 | 78 | Log.log("Error on ThemeChanger#apply(): " + ex.getMessage()); |
| @@ -28,7 +28,7 @@ | ||
| 28 | 28 | public abstract class Effect { |
| 29 | 29 | |
| 30 | 30 | public enum Type { |
| 31 | - Basic | |
| 31 | + Basic, Slide | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | public static Effect create(Type type, Map conf) throws Exception { |
| @@ -0,0 +1,168 @@ | ||
| 1 | +/************************************************************************** | |
| 2 | + Moenizer - Allow to set background image for OmegaT. | |
| 3 | + | |
| 4 | + Copyright (C) 2014 Yu Tang | |
| 5 | + Home page: http://sourceforge.jp/users/yu-tang/ | |
| 6 | + Support center: http://sourceforge.jp/users/yu-tang/pf/Moenizer/ | |
| 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.effect; | |
| 18 | + | |
| 19 | +import java.awt.Color; | |
| 20 | +import java.awt.image.BufferedImage; | |
| 21 | +import java.io.File; | |
| 22 | +import java.io.IOException; | |
| 23 | +import java.net.MalformedURLException; | |
| 24 | +import java.net.URL; | |
| 25 | +import java.util.ArrayList; | |
| 26 | +import java.util.EnumSet; | |
| 27 | +import java.util.List; | |
| 28 | +import java.util.Map; | |
| 29 | +import java.util.concurrent.ScheduledThreadPoolExecutor; | |
| 30 | +import java.util.concurrent.TimeUnit; | |
| 31 | +import javax.imageio.ImageIO; | |
| 32 | +import jp.sourceforge.users.yutang.omegat.plugin.moenizer.MoeUI; | |
| 33 | +import jp.sourceforge.users.yutang.omegat.plugin.moenizer.MoeUtil; | |
| 34 | +import org.omegat.util.Log; | |
| 35 | +import org.omegat.util.gui.UIThreadsUtil; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * | |
| 39 | + * @author Yu-Tang | |
| 40 | + */ | |
| 41 | +public class SlideEffect extends Effect implements Runnable { | |
| 42 | + | |
| 43 | + private final String KEY_TARGET = "target"; | |
| 44 | + private final String KEY_OPACITY = "opacity"; | |
| 45 | + private final String KEY_IMAGE = "image"; | |
| 46 | + private final String KEY_PATHS = "paths"; | |
| 47 | + private final String KEY_BGCOLOR = "bgColor"; | |
| 48 | + private final String KEY_EXCLUDE = "exclude"; | |
| 49 | + private final String KEY_INTERVAL = "interval"; // in minutes | |
| 50 | + | |
| 51 | + private MoeUI.Parts target = MoeUI.Parts.MainWindow; | |
| 52 | + private float opacity = 0.5f; | |
| 53 | + private List<String> images = null; | |
| 54 | + private Color bgColor = null; | |
| 55 | + private EnumSet<MoeUI.Parts> exclude = null; | |
| 56 | + private int intervalInMinutes = 1; | |
| 57 | + private int currentImageIndex = 0; | |
| 58 | + private MoeUI ui = null; | |
| 59 | + | |
| 60 | + public SlideEffect(Map<String, Object> config) { | |
| 61 | + target = get(KEY_TARGET, config, target); | |
| 62 | + if (config.containsKey(KEY_IMAGE)) { | |
| 63 | + Map conf = (Map) config.get(KEY_IMAGE); | |
| 64 | + images = getImages(get(KEY_PATHS, conf, images)); | |
| 65 | + opacity = get(KEY_OPACITY, conf, opacity); | |
| 66 | + } | |
| 67 | + Integer rgb = get(KEY_BGCOLOR, config, null); | |
| 68 | + if (rgb != null) { | |
| 69 | + bgColor = new Color(rgb); | |
| 70 | + } | |
| 71 | + List<MoeUI.Parts> excludeList = new ArrayList<MoeUI.Parts>(); | |
| 72 | + exclude = getExcludeParts(get(KEY_EXCLUDE, config, excludeList)); | |
| 73 | + intervalInMinutes = get(KEY_INTERVAL, config, intervalInMinutes); | |
| 74 | + } | |
| 75 | + | |
| 76 | + @Override | |
| 77 | + public void invoke(MoeUI ui, ScheduledThreadPoolExecutor service) { | |
| 78 | + if (images.isEmpty()) { | |
| 79 | + return; | |
| 80 | + } | |
| 81 | + | |
| 82 | + try { | |
| 83 | + ui.setBackground(target, getImage(images.get(0))); | |
| 84 | + } catch (MalformedURLException ex) { | |
| 85 | + Log.log(ex.getMessage()); | |
| 86 | + } catch (IOException ex) { | |
| 87 | + Log.log(ex.getMessage()); | |
| 88 | + } | |
| 89 | + | |
| 90 | + ui.setOpacity(target, opacity); | |
| 91 | + ui.setBackground(target, bgColor); | |
| 92 | + ui.transparent(target, exclude); | |
| 93 | + | |
| 94 | + // schedule next execution | |
| 95 | + if (images.size() > 1) { | |
| 96 | + this.ui = ui; | |
| 97 | + service.scheduleAtFixedRate( | |
| 98 | + this, | |
| 99 | + intervalInMinutes, | |
| 100 | + intervalInMinutes, | |
| 101 | + TimeUnit.MINUTES); | |
| 102 | + } | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public void run() { | |
| 107 | + // increment index | |
| 108 | + currentImageIndex ++; | |
| 109 | + if (currentImageIndex >= images.size()) { | |
| 110 | + currentImageIndex = 0; | |
| 111 | + } | |
| 112 | + | |
| 113 | + UIThreadsUtil.executeInSwingThread(new Runnable() { | |
| 114 | + | |
| 115 | + @Override | |
| 116 | + public void run() { | |
| 117 | + try { | |
| 118 | + ui.setBackground(target, getImage(images.get(currentImageIndex))); | |
| 119 | + ui.repaint(); | |
| 120 | + } catch (MalformedURLException ex) { | |
| 121 | + Log.log(ex.getMessage()); | |
| 122 | + } catch (IOException ex) { | |
| 123 | + Log.log(ex.getMessage()); | |
| 124 | + } | |
| 125 | + } | |
| 126 | + }); | |
| 127 | + } | |
| 128 | + | |
| 129 | + private List<String> getImages(List<String> paths) { | |
| 130 | + List<String> ret = new ArrayList<String>(); | |
| 131 | + for (String path: paths) { | |
| 132 | + String lcased = path.toLowerCase(); | |
| 133 | + if (lcased.startsWith("http://") || lcased.startsWith("https://")) { | |
| 134 | + ret.add(path); | |
| 135 | + } else { | |
| 136 | + File file = new File(path); | |
| 137 | + if (file.isFile()) { | |
| 138 | + ret.add(path); | |
| 139 | + } else if (file.isDirectory()) { | |
| 140 | + try { | |
| 141 | + List<String> imagePaths = MoeUtil.collectImagePaths(file); | |
| 142 | + ret.addAll(imagePaths); | |
| 143 | + } catch (IOException ex) { | |
| 144 | + // ignore | |
| 145 | + } | |
| 146 | + } | |
| 147 | + } | |
| 148 | + } | |
| 149 | + return ret; | |
| 150 | + } | |
| 151 | + | |
| 152 | + private EnumSet<MoeUI.Parts> getExcludeParts(List<MoeUI.Parts> exclude) { | |
| 153 | + EnumSet<MoeUI.Parts> excludeParts = EnumSet.noneOf(MoeUI.Parts.class); | |
| 154 | + for (MoeUI.Parts part: EnumSet.allOf(MoeUI.Parts.class)) { | |
| 155 | + if (exclude.contains(part)) { | |
| 156 | + excludeParts.add(part); | |
| 157 | + } | |
| 158 | + } | |
| 159 | + return excludeParts; | |
| 160 | + } | |
| 161 | + | |
| 162 | + private BufferedImage getImage(String path) throws IOException { | |
| 163 | + String lcased = path.toLowerCase(); | |
| 164 | + return lcased.startsWith("http://")|| lcased.startsWith("https://") | |
| 165 | + ? ImageIO.read(new URL(path)) | |
| 166 | + : ImageIO.read(new File(path)); | |
| 167 | + } | |
| 168 | +} |