package org.openslx.dozmod.gui;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import org.apache.log4j.Logger;
import org.openslx.dozmod.App;
import org.openslx.dozmod.Config;
import org.openslx.dozmod.gui.Gui.GuiCallable;
import org.openslx.dozmod.gui.helper.CompositePage;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.gui.window.DisclaimerWindow;
import org.openslx.dozmod.gui.window.ImageListWindow;
import org.openslx.dozmod.gui.window.LectureListWindow;
import org.openslx.dozmod.gui.window.LoginWindow;
import org.openslx.dozmod.gui.window.MainMenuWindow;
import org.openslx.dozmod.gui.window.VirtualizerNoticeWindow;
import org.openslx.dozmod.thrift.Session;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.thrifthelper.ThriftManager.ErrorCallback;
import org.openslx.util.QuickTimer;
public abstract class MainWindow {
private final static Logger LOGGER = Logger.getLogger(MainWindow.class);
private static final JFrame mainShell;
private static CompositePage currentPage;
private static final Map<Class<? extends CompositePage>, CompositePage> pages = new ConcurrentHashMap<>();
private static final String THRIFT_CONNECTION_ERROR = "Lost connection to the masterserver. Do you want to retry?";
/**
* Set the visible page of the main window.
*
* @param clazz
*/
public static void showPage(Class<? extends CompositePage> clazz) {
if (currentPage != null) {
if (!currentPage.requestHide()) {
return; // Canceled by currently shown page
}
currentPage.setVisible(false);
}
currentPage = pages.get(clazz);
if (currentPage == null) {
Gui.showMessageBox("Tried to show unknown page " + clazz.getSimpleName(), MessageType.ERROR,
LOGGER, null);
Gui.exit(1);
return;
}
// sets the starting preferred size.
currentPage.requestShow();
currentPage.setVisible(true);
mainShell.validate();
}
public static void centerShell(Window shell) {
Gui.centerShellOverShell(mainShell, shell);
}
/**
* Initializes the GUI by creating the main window, adding the menu and
* creating the login mask as the first content window.
* Further sets up the global thrift error callback to catch any
* connection errors during the communication with the servers.
*/
static {
// init SWT stuff
mainShell = new JFrame("bwLehrstuhl");
mainShell.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
// Catch the close button (X)
mainShell.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
MainWindow.askApplicationQuit();
}
});
// Set up thrift error message displaying
ThriftManager.setErrorCallback(new ErrorCallback() {
@Override
public boolean thriftError(int failCount, String method, final Throwable t) {
// if it's the first fail, retry immediately
if (failCount == 1)
return true;
// Otherwise, ask user if we should retry
return Gui.syncExec(new GuiCallable<Boolean>() {
@Override
public Boolean run() {
return Gui.showMessageBox(THRIFT_CONNECTION_ERROR, MessageType.ERROR_RETRY, LOGGER, t);
}
});
}
});
// Same for config errors
Config.setErrorCallback(new Config.ErrorCallback() {
@Override
public void writeError(final Throwable t) {
Gui.asyncExec(new Runnable() {
@Override
public void run() {
Gui.showMessageBox("Konnte Programmeinstellungen nicht speichern", MessageType.WARNING,
LOGGER, t);
}
});
}
});
// Global key listener
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyChar() == 17) { // Ctrl-Q = Quit
askApplicationQuit();
event.consume();
}
}
});
createMenu();
// Set layout for the mainshell, items added to the shell should get a gridData
mainShell.setLayout(new BoxLayout(mainShell, BoxLayout.PAGE_AXIS));
mainShell.setMinimumSize(new Dimension(850, 650));
// register all pages of the main window
registerPage(new MainMenuWindow(mainShell));
registerPage(new ImageListWindow(mainShell));
registerPage(new LectureListWindow(mainShell));
// Show main menu by default
showPage(MainMenuWindow.class);
// center the window on the primary monitor
Gui.centerShell(mainShell);
Gui.limitShellSize(mainShell);
// here we can check for Session information
if (Session.getSatelliteToken() != null) {
// Wait for proxy server init
App.waitForInit();
// TODO: Try to resume session
}
// Session resume probably failed, show login window
if (Session.getSatelliteToken() == null) {
// User did not login, show the login mask
LoginWindow.open();
}
}
/**
* Request application quit. Will show a message box asking the user for
* confirmation.
*/
protected static void askApplicationQuit() {
// TODO: Only ask if an upload or download is running,, wizard is open etc..
if (Gui.showMessageBox("Are you sure you want to quit?", MessageType.QUESTION_YESNO, null, null)) {
QuickTimer.cancel();
Gui.exit(0);
}
}
/**
* Register a page that can be displayed in the main window.
*
* @param window
*/
private static synchronized void registerPage(CompositePage window) {
Class<? extends CompositePage> clazz = window.getClass();
if (pages.containsKey(clazz))
throw new IllegalArgumentException("Page " + clazz.getSimpleName() + " already registered!");
pages.put(clazz, window);
window.setVisible(false);
}
private static void createMenu() {
// the File menu button
JMenuBar menuBar = new JMenuBar();
mainShell.setJMenuBar(menuBar);
JMenu cascadeFileMenu = new JMenu("&File");
menuBar.add(cascadeFileMenu);
JMenuItem exitItem = new JMenuItem("&Exit");
exitItem.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent arg0) {
askApplicationQuit();
}
});
// the About menu button
JMenu cascadeAboutMenu = new JMenu("&About");
menuBar.add(cascadeAboutMenu);
JMenuItem disclaimerItem = new JMenuItem("&Disclaimer");
disclaimerItem.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent arg0) {
DisclaimerWindow.open(false);
}
});
JMenuItem virtualizerNoticeItem = new JMenuItem("&Virtualizer");
virtualizerNoticeItem.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent arg0) {
VirtualizerNoticeWindow.open(false);
}
});
}
public static void open() {
mainShell.setVisible(true);
}
}