OmegaT の背景に画像を表示します。
MoeRootPaneUI クラスを利用した操作方法に実装を移行
| @@ -63,6 +63,7 @@ | ||
| 63 | 63 | public MoeConfig(File file) throws IOException { |
| 64 | 64 | this.file = file; |
| 65 | 65 | if (file.isFile()) { |
| 66 | + //@@TODO setBinding で文字列の指定を追い出す | |
| 66 | 67 | config = new ConfigSlurper().parse(file.toURI().toURL()); |
| 67 | 68 | addAll(sortedConfigs, config); |
| 68 | 69 | } |
| @@ -112,7 +112,7 @@ | ||
| 112 | 112 | while (ui == null) { |
| 113 | 113 | TimeUnit.MILLISECONDS.sleep(100); |
| 114 | 114 | } |
| 115 | - ui.setBackground(image); | |
| 115 | + //ui.setBackground(image); | |
| 116 | 116 | } |
| 117 | 117 | } |
| 118 | 118 | return null; |
| @@ -62,6 +62,7 @@ | ||
| 62 | 62 | IEffect effect = Effect.create(Effect.Type.valueOf(type), conf); |
| 63 | 63 | effect.invoke(model); |
| 64 | 64 | } catch (Exception ex) { |
| 65 | + ex.printStackTrace(); | |
| 65 | 66 | Log.log("Error on ThemeChanger#apply(): " + ex.getMessage()); |
| 66 | 67 | } |
| 67 | 68 | } |
| @@ -40,7 +40,7 @@ | ||
| 40 | 40 | private final String KEY_IMAGE = "image"; |
| 41 | 41 | private final String KEY_EXCLUDE = "exclude"; |
| 42 | 42 | |
| 43 | - private String target = "mainWindow"; | |
| 43 | + private Parts target = Parts.MainWindow; | |
| 44 | 44 | private float opacity = 0.5f; |
| 45 | 45 | private String image = ""; |
| 46 | 46 | private List<String> exclude = new ArrayList<String>(); |
| @@ -47,11 +47,12 @@ | ||
| 47 | 47 | |
| 48 | 48 | public SimpleImage(Map config) { |
| 49 | 49 | if (config.containsKey(KEY_TARGET)) { |
| 50 | - target = (String) config.get(KEY_TARGET); | |
| 51 | - if (!target.equals("mainWindow")) { | |
| 52 | - //@@TODO 他のtargetにも対応 | |
| 53 | - throw new IllegalArgumentException( | |
| 54 | - "target argument '" + target + "' is not supported."); | |
| 50 | + //@@TODO 設定自体を Enum で受け取れるように | |
| 51 | + String targetName = (String) config.get(KEY_TARGET); | |
| 52 | + try { | |
| 53 | + target = Parts.valueOf(targetName); | |
| 54 | + } catch (IllegalArgumentException ex) { | |
| 55 | + Log.log("warning: target name '" + targetName + "' is not found in Parts enum."); | |
| 55 | 56 | } |
| 56 | 57 | } |
| 57 | 58 |
| @@ -84,9 +85,9 @@ | ||
| 84 | 85 | try { |
| 85 | 86 | String lcased = image.toLowerCase(); |
| 86 | 87 | if (lcased.startsWith("http://") || lcased.startsWith("https://")) { |
| 87 | - ui.setBackground(ImageIO.read(new URL(image))); | |
| 88 | + ui.setBackground(target, ImageIO.read(new URL(image))); | |
| 88 | 89 | } else { |
| 89 | - ui.setBackground(ImageIO.read(new File(image))); | |
| 90 | + ui.setBackground(target, ImageIO.read(new File(image))); | |
| 90 | 91 | } |
| 91 | 92 | } catch (MalformedURLException ex) { |
| 92 | 93 | Log.log(ex.getMessage()); |
| @@ -94,9 +95,11 @@ | ||
| 94 | 95 | Log.log(ex.getMessage()); |
| 95 | 96 | } |
| 96 | 97 | |
| 97 | - ui.setOpacity(opacity); | |
| 98 | + ui.setOpacity(target, opacity); | |
| 98 | 99 | |
| 99 | - ui.transparent(excludeParts); | |
| 100 | + if (target == Parts.MainWindow) { | |
| 101 | + ui.transparent(excludeParts); | |
| 102 | + } | |
| 100 | 103 | } |
| 101 | 104 | |
| 102 | 105 | } |
| @@ -30,14 +30,19 @@ | ||
| 30 | 30 | import java.awt.Graphics; |
| 31 | 31 | import java.awt.SystemColor; |
| 32 | 32 | import java.awt.image.BufferedImage; |
| 33 | +import java.util.EnumMap; | |
| 33 | 34 | import java.util.EnumSet; |
| 35 | +import java.util.Map; | |
| 34 | 36 | import javax.swing.JComponent; |
| 35 | 37 | import javax.swing.JEditorPane; |
| 36 | 38 | import javax.swing.JFrame; |
| 37 | 39 | import javax.swing.JMenuBar; |
| 38 | 40 | import javax.swing.JPanel; |
| 41 | +import javax.swing.JRootPane; | |
| 39 | 42 | import javax.swing.JScrollPane; |
| 43 | +import javax.swing.JTextPane; | |
| 40 | 44 | import javax.swing.SwingUtilities; |
| 45 | +import javax.swing.plaf.ComponentUI; | |
| 41 | 46 | import org.omegat.core.Core; |
| 42 | 47 | import org.omegat.core.CoreEvents; |
| 43 | 48 | import org.omegat.core.events.IProjectEventListener; |
| @@ -51,14 +56,14 @@ | ||
| 51 | 56 | |
| 52 | 57 | private static MoeUI moeUI; |
| 53 | 58 | |
| 54 | - private JFrame frame; | |
| 55 | - private MoeLayeredPane layeredPane; | |
| 56 | - private Container contentPane; | |
| 57 | - private JMenuBar menuBar; | |
| 58 | - private DockingDesktop desktop; | |
| 59 | - private JPanel statusBar; | |
| 60 | - private AutoHideButtonPanel buttonPanel; | |
| 61 | - private float opacity = 0.5f; | |
| 59 | + private final JFrame frame; | |
| 60 | + private final JRootPane rootPane; | |
| 61 | + private final Container contentPane; | |
| 62 | + private final JMenuBar menuBar; | |
| 63 | + private final DockingDesktop desktop; | |
| 64 | + private final JPanel statusBar; | |
| 65 | + private final AutoHideButtonPanel buttonPanel; | |
| 66 | + private final Map<Parts, ComponentUI> uis; | |
| 62 | 67 | |
| 63 | 68 | private boolean makeTransparentMenubar = true; |
| 64 | 69 | private boolean makeTransparentButtonPanel = true; |
| @@ -65,9 +70,14 @@ | ||
| 65 | 70 | private boolean makeTransparentStatusbar = true; |
| 66 | 71 | private boolean makeTransparentPaneTitlebar = true; |
| 67 | 72 | private boolean isEditorTransparent = false; |
| 68 | - | |
| 73 | + | |
| 69 | 74 | public enum Parts { |
| 70 | - MenuBar, StatusBar, ButtonPanel, PaneTitleBar | |
| 75 | + MainWindow, | |
| 76 | + // Excluding parts for transparency | |
| 77 | + MenuBar, StatusBar, ButtonPanel, PaneTitleBar, | |
| 78 | + // Built-in panes | |
| 79 | + EDITOR, MATCHES, GLOSSARY, NOTES, COMMENTS, MACHINE_TRANSLATE, | |
| 80 | + DICTIONARY, MULTIPLE_TRANS | |
| 71 | 81 | } |
| 72 | 82 | |
| 73 | 83 | static { |
| @@ -78,7 +88,14 @@ | ||
| 78 | 88 | private MoeUI() { |
| 79 | 89 | UIThreadsUtil.mustBeSwingThread(); |
| 80 | 90 | |
| 81 | - initUI(); | |
| 91 | + frame = Core.getMainWindow().getApplicationFrame(); | |
| 92 | + rootPane = frame.getRootPane(); | |
| 93 | + contentPane = frame.getContentPane(); | |
| 94 | + menuBar = frame.getJMenuBar(); | |
| 95 | + statusBar = getJPanel(contentPane); | |
| 96 | + desktop = getDockingDesktop(contentPane); | |
| 97 | + buttonPanel = getButtonPanel(desktop); | |
| 98 | + uis = new EnumMap<Parts, ComponentUI>(Parts.class); | |
| 82 | 99 | } |
| 83 | 100 | |
| 84 | 101 | public static MoeUI getInstance() { |
| @@ -88,12 +105,90 @@ | ||
| 88 | 105 | return moeUI; |
| 89 | 106 | } |
| 90 | 107 | |
| 91 | - public void setOpacity(float opacity) { | |
| 92 | - this.opacity = opacity; | |
| 93 | - layeredPane.setOpacity(opacity); | |
| 108 | + public void setBackground(Parts target, BufferedImage image) { | |
| 109 | + UIThreadsUtil.mustBeSwingThread(); | |
| 110 | + | |
| 111 | + if (target == Parts.MainWindow) { | |
| 112 | + MoeRootPaneUI ui; | |
| 113 | + if (uis.containsKey(target)) { | |
| 114 | + ui = (MoeRootPaneUI) uis.get(target); | |
| 115 | + } else { | |
| 116 | + ui = new MoeRootPaneUI(); | |
| 117 | + rootPane.setUI(ui); | |
| 118 | + } | |
| 119 | + ui.setBackground(image); | |
| 120 | + uis.put(target, ui); | |
| 121 | + | |
| 122 | + } 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); | |
| 132 | + } | |
| 94 | 133 | } |
| 95 | 134 | |
| 135 | + public void setBackground(Parts target, Color color) { | |
| 136 | + UIThreadsUtil.mustBeSwingThread(); | |
| 137 | + | |
| 138 | + if (target == Parts.MainWindow) { | |
| 139 | + MoeRootPaneUI ui; | |
| 140 | + if (uis.containsKey(target)) { | |
| 141 | + ui = (MoeRootPaneUI) uis.get(target); | |
| 142 | + } else { | |
| 143 | + ui = new MoeRootPaneUI(); | |
| 144 | + rootPane.setUI(ui); | |
| 145 | + } | |
| 146 | + ui.setBackground(color); | |
| 147 | + uis.put(target, ui); | |
| 148 | + | |
| 149 | + } 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); | |
| 159 | + } | |
| 160 | + } | |
| 161 | + | |
| 162 | + public void setOpacity(Parts target, float opacity) { | |
| 163 | + UIThreadsUtil.mustBeSwingThread(); | |
| 164 | + | |
| 165 | + if (target == Parts.MainWindow) { | |
| 166 | + MoeRootPaneUI ui; | |
| 167 | + if (uis.containsKey(target)) { | |
| 168 | + ui = (MoeRootPaneUI) uis.get(target); | |
| 169 | + } else { | |
| 170 | + ui = new MoeRootPaneUI(); | |
| 171 | + rootPane.setUI(ui); | |
| 172 | + } | |
| 173 | + ui.setOpacity(opacity); | |
| 174 | + uis.put(target, ui); | |
| 175 | + | |
| 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); | |
| 186 | + } | |
| 187 | + } | |
| 188 | + | |
| 189 | + // MainWindow に画像や色を割り当てる場合のみ使用します | |
| 96 | 190 | public void transparent(EnumSet<Parts> exclude) { |
| 191 | + //@@TODO EDITOR などのペインが指定された場合に対応 | |
| 97 | 192 | if (exclude != null) { |
| 98 | 193 | makeTransparentMenubar = !exclude.contains(Parts.MenuBar); |
| 99 | 194 | makeTransparentButtonPanel = !exclude.contains(Parts.ButtonPanel); |
| @@ -110,17 +205,18 @@ | ||
| 110 | 205 | if (makeTransparentMenubar) { |
| 111 | 206 | transparent(menuBar); |
| 112 | 207 | } else { |
| 113 | - int marginTop = 0; | |
| 114 | - marginTop = menuBar.getHeight(); | |
| 208 | + int marginTop = menuBar.getHeight(); | |
| 115 | 209 | if (!makeTransparentPaneTitlebar) { |
| 116 | 210 | marginTop += getDockViewTitleBarHeight(desktop); |
| 117 | 211 | } |
| 118 | - layeredPane.setPaintMarginTop(marginTop); | |
| 212 | + MoeRootPaneUI ui = (MoeRootPaneUI) uis.get(Parts.MainWindow); | |
| 213 | + ui.setMarginTop(marginTop); | |
| 119 | 214 | } |
| 120 | 215 | transparentRecursive(contentPane); |
| 121 | 216 | transparentInstantStart(desktop); |
| 122 | 217 | |
| 123 | 218 | // try to make transparent editor pane |
| 219 | + //@@TODO エディターが除外パーツになっている場合を考慮 | |
| 124 | 220 | if (!isEditorTransparent) { |
| 125 | 221 | isEditorTransparent = transparentEditor(); |
| 126 | 222 | if (!isEditorTransparent) { |
| @@ -205,32 +301,53 @@ | ||
| 205 | 301 | return true; |
| 206 | 302 | } |
| 207 | 303 | |
| 208 | - public void setBackground(final BufferedImage image) { | |
| 209 | - UIThreadsUtil.executeInSwingThread(new Runnable() { | |
| 210 | - @Override | |
| 211 | - public void run() { | |
| 212 | - layeredPane.setBackground(image); | |
| 304 | + private JTextPane getTextPane(Parts pane) { | |
| 305 | +/* | |
| 306 | +dockable.getDockKey().getKey() | |
| 307 | + dockable.getComponent().class.name | |
| 308 | + dockable.getComponent().getViewport().getView().class.name | |
| 309 | +------------- | |
| 310 | +EDITOR | |
| 311 | + org.omegat.gui.main.DockablePanel | |
| 312 | +MATCHES | |
| 313 | + org.omegat.gui.main.DockableScrollPane | |
| 314 | + org.omegat.gui.matches.MatchesTextArea | |
| 315 | +GLOSSARY | |
| 316 | + org.omegat.gui.main.DockableScrollPane | |
| 317 | + org.omegat.gui.glossary.GlossaryTextArea | |
| 318 | +NOTES | |
| 319 | + org.omegat.gui.main.DockableScrollPane | |
| 320 | + org.omegat.gui.notes.NotesTextArea | |
| 321 | +COMMENTS | |
| 322 | + org.omegat.gui.main.DockableScrollPane | |
| 323 | + org.omegat.gui.comments.CommentsTextArea | |
| 324 | +MACHINE_TRANSLATE | |
| 325 | + org.omegat.gui.main.DockableScrollPane | |
| 326 | + org.omegat.gui.exttrans.MachineTranslateTextArea | |
| 327 | +DICTIONARY | |
| 328 | + org.omegat.gui.main.DockableScrollPane | |
| 329 | + org.omegat.gui.dictionaries.DictionariesTextArea | |
| 330 | +MULTIPLE_TRANS | |
| 331 | + org.omegat.gui.main.DockableScrollPane | |
| 332 | + org.omegat.gui.multtrans.MultipleTransPane | |
| 333 | + | |
| 334 | + xxxTextArea は、基本的に全部 JEditorPane の拡張。 | |
| 335 | + MULTIPLE_TRANS も、同じ。 | |
| 336 | + EntryInfoThreadPane -> EntryInfoPane -> JTextPane -> JEditorPane という感じ。 | |
| 337 | + | |
| 338 | + //@@TODOエディターも同じで扱えるのか? | |
| 339 | +*/ | |
| 340 | + final String PANE_NAME = pane.name(); | |
| 341 | + for (DockableState d: desktop.getDockables()) { | |
| 342 | + Dockable dockable = d.getDockable(); | |
| 343 | + if (dockable.getDockKey().getKey().equalsIgnoreCase(PANE_NAME)) { | |
| 344 | + JScrollPane sp = (JScrollPane) dockable.getComponent(); | |
| 345 | + return (JTextPane) sp.getViewport().getView(); | |
| 213 | 346 | } |
| 214 | - }); | |
| 347 | + } | |
| 348 | + return null; | |
| 215 | 349 | } |
| 216 | 350 | |
| 217 | - private void initUI() { | |
| 218 | - frame = Core.getMainWindow().getApplicationFrame(); | |
| 219 | - layeredPane = new MoeLayeredPane(); | |
| 220 | - contentPane = frame.getContentPane(); | |
| 221 | - menuBar = frame.getJMenuBar(); | |
| 222 | - statusBar = getJPanel(contentPane); | |
| 223 | - desktop = getDockingDesktop(contentPane); | |
| 224 | - buttonPanel = getButtonPanel(desktop); | |
| 225 | - | |
| 226 | - // replace LayeredPane with MoeLayeredPane | |
| 227 | - frame.setLayeredPane(layeredPane); | |
| 228 | - frame.setContentPane(contentPane); | |
| 229 | - frame.setJMenuBar(menuBar); | |
| 230 | - | |
| 231 | - frame.validate(); | |
| 232 | - } | |
| 233 | - | |
| 234 | 351 | private void transparent(JMenuBar menuBar) { |
| 235 | 352 | //menuBar.setUI ( new BasicMenuBarUI () { |
| 236 | 353 | // 上記だと初期表示時に、アクティブメニューがアクティブで描画されない。 |