/*
* Copyright (c) 2010-2011 by Stefan Laubenberger.
*
* Tyr is free software: you can redistribute it and/or modify
* it under the terms of the General Public License v2.0.
*
* Tyr 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:
* <http://www.gnu.org/licenses>
*
* This distribution is available at:
* <http://code.google.com/p/tyr/>
* <http://dev.laubenberger.net/tyr/>
*
* Contact information:
* Stefan Laubenberger
* Bullingerstrasse 53
* CH-8004 Zuerich
*
* <http://www.laubenberger.net>
*
* <laubenberger@gmail.com>
*/
package net.laubenberger.tyr.controller;
import java.awt.AWTException;
import java.awt.SystemTray;
import java.io.File;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import net.laubenberger.bogatyr.helper.HelperArray;
import net.laubenberger.bogatyr.helper.HelperCollection;
import net.laubenberger.bogatyr.helper.HelperIO;
import net.laubenberger.bogatyr.helper.HelperLog;
import net.laubenberger.bogatyr.helper.HelperMap;
import net.laubenberger.bogatyr.helper.HelperString;
import net.laubenberger.bogatyr.misc.extendedObject.ExtendedObjectAbstract;
import net.laubenberger.bogatyr.model.Model;
import net.laubenberger.bogatyr.model.application.ModelApplication;
import net.laubenberger.bogatyr.model.misc.Document;
import net.laubenberger.bogatyr.model.misc.Url;
import net.laubenberger.bogatyr.view.View;
import net.laubenberger.bogatyr.view.swing.Frame;
import net.laubenberger.bogatyr.view.swing.PopupMenu;
import net.laubenberger.bogatyr.view.swing.TrayIcon;
import net.laubenberger.tyr.misc.Callback;
import net.laubenberger.tyr.misc.ScalableIcon;
import net.laubenberger.tyr.model.FileType;
import net.laubenberger.tyr.model.ModuleConfig;
import net.laubenberger.tyr.model.ModuleData;
import net.laubenberger.tyr.service.ModuleDb;
import net.laubenberger.tyr.service.ModuleDbImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The implementation of an abstract module.
*
* @author Stefan Laubenberger
* @version 0.9.0 (20110529)
* @since 0.2.0
*/
public abstract class ModuleAbstract<M extends ModelApplication, V extends View> extends ExtendedObjectAbstract implements Module<M, V> {
static final Logger log = LoggerFactory.getLogger(ModuleAbstract.class);
private M model;
private V view;
// Settings for ModuleDb
private static final String DB_DRIVER = "org.hsqldb.jdbcDriver"; //$NON-NLS-1$
private static final String DB_URL = "jdbc:hsqldb:file:"; //$NON-NLS-1$
private static final String DB_USER = "SA"; //$NON-NLS-1$ //TODO let the module creator decide
private static final String DB_PASSWORD = HelperString.EMPTY_STRING; //TODO let the module creator decide
// Keys for ModuleData
protected static final String KEY_MODULE_ENABLED = "key.module.enabled"; //$NON-NLS-1$
protected static final String KEY_TRAYICON_ENABLED = "key.trayicon.enabled"; //$NON-NLS-1$
// Members
private final ModuleConfig moduleConfig;
final ModuleData moduleData;
private final ModuleDb moduleDb;
final Callback callback;
private final ScalableIcon iconLogo;
final JFrame owner;
final PopupMenu popup = new PopupMenu();
final TrayIcon trayIcon;
boolean isModuleEnabled;
boolean isTrayIconEnabled;
protected ModuleAbstract(final ModuleConfig moduleConfig, final ModuleData moduleData, final Callback callback,
final ScalableIcon iconLogo, final File dirDB) {
super();
if (log.isTraceEnabled()) log.trace(HelperLog.constructor(moduleConfig, moduleData, callback, iconLogo, dirDB));
// Thread.setDefaultUncaughtExceptionHandler(new Handler());
model = (M)moduleConfig;
this.moduleConfig = moduleConfig;
this.moduleData = moduleData;
this.callback = callback;
this.iconLogo = iconLogo;
moduleDb = new ModuleDbImpl(DB_DRIVER, DB_URL + dirDB.getAbsolutePath() + HelperIO.FILE_SEPARATOR
+ moduleConfig.getUUID() + FileType.DB.getExtension(), DB_USER, DB_PASSWORD);
owner = new Frame(moduleConfig.getName(), iconLogo.getIcon());
trayIcon = new TrayIcon(iconLogo.getIcon(), moduleConfig.getName() + HelperString.SPACE
+ moduleConfig.getVersion(), popup);
moduleConfig.getLocalizer().addListener(this);
setModuleEnabled(null == moduleData.getString(KEY_MODULE_ENABLED) ? true : moduleData
.getBoolean(KEY_MODULE_ENABLED));
}
/*
* Private methods
*/
void createLayout() {
if (log.isTraceEnabled()) log.trace(HelperLog.methodStart());
popup.removeAll();
for (final Object item : getMenuItems()) {
if (item instanceof Action) {
popup.add((Action) item);
} else if (item instanceof JComponent) {
popup.add((JComponent) item);
} else {
log.warn("Unsupported object in getMenuItems(): " + item); //$NON-NLS-1$
}
}
if (log.isTraceEnabled()) log.trace(HelperLog.methodExit());
}
void setLocale(final Locale locale) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(locale));
moduleConfig.getLocalizer().setLocale(locale);
createLayout();
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
void setLookAndFeelChanged() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
lookAndFeelChanged();
SwingUtilities.updateComponentTreeUI(popup);
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
void setFontSizeChanged() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
fontSizeChanged();
createLayout();
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
void setIconSizeChanged() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
iconSizeChanged();
createLayout();
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
/*
* Overridden methods
*/
/*
* Implemented methods
*/
@Override
public M getModel() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(model));
return model;
}
@Override
public V getView() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(view));
return view;
}
@Override
public void setModel(final M model) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(model));
this.model = model;
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public void setView(final V view) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(view));
this.view = view;
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public void run() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
setTrayIconEnabled(null == moduleData.getString(KEY_TRAYICON_ENABLED) ? false : moduleData
.getBoolean(KEY_TRAYICON_ENABLED));
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public ModuleConfig getModuleConfig() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(moduleConfig));
return moduleConfig;
}
@Override
public ModuleData getModuleData() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(moduleData));
return moduleData;
}
@Override
public ModuleDb getModuleDb() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(moduleDb));
return moduleDb;
}
@Override
public Callback getCallback() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(callback));
return callback;
}
@Override
public ScalableIcon getLogo() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(iconLogo));
return iconLogo;
}
@Override
public JFrame getOwner() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(owner));
return owner;
}
@Override
public TrayIcon getTrayIcon() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(trayIcon));
return trayIcon;
}
@Override
public JPopupMenu getPopup() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(popup));
return popup;
}
@Override
public boolean getModuleEnabled() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(isModuleEnabled));
return isModuleEnabled;
}
@Override
public boolean getTrayIconEnabled() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(isTrayIconEnabled));
return isTrayIconEnabled;
}
@Override
public void setModuleEnabled(final boolean isEnabled) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(isEnabled));
moduleData.addValue(KEY_MODULE_ENABLED, isEnabled);
isModuleEnabled = isEnabled;
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public void setTrayIconEnabled(final boolean isEnabled) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(isEnabled));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final SystemTray tray = SystemTray.getSystemTray();
moduleData.addValue(KEY_TRAYICON_ENABLED, isEnabled);
isTrayIconEnabled = isEnabled;
if (isEnabled) {
if (isModuleEnabled && !HelperArray.contains(tray.getTrayIcons(), trayIcon)) {
createLayout();
try {
tray.add(trayIcon);
} catch (AWTException ex) {
log.error("TrayIcon could not be added", ex); //$NON-NLS-1$
}
}
} else {
tray.remove(trayIcon);
}
}
});
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public void setPopupEnabled(final boolean isEnabled) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(isEnabled));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (isEnabled) {
trayIcon.setJPopupMenu(popup);
} else {
trayIcon.setJPopupMenu(null);
}
}
});
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public void displayMessage(final String title, final String message, final TrayIcon.MessageType messageType) {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart(title, message, messageType));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (isTrayIconEnabled) {
trayIcon.displayMessage(title, message, messageType);
} else {
callback.displayMessage(title, message, messageType);
}
}
});
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit());
}
@Override
public Map<String, Object> getReport() {
if (log.isDebugEnabled()) log.debug(HelperLog.methodStart());
final Map<String, Object> result = new HashMap<String, Object>();
result.put(Document.MEMBER_BUILD, moduleConfig.getBuild());
result.put(Document.MEMBER_CREATED, moduleConfig.getCreated());
result.put(Model.MEMBER_INSTANTIATED, moduleConfig.getInstantiated());
result.put(ModelApplication.MEMBER_DEBUG, moduleConfig.isDebug());
result.put(ModuleConfig.MEMBER_MODULE_CLASS, moduleConfig.getModuleClass());
result.put(ModuleConfig.MEMBER_LOCALIZER_BASE, moduleConfig.getLocalizerBase());
if (null != moduleConfig.getName()) {
result.put(Document.MEMBER_NAME, moduleConfig.getName());
}
if (null != moduleConfig.getVersion()) {
result.put(Document.MEMBER_VERSION, moduleConfig.getVersion());
}
if (null != moduleConfig.getUUID()) {
result.put(Model.MEMBER_UUID, moduleConfig.getUUID());
}
if (null != moduleConfig.getLanguage()) {
result.put(Document.MEMBER_LANGUAGE, moduleConfig.getLanguage());
}
if (null != moduleConfig.getUrl()) {
result.put(Url.MEMBER_URL, moduleConfig.getUrl());
}
if (null != moduleConfig.getName()) {
result.put(Document.MEMBER_NAME, moduleConfig.getName());
}
if (null != moduleConfig.getUpdateLocation()) {
result.put(ModelApplication.MEMBER_UPDATE_LOCATION, moduleConfig.getUpdateLocation());
}
if (null != moduleConfig.getProperty()) {
result.put(ModelApplication.MEMBER_PROPERTY, moduleConfig.getProperty());
}
if (null != moduleConfig.getLocalizer()) {
result.put(ModelApplication.MEMBER_LOCALIZER, moduleConfig.getLocalizer());
}
if (null != moduleConfig.getOrganizations()) {
result.put(Document.MEMBER_ORGANIZATIONS, HelperCollection.dump(moduleConfig.getOrganizations()));
}
if (null != moduleConfig.getPersons()) {
result.put(Document.MEMBER_PERSONS, HelperCollection.dump(moduleConfig.getPersons()));
}
if (null != moduleConfig.getTags()) {
result.put(Model.MEMBER_TAGS, HelperMap.dump(moduleConfig.getTags()));
}
if (null != moduleConfig.getJars()) {
result.put(ModuleConfig.MEMBER_JARS, HelperCollection.dump(moduleConfig.getJars()));
}
if (null != moduleConfig.getProperties()) {
result.put(ModuleConfig.MEMBER_PROPERTIES, moduleConfig.getProperties());
}
if (null != moduleConfig.getLogo()) {
result.put(ModuleConfig.MEMBER_LOGO, moduleConfig.getLogo());
}
if (null != moduleConfig.getLogoLarge()) {
result.put(ModuleConfig.MEMBER_LOGO_LARGE, moduleConfig.getLogoLarge());
}
if (log.isDebugEnabled()) log.debug(HelperLog.methodExit(result));
return result;
}
}