/* * Lilith - a log event viewer. * Copyright (C) 2007-2015 Joern Huxhorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.huxhorn.lilith.swing; import de.huxhorn.lilith.swing.linklistener.OpenUrlLinkListener; import de.huxhorn.sulky.swing.KeyStrokes; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.KeyStroke; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xhtmlrenderer.context.AWTFontResolver; import org.xhtmlrenderer.extend.FontResolver; import org.xhtmlrenderer.extend.TextRenderer; import org.xhtmlrenderer.layout.SharedContext; import org.xhtmlrenderer.simple.FSScrollPane; import org.xhtmlrenderer.simple.XHTMLPanel; import org.xhtmlrenderer.simple.extend.XhtmlNamespaceHandler; import org.xhtmlrenderer.swing.LinkListener; import org.xhtmlrenderer.swing.SelectionHighlighter; public class TipOfTheDayDialog extends JDialog { private static final long serialVersionUID = -1068053167252606619L; private final Logger logger = LoggerFactory.getLogger(TipOfTheDayDialog.class); private List<URL> tipsOfTheDay; private int currentTipOfTheDay; private ApplicationPreferences applicationPreferences; private XHTMLPanel helpPane; private XhtmlNamespaceHandler xhtmlNamespaceHandler; private JCheckBox showTipOfTheDayCheckbox; private static final int INSET = 10; public TipOfTheDayDialog(MainFrame owner) { super(owner); applicationPreferences = owner.getApplicationPreferences(); setTitle("Tip of the Day"); setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); setModal(false); JPanel content = new JPanel(new GridBagLayout()); setLayout(new GridLayout(1, 1)); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets.top = INSET; gbc.insets.bottom = 0; gbc.insets.left = INSET; gbc.insets.right = INSET; gbc.gridwidth = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.LINE_START; JLabel didYouKnowLabel = new JLabel("Did you know...?"); Font labelFont = didYouKnowLabel.getFont(); labelFont=labelFont.deriveFont(2.0f*labelFont.getSize2D()); didYouKnowLabel.setFont(labelFont); didYouKnowLabel.setIcon(Icons.DIALOG_INFO_ICON); content.add(didYouKnowLabel, gbc); gbc.anchor = GridBagConstraints.CENTER; initHelpResources(); helpPane = new XHTMLPanel(); { SharedContext sharedContext = helpPane.getSharedContext(); TextRenderer textRenderer = sharedContext.getTextRenderer(); textRenderer.setSmoothingThreshold(RendererConstants.SMOOTHING_THRESHOLD); FontResolver fontResolver = sharedContext.getFontResolver(); if(fontResolver instanceof AWTFontResolver && RendererConstants.MENSCH_FONT != null) { AWTFontResolver awtFontResolver = (AWTFontResolver) fontResolver; awtFontResolver.setFontMapping(RendererConstants.MONOSPACED_FAMILY, RendererConstants.MENSCH_FONT); if(logger.isInfoEnabled()) logger.info("Installed '{}' font.", RendererConstants.MONOSPACED_FAMILY); } } { LinkListener originalLinkListener = null; java.util.List mouseTrackingList = helpPane.getMouseTrackingListeners(); if(mouseTrackingList != null) { for(Object o : mouseTrackingList) { if(logger.isDebugEnabled()) logger.debug("Before MTL {}", o); if(o instanceof LinkListener) { helpPane.removeMouseTrackingListener((LinkListener) o); originalLinkListener = (LinkListener) o; } } } helpPane.addMouseTrackingListener(new OpenUrlLinkListener(owner, originalLinkListener)); } SelectionHighlighter helpPaneCaret = new SelectionHighlighter(); helpPaneCaret.install(helpPane); SelectionHighlighter.CopyAction copyAction = new SelectionHighlighter.CopyAction(); copyAction.install(helpPaneCaret); xhtmlNamespaceHandler = new XhtmlNamespaceHandler(); FSScrollPane helpScrollPane = new FSScrollPane(helpPane); helpScrollPane.setPreferredSize(new Dimension(600, 300)); gbc.gridy = 1; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.BOTH; content.add(helpScrollPane, gbc); gbc.gridy = 2; gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.LINE_START; showTipOfTheDayCheckbox = new JCheckBox("Show Tip of the Day on startup."); showTipOfTheDayCheckbox.setSelected(applicationPreferences.isShowingTipOfTheDay()); showTipOfTheDayCheckbox.addItemListener(new CheckboxListener()); showTipOfTheDayCheckbox.setMnemonic(KeyEvent.VK_S); content.add(showTipOfTheDayCheckbox, gbc); gbc.anchor = GridBagConstraints.CENTER; gbc.gridx = 0; JPanel buttonPanel = new JPanel(new GridBagLayout()); gbc.insets.top = 0; gbc.insets.bottom = 0; gbc.insets.left = 0; gbc.insets.right = INSET; buttonPanel.add(new JButton(new PreviousTipAction()), gbc); gbc.gridx = 1; buttonPanel.add(new JButton(new NextTipAction()), gbc); CloseAction closeAction = new CloseAction(); gbc.gridx = 2; gbc.insets.top = 0; gbc.insets.bottom = 0; gbc.insets.left = 0; gbc.insets.right = 0; buttonPanel.add(new JButton(closeAction), gbc); gbc.insets.top = INSET; gbc.insets.bottom = INSET; gbc.insets.left = INSET; gbc.insets.right = INSET; gbc.anchor = GridBagConstraints.LINE_END; gbc.gridx = 0; gbc.gridy = 3; content.add(buttonPanel, gbc); KeyStrokes.registerCommand(content, closeAction, "CLOSE_ACTION"); add(content); setCurrentTipOfTheDay(applicationPreferences.getCurrentTipOfTheDay() + 1); } private void nextTipOfTheDay() { setCurrentTipOfTheDay(currentTipOfTheDay + 1); } private void previousTipOfTheDay() { setCurrentTipOfTheDay(currentTipOfTheDay - 1); } private void setCurrentTipOfTheDay(int currentTipOfTheDay) { int count = tipsOfTheDay.size(); if(currentTipOfTheDay < 0) { currentTipOfTheDay = count - 1; } else if(currentTipOfTheDay >= count) { currentTipOfTheDay = 0; } this.currentTipOfTheDay = currentTipOfTheDay; applicationPreferences.setCurrentTipOfTheDay(currentTipOfTheDay); if(logger.isDebugEnabled()) logger.debug("Current Tip of the Day: {}", currentTipOfTheDay); helpPane.setDocument(tipsOfTheDay.get(currentTipOfTheDay).toExternalForm(), xhtmlNamespaceHandler); } private void initHelpResources() { tipsOfTheDay = new ArrayList<>(); for(int i = 0;; i++) { URL url = TipOfTheDayDialog.class.getResource("/tips/" + i + ".xhtml"); if(url == null) { break; } tipsOfTheDay.add(url); } if(logger.isDebugEnabled()) logger.debug("Tip of the Day URLs found: {}", tipsOfTheDay); if(logger.isInfoEnabled()) logger.info("Found {} Tips of the Day.", tipsOfTheDay.size()); } public void setShowingTipOfTheDay(boolean showingTipOfTheDay) { showTipOfTheDayCheckbox.setSelected(showingTipOfTheDay); } private class PreviousTipAction extends AbstractAction { private static final long serialVersionUID = -4025074394725104369L; private PreviousTipAction() { super("Previous Tip"); putValue(Action.MNEMONIC_KEY, KeyEvent.VK_P); } public void actionPerformed(ActionEvent e) { previousTipOfTheDay(); } } private class NextTipAction extends AbstractAction { private static final long serialVersionUID = 107240711521577323L; private NextTipAction() { super("Next Tip"); putValue(Action.MNEMONIC_KEY, KeyEvent.VK_N); } public void actionPerformed(ActionEvent e) { nextTipOfTheDay(); } } private class CloseAction extends AbstractAction { private static final long serialVersionUID = -3837690263247686627L; private CloseAction() { super("Close"); KeyStroke accelerator = LilithKeyStrokes.getKeyStroke(LilithKeyStrokes.ESCAPE); putValue(Action.ACCELERATOR_KEY, accelerator); putValue(Action.MNEMONIC_KEY, KeyEvent.VK_C); } public void actionPerformed(ActionEvent e) { setVisible(false); // workaround for http://sourceforge.net/apps/trac/lilith/ticket/72 below Container parentContainer = getParent(); if(parentContainer != null) { parentContainer.requestFocus(); } // workaround for http://sourceforge.net/apps/trac/lilith/ticket/72 above } } private class CheckboxListener implements ItemListener { public void itemStateChanged(ItemEvent e) { Object source = e.getItemSelectable(); if(source == showTipOfTheDayCheckbox) { applicationPreferences.setShowingTipOfTheDay(showTipOfTheDayCheckbox.isSelected()); } } } }