OmegaT の背景に画像を表示します。
不透明度の指定対象をメインウィンドウのみに制限
詳細については、チケット #50238 のコメントを参照
| @@ -1,35 +0,0 @@ | ||
| 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; | |
| 18 | - | |
| 19 | -import java.awt.Color; | |
| 20 | -import java.awt.image.BufferedImage; | |
| 21 | - | |
| 22 | -/** | |
| 23 | - * | |
| 24 | - * @author Yu-Tang | |
| 25 | - */ | |
| 26 | -public interface IMoeUI { | |
| 27 | - public void setBackground(BufferedImage image); | |
| 28 | - | |
| 29 | - public void setBackground(Color color); | |
| 30 | - | |
| 31 | - public void setMarginTop(int marginTop); | |
| 32 | - | |
| 33 | - public void setOpacity(float opacity); | |
| 34 | - | |
| 35 | -} |
| @@ -34,17 +34,18 @@ | ||
| 34 | 34 | private BufferedImage tiledImage = null; |
| 35 | 35 | private Color bgColor = null; |
| 36 | 36 | private JComponent component = null; |
| 37 | - private final float DEFAULT_ALPHA = 0.5f; | |
| 37 | + private final float DEFAULT_ALPHA = MoeUI.OPACITY_HALF; | |
| 38 | 38 | private float alpha = DEFAULT_ALPHA; |
| 39 | - private AlphaComposite alphaComposite = null; | |
| 39 | + private AlphaComposite alphaComposite = getAlphaComposite(alpha); | |
| 40 | 40 | private int marginTop = 0; |
| 41 | 41 | |
| 42 | 42 | public void setOpacity(float opacity) { |
| 43 | 43 | this.alpha = opacity; |
| 44 | - this.alphaComposite = getAlphaComposite(opacity); | |
| 44 | + this.alphaComposite = opacity >= MoeUI.OPACITY_OPAQUE ? | |
| 45 | + null : getAlphaComposite(opacity); | |
| 45 | 46 | } |
| 46 | 47 | |
| 47 | - public void setBackground(BufferedImage image) { | |
| 48 | + public void setBackgroundImage(BufferedImage image) { | |
| 48 | 49 | this.image = image; |
| 49 | 50 | |
| 50 | 51 | if (component == null) { |
| @@ -55,10 +56,18 @@ | ||
| 55 | 56 | } |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | - public void setBackground(Color color) { | |
| 59 | + public void setBackgroundColor(Color color) { | |
| 59 | 60 | this.bgColor = color; |
| 60 | 61 | } |
| 61 | 62 | |
| 63 | + public BufferedImage getBackgroundImage() { | |
| 64 | + return image; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public Color getBackgroundColor() { | |
| 68 | + return bgColor; | |
| 69 | + } | |
| 70 | + | |
| 62 | 71 | public void setComponent(JComponent c) { |
| 63 | 72 | // change transparent component to opaque |
| 64 | 73 | if (!c.isOpaque()) { |
| @@ -39,7 +39,7 @@ | ||
| 39 | 39 | * |
| 40 | 40 | * @author Yu-Tang |
| 41 | 41 | */ |
| 42 | -public class MoeRootPaneUI extends BasicRootPaneUI implements IMoeUI { | |
| 42 | +public class MoeRootPaneUI extends BasicRootPaneUI implements IMoePaneUI { | |
| 43 | 43 | |
| 44 | 44 | private MoeUIDelegator uiDelegator = null; |
| 45 | 45 |
| @@ -56,21 +56,30 @@ | ||
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | @Override |
| 59 | - public void setBackground(BufferedImage image) { | |
| 60 | - uiDelegator.setBackground(image); | |
| 59 | + public BufferedImage getBackgroundImage() { | |
| 60 | + return uiDelegator.getBackgroundImage(); | |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | @Override |
| 64 | - public void setBackground(Color color) { | |
| 65 | - uiDelegator.setBackground(color); | |
| 64 | + public void setBackgroundImage(BufferedImage image) { | |
| 65 | + uiDelegator.setBackgroundImage(image); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | @Override |
| 69 | + public Color getBackgroundColor() { | |
| 70 | + return uiDelegator.getBackgroundColor(); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public void setBackgroundColor(Color color) { | |
| 75 | + uiDelegator.setBackgroundColor(color); | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 69 | 79 | public void setMarginTop(int marginTop) { |
| 70 | 80 | uiDelegator.setMarginTop(marginTop); |
| 71 | 81 | } |
| 72 | 82 | |
| 73 | - @Override | |
| 74 | 83 | public void setOpacity(float opacity) { |
| 75 | 84 | uiDelegator.setOpacity(opacity); |
| 76 | 85 | } |
| @@ -26,7 +26,7 @@ | ||
| 26 | 26 | * |
| 27 | 27 | * @author Yu-Tang |
| 28 | 28 | */ |
| 29 | -public class MoeTextPaneUI extends BasicTextPaneUI implements IMoeUI { | |
| 29 | +public class MoeTextPaneUI extends BasicTextPaneUI implements IMoePaneUI { | |
| 30 | 30 | |
| 31 | 31 | private MoeUIDelegator uiDelegator = null; |
| 32 | 32 |
| @@ -33,6 +33,11 @@ | ||
| 33 | 33 | public MoeTextPaneUI() { |
| 34 | 34 | super(); |
| 35 | 35 | uiDelegator = new MoeUIDelegator(); |
| 36 | + | |
| 37 | + // MoeTextPaneUI は個別ペイン用の UI なので、仕様上の制約により不透明度 | |
| 38 | + // を設定できません(1.0f 固定 = 不透明)。そのため、ここで固定値を設定 | |
| 39 | + // して、setter を空実装にしておきます。 | |
| 40 | + uiDelegator.setOpacity(MoeUI.OPACITY_OPAQUE); | |
| 36 | 41 | } |
| 37 | 42 | |
| 38 | 43 | @Override |
| @@ -43,28 +48,39 @@ | ||
| 43 | 48 | } |
| 44 | 49 | |
| 45 | 50 | @Override |
| 46 | - public void setBackground(BufferedImage image) { | |
| 47 | - uiDelegator.setBackground(image); | |
| 51 | + public BufferedImage getBackgroundImage() { | |
| 52 | + return uiDelegator.getBackgroundImage(); | |
| 48 | 53 | } |
| 49 | 54 | |
| 50 | 55 | @Override |
| 51 | - public void setBackground(Color color) { | |
| 52 | - uiDelegator.setBackground(color); | |
| 56 | + public void setBackgroundImage(BufferedImage image) { | |
| 57 | + uiDelegator.setBackgroundImage(image); | |
| 53 | 58 | } |
| 54 | 59 | |
| 55 | 60 | @Override |
| 56 | - public void setMarginTop(int marginTop) { | |
| 57 | - uiDelegator.setMarginTop(marginTop); | |
| 61 | + public Color getBackgroundColor() { | |
| 62 | + return uiDelegator.getBackgroundColor(); | |
| 58 | 63 | } |
| 59 | 64 | |
| 60 | 65 | @Override |
| 61 | - public void setOpacity(float opacity) { | |
| 62 | - uiDelegator.setOpacity(opacity); | |
| 66 | + public void setBackgroundColor(Color color) { | |
| 67 | + uiDelegator.setBackgroundColor(color); | |
| 63 | 68 | } |
| 64 | 69 | |
| 65 | 70 | @Override |
| 71 | + public void setMarginTop(int marginTop) { | |
| 72 | + uiDelegator.setMarginTop(marginTop); | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Override | |
| 66 | 76 | protected void paintBackground(Graphics g) { |
| 67 | 77 | uiDelegator.paintBackground(g); |
| 68 | 78 | } |
| 69 | 79 | |
| 80 | + public MoeTextPaneUI clone() { | |
| 81 | + MoeTextPaneUI ui = new MoeTextPaneUI(); | |
| 82 | + ui.setBackgroundImage(uiDelegator.getBackgroundImage()); | |
| 83 | + ui.setBackgroundColor(uiDelegator.getBackgroundColor()); | |
| 84 | + return ui; | |
| 85 | + } | |
| 70 | 86 | } |
| @@ -0,0 +1,36 @@ | ||
| 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; | |
| 18 | + | |
| 19 | +import java.awt.Color; | |
| 20 | +import java.awt.image.BufferedImage; | |
| 21 | + | |
| 22 | +/** | |
| 23 | + * | |
| 24 | + * @author Yu-Tang | |
| 25 | + */ | |
| 26 | +public interface IMoePaneUI { | |
| 27 | + public BufferedImage getBackgroundImage(); | |
| 28 | + | |
| 29 | + public void setBackgroundImage(BufferedImage image); | |
| 30 | + | |
| 31 | + public Color getBackgroundColor(); | |
| 32 | + | |
| 33 | + public void setBackgroundColor(Color color); | |
| 34 | + | |
| 35 | + public void setMarginTop(int marginTop); | |
| 36 | +} |
| @@ -91,9 +91,7 @@ | ||
| 91 | 91 | |
| 92 | 92 | ui.setOpacity(target, opacity); |
| 93 | 93 | |
| 94 | - if (target == Parts.MainWindow) { | |
| 95 | - ui.transparent(excludeParts); | |
| 96 | - } | |
| 94 | + ui.transparent(target, excludeParts); | |
| 97 | 95 | } |
| 98 | 96 | |
| 99 | 97 | } |
| @@ -43,9 +43,11 @@ | ||
| 43 | 43 | import javax.swing.JTextPane; |
| 44 | 44 | import javax.swing.SwingUtilities; |
| 45 | 45 | import javax.swing.plaf.ComponentUI; |
| 46 | +import javax.swing.text.Highlighter; | |
| 46 | 47 | import org.omegat.core.Core; |
| 47 | 48 | import org.omegat.core.CoreEvents; |
| 48 | 49 | import org.omegat.core.events.IProjectEventListener; |
| 50 | +import org.omegat.util.Log; | |
| 49 | 51 | import org.omegat.util.gui.UIThreadsUtil; |
| 50 | 52 | |
| 51 | 53 | /** |
| @@ -53,9 +55,12 @@ | ||
| 53 | 55 | * @author Yu-Tang |
| 54 | 56 | */ |
| 55 | 57 | public class MoeUI implements IProjectEventListener { |
| 56 | - | |
| 58 | + | |
| 59 | + public static final float OPACITY_OPAQUE = 1.0f; | |
| 60 | + public static final float OPACITY_HALF = 0.5f; | |
| 61 | + | |
| 57 | 62 | private static MoeUI moeUI; |
| 58 | - | |
| 63 | + | |
| 59 | 64 | private final JFrame frame; |
| 60 | 65 | private final JRootPane rootPane; |
| 61 | 66 | private final Container contentPane; |
| @@ -116,19 +121,11 @@ | ||
| 116 | 121 | ui = new MoeRootPaneUI(); |
| 117 | 122 | rootPane.setUI(ui); |
| 118 | 123 | } |
| 119 | - ui.setBackground(image); | |
| 124 | + ui.setBackgroundImage(image); | |
| 120 | 125 | uis.put(target, ui); |
| 121 | 126 | |
| 122 | 127 | } else if (target.compareTo(Parts.EDITOR) >= 0) { |
| 123 | - MoeTextPaneUI ui; | |
| 124 | - if (uis.containsKey(target)) { | |
| 125 | - ui = (MoeTextPaneUI) uis.get(target); | |
| 126 | - } else { | |
| 127 | - ui = new MoeTextPaneUI(); | |
| 128 | - getTextPane(target).setUI(ui); | |
| 129 | - } | |
| 130 | - ui.setBackground(image); | |
| 131 | - uis.put(target, ui); | |
| 128 | + getTextPaneUI(target).setBackgroundImage(image); | |
| 132 | 129 | } |
| 133 | 130 | } |
| 134 | 131 |
| @@ -143,19 +140,11 @@ | ||
| 143 | 140 | ui = new MoeRootPaneUI(); |
| 144 | 141 | rootPane.setUI(ui); |
| 145 | 142 | } |
| 146 | - ui.setBackground(color); | |
| 143 | + ui.setBackgroundColor(color); | |
| 147 | 144 | uis.put(target, ui); |
| 148 | 145 | |
| 149 | 146 | } else if (target.compareTo(Parts.EDITOR) >= 0) { |
| 150 | - MoeTextPaneUI ui; | |
| 151 | - if (uis.containsKey(target)) { | |
| 152 | - ui = (MoeTextPaneUI) uis.get(target); | |
| 153 | - } else { | |
| 154 | - ui = new MoeTextPaneUI(); | |
| 155 | - getTextPane(target).setUI(ui); | |
| 156 | - } | |
| 157 | - ui.setBackground(color); | |
| 158 | - uis.put(target, ui); | |
| 147 | + getTextPaneUI(target).setBackgroundColor(color); | |
| 159 | 148 | } |
| 160 | 149 | } |
| 161 | 150 |
| @@ -173,30 +162,53 @@ | ||
| 173 | 162 | ui.setOpacity(opacity); |
| 174 | 163 | uis.put(target, ui); |
| 175 | 164 | |
| 176 | - } else if (target.compareTo(Parts.EDITOR) >= 0) { | |
| 177 | - MoeTextPaneUI ui; | |
| 178 | - if (uis.containsKey(target)) { | |
| 179 | - ui = (MoeTextPaneUI) uis.get(target); | |
| 180 | - } else { | |
| 181 | - ui = new MoeTextPaneUI(); | |
| 182 | - getTextPane(target).setUI(ui); | |
| 183 | - } | |
| 184 | - ui.setOpacity(opacity); | |
| 185 | - uis.put(target, ui); | |
| 165 | + } else { | |
| 166 | + // noop | |
| 167 | + // メインウィンドウ以外の個別ペインは不透明度 1.0f 固定とします。 | |
| 168 | + // 半透過にすると、残像が残るためです。 | |
| 169 | + Log.log("warning: setOpacity(" + target.name() + ", " + opacity | |
| 170 | + + ") is ignored. Opacity is available only for MainWindow."); | |
| 186 | 171 | } |
| 187 | 172 | } |
| 188 | 173 | |
| 189 | - // MainWindow に画像や色を割り当てる場合のみ使用します | |
| 190 | - public void transparent(EnumSet<Parts> exclude) { | |
| 191 | - //@@TODO EDITOR などのペインが指定された場合に対応 | |
| 192 | - if (exclude != null) { | |
| 193 | - makeTransparentMenubar = !exclude.contains(Parts.MenuBar); | |
| 194 | - makeTransparentButtonPanel = !exclude.contains(Parts.ButtonPanel); | |
| 195 | - makeTransparentStatusbar = !exclude.contains(Parts.StatusBar); | |
| 196 | - makeTransparentPaneTitlebar = !exclude.contains(Parts.PaneTitleBar); | |
| 174 | + // MainWindow と EDITOR に画像や色を割り当てる場合のみ使用します | |
| 175 | + public void transparent(Parts target, EnumSet<Parts> exclude) { | |
| 176 | + switch (target) { | |
| 177 | + case MainWindow: | |
| 178 | + if (exclude != null) { | |
| 179 | + makeTransparentMenubar = !exclude.contains(Parts.MenuBar); | |
| 180 | + makeTransparentButtonPanel = !exclude.contains(Parts.ButtonPanel); | |
| 181 | + makeTransparentStatusbar = !exclude.contains(Parts.StatusBar); | |
| 182 | + makeTransparentPaneTitlebar = !exclude.contains(Parts.PaneTitleBar); | |
| 183 | + } | |
| 184 | + transparent(); | |
| 185 | + break; | |
| 186 | + | |
| 187 | + case EDITOR: | |
| 188 | + UIThreadsUtil.mustBeSwingThread(); | |
| 189 | + transparentInstantStart(desktop); | |
| 190 | + | |
| 191 | + // エディター(インスタントスタートではない方) ペインに個別に | |
| 192 | + // 背景を設定するためには、結局プロジェクトのロード時に現在の | |
| 193 | + // エフェクト設定で再度エディターを取得して setUI し直す必要がある。 | |
| 194 | + // この行が実行される時点では、インスタントスタートと編集画面の | |
| 195 | + // どちらのモードか不明なので、いったん編集画面の設定を試みて、 | |
| 196 | + // 失敗したらプロジェクトのロード時に再試行するクロージャを投げる。 | |
| 197 | + final JEditorPane editor = getJEditorPaneFromEditor(desktop); | |
| 198 | + final MoeTextPaneUI ui = getTextPaneUI(Parts.EDITOR); | |
| 199 | + if (editor == null || editor instanceof javax.swing.JTextPane) { | |
| 200 | + // Editor is not available yet. Wait for project open event. | |
| 201 | + EditorUIRunner editorUIRunner = new EditorUIRunner(); | |
| 202 | + editorUIRunner.setBackgroundImage(ui.getBackgroundImage()); | |
| 203 | + editorUIRunner.setBackgroundColor(ui.getBackgroundColor()); | |
| 204 | + CoreEvents.registerProjectChangeListener(editorUIRunner); | |
| 205 | + } else { | |
| 206 | + // Editor is found. Set UI and migrate highlighter. | |
| 207 | + Highlighter h = editor.getHighlighter(); // save old highlighter | |
| 208 | + editor.setUI(ui); | |
| 209 | + editor.setHighlighter(h); // restore highlighter | |
| 210 | + } | |
| 197 | 211 | } |
| 198 | - | |
| 199 | - transparent(); | |
| 200 | 212 | } |
| 201 | 213 | |
| 202 | 214 | private void transparent() { |
| @@ -294,7 +306,7 @@ | ||
| 294 | 306 | * |
| 295 | 307 | int alpha = 100; // transparent <- 0...255 -> opaque |
| 296 | 308 | Color color = SystemColor.menu; |
| 297 | - editor.setBackground(new Color( color.getRGB() & 0xffffff | 100 << 24, true)); | |
| 309 | + editor.setBackgroundImage(new Color( color.getRGB() & 0xffffff | 100 << 24, true)); | |
| 298 | 310 | * */ |
| 299 | 311 | editor.setOpaque(false); |
| 300 | 312 | frame.repaint(); |
| @@ -301,7 +313,7 @@ | ||
| 301 | 313 | return true; |
| 302 | 314 | } |
| 303 | 315 | |
| 304 | - private JEditorPane getTextPane(Parts pane) { | |
| 316 | + private JEditorPane getJEditorPane(Parts pane) { | |
| 305 | 317 | /* |
| 306 | 318 | dockable.getDockKey().getKey() |
| 307 | 319 | dockable.getComponent().class.name |
| @@ -550,4 +562,65 @@ | ||
| 550 | 562 | } |
| 551 | 563 | return null; |
| 552 | 564 | } |
| 565 | + | |
| 566 | + private MoeTextPaneUI getTextPaneUI(Parts target) { | |
| 567 | + MoeTextPaneUI ui; | |
| 568 | + if (uis.containsKey(target)) { | |
| 569 | + ui = (MoeTextPaneUI) uis.get(target); | |
| 570 | + } else { | |
| 571 | + ui = new MoeTextPaneUI(); | |
| 572 | + JEditorPane pane = getJEditorPane(target); | |
| 573 | + Highlighter h = pane.getHighlighter(); // save old highlighter | |
| 574 | + pane.setUI(ui); | |
| 575 | + pane.setHighlighter(h); // restore highlighter | |
| 576 | + if (!pane.isOpaque()) { | |
| 577 | + pane.setOpaque(true); | |
| 578 | + if (target == Parts.EDITOR) { | |
| 579 | + isEditorTransparent = false; | |
| 580 | + } | |
| 581 | + } | |
| 582 | + uis.put(target, ui); | |
| 583 | + } | |
| 584 | + return ui; | |
| 585 | + } | |
| 586 | + | |
| 587 | + /** | |
| 588 | + * エディター専用の UI です。プロジェクトの開始時にエディターに自身を UI と | |
| 589 | + * して自動設定します。 | |
| 590 | + * 呼び出し側で、このクラスのインスタンスをプロジェクトイベントのリスナーに | |
| 591 | + * 登録しておく必要があります。 | |
| 592 | + */ | |
| 593 | + private class EditorUIRunner extends MoeTextPaneUI | |
| 594 | + implements IProjectEventListener, Runnable { | |
| 595 | + | |
| 596 | + @Override | |
| 597 | + public void run() { | |
| 598 | + // 実行は一回きりで良いので、リスナー登録を解除する | |
| 599 | + CoreEvents.unregisterProjectChangeListener(this); | |
| 600 | + | |
| 601 | + // エディターに UI を設定し、ハイライターを復元する | |
| 602 | + JEditorPane editor = getJEditorPaneFromEditor(desktop); | |
| 603 | + Highlighter h = editor.getHighlighter(); // save old highlighter | |
| 604 | + editor.setUI(this); //@@TODO このインスタンスを管理する必要がある | |
| 605 | + editor.setHighlighter(h); // restore highlighter | |
| 606 | + | |
| 607 | + // エディターが透明の場合は不透過に設定する | |
| 608 | + if (!editor.isOpaque()) { | |
| 609 | + editor.setOpaque(true); | |
| 610 | + isEditorTransparent = false; | |
| 611 | + } | |
| 612 | + } | |
| 613 | + | |
| 614 | + @Override | |
| 615 | + public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) { | |
| 616 | + switch (eventType) { | |
| 617 | + case CREATE: | |
| 618 | + case LOAD: | |
| 619 | + // ここですぐエディターの透過処理をしてもうまく適用されないので、 | |
| 620 | + // 遅延処理する。 | |
| 621 | + SwingUtilities.invokeLater(this); | |
| 622 | + } | |
| 623 | + } | |
| 624 | + | |
| 625 | + } | |
| 553 | 626 | } |