/* * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.ide.util; import com.intellij.CommonBundle; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.impl.DefaultKeymap; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.ResourceUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.StringReader; import java.net.URL; /** * @author dsl * @author Konstantin Bulenkov */ public class TipUIUtil { @NonNls private static final String SHORTCUT_ENTITY = "&shortcut:"; private TipUIUtil() { } @NotNull public static String getPoweredByText(@NotNull TipAndTrickBean tip) { PluginDescriptor descriptor = tip.getPluginDescriptor(); return descriptor instanceof IdeaPluginDescriptor && !PluginManagerCore.CORE_PLUGIN_ID.equals(descriptor.getPluginId().getIdString()) ? ((IdeaPluginDescriptor)descriptor).getName() : ""; } public static void openTipInBrowser(String tipFileName, JEditorPane browser, Class providerClass) { TipAndTrickBean tip = TipAndTrickBean.findByFileName(tipFileName); if (tip == null && StringUtil.isNotEmpty(tipFileName)) { tip = new TipAndTrickBean(); tip.fileName = tipFileName; } openTipInBrowser(tip, browser); } public static void openTipInBrowser(@Nullable TipAndTrickBean tip, JEditorPane browser) { if (tip == null) return; try { PluginDescriptor pluginDescriptor = tip.getPluginDescriptor(); ClassLoader tipLoader = pluginDescriptor == null ? TipUIUtil.class.getClassLoader() : ObjectUtils.notNull(pluginDescriptor.getPluginClassLoader(), TipUIUtil.class.getClassLoader()); URL url = ResourceUtil.getResource(tipLoader, "/tips/", tip.fileName); if (url == null) { setCantReadText(browser, tip); return; } StringBuffer text = new StringBuffer(ResourceUtil.loadText(url)); updateShortcuts(text); updateImages(text, tipLoader); String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName()); String major = ApplicationInfo.getInstance().getMajorVersion(); replaced = replaced.replace("&majorVersion;", major); String minor = ApplicationInfo.getInstance().getMinorVersion(); replaced = replaced.replace("&minorVersion;", minor); replaced = replaced.replace("&majorMinorVersion;", major + ("0".equals(minor) ? "" : ("." + minor))); replaced = replaced.replace("&settingsPath;", CommonBundle.settingsActionPath()); if (UIUtil.isUnderDarcula()) { replaced = replaced.replace("css/tips.css", "css/tips_darcula.css"); } browser.read(new StringReader(replaced), url); } catch (IOException e) { setCantReadText(browser, tip); } } private static void setCantReadText(JEditorPane browser, TipAndTrickBean bean) { try { String plugin = getPoweredByText(bean); String product = ApplicationNamesInfo.getInstance().getFullProductName(); if (!plugin.isEmpty()) { product += " and " + plugin + " plugin"; } String message = IdeBundle.message("error.unable.to.read.tip.of.the.day", bean.fileName, product); browser.read(new StringReader(message), null); } catch (IOException ignored) { } } private static void updateImages(StringBuffer text, ClassLoader tipLoader) { final boolean dark = UIUtil.isUnderDarcula(); final boolean retina = UIUtil.isRetina(); // if (!dark && !retina) { // return; // } String suffix = ""; if (retina) suffix += "@2x"; if (dark) suffix += "_dark"; int index = text.indexOf("", index + 1); if (end == -1) return; final String img = text.substring(index, end + 1).replace('\r', ' ').replace('\n',' '); final int srcIndex = img.indexOf("src="); final int endIndex = img.indexOf(".png", srcIndex); if (endIndex != -1) { String path = img.substring(srcIndex + 5, endIndex); if (!path.endsWith("_dark") && !path.endsWith("@2x")) { path += suffix + ".png"; URL url = ResourceUtil.getResource(tipLoader, "/tips/", path); if (url != null) { String newImgTag = ""; } text.replace(lastIndex, actionIdEnd + 1, shortcutText); lastIndex += shortcutText.length(); } } @Nullable private static String getShortcutText(String actionId, Keymap keymap) { for (final Shortcut shortcut : keymap.getShortcuts(actionId)) { if (shortcut instanceof KeyboardShortcut) { return KeymapUtil.getShortcutText(shortcut); } } return null; } @NotNull public static JEditorPane createTipBrowser() { JEditorPane browser = new JEditorPane(); browser.setEditable(false); browser.setBackground(UIUtil.getTextFieldBackground()); browser.addHyperlinkListener( new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { BrowserUtil.browse(e.getURL()); } } } ); URL resource = ResourceUtil.getResource(TipUIUtil.class, "/tips/css/", UIUtil.isUnderDarcula() ? "tips_darcula.css" : "tips.css"); final StyleSheet styleSheet = UIUtil.loadStyleSheet(resource); HTMLEditorKit kit = new HTMLEditorKit() { @Override public StyleSheet getStyleSheet() { return styleSheet != null ? styleSheet : super.getStyleSheet(); } }; browser.setEditorKit(kit); return browser; } }