Java tutorial
/* * TV-Browser * Copyright (C) 04-2003 Martin Oberhauser (martin@tvbrowser.org) * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * CVS information: * $RCSfile$ * $Source$ * $Date: 2010-11-01 17:06:15 +0100 (Mon, 01 Nov 2010) $ * $Author: bananeweizen $ * $Revision: 6804 $ */ package tvbrowser.ui.mainframe; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.io.StringWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.TooManyListenersException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.WindowConstants; import org.apache.commons.lang.math.RandomUtils; import tvbrowser.TVBrowser; import tvbrowser.core.ChannelList; import tvbrowser.core.DateListener; import tvbrowser.core.Settings; import tvbrowser.core.TvDataBase; import tvbrowser.core.TvDataUpdater; import tvbrowser.core.filters.FilterComponent; import tvbrowser.core.filters.FilterComponentList; import tvbrowser.core.filters.FilterList; import tvbrowser.core.filters.FilterManagerImpl; import tvbrowser.core.filters.ShowAllFilter; import tvbrowser.core.filters.filtercomponents.ChannelFilterComponent; import tvbrowser.core.plugin.PluginProxy; import tvbrowser.core.plugin.PluginProxyManager; import tvbrowser.core.tvdataservice.TvDataServiceProxy; import tvbrowser.core.tvdataservice.TvDataServiceProxyManager; import tvbrowser.extras.favoritesplugin.FavoritesPlugin; import tvbrowser.extras.reminderplugin.ReminderPlugin; import tvbrowser.ui.DontShowAgainOptionBox; import tvbrowser.ui.aboutbox.AboutBox; import tvbrowser.ui.filter.dlgs.SelectFilterDlg; import tvbrowser.ui.finder.DateSelector; import tvbrowser.ui.finder.FinderPanel; import tvbrowser.ui.finder.calendar.CalendarPanel; import tvbrowser.ui.finder.calendar.CalendarTablePanel; import tvbrowser.ui.licensebox.LicenseBox; import tvbrowser.ui.mainframe.actions.TVBrowserAction; import tvbrowser.ui.mainframe.actions.TVBrowserActions; import tvbrowser.ui.mainframe.searchfield.SearchField; import tvbrowser.ui.mainframe.searchfield.SearchFilter; import tvbrowser.ui.mainframe.toolbar.ContextMenu; import tvbrowser.ui.mainframe.toolbar.DefaultToolBarModel; import tvbrowser.ui.mainframe.toolbar.MoreButton; import tvbrowser.ui.mainframe.toolbar.ToolBar; import tvbrowser.ui.pluginview.PluginView; import tvbrowser.ui.programtable.DefaultProgramTableModel; import tvbrowser.ui.programtable.FilterPanel; import tvbrowser.ui.programtable.KeyboardAction; import tvbrowser.ui.programtable.ProgramTable; import tvbrowser.ui.programtable.ProgramTableScrollPane; import tvbrowser.ui.settings.BlockedPlugin; import tvbrowser.ui.settings.SettingsDialog; import tvbrowser.ui.update.PluginAutoUpdater; import tvbrowser.ui.update.SoftwareUpdateDlg; import tvbrowser.ui.update.SoftwareUpdateItem; import util.browserlauncher.Launch; import util.exc.ErrorHandler; import util.io.IOUtilities; import util.misc.OperatingSystem; import util.ui.Localizer; import util.ui.UiUtilities; import util.ui.progress.Progress; import util.ui.progress.ProgressWindow; import util.ui.view.Node; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.Sizes; import devplugin.Channel; import devplugin.ChannelDayProgram; import devplugin.Date; import devplugin.Plugin; import devplugin.Program; import devplugin.ProgramFilter; import devplugin.ProgressMonitor; import devplugin.SettingsItem; import devplugin.Version; /** * TV-Browser * * @author Martin Oberhauser */ public class MainFrame extends JFrame implements DateListener, DropTargetListener { private static final Logger mLog = java.util.logging.Logger.getLogger(tvbrowser.TVBrowser.class.getName()); /** The localizer for this class. */ public static final util.ui.Localizer mLocalizer = util.ui.Localizer.getLocalizerFor(MainFrame.class); private Node mTimebuttonsNode, mDateNode, mRootNode, mChannelNode; private Node mPluginsNode; private JDialog mConfigAssistantDialog; private SoftwareUpdateItem[] mSoftwareUpdateItems = null; private ProgramTableScrollPane mProgramTableScrollPane; private DefaultProgramTableModel mProgramTableModel; private Thread downloadingThread; private JPanel jcontentPane; private DefaultToolBarModel mToolBarModel; private ToolBar mToolBar; private JPanel mToolBarPanel; private SearchField mSearchField; private StatusBar mStatusBar; private DateSelector mFinderPanel; private static MainFrame mSingleton; private ChannelChooserPanel mChannelChooser; private MenuBar mMenuBar; private Component mCenterComponent; private boolean mIsVisible; private static boolean mShuttingDown = false; private static boolean mStarting = true; private Node mMainframeNode; private Node mNavigationNode; private Node mDateChannelNode; private Date mCurrentDay; private PluginView mPluginView; private int mXPos, mYPos, mWidth, mHeight; /** Panel that Displays current Filter-Name */ private FilterPanel mFilterPanel; private TimeChooserPanel mTimeChooserPanel; /** Store the Viewposition if a Filter is selected*/ private Point mStoredViewPosition; private String mCurrentFilterName; private int mLastTimerMinutesAfterMidnight; private static Date[] mChannelDateArr; private static int[] mOnAirRowProgramsArr; private boolean mSettingsWillBeOpened; private long mLastAutoUpdateRun; private long mLastAutoUpdateRunBuffer; private int mAutoDownloadTimer; private boolean mIsAskingUpdate = false; private Timer mTimer; private MainFrame() { super(TVBrowser.MAINWINDOW_TITLE); mIsVisible = false; mSettingsWillBeOpened = false; mAutoDownloadTimer = -1; mLastTimerMinutesAfterMidnight = -1; mLastAutoUpdateRun = System.currentTimeMillis(); mChannelDateArr = null; mOnAirRowProgramsArr = null; mStatusBar = new StatusBar(); if (OperatingSystem.isMacOs()) { /* create the menu bar for MacOS X */ try { Class<?> impl = Class.forName("tvbrowser.ui.mainframe.macosx.MacOSXMenuBar"); Class<? extends MainFrame> mainFrameClass = this.getClass(); Class<?> jlabelClass = Class.forName("javax.swing.JLabel"); Constructor<?> cons = impl.getConstructor(new Class[] { mainFrameClass, jlabelClass }); mMenuBar = (MenuBar) cons.newInstance(new Object[] { this, mStatusBar.getLabel() }); } catch (Exception e) { if (TVBrowser.isTransportable()) { mLog.info("Using default menu bar (instead of MacOSXMenuBar) for transportable version."); } mLog.warning("Could not instantiate MacOSXMenuBar\n" + e.toString()); if (e.getCause() != null) { StringWriter sw = new StringWriter(); e.getCause().printStackTrace(new PrintWriter(sw)); mLog.warning(sw.toString()); } mMenuBar = new DefaultMenuBar(this, mStatusBar.getLabel()); mLog.info("Using default menu bar"); } } else { mMenuBar = new DefaultMenuBar(this, mStatusBar.getLabel()); } // create content jcontentPane = (JPanel) getContentPane(); jcontentPane.setLayout(new BorderLayout()); JPanel skinPanel = new JPanel(); skinPanel.setLayout(new BorderLayout()); JPanel centerPanel = new JPanel(new BorderLayout()); centerPanel.setOpaque(false); centerPanel.setBorder(BorderFactory.createEmptyBorder()); mFilterPanel = new FilterPanel(); mFilterPanel.setVisible(false); mTimeChooserPanel = new TimeChooserPanel(this); centerPanel.add(mFilterPanel, BorderLayout.NORTH); Channel[] channelArr = ChannelList.getSubscribedChannels(); int startOfDay = Settings.propProgramTableStartOfDay.getInt(); int endOfDay = Settings.propProgramTableEndOfDay.getInt(); mProgramTableModel = new DefaultProgramTableModel(channelArr, startOfDay, endOfDay); mProgramTableScrollPane = new ProgramTableScrollPane(mProgramTableModel); centerPanel.add(mProgramTableScrollPane); createDateSelector(); skinPanel.add(centerPanel, BorderLayout.CENTER); mChannelChooser = new ChannelChooserPanel(this); /* create structure */ mRootNode = new Node(null); if (Settings.propPluginViewIsLeft.getBoolean()) { mPluginsNode = new Node(mRootNode); } else { mNavigationNode = new Node(mRootNode); } mMainframeNode = new Node(mRootNode); Node programtableNode = new Node(mMainframeNode); if (Settings.propPluginViewIsLeft.getBoolean()) { mNavigationNode = new Node(mMainframeNode); } else { mPluginsNode = new Node(mMainframeNode); } mTimebuttonsNode = new Node(mNavigationNode); mDateChannelNode = new Node(mNavigationNode); mDateNode = new Node(mDateChannelNode); mChannelNode = new Node(mDateChannelNode); mRootNode.setProperty(Settings.propViewRoot); mMainframeNode.setProperty(Settings.propViewMainframe); mNavigationNode.setProperty(Settings.propViewNavigation); mDateChannelNode.setProperty(Settings.propViewDateChannel); /* create views */ programtableNode.setLeaf(skinPanel); this.setShowPluginOverview(Settings.propShowPluginView.getBoolean()); this.setShowTimeButtons(Settings.propShowTimeButtons.getBoolean()); this.setShowDatelist(Settings.propShowDatelist.getBoolean()); this.setShowChannellist(Settings.propShowChannels.getBoolean()); updateToolbar(); dateChanged(new devplugin.Date(), null, null); mCenterComponent = mRootNode.getComponent(); if (mCenterComponent != null) { jcontentPane.add(mCenterComponent, BorderLayout.CENTER); } if (Settings.propIsStatusbarVisible.getBoolean()) { jcontentPane.add(mStatusBar, BorderLayout.SOUTH); } setJMenuBar(mMenuBar); addContextMenuMouseListener(mMenuBar); // set program filter FilterList filterList = FilterList.getInstance(); ProgramFilter filter = filterList.getFilterByName(Settings.propLastUsedFilter.getString()); if (filter == null) { filter = FilterManagerImpl.getInstance().getDefaultFilter(); } setProgramFilter(filter); // set channel group filter String channelGroupName = Settings.propLastUsedChannelGroup.getString(); if (channelGroupName != null) { FilterComponent component = FilterComponentList.getInstance() .getFilterComponentByName(channelGroupName); if (component != null && component instanceof ChannelFilterComponent) { setChannelGroup((ChannelFilterComponent) component); } } addKeyboardAction(); mTimer = new Timer(10000, new ActionListener() { public void actionPerformed(ActionEvent evt) { handleTimerEvent(); } }); mTimer.start(); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); //create the drop target for installation of Plugins with Drag'N'Drop on MainFrame DropTarget target = new DropTarget(); try { target.addDropTargetListener(this); } catch (TooManyListenersException e1) { //ignore } this.setDropTarget(target); } /** * */ public void createDateSelector() { switch (Settings.propViewDateLayout.getInt()) { case 1: mFinderPanel = new CalendarTablePanel(); break; case 2: mFinderPanel = new CalendarPanel(); break; default: mFinderPanel = new FinderPanel(); } mFinderPanel.setDateListener(this); } /** * Switch the fullscreen mode of TV-Browser */ public void switchFullscreenMode() { dispose(); SwingUtilities.invokeLater(new Runnable() { public void run() { GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); if (isFullScreenMode()) { // switch back from fullscreen device.setFullScreenWindow(null); setUndecorated(false); setBounds(mXPos, mYPos, mWidth, mHeight); if (mMenuBar != null) { mMenuBar.setFullscreenItemChecked(false); mMenuBar.setVisible(true); } if (mToolBarPanel != null) { mToolBarPanel.setVisible(Settings.propIsToolbarVisible.getBoolean()); } if (mStatusBar != null) { mStatusBar.setVisible(Settings.propIsStatusbarVisible.getBoolean()); } if (mChannelChooser != null) { mChannelChooser.setVisible(Settings.propShowChannels.getBoolean()); } if (mFinderPanel != null) { mFinderPanel.getComponent().setVisible(Settings.propShowDatelist.getBoolean()); } setVisible(true); setShowPluginOverview(Settings.propShowPluginView.getBoolean(), false); setShowTimeButtons(Settings.propShowTimeButtons.getBoolean(), false); setShowDatelist(Settings.propShowDatelist.getBoolean(), false); setShowChannellist(Settings.propShowChannels.getBoolean(), false); } else { // switch into fullscreen mXPos = getX(); mYPos = getY(); mWidth = getWidth(); mHeight = getHeight(); setShowPluginOverview(false, false); setShowTimeButtons(false, false); setShowDatelist(false, false); setShowChannellist(false, false); if (mStatusBar != null) { mMenuBar.setFullscreenItemChecked(true); mStatusBar.setVisible(false); } if (mChannelChooser != null) { mChannelChooser.setVisible(false); } if (mMenuBar != null) { mMenuBar.setVisible(false); } if (mToolBarPanel != null) { mToolBarPanel.setVisible(false); } if (mFinderPanel != null) { mFinderPanel.getComponent().setVisible(false); } setUndecorated(true); final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); if (device.isFullScreenSupported() && OperatingSystem.isMacOs()) { device.setFullScreenWindow(MainFrame.getInstance()); } else { setLocation(0, 0); setSize(screen); } setVisible(true); mProgramTableScrollPane.requestFocusInWindow(); new Thread("Fullscreen border detection") { public void run() { setPriority(Thread.MIN_PRIORITY); while (isFullScreenMode()) { final Point p = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(p, MainFrame.this); if (isActive()) { // mouse pointer is at top if (p.y <= 10) { if (mToolBarPanel != null && mToolBar.getToolbarLocation() .compareTo(BorderLayout.NORTH) == 0) { if (!mToolBarPanel.isVisible()) { mToolBarPanel .setVisible(Settings.propIsToolbarVisible.getBoolean()); } } if (p.y <= 0) { mMenuBar.setVisible(true); } } else if (p.y > (mMenuBar != null && mMenuBar.isVisible() ? mMenuBar.getHeight() : 0) + (Settings.propIsToolbarVisible.getBoolean() ? mToolBarPanel.getHeight() : 0)) { if (mMenuBar.isVisible()) { mMenuBar.setVisible(!isFullScreenMode()); } if (mToolBarPanel != null && mToolBarPanel.isVisible() && mToolBar .getToolbarLocation().compareTo(BorderLayout.NORTH) == 0) { mToolBarPanel.setVisible(!isFullScreenMode()); } } // mouse pointer is at the bottom if (p.y >= screen.height - 1) { if (mStatusBar != null && !mStatusBar.isVisible()) { mStatusBar.setVisible(Settings.propIsStatusbarVisible.getBoolean()); } } else if (mStatusBar != null && mStatusBar.isVisible() && p.y < screen.height - mStatusBar.getHeight()) { mStatusBar.setVisible(!isFullScreenMode()); } // mouse pointer is on the left side if (p.x <= 5) { if (p.x == 0 && mToolBarPanel != null && mToolBar.getToolbarLocation() .compareTo(BorderLayout.WEST) == 0) { if (!mToolBarPanel.isVisible()) { mToolBarPanel .setVisible(Settings.propIsToolbarVisible.getBoolean()); } } if (Settings.propPluginViewIsLeft.getBoolean()) { if (Settings.propShowPluginView.getBoolean()) { SwingUtilities.invokeLater(new Runnable() { public void run() { setShowPluginOverview(true, false); } }); } } else { checkIfToShowTimeDateChannelList(); } } else { int toolBarWidth = (mToolBarPanel != null && mToolBarPanel.isVisible() && mToolBar.getToolbarLocation().compareTo(BorderLayout.WEST) == 0) ? mToolBarPanel.getWidth() : 0; if (p.x > toolBarWidth && toolBarWidth != 0) { mToolBarPanel.setVisible(!isFullScreenMode()); } if (Settings.propPluginViewIsLeft.getBoolean()) { if (Settings.propShowPluginView.getBoolean() && mPluginView != null && mPluginView.isVisible() && p.x > mPluginView.getWidth() + toolBarWidth + 25) { SwingUtilities.invokeLater(new Runnable() { public void run() { setShowPluginOverview(!isFullScreenMode(), false); } }); } } else if (Settings.propShowChannels.getBoolean() || Settings.propShowDatelist.getBoolean() || Settings.propShowTimeButtons.getBoolean()) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (mChannelChooser != null && mChannelChooser.isVisible() && p.x > mChannelChooser.getWidth()) { setShowChannellist(!isFullScreenMode(), false); } if (mFinderPanel != null && mFinderPanel.getComponent().isVisible() && p.x > mFinderPanel.getComponent().getWidth()) { setShowDatelist(!isFullScreenMode(), false); } if (mTimeChooserPanel != null && mTimeChooserPanel.isVisible() && p.x > mTimeChooserPanel.getWidth()) { setShowTimeButtons(!isFullScreenMode(), false); } } }); } } // mouse pointer is on the right side if (p.x >= screen.width - 1) { if (!Settings.propPluginViewIsLeft.getBoolean()) { if (Settings.propShowPluginView.getBoolean()) { SwingUtilities.invokeLater(new Runnable() { public void run() { setShowPluginOverview(true, false); } }); } } else { checkIfToShowTimeDateChannelList(); } } else { if (!Settings.propPluginViewIsLeft.getBoolean()) { if (Settings.propShowPluginView.getBoolean() && mPluginView != null && mPluginView.isVisible() && p.x < screen.width - mPluginView.getWidth()) { SwingUtilities.invokeLater(new Runnable() { public void run() { setShowPluginOverview(!isFullScreenMode(), false); } }); } } else if (Settings.propShowChannels.getBoolean() || Settings.propShowDatelist.getBoolean() || Settings.propShowTimeButtons.getBoolean()) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (mChannelChooser != null && mChannelChooser.isVisible() && p.x < screen.width - mChannelChooser.getWidth()) { setShowChannellist(!isFullScreenMode(), false); } if (mFinderPanel != null && mFinderPanel.getComponent().isVisible() && p.x < screen.width - mFinderPanel.getComponent().getWidth()) { setShowDatelist(!isFullScreenMode(), false); } if (mTimeChooserPanel != null && mTimeChooserPanel.isVisible() && p.x < screen.width - mTimeChooserPanel.getWidth()) { setShowTimeButtons(!isFullScreenMode(), false); } } }); } } } try { Thread.sleep(200); } catch (Exception e) { } } } }.start(); } } }); } private void checkIfToShowTimeDateChannelList() { if (Settings.propShowTimeButtons.getBoolean() || Settings.propShowDatelist.getBoolean() || Settings.propShowChannels.getBoolean()) { SwingUtilities.invokeLater(new Runnable() { public void run() { if (Settings.propShowTimeButtons.getBoolean() && !mTimeChooserPanel.isVisible()) { setShowTimeButtons(true, false); } if (Settings.propShowDatelist.getBoolean() && !mFinderPanel.getComponent().isVisible()) { setShowDatelist(true, false); } if (Settings.propShowChannels.getBoolean() && !mChannelChooser.isVisible()) { setShowChannellist(true, false); } } }); } } /** * Adds the keyboard actions for going to the program table with the keyboard. * */ public void addKeyboardAction() { mProgramTableScrollPane.deSelectItem(); // register the global hot keys, so they also work when the main menu is not visible for (final TVBrowserAction action : TVBrowserActions.getActions()) { KeyStroke keyStroke = action.getAccelerator(); if (keyStroke != null) { rootPane.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { if (action.isEnabled()) { action.actionPerformed(null); } } }, keyStroke, JComponent.WHEN_IN_FOCUSED_WINDOW); } } KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_UP), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_UP), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_RIGHT), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_RIGHT), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_DOWN), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_DOWN), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_LEFT), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_LEFT), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0, true); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_CONTEXTMENU), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, 0, true); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_CONTEXTMENU), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_DESELECT), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_L, 0, true); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_SINGLECLICK), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_DOUBLECLICK), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_M, 0, true); rootPane.registerKeyboardAction(new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_MIDDLECLICK), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_O, 0, true); rootPane.registerKeyboardAction( new KeyboardAction(mProgramTableScrollPane, KeyboardAction.KEY_MIDDLE_DOUBLE_CLICK), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(TVBrowserActions.goToNextDay, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK); rootPane.registerKeyboardAction(TVBrowserActions.goToPreviousDay, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); // return from full screen using ESCAPE stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); rootPane.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { if (isFullScreenMode()) { TVBrowserActions.fullScreen.actionPerformed(null); } else { mProgramTableScrollPane.getProgramTable().stopAutoScroll(); mAutoDownloadTimer = -1; mLastTimerMinutesAfterMidnight = IOUtilities.getMinutesAfterMidnight(); TVBrowser.stopAutomaticDownload(); if (TVBrowserActions.update.isUpdating()) { TVBrowserActions.update.actionPerformed(null); } } } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0); rootPane.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { goToLeftSide(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_END, 0); rootPane.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { goToRightSide(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_MASK); rootPane.registerKeyboardAction(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mProgramTableScrollPane.scrollPageRight(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); stroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_MASK); rootPane.registerKeyboardAction(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mProgramTableScrollPane.scrollPageLeft(); } }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); this.setRootPane(rootPane); } protected void goToRightSide() { Channel[] channels = MainFrame.getInstance().getProgramTableModel().getShownChannels(); if (channels != null && channels.length > 0) { mProgramTableScrollPane.scrollToChannel(channels[channels.length - 1]); } } protected void goToLeftSide() { Channel[] channels = MainFrame.getInstance().getProgramTableModel().getShownChannels(); if (channels != null && channels.length > 0) { mProgramTableScrollPane.scrollToChannel(channels[0]); } } public JLabel getStatusBarLabel() { return mStatusBar.getLabel(); } public void updateToolbar() { JPanel contentPane = (JPanel) getContentPane(); if (mToolBarPanel != null) { contentPane.remove(mToolBarPanel); } mToolBarModel = DefaultToolBarModel.getInstance(); mToolBar = new ToolBar(mToolBarModel); mToolBar.setOpaque(false); String location = mToolBar.getToolbarLocation(); if (Settings.propIsToolbarVisible.getBoolean()) { if (mToolBarPanel == null) { mToolBarPanel = new JPanel(new BorderLayout()) { public void updateUI() { super.updateUI(); setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, getBackground().darker())); } }; addContextMenuMouseListener(mToolBarPanel); mSearchField = new SearchField(); } else { mToolBarPanel.removeAll(); } if (location.compareTo(BorderLayout.NORTH) == 0) { mToolBarPanel.add(MoreButton.wrapToolBar(mToolBar, this), BorderLayout.CENTER); if (Settings.propIsSearchFieldVisible.getBoolean()) { mToolBarPanel.add(mSearchField, BorderLayout.EAST); } } else { mToolBarPanel.add(MoreButton.wrapToolBar(mToolBar, this), BorderLayout.WEST); if (Settings.propIsSearchFieldVisible.getBoolean()) { mToolBarPanel.add(mSearchField, BorderLayout.SOUTH); } } contentPane.add(mToolBarPanel, location); } contentPane.invalidate(); contentPane.updateUI(); } private void addContextMenuMouseListener(final JComponent c) { c.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { ContextMenu menu = new ContextMenu(c); menu.show(e.getX(), e.getY()); } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { ContextMenu menu = new ContextMenu(c); menu.show(e.getX(), e.getY()); } } }); } public ProgramTableScrollPane getProgramTableScrollPane() { return mProgramTableScrollPane; } public ToolBar getToolbar() { return mToolBar; } public JPanel getToolBarPanel() { return mToolBarPanel; } public DefaultProgramTableModel getProgramTableModel() { return mProgramTableModel; } public static MainFrame getInstance() { if (mSingleton == null) { mSingleton = new MainFrame(); } return mSingleton; } public void updateTimeButtons() { mToolBar.updateTimeButtons(); mTimeChooserPanel.updateButtons(); mMenuBar.updateTimeItems(); } public boolean isShowAllFilterActivated() { return (mProgramTableModel == null) || (mProgramTableModel.getProgramFilter() instanceof ShowAllFilter); } /** * check if the default filter is active * @return true, if the default filter is active * @since 2.6 */ public boolean isDefaultFilterActivated() { if (mProgramTableModel == null) { return true; } ProgramFilter filter = mProgramTableModel.getProgramFilter(); return (Settings.propDefaultFilter.getString() .equals(filter.getClass().getName() + "###" + filter.getName())); } public void setProgramFilter(ProgramFilter filter) { boolean isDefaultFilter = filter.equals(FilterManagerImpl.getInstance().getDefaultFilter()); if (!isDefaultFilter) { // Store Position mStoredViewPosition = mProgramTableScrollPane.getViewport().getViewPosition(); } if (mProgramTableModel.getProgramFilter() instanceof SearchFilter && !(filter instanceof SearchFilter)) { mSearchField.deactivateSearch(); } mProgramTableScrollPane.deSelectItem(); mProgramTableModel.setProgramFilter(filter); mMenuBar.updateFiltersMenu(); mToolBarModel.setFilterButtonSelected(!isDefaultFilter); updateFilterPanel(); mToolBar.update(); addKeyboardAction(); if (mPluginView != null) { mPluginView.repaint(); } if (mCurrentFilterName == null || !mCurrentFilterName.equals(filter.getName())) { if ((mStoredViewPosition != null) && (isDefaultFilter)) { // Recreate last Position SwingUtilities.invokeLater(new Runnable() { public void run() { if (mStoredViewPosition != null) { mProgramTableScrollPane.getViewport().setViewPosition(mStoredViewPosition); } } }); } else { // on switching filters go to now, but only if we are at current date SwingUtilities.invokeLater(new Runnable() { public void run() { if (getCurrentSelectedDate().equals(Date.getCurrentDate()) && !isStarting()) { scrollToNow(); } } }); } } mCurrentFilterName = filter.getName(); mProgramTableScrollPane.requestFocusInWindow(); } /** * Set the active channel group * @param channelFilter * @since 2.6 */ public void setChannelGroup(ChannelFilterComponent channelFilter) { mProgramTableModel.setChannelGroup(channelFilter); if (channelFilter != null) { Settings.propLastUsedChannelGroup.setString(channelFilter.getName()); } else { Settings.propLastUsedChannelGroup.setString(null); } mChannelChooser.setChannelGroup(channelFilter); mMenuBar.updateChannelGroupMenu(); } public void updateFilterPanel() { ProgramFilter filter = mProgramTableModel.getProgramFilter(); boolean filterVisible = !filter.equals(FilterManagerImpl.getInstance().getDefaultFilter()) && mMenuBar.isShowFilterPanelEnabled(); if (filterVisible) { mFilterPanel.setCurrentFilter(filter); } mFilterPanel.setVisible(filterVisible); Settings.propShowFilterBar.setBoolean(mMenuBar.isShowFilterPanelEnabled()); } public ProgramFilter getProgramFilter() { if (mProgramTableModel == null) { return null; } return mProgramTableModel.getProgramFilter(); } public ChannelFilterComponent getChannelGroup() { if (mProgramTableModel == null) { return null; } return mProgramTableModel.getChannelGroup(); } public void quit() { String[] options = { mLocalizer.msg("exitConfirmTitle", "Exit TV-Browser"), Localizer.getLocalization(Localizer.I18N_CANCEL) }; if (DontShowAgainOptionBox.showOptionDialog("MainFrame.askForExitConfirm", this.isActive() ? this : null, mLocalizer.msg("exitConirmText", "Do you really want to quit TV-Browser?"), options[0], JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION, options, options[0], null) != JOptionPane.YES_OPTION) { return; } TVBrowser.removeTray(); quit(true); } public void quit(boolean log) { quit(log, false); } private void quit(boolean log, boolean export) { mTimer.stop(); // disable the update timer to avoid new update events if (log && downloadingThread != null && downloadingThread.isAlive()) { final JDialog info = new JDialog(UiUtilities.getLastModalChildOf(this)); info.setModal(true); info.setUndecorated(true); info.toFront(); JPanel main = new JPanel(new FormLayout("5dlu,pref,5dlu", "5dlu,pref,5dlu")); main.setBorder(BorderFactory.createLineBorder(Color.black)); main.add( new JLabel(mLocalizer.msg("downloadinfo", "A data update is running. TV-Browser will be closed when the update is done.")), new CellConstraints().xy(2, 2)); info.setContentPane(main); info.pack(); info.setLocationRelativeTo(this); SwingUtilities.invokeLater(new Runnable() { public void run() { if (downloadingThread != null && downloadingThread.isAlive()) { try { downloadingThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } info.setVisible(false); info.dispose(); } }); info.setVisible(true); } if (log && this.isUndecorated()) { switchFullscreenMode(); } if (mShuttingDown) { return; } mShuttingDown = true; if (log) { FavoritesPlugin.getInstance().handleTvBrowserIsShuttingDown(); } if (log) { mLog.info("Finishing plugins"); } PluginProxyManager.getInstance().shutdownAllPlugins(log); if (log) { mLog.info("Storing dataservice settings"); } TvDataServiceProxyManager.getInstance().shutDown(); FavoritesPlugin.getInstance().store(); ReminderPlugin.getInstance().store(); TVBrowser.shutdown(log); if (log) { mLog.info("Closing TV data base"); } try { TvDataBase.getInstance().close(); } catch (Exception exc) { if (log) { mLog.log(Level.WARNING, "Closing database failed", exc); } } if (export) { Settings.propTVDataDirectory.resetToDefault(); Settings.copyToSystem(); } if (log) { mLog.info("Quitting"); System.exit(0); } } /** * Gets if TV-Browser is currently being shutting down. * @return True if TV-Browser is shutting down. * @since 2.5.3 */ public static boolean isShuttingDown() { return mShuttingDown; } /** * Gets whether TV-Browser is currently being started. * @return True if TV-Browser is currently being started. * @since 2.5.3 */ public static boolean isStarting() { return mStarting; } /** * Handles done TV-Browser start. */ public void handleTvBrowserStartFinished() { mStarting = false; } private void runAutoUpdate() { ArrayList<TvDataServiceProxy> dataServices = new ArrayList<TvDataServiceProxy>(); ArrayList<TvDataServiceProxy> checkedServices = new ArrayList<TvDataServiceProxy>(0); Channel[] channels = Settings.propSubscribedChannels.getChannelArray(); for (Channel channel : channels) { if (!checkedServices.contains(channel.getDataServiceProxy())) { checkedServices.add(channel.getDataServiceProxy()); if (channel.getDataServiceProxy().supportsAutoUpdate()) { dataServices.add(channel.getDataServiceProxy()); } } } checkedServices.clear(); if (!dataServices.isEmpty() && licenseForTvDataServicesWasAccepted( dataServices.toArray(new TvDataServiceProxy[dataServices.size()]))) { runUpdateThread(14, dataServices.toArray(new TvDataServiceProxy[dataServices.size()]), true); } mLastAutoUpdateRun = System.currentTimeMillis(); } /** * Resets the arrays of on air programs for reloading all. */ public static void resetOnAirArrays() { mChannelDateArr = null; mOnAirRowProgramsArr = null; } private void handleTimerEvent() { Date date = Date.getCurrentDate(); if (mLastTimerMinutesAfterMidnight == -1) { resetOnAirArrays(); mAutoDownloadTimer = RandomUtils.nextInt(24 * 60 - 10); } // Avoid a repaint 6 times a minute (Once a minute is enough) try { int minutesAfterMidnight = IOUtilities.getMinutesAfterMidnight(); boolean onAirChanged = false; if (minutesAfterMidnight != mLastTimerMinutesAfterMidnight && (downloadingThread == null || !downloadingThread.isAlive())) { mLastTimerMinutesAfterMidnight = minutesAfterMidnight; Channel[] ch = ChannelList.getSubscribedChannels(); if (ch != null) { /* If no date array is available we have to find * the on air programs */ if (mChannelDateArr == null) { onAirChanged = true; fillOnAirArrays(ch); } else { /* We have a date array and can test the programs */ for (int i = 0; i < mChannelDateArr.length; i++) { if (mChannelDateArr[i] != null) { ChannelDayProgram chProg = TvDataBase.getInstance() .getDayProgram(mChannelDateArr[i], ch[i]); if (chProg != null && chProg.getProgramCount() > 0 && mOnAirRowProgramsArr[i] != -1) { if (mOnAirRowProgramsArr[i] >= chProg.getProgramCount()) { fillOnAirArrays(ch); mLog.warning("Reset of on-air-arrays"); } Program p = chProg.getProgramAt(mOnAirRowProgramsArr[i]); if (p.isOnAir()) { p.validateMarking(); } else if (p.isExpired()) { onAirChanged = true; p.validateMarking(); int n = mOnAirRowProgramsArr[i] + 1; if (n < chProg.getProgramCount()) { mOnAirRowProgramsArr[i] = n; chProg.getProgramAt(mOnAirRowProgramsArr[i]).validateMarking(); } else { /* The last day program is expired so we have to * look for the on air program on the next day */ mChannelDateArr[i] = mChannelDateArr[i].addDays(1); chProg = TvDataBase.getInstance().getDayProgram(mChannelDateArr[i], ch[i]); // The next day has no data if (chProg == null || chProg.getProgramCount() < 1) { mOnAirRowProgramsArr[i] = -1; } else { mOnAirRowProgramsArr[i] = 0; chProg.getProgramAt(mOnAirRowProgramsArr[i]).validateMarking(); } } } } else if (mChannelDateArr[i].compareTo(Date.getCurrentDate()) < 0) { /* If the date array for the channel contains a date * earlier than today we have to use today instead */ mChannelDateArr[i] = Date.getCurrentDate(); onAirChanged = true; chProg = TvDataBase.getInstance().getDayProgram(mChannelDateArr[i], ch[i]); if (chProg != null && chProg.getProgramCount() > 0) { mOnAirRowProgramsArr[i] = 0; chProg.getProgramAt(mOnAirRowProgramsArr[i]).validateMarking(); } } } } } } } if (onAirChanged) { if (Settings.propTableLayout.getString().equals(Settings.LAYOUT_OPTIMIZED_COMPACT_TIME_BLOCK)) { mProgramTableScrollPane.getProgramTable().updateLayout(); } // update filtered view if the "on air" condition changed for any program if (!getProgramFilter().equals(FilterManagerImpl.getInstance().getDefaultFilter())) { setProgramFilter(getProgramFilter()); } } } catch (Exception e) { } if (mPluginView != null) { mPluginView.repaint(); } if ((mLastAutoUpdateRun + Settings.propDataServiceAutoUpdateTime.getInt() * 60000L) <= System .currentTimeMillis() && !TvDataUpdater.getInstance().isDownloading()) { runAutoUpdate(); } if (Settings.propAutoDataDownloadEnabled.getBoolean() && (mAutoDownloadTimer < IOUtilities.getMinutesAfterMidnight() || !date.equals(mCurrentDay)) && mAutoDownloadTimer != -1 && (downloadingThread == null || !downloadingThread.isAlive())) { TVBrowser.handleAutomaticDownload(); mAutoDownloadTimer = -1; } if (date.equals(mCurrentDay)) { return; } if (mCurrentDay != null) { if (mProgramTableModel.getDate().compareTo(Date.getCurrentDate().addDays(-1)) < 0) { scrollToNow(); } Thread deletionThread = new Thread("Deferring data deletion") { @Override public void run() { // wait up to an hour to start data deletion // this better distributes the server load which is caused by the (plugins) Internet access during the data update try { sleep((long) (Math.random() * 3600 * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } // now delete the data SwingUtilities.invokeLater(new Runnable() { public void run() { mLog.info("Deleting expired TV listings..."); TvDataBase.getInstance().deleteExpiredFiles(1, true); } }); } }; deletionThread.start(); } mLastTimerMinutesAfterMidnight = -1; mCurrentDay = date; if (mFinderPanel != null) { mFinderPanel.updateContent(); } if (mPluginView != null) { mPluginView.update(); } } private void fillOnAirArrays(Channel[] ch) { mChannelDateArr = new Date[ch.length]; mOnAirRowProgramsArr = new int[ch.length]; Arrays.fill(mOnAirRowProgramsArr, -1); Date currentDate = Date.getCurrentDate(); for (int i = 0; i < ch.length; i++) { ChannelDayProgram chProg = TvDataBase.getInstance().getDayProgram(currentDate, ch[i]); if (chProg == null) { mChannelDateArr[i] = null; } else { int n = chProg.getProgramCount(); for (int j = 0; j < n; j++) { Program p = chProg.getProgramAt(j); if (p.isOnAir() || !p.isExpired()) { p.validateMarking(); mOnAirRowProgramsArr[i] = j; mChannelDateArr[i] = currentDate; break; } } if (mOnAirRowProgramsArr[i] == -1) { chProg = TvDataBase.getInstance().getDayProgram(currentDate.addDays(1), ch[i]); if (chProg != null && chProg.getProgramCount() > 0 && chProg.getProgramAt(0).isOnAir()) { chProg.getProgramAt(0).validateMarking(); mOnAirRowProgramsArr[i] = 0; } mChannelDateArr[i] = currentDate.addDays(1); } } } } public void updatePluginsMenu() { mMenuBar.updatePluginsMenu(); } public void scrollToProgram(final Program program) { scrollToProgram(program, null); } public void scrollToProgram(final Program program, final Runnable callback) { if (!getProgramFilter().accept(program)) { int result = JOptionPane.showOptionDialog(this, mLocalizer.msg("programFiltered", "The program {0} is not visible with the filter {1} being active.\nDo you want to deactivate the filter?", program.getTitle(), getProgramFilter().getName()), mLocalizer.msg("programNotVisible", "Program not visible"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); if (result == JOptionPane.YES_OPTION) { mStoredViewPosition = null; setProgramFilter(FilterManagerImpl.getInstance().getAllFilter()); } } mProgramTableScrollPane.resetScrolledTime(); // invoke scrolling later as the upper filter deactivation may have pending operations for the UI // so we currently can't scroll there yet SwingUtilities.invokeLater(new Runnable() { public void run() { mProgramTableScrollPane.scrollToChannel(program.getChannel()); scrollTo(program.getDate(), program.getStartTime(), callback); } }); } public void scrollToTime(int time) { mProgramTableScrollPane.deSelectItem(); mProgramTableScrollPane.scrollToTime(time); mProgramTableScrollPane.requestFocusInWindow(); } public void scrollToNow() { mProgramTableScrollPane.resetScrolledTime(); Calendar cal = Calendar.getInstance(); int hour = cal.get(Calendar.HOUR_OF_DAY); devplugin.Date day = new devplugin.Date(); scrollTo(day, hour * 60 + cal.get(Calendar.MINUTE)); mProgramTableScrollPane.requestFocusInWindow(); } private void scrollTo(Date day, int minute) { scrollTo(day, minute, null); } private void scrollTo(Date day, int minute, final Runnable callback) { mProgramTableScrollPane.deSelectItem(); // Choose the day. // NOTE: If its early in the morning before the set "day start" we should // stay at the last day - otherwise the user won't see the current // program. But until when should we stay at the old day? // Example: day start: 0:00, day end: 6:00 // Directly after the day start is not a good choice, because the new // day program table will not contain programs that started before 0:00. // Directly after the day end is also not a good choice, because a // minute before the old day program will not contain the coming programs. // So I think the best choice will be the middle, in this case 3:00. // If the day start is later as the day end, then the table have to show the // old date until the day end is reached. int dayStart = Settings.propProgramTableStartOfDay.getInt(); int dayEnd = Settings.propProgramTableEndOfDay.getInt(); if ((dayStart >= dayEnd && minute < dayEnd) // no overlapping -> stay on last day until day end || (dayStart < dayEnd && minute <= (dayEnd + dayStart) / 2)) { // overlapping -> stay until the middle between both times day = day.addDays(-1); minute += 24 * 60; } // Change to the shown day program to today if necessary // and scroll to "now" afterwards final int scrollMinute = minute; mFinderPanel.markDate(day, new Runnable() { public void run() { // Scroll to now mProgramTableScrollPane.scrollToTime(scrollMinute); if (callback != null) { callback.run(); } } }); } public void runSetupAssistant() { ProgressWindow progWin = new ProgressWindow(this, mLocalizer.msg("loadingAssistant", "")); final JFrame parent = this; progWin.run(new Progress() { public void run() { mConfigAssistantDialog = new tvbrowser.ui.configassistant.ConfigAssistant(parent); } }); util.ui.UiUtilities.centerAndShow(mConfigAssistantDialog); mConfigAssistantDialog.setVisible(false); mConfigAssistantDialog.dispose(); mConfigAssistantDialog = null; Settings.handleChangedSettings(); boolean dataAvailable = TvDataBase.getInstance().dataAvailable(new Date()); if (!dataAvailable) { askForDataUpdateNoDataAvailable(); } } public void copySettingsToSystem() { if (TVBrowser.isTransportable()) { String[] options = { mLocalizer.msg("copy", "Copy"), mLocalizer.msg("dontCopy", "Don't copy") }; String title = mLocalizer.msg("copyToSystemTitle", "Copy settings and data to system"); String msg = mLocalizer.msg("copyToSystemMsg", "Should the settings and TV data be copied to the system?\nTV-Browser will therefor will be quit automatically."); if (JOptionPane.showOptionDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]) == JOptionPane.YES_OPTION) { quit(true, true); } } } // public void runTvBrowserUpdateAssistant() { // TvBrowserUpdateAssistant dlg = new TvBrowserUpdateAssistant(this); // UiUtilities.centerAndShow(dlg); // } public void storeSettings() { mToolBarModel.store(); mToolBar.storeSettings(); mRootNode.storeProperties(); ProgramFilter filter = getProgramFilter(); if (filter != null) { if (!(filter instanceof SearchFilter)) { Settings.propLastUsedFilter.setString(mCurrentFilterName); } else { Settings.propLastUsedFilter.setString(FilterManagerImpl.getInstance().getDefaultFilter().getName()); } } else { Settings.propLastUsedFilter.setString(FilterManagerImpl.getInstance().getDefaultFilter().getName()); } ChannelFilterComponent channelGroup = getChannelGroup(); if (channelGroup != null) { Settings.propLastUsedChannelGroup.setString(channelGroup.getName()); } else { Settings.propLastUsedChannelGroup.setString(null); } } protected void showPluginInfoDlg() { Window parent = UiUtilities.getLastModalChildOf(this); PluginInformationDialog dlg = new PluginInformationDialog(parent); Settings.layoutWindow("main.pluginInfoDlg", dlg, new Dimension(Sizes.dialogUnitXAsPixel(420, dlg), Sizes.dialogUnitYAsPixel(215, dlg))); dlg.setVisible(true); } private void onDownloadStart() { mAutoDownloadTimer = -1; TVBrowserActions.update.setUpdating(true); if (!Settings.propPluginInfoDialogWasShown.getBoolean()) { Date compareDate = Settings.propFirstStartDate.getDate().addDays((int) (Math.random() * 4 + 3)); if (compareDate.compareTo(Date.getCurrentDate()) <= 0) { showPluginInfoDlg(); Settings.propPluginInfoDialogWasShown.setBoolean(true); } } mLastAutoUpdateRunBuffer = mLastAutoUpdateRun; mLastAutoUpdateRun = System.currentTimeMillis() + 3600000; mToolBar.updateUpdateButton(true); mMenuBar.showStopMenuItem(); Settings.propLastDownloadDate.setDate(Date.getCurrentDate()); } private void onDownloadDone() { TVBrowserActions.update.setUpdating(false); TvDataUpdater.getInstance().stopDownload(); mStatusBar.getProgressBar().setValue(0); mToolBar.updateUpdateButton(false); mMenuBar.showUpdateMenuItem(); mLastAutoUpdateRun = mLastAutoUpdateRunBuffer; mFinderPanel.updateItems(); resetOnAirArrays(); mAutoDownloadTimer = -1; DontShowAgainOptionBox.showOptionDialog("downloadDone", MainFrame.getInstance(), mLocalizer.msg("downloaddone.message", "The download is done."), mLocalizer.msg("downloaddone.title", "Done")); } /** * Updates the entries of the finder panal. * @since 2.2.2/2.5.1 */ public void handleChangedTvDataDir() { mFinderPanel.updateItems(); changeDate(Date.getCurrentDate(), null, new Runnable() { public void run() { scrollToNow(); resetOnAirArrays(); } }); } public void showChannel(Channel ch) { mProgramTableScrollPane.scrollToChannel(ch); } /** * Updates the program table and the finder panel. * <p> * Called when new TV listings was downloaded or when TV data was imported. */ private void newTvDataAvailable(boolean scroll) { if (scroll) { changeDate(mFinderPanel.getSelectedDate(), null, new Runnable() { public void run() { scrollToNow(); } }); } else { changeDate(mFinderPanel.getSelectedDate(), null, null); } mMenuBar.updateDateItems(); } public void goTo(Date date) { mProgramTableScrollPane.deSelectItem(); mFinderPanel.markDate(date); } public void goToNextDay() { mProgramTableScrollPane.deSelectItem(); mFinderPanel.markNextDate(); } public void goToPreviousDay() { mProgramTableScrollPane.deSelectItem(); mFinderPanel.markPreviousDate(); } /** * show same week day 7 days later * @since 2.7 */ public void goToNextWeek() { mProgramTableScrollPane.deSelectItem(); mFinderPanel.markNextWeek(); } /** * show same week day 7 days earlier * @since 2.7 */ public void goToPreviousWeek() { mProgramTableScrollPane.deSelectItem(); mFinderPanel.markPreviousWeek(); } /** * @since 2.7 */ public void goToToday() { goTo(devplugin.Date.getCurrentDate()); } public Date getCurrentSelectedDate() { return mFinderPanel.getSelectedDate(); } private void changeDate(final Date date, final ProgressMonitor monitor, final Runnable callback) { SwingUtilities.invokeLater(new Runnable() { public void run() { final int currentTime = mProgramTableScrollPane.getScrolledTime(); mProgramTableScrollPane.deSelectItem(); mProgramTableModel.setDate(date, monitor, new Runnable() { @Override public void run() { if (callback != null) { callback.run(); } if (currentTime >= 0) { mProgramTableScrollPane.scrollToTime(currentTime); } } }); } }); } /** * Implementation of Interface DateListener */ public void dateChanged(final devplugin.Date date, devplugin.ProgressMonitor monitor, Runnable callback) { changeDate(date, monitor, callback); super.setTitle(TVBrowser.MAINWINDOW_TITLE + " - " + date.getLongDateString()); if (mToolBar != null) { mToolBar.dateChanged(date, monitor, callback); } } public void runUpdateThread(final int daysToDownload, final TvDataServiceProxy[] services, final boolean autoUpdate) { downloadingThread = new Thread("TV data update") { public void run() { onDownloadStart(); final boolean scroll = !autoUpdate && !TvDataBase.getInstance().dataAvailable(Date.getCurrentDate()) && getProgramTableModel().getDate() != null && getProgramTableModel().getDate().compareTo(Date.getCurrentDate()) == 0; JProgressBar progressBar = mStatusBar.getProgressBar(); try { TvDataUpdater.getInstance().downloadTvData(daysToDownload, services, progressBar, mStatusBar.getLabel()); } catch (Throwable t) { String msg = mLocalizer.msg("error.3", "An unexpected error occurred during update."); ErrorHandler.handle(msg, t); } finally { SwingUtilities.invokeLater(new Runnable() { public void run() { onDownloadDone(); newTvDataAvailable(scroll); if ((Settings.propLastPluginsUpdate.getDate() == null || Settings.propLastPluginsUpdate .getDate().addDays(7).compareTo(Date.getCurrentDate()) <= 0)) { PluginAutoUpdater.searchForPluginUpdates(mStatusBar.getLabel()); } } }); } } }; downloadingThread.setPriority(Thread.MIN_PRIORITY); downloadingThread.start(); } public void updateChannellist() { updateChannelChooser(); mMenuBar.updateChannelItems(); } public void updateChannelChooser() { mChannelChooser.updateChannelChooser(); } /** * Starts the TV listings update with the given reason shown in the dialog * * @param numberOfDays * @param reason The reason for initiating the download */ synchronized public void updateTvData(final int numberOfDays, final String reason) { if (mIsAskingUpdate) { return; } if (TvDataUpdater.getInstance().isDownloading()) { return; } if (downloadingThread != null && downloadingThread.isAlive()) { return; } mIsAskingUpdate = true; try { if (ChannelList.getNumberOfSubscribedChannels() == 0) { int result = JOptionPane.showOptionDialog(this, mLocalizer.msg("subscribeBeforeUpdate.msg", "You have not defined any channels.\n\nDo you want to subscribe to some channels before starting the data update?"), mLocalizer.msg("subscribeBeforeUpdate.title", "No subscribed channels"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); if (result == JOptionPane.YES_OPTION) { showSettingsDialog(SettingsItem.CHANNELS); } } else { if (TvDataUpdater.getInstance().isDownloading()) { TvDataUpdater.getInstance().stopDownload(); } else { UpdateDlg dlg = new UpdateDlg(this, true, reason); if (numberOfDays > 0) { dlg.setNumberOfDays(numberOfDays); } dlg.pack(); UiUtilities.centerAndShow(dlg); int daysToDownload = dlg.getResult(); if (daysToDownload != UpdateDlg.CANCEL && licenseForTvDataServicesWasAccepted(dlg.getSelectedTvDataServices())) { runUpdateThread(daysToDownload, dlg.getSelectedTvDataServices(), false); } } } } finally { mIsAskingUpdate = false; } } /** * Starts the TV listings update without a special reason shown in the dialog */ public void updateTvData() { updateTvData(0, null); } /** * Checks if all users services license were accepted. * * @param updateServices * The service to check for license. * * @return If all used service licenses were accepted. */ public boolean licenseForTvDataServicesWasAccepted(TvDataServiceProxy[] updateServices) { boolean accept = true; String[] acceptedFor = Settings.propAcceptedLicenseArrForServiceIds.getStringArray(); for (TvDataServiceProxy serviceProxy : updateServices) { boolean found = false; for (String acceptedService : acceptedFor) { if (serviceProxy.getId().compareTo(acceptedService) == 0) { found = true; break; } } if (!found && serviceProxy.getInfo().getLicense() != null) { LicenseBox box = new LicenseBox(this, serviceProxy.getInfo().getLicense(), true); util.ui.UiUtilities.centerAndShow(box); accept = accept && box.agreed(); if (box.agreed()) { String[] oldIds = Settings.propAcceptedLicenseArrForServiceIds.getStringArray(); String[] newIds = new String[oldIds.length + 1]; System.arraycopy(acceptedFor, 0, newIds, 0, oldIds.length); newIds[newIds.length - 1] = serviceProxy.getId(); Settings.propAcceptedLicenseArrForServiceIds.setStringArray(newIds); } } } return accept; } /** * Shows the settings dialog. */ public void showSettingsDialog() { showSettingsDialog(Settings.propLastUsedSettingsPath.getString()); } /** * Show Settings Dialog for a specific TabId * * @param visibleTabId * Id of the specific Tab */ public void showSettingsDialog(final String visibleTabId) { if (mSettingsWillBeOpened) { return; } new Thread(new Runnable() { public void run() { mSettingsWillBeOpened = true; // show busy cursor Window comp = UiUtilities.getLastModalChildOf(MainFrame.getInstance()); ProgramTable programTable = MainFrame.getInstance().getProgramTableScrollPane().getProgramTable(); Cursor oldWindowCursor = comp.getCursor(); Cursor oldTableCursor = programTable.getCursor(); comp.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); programTable.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); SettingsDialog dlg = new SettingsDialog(MainFrame.this, visibleTabId); dlg.centerAndShow(); // restore cursors programTable.setCursor(oldTableCursor); comp.setCursor(oldWindowCursor); SwingUtilities.invokeLater(new Runnable() { public void run() { Settings.handleChangedSettings(); if (mPluginView != null) { mPluginView.refreshTree(); } } }); mSettingsWillBeOpened = false; } }, "Show settings dialog").start(); } /***************************************************************************** * Show the Settings for a specific Plugin * * @param plugin * Plugin to show */ public void showSettingsDialog(Plugin plugin) { showSettingsDialog(plugin.getId()); } /** * Shows the about box */ public void showAboutBox() { AboutBox box = new AboutBox(this); box.setSize(500, 580); UiUtilities.centerAndShow(box); box.dispose(); } public void showUpdatePluginsDlg(boolean noQuestion) { int answer = JOptionPane.YES_OPTION; if (!noQuestion) { Object[] options = { mLocalizer.msg("checknow", "Check now"), Localizer.getLocalization(Localizer.I18N_CANCEL) }; String msg = mLocalizer.msg("question.1", "do you want to check for new plugins"); answer = JOptionPane.showOptionDialog(this, msg, mLocalizer.msg("title.1", "update plugins"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]); } if (answer == JOptionPane.YES_OPTION) { updatePlugins(PluginAutoUpdater.DEFAULT_PLUGINS_DOWNLOAD_URL, false, mStatusBar.getLabel(), false); } } /** * Search for updates of plugins. * * @param baseUrl The url string to load the plugin updates from. * @param showOnlyUpdates If the dialog is only to show when updates of * installed plugins are found. * @param infoLabel The label to use to show infos. * @param dontShowUpdateDlg If the dialog should not be shown even if updates * are available. (User has disabled automatically plugin updates.) */ public void updatePlugins(final String baseUrl, final boolean showOnlyUpdates, final JLabel infoLabel, final boolean dontShowUpdateDlg) { new Thread("Plugin Update Thread") { public void run() { try { infoLabel.setText(mLocalizer.msg("searchForPluginUpdates", "Search for plugin updates...")); java.net.URL url = new java.net.URL(baseUrl + "/" + PluginAutoUpdater.PLUGIN_UPDATES_FILENAME); SoftwareUpdater softwareUpdater = new SoftwareUpdater(url, showOnlyUpdates, false); mSoftwareUpdateItems = softwareUpdater.getAvailableSoftwareUpdateItems(); infoLabel.setText(""); } catch (java.io.IOException e) { e.printStackTrace(); } if (!dontShowUpdateDlg) { if (mSoftwareUpdateItems == null && !showOnlyUpdates) { JOptionPane.showMessageDialog(UiUtilities.getLastModalChildOf(MainFrame.getInstance()), mLocalizer.msg("error.1", "software check failed.")); } else if (mSoftwareUpdateItems != null && mSoftwareUpdateItems.length == 0 && !showOnlyUpdates) { JOptionPane.showMessageDialog(UiUtilities.getLastModalChildOf(MainFrame.getInstance()), mLocalizer.msg("error.2", "No new items available")); } else if (mSoftwareUpdateItems != null && mSoftwareUpdateItems.length > 0) { Window parent = UiUtilities.getLastModalChildOf(MainFrame.getInstance()); SoftwareUpdateDlg dlg = new SoftwareUpdateDlg(parent, baseUrl, showOnlyUpdates, mSoftwareUpdateItems); //dlg.setSoftwareUpdateItems(mSoftwareUpdateItems); dlg.setLocationRelativeTo(parent); dlg.setVisible(true); } } BlockedPlugin[] newlyBlocked = Settings.propBlockedPluginArray.getNewBlockedPlugins(); if (newlyBlocked != null && newlyBlocked.length > 0) { StringBuilder message = new StringBuilder(); for (BlockedPlugin blockedPlugin : newlyBlocked) { PluginProxy plugin = PluginProxyManager.getInstance() .getPluginForId(blockedPlugin.getPluginId()); if (plugin == null) { TvDataServiceProxy dataService = TvDataServiceProxyManager.getInstance() .findDataServiceById(blockedPlugin.getPluginId()); if (dataService != null && blockedPlugin.isBlockedVersion(dataService.getId(), dataService.getInfo().getVersion())) { message.append("\n").append(dataService.getInfo().getName()).append(" (") .append(blockedPlugin.getBlockStart()).append(" - ") .append(blockedPlugin.getBlockEnd()).append(")"); } } else if (blockedPlugin.isBlockedVersion(plugin)) { message.append("\n").append(plugin.getInfo().getName()).append(" (") .append(blockedPlugin.getBlockStart()).append(" - ") .append(blockedPlugin.getBlockEnd()).append(")"); } } if (message.length() > 0) { message.insert(0, mLocalizer.msg("update.blockedInfo", "The following Plugins were blocked and cannot be used in their current version:\n")); showInfoTextMessage(mLocalizer.msg("update.blockedPlugins", "Plugins blocked!"), message.toString(), 450); } } Settings.propLastPluginsUpdate.setDate(Date.getCurrentDate()); infoLabel.setText(""); mSoftwareUpdateItems = null; } }.start(); } public void showFromTray(int state) { super.setVisible(true); toFront(); setExtendedState(state); mIsVisible = true; } public void setVisible(boolean visible) { super.setVisible(visible); mIsVisible = visible; } public void repaint() { super.repaint(); mRootNode.update(); } public void askForDataUpdate(final String message, final int numberOfDays) { updateTvData(numberOfDays, message); } private void askForDataUpdate(final String reason) { askForDataUpdate(reason, 0); } public void askForDataUpdateNoDataAvailable() { if (mProgramTableModel.getAvailableChannelCount() > 0) { askForDataUpdate(mLocalizer.msg("askforupdatedlg.noData", "No TV data for todays program available.")); } } public void askForDataUpdateChannelsAdded() { askForDataUpdate(mLocalizer.msg("askforupdatedlg.addedChannels", "You have added channels.")); } public void showFilterDialog() { SelectFilterDlg dlg = new SelectFilterDlg(this); util.ui.UiUtilities.centerAndShow(dlg); mMenuBar.updateFiltersMenu(); } public void updateFilterMenu() { mMenuBar.updateFiltersMenu(); } public void showHelpDialog() { Locale locale = Locale.getDefault(); String language = locale.getLanguage(); java.io.File indexFile = new java.io.File("help/" + language + "/index.html"); if (!indexFile.exists()) { indexFile = new java.io.File("help/default/index.html"); } Launch.openURL(indexFile.getAbsolutePath()); } /** * Updates the TimeChooser-Buttons */ public void updateButtons() { mMenuBar.updateTimeItems(); if (mTimebuttonsNode.getLeaf() != null) { ((TimeChooserPanel) mTimebuttonsNode.getLeaf()).updateButtons(); } } public void setShowToolbar(boolean visible) { Settings.propIsToolbarVisible.setBoolean(visible); mMenuBar.updateViewToolbarItem(); updateToolbar(); } public void setShowSearchField(boolean visible) { Settings.propIsSearchFieldVisible.setBoolean(visible); updateToolbar(); } private void updateViews() { if (mIsVisible) { jcontentPane = (JPanel) getContentPane(); jcontentPane.remove(mCenterComponent); mCenterComponent = mRootNode.getComponent(); jcontentPane.add(mCenterComponent, BorderLayout.CENTER); jcontentPane.validate(); jcontentPane.requestFocus(); mRootNode.update(); } } public void setShowTimeButtons(boolean visible) { setShowTimeButtons(visible, true); } public void setShowTimeButtons(boolean visible, boolean save) { if (visible) { mTimebuttonsNode.setLeaf(mTimeChooserPanel); } else { mTimebuttonsNode.setLeaf(null); } mTimeChooserPanel.setVisible(visible); if (save) { Settings.propShowTimeButtons.setBoolean(visible); } updateViews(); } public void setShowDatelist(boolean visible) { setShowDatelist(visible, true); } public void setShowDatelist(boolean visible, boolean save) { if (visible) { mDateNode.setLeaf(new DateChooserPanel(this, mFinderPanel.getComponent())); } else { mDateNode.setLeaf(null); } mFinderPanel.getComponent().setVisible(visible); if (save) { Settings.propShowDatelist.setBoolean(visible); } updateViews(); } public void setShowChannellist(boolean visible) { setShowChannellist(visible, true); } public void setShowChannellist(boolean visible, boolean save) { if (visible) { mChannelNode.setLeaf(mChannelChooser); } else { mChannelNode.setLeaf(null); } mChannelChooser.setVisible(visible); if (save) { Settings.propShowChannels.setBoolean(visible); } updateViews(); } public void setPluginViewButton(boolean selected) { if (mToolBarModel != null) { mToolBar.update(); } } public void setShowPluginOverview(boolean visible) { setShowPluginOverview(visible, true); } /** * Gets if the plugin overview is shown. * <p> * @return <code>true</code> if the plugin overview is shown, <code>false</code> otherwise. * @since 2.2.2 */ public boolean isShowingPluginOverview() { return mPluginView != null; } public void setShowPluginOverview(boolean visible, boolean save) { if (visible) { mPluginView = new PluginView(); } else { mPluginView = null; } mPluginsNode.setLeaf(mPluginView); TVBrowserActions.pluginView.putValue(ToolBar.ACTION_IS_SELECTED, Boolean.valueOf(visible)); mMenuBar.setPluginViewItemChecked(visible); if (save) { Settings.propShowPluginView.setBoolean(visible); } updateViews(); } /** * Makes the StatusBar visible * * @param visible * true if Statusbar should be visible */ public void setShowStatusbar(boolean visible) { JPanel contentPane = (JPanel) getContentPane(); Settings.propIsStatusbarVisible.setBoolean(visible); if (visible && !contentPane.isAncestorOf(mStatusBar)) { jcontentPane.add(mStatusBar, BorderLayout.SOUTH); } else if (contentPane.isAncestorOf(mStatusBar)) { jcontentPane.remove(mStatusBar); } contentPane.invalidate(); contentPane.repaint(); } public ProgressMonitor createProgressMonitor() { return mStatusBar.createProgressMonitor(); } public void selectChannel(Channel channel) { mChannelChooser.selectChannel(channel); } /** * increase/decrease the font of the program table * * @param offset positive values increase font, negative values decrease font, zero sets to default again */ public void changeFontSize(int offset) { if (util.ui.ProgramPanel.updateFonts(offset)) { tvbrowser.ui.programtable.ChannelPanel.fontChanged(); ProgramTableScrollPane scrollPane = getProgramTableScrollPane(); scrollPane.forceRepaintAll(); } } /** * increase/decrease the width of the program table columns * * @param offset positive values increase column width, * negative values decrease column width, zero sets to default again */ public void changeColumnWidth(int offset) { int columnWidth = util.ui.ProgramPanel.updateColumnWidth(offset); ProgramTableScrollPane scrollPane = getProgramTableScrollPane(); scrollPane.setColumnWidth(columnWidth); scrollPane.forceRepaintAll(); } public StatusBar getStatusBar() { return mStatusBar; } /** * get whether the mainframe is currently in full screen mode * * @return in full screen mode * @since 2.5.3 */ public boolean isFullScreenMode() { return isUndecorated(); } public void updatePluginTree() { if (mPluginView != null) { mPluginView.refreshTree(); } } /** * extract the drag and drop targets from the event * @param transferable * @param dataFlavors * @return */ private File[] getDragDropPlugins(final DataFlavor[] dataFlavors, final Transferable transferable) { HashSet<File> files = new HashSet<File>(); for (DataFlavor flavor : dataFlavors) { try { Object data = transferable.getTransferData(flavor); if (data instanceof List) { for (Object o : ((List) data)) { if (o instanceof File) { addPluginFile((File) o, files); } } if (!files.isEmpty()) { break; } } else if (data instanceof String) { String name = ((String) data).trim(); if (name.toLowerCase().endsWith("jar")) { File pluginFile = new File(name); if (pluginFile.canRead()) { addPluginFile(pluginFile, files); if (!files.isEmpty()) { break; } } else { try { URI uri = new URI(name); addPluginFile(new File(uri), files); } catch (URISyntaxException e) { // ignore } if (!files.isEmpty()) { break; } } } } } catch (UnsupportedFlavorException e) { //ignore } catch (IOException e) { //ignore } } return files.toArray(new File[files.size()]); } private void addPluginFile(final File file, final HashSet<File> files) { if (file.isFile() && file.getName().toLowerCase().endsWith(".jar") && file.canRead()) { files.add(file); } } @Override public void dragEnter(DropTargetDragEvent dtde) { File[] files = getDragDropPlugins(dtde.getCurrentDataFlavors(), dtde.getTransferable()); if (files.length > 0) { dtde.acceptDrag(dtde.getDropAction()); } else { dtde.rejectDrag(); } } @Override public void dragExit(DropTargetEvent dte) { // empty } @Override public void dragOver(DropTargetDragEvent dtde) { // empty } @Override public void drop(DropTargetDropEvent dtde) { dtde.acceptDrop(dtde.getDropAction()); File[] files = getDragDropPlugins(dtde.getCurrentDataFlavors(), dtde.getTransferable()); try { File tmpFile = File.createTempFile("plugins", ".txt"); StringBuilder alreadyInstalled = new StringBuilder(); StringBuilder notCompatiblePlugins = new StringBuilder(); for (File jarFile : files) { ClassLoader classLoader = null; try { URL[] urls = new URL[] { jarFile.toURI().toURL() }; classLoader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader()); } catch (MalformedURLException exc) { } if (classLoader != null) { // Get the plugin name String pluginName = jarFile.getName(); pluginName = pluginName.substring(0, pluginName.length() - 4); try { String pluginId = "java." + pluginName.toLowerCase() + "." + pluginName; PluginProxy installedPlugin = PluginProxyManager.getInstance().getPluginForId(pluginId); TvDataServiceProxy service = TvDataServiceProxyManager.getInstance() .findDataServiceById(pluginName.toLowerCase() + '.' + pluginName); Class<?> pluginClass = classLoader.loadClass(pluginName.toLowerCase() + '.' + pluginName); Method getVersion = pluginClass.getMethod("getVersion", new Class[0]); Version version1 = null; try { version1 = (Version) getVersion.invoke(pluginClass, new Object[0]); } catch (Throwable t1) { t1.printStackTrace(); } if (installedPlugin != null && (installedPlugin.getInfo().getVersion().compareTo(version1) > 0 || (installedPlugin.getInfo().getVersion().compareTo(version1) == 0 && version1.isStable()))) { alreadyInstalled.append(installedPlugin.getInfo().getName()).append('\n'); } else if (service != null && (service.getInfo().getVersion().compareTo(version1) > 0 || (service.getInfo().getVersion().compareTo(version1) == 0 && version1.isStable()))) { alreadyInstalled.append(service.getInfo().getName()).append('\n'); } else { RandomAccessFile write = new RandomAccessFile(tmpFile, "rw"); String versionString = Integer.toString(version1.getMajor()) + '.' + (version1.getMinor() / 10) + (version1.getMinor() % 10) + '.' + version1.getSubMinor(); write.seek(write.length()); write.writeBytes("[plugin:" + pluginName + "]\n"); write.writeBytes("name_en=" + pluginName + "\n"); write.writeBytes("filename=" + jarFile.getName() + "\n"); write.writeBytes("version=" + versionString + "\n"); write.writeBytes("stable=" + version1.isStable() + "\n"); write.writeBytes("download=" + jarFile.toURI().toURL() + "\n"); write.writeBytes("category=unknown\n"); write.close(); } } catch (Exception e) { notCompatiblePlugins.append(jarFile.getName()).append("\n"); } } } if (alreadyInstalled.length() > 0) { showInfoTextMessage( mLocalizer.msg("update.alreadyInstalled", "The following Plugin in current version are already installed:"), alreadyInstalled.toString(), 400); } if (notCompatiblePlugins.length() > 0) { showInfoTextMessage( mLocalizer.msg("update.noTVBPlugin", "This following files are not TV-Browser Plugins:"), notCompatiblePlugins.toString(), 400); } if (tmpFile.length() > 0) { java.net.URL url = tmpFile.toURI().toURL(); SoftwareUpdater softwareUpdater = new SoftwareUpdater(url, false, true); mSoftwareUpdateItems = softwareUpdater.getAvailableSoftwareUpdateItems(); dtde.dropComplete(true); SoftwareUpdateDlg updateDlg = new SoftwareUpdateDlg(this, false, mSoftwareUpdateItems); updateDlg.setVisible(true); } else { dtde.rejectDrop(); dtde.dropComplete(false); } if (!tmpFile.delete()) { tmpFile.deleteOnExit(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void dropActionChanged(DropTargetDragEvent dtde) { // TODO Auto-generated method stub } private void showInfoTextMessage(String header, String infoText, int width) { JTextArea textArea = new JTextArea(infoText); textArea.setEditable(false); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); JScrollPane scrollPane = new JScrollPane(textArea); scrollPane.setPreferredSize(new Dimension(width, 150)); Object[] msg = { header, scrollPane }; JOptionPane.showMessageDialog(this, msg, Localizer.getLocalization(Localizer.I18N_INFO), JOptionPane.INFORMATION_MESSAGE); } public void updateChannelGroupMenu(JMenu channelGroupMenu) { mMenuBar.updateChannelGroupMenu(channelGroupMenu); } public boolean getUserRequestCopyToSystem() { return mMenuBar.getUserRequestedCopyToSystem(); } }