/*
* 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: 2011-03-22 17:08:48 +0100 (Tue, 22 Mar 2011) $
* $Author: bananeweizen $
* $Revision: 6961 $
*/
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.InvocationTargetException;
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.UIThreadRunner;
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 UserAwayDetector mAwayDetector = new UserAwayDetector();
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()) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
mToolBarPanel.setVisible(Settings.propIsToolbarVisible.getBoolean());
}
});
}
}
if (p.y <= 0) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
mMenuBar.setVisible(true);
}
});
}
}
else if(p.y > (mMenuBar != null && mMenuBar.isVisible() ? mMenuBar.getHeight() : 0) + (Settings.propIsToolbarVisible.getBoolean() ? mToolBarPanel.getHeight() : 0)) {
if(mMenuBar.isVisible()) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
mMenuBar.setVisible(!isFullScreenMode());
}
});
}
if(mToolBarPanel != null && mToolBarPanel.isVisible() && mToolBar.getToolbarLocation().compareTo(BorderLayout.NORTH) == 0) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
mToolBarPanel.setVisible(!isFullScreenMode());
}
});
}
}
// mouse pointer is at the bottom
if(p.y >= screen.height - 1 ) {
if(mStatusBar != null && !mStatusBar.isVisible()) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
mStatusBar.setVisible(Settings.propIsStatusbarVisible.getBoolean());
}
});
}
}
else if(mStatusBar != null && mStatusBar.isVisible() && p.y < screen.height - mStatusBar.getHeight()) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
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()) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
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) {
UIThreadRunner.invokeLater(new Runnable() {
@Override
public void run() {
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;
mMenuBar.updateChannelGroupMenu();
}
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() {
checkAutomaticGotoNow();
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 checkAutomaticGotoNow() {
if (mAwayDetector.isAway()) {
scrollToNow();
}
}
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() {
try {
UIThreadRunner.invokeAndWait(new Runnable() {
@Override
public void run() {
mConfigAssistantDialog = new tvbrowser.ui.configassistant.ConfigAssistant(
parent);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
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;
}
try {
UIThreadRunner.invokeAndWait(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;
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*****************************************************************************
* 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) {
final Window parent = UiUtilities.getLastModalChildOf(MainFrame
.getInstance());
try {
UIThreadRunner.invokeAndWait(new Runnable() {
@Override
public void run() {
SoftwareUpdateDlg dlg = new SoftwareUpdateDlg(parent, baseUrl,
showOnlyUpdates, mSoftwareUpdateItems);
//dlg.setSoftwareUpdateItems(mSoftwareUpdateItems);
dlg.setLocationRelativeTo(parent);
dlg.setVisible(true);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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();
}
}