/*
* File : ExtendedPlayer.java
* Created : 25-oct-2001 10:10
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* 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 (see the LICENSE file).
*/
package edu.xtec.jclic;
import edu.xtec.jclic.accessibility.FressaFunctions;
import edu.xtec.jclic.fileSystem.*;
import edu.xtec.jclic.misc.Utils;
import edu.xtec.jclic.project.*;
import edu.xtec.util.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.08.29
*/
public class ExtendedPlayer extends Player {
JFrame debugFrame=null;
public static final String MESSAGES_BUNDLE="messages.PlayerMessages";
protected int recentFilesOffset;
protected JMenuBar menuBar;
protected JMenu fileMenu, recentFilesMenu, activityMenu, toolsMenu, helpMenu;
protected PlayerSettings settings;
protected FressaFunctions fressa;
/** Creates new ExtendedPlayer */
public ExtendedPlayer(Options options){
super(options);
}
@Override
protected void init(){
//settings=PlayerSettings.loadPlayerSettings(this, options);
settings=PlayerSettings.loadPlayerSettings(this);
super.init();
settings.checkLibrary();
if(settings.fressaEnabled)
fressa=new FressaFunctions(options);
}
protected void doInstall(String fileName){
if(settings.promptPassword(this, new String[]{"install_info_description", "settings_passwordRequired"})){
try{
ProjectInstallerDlg pi=ProjectInstallerDlg.getProjectInstallerDlg(this, settings.libraryManager, fileName);
if(pi!=null){
pi.setVisible(true);
if(pi.result!=null && !pi.cancel){
if(pi.launchNow && pi.pathToMainProject!=null)
load(pi.pathToMainProject, null);
else
launchProjectLibrary(pi.result);
}
}
} catch(Exception ex){
System.err.println("Error installing: "+ex.getMessage());
}
}
}
@Override
public boolean start(String fullPath, String sequence){
boolean result=super.start(fullPath, sequence);
if(!result){
try{
ProjectLibrary pl=settings.libraryManager.getAutoStartProjectLibrary();
if(pl!=null)
launchProjectLibrary(pl);
} catch(Exception ex){
System.err.println("Error loading autoStart project library!\n"+ex);
}
}
return result;
}
@Override
public boolean load(String fullPath, String sequence){
boolean result=false;
if(fullPath!=null && sequence==null && fullPath.endsWith(ProjectInstaller.INSTALLER_EXTENSION))
doInstall(fullPath);
else
result=super.load(fullPath, sequence);
return result;
}
@Override
public Messages setMessages(){
super.setMessages();
messages.addBundle(MESSAGES_BUNDLE);
return messages;
}
@Override
protected FileSystem createFileSystem(){
return settings.fileSystem;
}
protected void createMenu(){
menuBar=new JMenuBar();
fileMenu=new JMenu(messages.get("m_File"));
fileMenu.setMnemonic(messages.get("m_File_Mnemonic").charAt(0));
fileMenu.add(new KJMenuItem(getAction(ACTION_OPEN_FILE)));
fileMenu.add(new KJMenuItem(getAction(ACTION_OPEN_URL)));
menuBar.add(fileMenu);
activityMenu=new JMenu(messages.get("m_Activity"));
activityMenu.setMnemonic(messages.get("m_Activity_Mnemonic").charAt(0));
activityMenu.add(new KJMenuItem(getAction(ACTION_NEXT)));
activityMenu.add(new KJMenuItem(getAction(ACTION_PREV)));
activityMenu.add(new KJMenuItem(getAction(ACTION_RETURN)));
activityMenu.add(new KJMenuItem(getAction(ACTION_RESET)));
activityMenu.addSeparator();
activityMenu.add(new KJMenuItem(getAction(ACTION_INFO)));
activityMenu.add(new KJMenuItem(getAction(ACTION_HLP)));
activityMenu.add(new KJMenuItem(getAction(ACTION_REPORTS)));
activityMenu.addSeparator();
activityMenu.add(new KJMenuItem(getAction(ACTION_AUDIO)));
menuBar.add(activityMenu);
toolsMenu=new JMenu(messages.get("m_Tools"));
toolsMenu.setMnemonic(messages.get("m_Tools_Mnemonic").charAt(0));
toolsMenu.add(new KJMenuItem(getAction(ACTION_LIBRARIES)));
toolsMenu.add(new KJMenuItem(getAction(ACTION_SETTINGS)));
menuBar.add(toolsMenu);
helpMenu=new JMenu(messages.get("m_Help"));
helpMenu.setMnemonic(messages.get("m_Help_Mnemonic").charAt(0));
helpMenu.add(new KJMenuItem(getAction(ACTION_ABOUT)));
menuBar.add(helpMenu);
}
protected void postCreateMenu(){
fileMenu.addSeparator();
fileMenu.add(new KJMenuItem(getAction(ACTION_EXIT)));
fileMenu.addSeparator();
recentFilesMenu=fileMenu;
recentFilesOffset=fileMenu.getItemCount();
updateRecentFilesMenu();
}
@Override
public void addTo(RootPaneContainer cont, Object constraints){
super.addTo(cont, constraints);
checkMenu(false);
}
protected void checkMenu(boolean recreate){
JRootPane rp=getRootPane();
if(rp==null)
return;
if(recreate || rp.getJMenuBar()==null){
if(recreate || menuBar==null){
createMenu();
postCreateMenu();
}
rp.setJMenuBar(menuBar);
rp.revalidate();
}
}
protected void updateRecentFilesMenu(){
if(recentFilesMenu!=null && recentFilesOffset>=0){
JMenuItem jmi;
int itemsToRemove=recentFilesMenu.getItemCount()-recentFilesOffset;
for(int i=0; i<itemsToRemove; i++)
recentFilesMenu.remove(recentFilesOffset);
for(int i=0; i<PlayerSettings.MAX_RECENT; i++){
if(settings.recentFiles[i]!=null){
String s=settings.recentFiles[i];
int k=s.lastIndexOf('\\');
if(k<0)
k=s.lastIndexOf('/');
if(k>=0)
s=s.substring(k+1);
createMenuItem(recentFilesMenu, Integer.toString(i+1)+". "+s, "recent"+i, true, KeyStroke.getKeyStroke(KeyEvent.VK_1+i, ActionEvent.ALT_MASK));
}
}
}
}
JMenuItem createMenuItem(JComponent parent, String text, String actionCommand, boolean mnemonic, KeyStroke accelerator){
JMenuItem jmi=new JMenuItem(text);
if(actionCommand!=null){
jmi.setActionCommand(actionCommand);
jmi.addActionListener(this);
}
if(mnemonic)
jmi.setMnemonic(jmi.getText().charAt(0));
if(accelerator!=null)
jmi.setAccelerator(accelerator);
parent.add(jmi);
return jmi;
}
public static final int
ACTION_OPEN_FILE=NUM_ACTIONS,
ACTION_OPEN_URL=NUM_ACTIONS+1,
ACTION_EXIT=NUM_ACTIONS+2,
ACTION_SETTINGS=NUM_ACTIONS+3,
ACTION_LIBRARIES=NUM_ACTIONS+4,
ACTION_ABOUT=NUM_ACTIONS+5,
NUM_ACTIONS_EXT=NUM_ACTIONS+6;
public static final String[] ACTION_NAME_EXT={"openFile", "openUrl", "exit", "settings", "libraries", "helpAbout"};
public static final String[] ACTION_ICONS_EXT={
"icons/file_open.gif",
"icons/world.gif",
"icons/exit_small.gif",
"icons/settings.gif",
"icons/database.gif",
"icons/help.gif"
};
@Override
protected int getNumActions(){
return NUM_ACTIONS_EXT;
}
@Override
protected void buildActions(){
super.buildActions();
actions[ACTION_OPEN_FILE]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
FileSystem fs=project.getFileSystem();
if(fs.isUrlBased())
fs=settings.fileSystem;
int[] filters={Utils.ALL_CLIC_FF, Utils.INSTALL_FF, Utils.ALL_JCLIC_FF};
String result=fs.chooseFile(null, false, filters, options, null, ExtendedPlayer.this, false);
if(result!=null){
String fileName=fs.getFullFileNamePath(result);
if(load(fileName, null))
addRecentFile(fileName);
}
}
};
actions[ACTION_OPEN_URL]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
String url=messages.showInputDlg(ExtendedPlayer.this, "URL_OPEN", "URL", "http://", "URL_OPEN", false);
if(url!=null){
url=url.trim();
// Check if the protocol was entered twice in the string
//if(url.startsWith("http://http://"))
if(url.indexOf("://", 7)>=0)
url=url.substring(7);
if(url.length()>0 && !url.equals("http://")){
if(load(url, null))
addRecentFile(url);
}
}
}
};
actions[ACTION_EXIT]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
exit();
}
};
actions[ACTION_SETTINGS]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
String currentLook=options.getString(LFUtil.LOOK_AND_FEEL);
String currentLanguage=options.getString(Messages.LANGUAGE);
String currentCountry=options.getString(Messages.COUNTRY);
String currentVariant=options.getString(Messages.VARIANT);
String currentSkin=options.getString(SKIN);
String currentReporterClass=settings.reporterClass;
String currentReporterParams=settings.reporterParams;
boolean currentReporterEnabled=settings.reporterEnabled;
String currentMediaSystem=settings.mediaSystem;
if(settings.edit(ExtendedPlayer.this)){
settings.save();
options.syncProperties(settings.getProperties(), false);
if(!settings.skin.equals(currentSkin)){
initSkin();
setSkin(null);
}
else if(getSkin()!=null){
AbstractButton bt=getSkin().getButton(ACTION_AUDIO);
if(bt!=null)
bt.setSelected(!audioEnabled);
}
boolean recreateMenu=false;
if(!settings.lookAndFeel.equals(currentLook)){
options.setLookAndFeel();
recreateMenu=true;
}
if(settings.language!=null &&
(!StrUtils.compareObjects(settings.language, currentLanguage) ||
!StrUtils.compareObjects(settings.country, currentCountry) ||
!StrUtils.compareObjects(settings.variant, currentVariant))){
setMessages();
recreateMenu=true;
}
if(recreateMenu){
checkMenu(true);
}
if(settings.reporterEnabled &&
(!settings.reporterClass.equals(currentReporterClass) ||
!settings.reporterParams.equals(currentReporterParams))){
initReporter();
}
audioEnabled=settings.soundEnabled;
edu.xtec.jclic.media.EventSounds.globalEnabled=settings.systemSounds;
if(!currentMediaSystem.equals(settings.mediaSystem)){
options.put(MEDIA_SYSTEM, settings.mediaSystem);
edu.xtec.jclic.media.CheckMediaSystem.check(options, false);
createEventSounds();
}
}
}
};
actions[ACTION_LIBRARIES]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
try{
ProjectLibrary pl=settings.libraryManager.selectProjectLibrary(true, false);
if(pl!=null)
launchProjectLibrary(pl);
} catch(Exception ex){
messages.showErrorWarning(ExtendedPlayer.this, "error_launchLibrary", ex);
}
}
};
actions[ACTION_ABOUT]=new AbstractAction(){
public void actionPerformed(ActionEvent ev){
showAbout(false);
}
};
}
@Override
protected String getActionName(int actionId){
if(actionId>=NUM_ACTIONS && actionId<NUM_ACTIONS_EXT)
return ACTION_NAME_EXT[actionId-NUM_ACTIONS];
return super.getActionName(actionId);
}
@Override
protected Icon getActionIcon(int actionId){
if(actionId>=NUM_ACTIONS && actionId<NUM_ACTIONS_EXT)
return ResourceManager.getImageIcon(ACTION_ICONS_EXT[actionId-NUM_ACTIONS]);
return super.getActionIcon(actionId);
}
@Override
protected boolean processActionEvent(String ac){
if(ac.startsWith("recent") && ac.length()>6){
try{
int i=Integer.parseInt(ac.substring(6));
if(i>=0 && i<PlayerSettings.MAX_RECENT && settings.recentFiles[i]!=null)
load(settings.recentFiles[i], null);
} catch(Exception ex){
System.err.println("invalid command: "+ac);
}
}
else
return super.processActionEvent(ac);
return true;
}
protected void launchProjectLibrary(ProjectLibrary pl){
if(pl!=null){
setProject(null);
edu.xtec.jclic.media.MediaContent mc=new edu.xtec.jclic.media.MediaContent();
mc.externalParam=pl.getFullPath();
mc.mediaFileName=pl.activitySequence.getElement(0, false).getTag();
mc.mediaType=edu.xtec.jclic.media.MediaContent.RUN_CLIC_PACKAGE;
playMedia(mc, null);
}
}
protected void addRecentFile(String fName){
settings.addRecentFile(fName);
updateRecentFilesMenu();
settings.save();
}
/**
* FressaFunctions offers special accessibility features
* like atomatic scanning and voice synthesis.
* @return The FressaFunctions object, or <CODE>null</CODE> if accessibility features are not enabled
*/
@Override
public edu.xtec.jclic.accessibility.FressaFunctions getFressa(){
return fressa;
}
}