Logo Search packages:      
Sourcecode: jclic version File versions  Download package

Player.java

/*
 * File    : Player.java
 * Created : 18-dec-2000 10:21
 * 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.bags.ActivityBagElement;
import edu.xtec.jclic.bags.ActivitySequenceElement;
import edu.xtec.jclic.bags.JumpInfo;
import edu.xtec.jclic.boxes.ActiveBox;
import edu.xtec.jclic.boxes.ActiveBoxContent;
import edu.xtec.jclic.boxes.BoxBase;
import edu.xtec.jclic.boxes.BoxConnector;
import edu.xtec.jclic.boxes.Counter;
import edu.xtec.jclic.clic3.Clic3;
import edu.xtec.jclic.fileSystem.FileSystem;
import edu.xtec.jclic.fileSystem.ZipFileSystem;
import edu.xtec.jclic.media.ActiveMediaBag;
import edu.xtec.jclic.media.ActiveMediaPlayer;
import edu.xtec.jclic.media.CheckMediaSystem;
import edu.xtec.jclic.media.EventSounds;
import edu.xtec.jclic.media.JavaSoundAudioBuffer;
import edu.xtec.jclic.media.MediaContent;
import edu.xtec.jclic.misc.Utils;
import edu.xtec.jclic.project.JClicProject;
import edu.xtec.jclic.report.Reporter;
import edu.xtec.jclic.skins.AboutWindow;
import edu.xtec.jclic.skins.Skin;
import edu.xtec.util.BrowserLauncher;
import edu.xtec.util.FontCheck;
import edu.xtec.util.Html;
import edu.xtec.util.Messages;
import edu.xtec.util.Options;
import edu.xtec.util.ResourceManager;
import edu.xtec.util.StrUtils;
import edu.xtec.util.SwingWorker;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Locale;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.Timer;


/**
 * <CODE>Player</CODE> is one of the the main classes of the JClic system. It implements the
 * {@link edu.xtec.jclic.PlayStation} interface, so it can read and play JClic
 * projects from files or streams. In order to allow activities to run,
 * <CODE>Player</CODE> provides them of all the necessary resources: media bags
 * (to load and realize images and other media contents), sequence control,
 * report system management, user interface (loading and management of skins),
 * display of system messages, etc.
 * Player is also a {@link edu.xtec.jclic.RunnableComponent}, so it can be
 * embedded in applets, frames and other containers.
 * @author Francesc Busquets (fbusquets@xtec.net)
 * @version 1.0
 */
00106 public class Player extends JPanel implements Constants, RunnableComponent, PlayStation, ActionListener {
    
    // check fonts
    //private static final Font CHECK_ARIAL=FontCheck.checkSystemFont("Arial", "arial2.ttf");
    
    // static fields
    /**
     * Name of the resource corresponding to the default skin of JClic.
     */
00115     public static final String DEFAULT_SKIN="@default.xml";
    /**
     * Name of the default reporter used by JClic.
     */
00119     public static final String DEFAULT_REPORTER="Reporter";
    /**
     * List of the names of the internal resources corresponding to the default
     * event sounds used by JClic.
     */
00124     public static final String[] DEFAULT_EVENT_SOUNDS={
        
        // MP3
        /*START*/ "sounds/start.mp3",
        /*CLICK*/ "sounds/click.mp3",
        /*ACTION_ERROR*/ "sounds/action_error.mp3",
        /*ACTION_OK*/ "sounds/action_ok.mp3",
        /*FINISHED_ERROR*/ "sounds/finished_error.mp3",
        /*FINISHED_OK*/ "sounds/finished_ok.mp3"
        
    };
    
    /**
     * List of the names of the internal resources corresponding to the default icons
     * associated to the basic actions defined in {@link edu.xtec.jclic.Constants}.
     */
00140     public static final String[] ACTION_ICONS={
        "icons/prev.gif",
        "icons/next.gif",
        "icons/return.gif",
        "icons/reset.gif",
        "icons/info_small.gif",
        "icons/help.gif",
        "icons/audio_on.gif",
        "icons/logo_button.gif"
    };
    
    /**
     * The default name of the application (JClic)
     */
00154     public static final String DEFAULT_APP_NAME="JClic";
    
    /**
     * Array containing the {@link javax.swing.Action} objects used by the player.
     */
00159     protected Action[] actions;
    
    /**
     * The main {@link edu.xtec.util.Messages} object.
     */
00164     protected Messages messages;
    
    /**
     * The {@link edu.xtec.jclic.JClicProject} currently hosted by the
     * <CODE>Player</CODE>.
     */
00170     protected JClicProject project;
    
    /**
     * The UI element (<CODE>Panel</CODE>)of the <CODE>Activity</CODE> currently
     * running in the <CODE>Player</CODE>.
     */
00176     protected Activity.Panel actPanel;
    
    /**
     * This object manages a list with the names of all the activities
     * currently played by the user in this <CODE>Player</CODE>.
     */
00182     protected PlayerHistory history;
    
    /**
     * Current {@link edu.xtec.jclic.skins.Skin} of the <CODE>Player</CODE>.
     */
00187     protected Skin skin;
    
    /**
     * Default skin of this <CODE>Player</CODE>. Users can override the
     * <CODE>DEFAULT_SKIN</CODE> setting and choose another Skin to be used by
     * default in JClic.
     */
00194     protected Skin defaultSkin;
    
    /**
     * Bag of realized media objects, ready to play.
     */
00199     protected ActiveMediaBag activeMediaBag;
    
    /**
     * Current reporter used by this <CODE>Player</CODE>.
     */
00204     protected Reporter reporter;
    
    /**
     * Current set of system sonds used in this <CODE>Player</CODE>.
     */
00209     protected EventSounds eventSounds;
    
    /**
     * Main <CODE>Timer</CODE>, used to feed the time conter. This timer generates an
     * <CODE>ActionPerformed</CODE> event every second.
     */
00215     protected Timer timer;
    
    /**
     * This flag indicates if the <CODE>Player</CODE> must play the sounds (including
     * system sounds) and other media contents of the activities.
     */
00221     protected boolean audioEnabled=true;
    
    /**
     * This flag indicates if the program must write verbose info to the system console.
     */
00226     protected boolean trace=false;
    
    /**
     * This flag indicates if the navigation buttons (<I>go to next activity</I> and
     * <I>go back</I>) are enabled o disabled.
     */
00232     protected boolean navButtonsDisabled=false;
    
    /**
     * When this flag is <CODE>true</CODE>, the navigation buttons are always enabled,
     * despite of the indications made by the activities or the sequence control system.
     * Used only for debugging projects with complicated sequence chaining.
     */
00239     protected boolean navButtonsAlways=false;
    
    /**
     * The main name of the application in wich this <CODE>Player</CODE> is running.
     */
00244     protected String appName=DEFAULT_APP_NAME;
    
    Timer delayedTimer;
    Action delayedAction;
    Object currentConstraints;
    int[] counterVal=new int[NUM_COUNTERS];
    Cursor[] cursors=new Cursor[3];
    Options options;
    Image splashImg;
    Point bgImageOrigin=new Point();
    private SwingWorker worker=null;
    
    /**
     * Creates a new <CODE>Player</CODE> object.
     * @param options Options object to be used in the initialization process
     */
00260     public Player(Options options) {
        this(options, null);
    }
    
    /**
     * Creates a new <CODE>Player</CODE> object that will be initially loaded with a specific
     * <CODE>JClicProject</CODE>.
     * @param options Options object to be used in the initialization process
     * @param project JClic project to load (can be <CODE>null</CODE>)
     */
00270     public Player(Options options, JClicProject project) {
        this.options=options;
        this.project=project;
        init();
    }
    
    /**
     * Main initialization process, called once by constructors. Subclasses of
     * <CODE>Player</CODE> should override this method to initialize additional members.
     */
00280     protected void init(){
        options.setLookAndFeel();
        CheckMediaSystem.check(options, false);
        setPreferredSize(new Dimension(600, 400));
        setLayout(null);
        Utils.checkRenderingHints(options);
        BoxConnector.checkOptions(options);
        ActiveBox.checkOptions(options);
        for(int i=0; i<NUM_COUNTERS; i++)
            counterVal[i]=0;
        setMessages();
        buildActions();
        setActionsText();
        history=new PlayerHistory(this);
        trace=options.getBoolean(TRACE);
        ActiveBox.compressImages=options.getBoolean(COMPRESS_IMAGES, true);
        audioEnabled=options.getBoolean(AUDIO_ENABLED, true);
        navButtonsAlways=options.getBoolean(NAV_BUTTONS_ALWAYS, false);
        setProject(project);
        activeMediaBag=new ActiveMediaBag();
        initSkin();
        setSkin(skin);
        setSystemMessage(getMessages().get("msg_initializing"), null);
        setWaitCursor(true);
        createCursors();
        createEventSounds();
        initTimers();
        splashImg=ResourceManager.getImageIcon(LOGO_ICON).getImage();
        if(skin!=null && skin.hasMemMonitor())
            skin.setMem(Runtime.getRuntime().freeMemory());
        setWaitCursor(false);
        setWindowTitle();
        setSystemMessage(getMessages().get("msg_ready"), null);
    }
    
    /**
     * Starts off the player, loading a specific project if specified. This
     * method is defined in the {@link RunnableComponent} interface.
     * @param fullPath Full path to the JClic project file to be loaded. Can be
     * <I>null</I>.
     * @param sequence Optional parameter, used only when <CODE>fullPath</CODE>
     * is not <I>null</I>. It
     * indicates the sequence where the to start. It's also possible to indicate
     * a string representation of a number "N". In this case, the player will
     * start with the activity indicated by the Nth element of the main sequence
     * of the project.
     * @return <CODE>true</CODE> if the player starts successfully.
     * <CODE>false</CODE> otherwise.
     */
00329     public boolean start(String fullPath, String sequence){
        initReporter();
        if(fullPath!=null)
            return load(fullPath, sequence);
        else
            return false;
    }
    
    /**
     * This method is called when the container gains the focus for the first
     * time or after have lost it. Not used in <CODE>Player</CODE>.
     */
00341     public void activate() {
    }
    
    /**
     * Instructs the RunnableComponent to stop working.
     */
00347     public void stop(){
        stopMedia(-1);
    }
    
    /**
     *
     * @throws Throwable
     */
00355     protected void finalize() throws Throwable {
        end();
        super.finalize();
    }
    
    /**
     * Executes miscellaneous finalization routines.
     */
00363     public void end(){
        if(worker!=null){
            worker.interrupt();
            worker=null;
        }
        stopMedia();
        closeHelpWindow();
        if(actPanel!=null){
            actPanel.end();
            remove(actPanel);
            actPanel=null;
        }
        if(eventSounds!=null){
            eventSounds.close();
            eventSounds=null;
        }
        if(project!=null){
            project.end();
            project=null;
        }
        if(activeMediaBag!=null)
            activeMediaBag.removeAll();
        if(reporter!=null){
            reporter.end();
            reporter=null;
        }
    }
    
    /**
     * Creates and initializes the members of the {@link cursors} array.
     */
00394     protected void createCursors(){
        try{
            Toolkit tk=Toolkit.getDefaultToolkit();
            
            cursors[HAND_CURSOR]=tk.createCustomCursor(
            ResourceManager.getImageIcon("cursors/hand.gif").getImage(),
            new Point(8,0), "hand");
            
            cursors[OK_CURSOR]=tk.createCustomCursor(
            ResourceManager.getImageIcon("cursors/ok.gif").getImage(),
            new Point(0,0), "ok");
            
            cursors[REC_CURSOR]=tk.createCustomCursor(
            ResourceManager.getImageIcon("cursors/micro.gif").getImage(),
            new Point(15,3), "record");
            
        }catch(Exception e){
            System.err.println("Error creating cursor:\n"+e);
        }
    }
    
    /**
     * Creates the {@link eventSounds} member and initializes the sound system.
     */
00418     protected void createEventSounds(){
        
        // Workaround for a JavaSound bug in Mac OS X
        if(options.getBoolean(Options.MAC)){
            try{
                JavaSoundAudioBuffer.initialize();
            } catch(Exception ex){
                System.err.println("Error initializing AudioBuffer lines:\n"+ex);
            }
        }
        // end of workaround
        
        eventSounds=new EventSounds(null);
        try{
            for(int i=0; i<DEFAULT_EVENT_SOUNDS.length; i++){
                String s=DEFAULT_EVENT_SOUNDS[i];
                eventSounds.setDataSource(i, ResourceManager.getResourceAsByteArray(s), options);
            }
            eventSounds.realize(options, project.mediaBag);
        } catch(Exception ex){
            System.err.println("Error reading system sound:\""+ex);
        }
        EventSounds.globalEnabled=options.getBoolean(SYSTEM_SOUNDS, true);
    }
    
    /**
     * Creates and initializes the {@link reporter} member.
     */
00446     protected void initReporter(){
        if(reporter!=null){
            reporter.end();
            reporter=null;
        }
        String reporterClassName=StrUtils.secureString(options.getString(REPORTER_CLASS), DEFAULT_REPORTER);
        try{
            reporter=Reporter.getReporter(reporterClassName,
            options.getString(REPORTER_PARAMS), this, messages);
        } catch(Exception ex){
            reporter=null;
            messages.showErrorWarning(this, "report_err_creating", reporterClassName, ex, null);
        }
    }
    
    /**
     * Creates and initializes the {@link defaultSkin} member.
     */
00464     protected void initSkin(){
        String s="";
        try{
            FileSystem fsSk=null;
            s=options.getString(SKIN);
            if(s==null)
                s=DEFAULT_SKIN;
            else if(!s.startsWith(Skin.INTERNAL_SKIN_PREFIX)){
                fsSk=new FileSystem(FileSystem.getPathPartOf(s), this);
                s=FileSystem.getFileNameOf(s);
            }
            defaultSkin=Skin.getSkin(s, fsSk, this);
            actions[ACTION_REPORTS].setEnabled(true);
            //actions[ACTION_AUDIO].setEnabled(options.get(MEDIA_SYSTEM)!=null);
            actions[ACTION_AUDIO].setEnabled(true);
        }
        catch(Exception ex){
            System.err.println("Error creating skin \""+s+"\":\n"+ex);
        }
    }
    
    /**
     * Creates and initializes the members {@link timer}, {@link delayedTimer} and
     * {@link delayedAction}
     */
00489     protected void initTimers(){
        timer=new Timer(1000, this);
        delayedTimer=new Timer(1000, this);
        delayedTimer.setRepeats(false);
        delayedAction=null;
    }
    
    /**
     * If open, closes the help dialog window.
     */
00499     public void closeHelpWindow(){
        if(skin!=null){
            if(skin.currentHelpWindow!=null)
                skin.currentHelpWindow.setVisible(false);
            if(skin.currentAboutWindow!=null)
                skin.currentAboutWindow.setVisible(false);
        }
    }
    
    /**
     * Creates and initializes the {@link messages} member.
     * @return The <CODE>messages</CODE> member.
     */
00512     protected Messages setMessages(){
        messages=Messages.getMessages(options, DEFAULT_BUNDLE);
        messages.addBundle(COMMON_SETTINGS);
        setLocale(messages.getLocale());
        Locale.setDefault(messages.getLocale());
        setActionsText();
        if(skin!=null){
            skin.setLocale(messages.getLocale());
        }
        return messages;
    }
    
    public Component getTopComponent(){
        if(skin!=null)
            return skin;
        return this;
    }
    
    public Skin getSkin(){
        return skin;
    }
    
    /**
     *
     * @param newSkin
     */
00538     public void setSkin(Skin newSkin){
        if(newSkin==null)
            newSkin=defaultSkin;
        
        if(newSkin!=null && !newSkin.equals(skin)){
            Container top=null;
            Object [] currentSkinSettings=null;
            
            if(skin!=null){
                currentSkinSettings=skin.getCurrentSettings();
                skin.detach();
                top=skin.getParent();
                top.remove(skin);
            }
            
            newSkin.attach(this);
            skin=newSkin;
            
            if(top!=null){
                RootPaneContainer rpc=null;
                while(top!=null && rpc==null){
                    if(top instanceof RootPaneContainer)
                        rpc=(RootPaneContainer)top;
                    else
                        top=top.getParent();
                }
                
                if(rpc!=null){
                    addTo(rpc, currentConstraints);
                    //top.invalidate();
                    top.validate();
                    top.repaint();
                }
            }
            
            if(currentSkinSettings!=null && skin!=null)
                skin.setCurrentSettings(currentSkinSettings);
        }
    }
    
    public void addTo(RootPaneContainer cont, Object constraints){
        currentConstraints=constraints;
        if(constraints==null){
            cont.getContentPane().add(getTopComponent());
        }
        else{
            cont.getContentPane().add(getTopComponent(), constraints);
        }
    }
    
    protected FileSystem createFileSystem(){
        return new FileSystem(this);
    }
    
    protected void setProject(JClicProject p) {
        if(project!=null){
            if(project!=p)
                project.end();
            removeActivity();
        }
        project=(p!=null ? p : new JClicProject(this, createFileSystem(), null));
        project.realize(eventSounds, this);
        if(project.skin!=null)
            defaultSkin=project.skin;
    }
    
    public boolean load(String fullPath, String sequence){
        load(fullPath, sequence, null, null);
        return true;
    }
    
    public void load(final String sFullPath, final String sSequence,
    final String sActivity, final ActivityBagElement sAbe){
        
        if(worker!=null){
            return;
        }
        
        worker=new SwingWorker(){
            Activity.Panel actp;
            Exception exception=null;
            Player thisPlayer=Player.this;
            
            public Object construct(){
                
                if(skin!=null)
                    skin.startAnimation();
                
                setWaitCursor(true);
                
                String fullPath=Clic3.pacNameToLowerCase(sFullPath);
                String sequence=Clic3.pacNameToLowerCase(sSequence);
                Activity act=null;
                String activityName=sActivity;
                ActivityBagElement abe=sAbe;
                FileSystem fileSystem=project.getFileSystem();
                
                try{
                    // Step 1: load or create project and set a valid value for "sequence"
                    if(fullPath!=null){
                        setSystemMessage(messages.get("msg_loading_project"),
                        FileSystem.getFileNameOf(fullPath));
                        if(sequence==null)
                            sequence="0";
                        
                        // Check fileSystem and projectName
                        if(fileSystem!=null){
                            fullPath=fileSystem.getUrl(fullPath);
                            if(fullPath.startsWith("file://"))
                                fullPath=fullPath.substring(7);
                        }
                        String projectName=null;
                        if(fullPath.endsWith(".jclic.zip")){
                            fileSystem=FileSystem.createFileSystem(fullPath, thisPlayer);
                            String[] projects=((ZipFileSystem)fileSystem).getEntries(".jclic");
                            if(projects==null)
                                throw new Exception("File "+fullPath+" does not contain any jclic project");
                            projectName=projects[0];
                        }
                        else{
                            fileSystem=new FileSystem(FileSystem.getPathPartOf(fullPath), thisPlayer);
                            projectName=FileSystem.getFileNameOf(fullPath);
                        }
                        
                        // Set project
                        if(projectName.endsWith(".jclic")){
                            org.jdom.Document doc=fileSystem.getXMLDocument(projectName);
                            setProject(JClicProject.getJClicProject(doc.getRootElement(),
                            thisPlayer, fileSystem, fullPath));
                            if(reporter!=null)
                                reporter.newSession(project, thisPlayer, messages);
                        }
                        else{
                            sequence=projectName;
                            setProject(new JClicProject(thisPlayer, fileSystem, fullPath));
                        }
                    }
                    
                    // Step 2: load ActivitySequenceElement ase
                    if(sequence!=null){
                        String seqName=FileSystem.stdFn(sequence);
                        setSystemMessage(messages.get("msg_loading_project"), FileSystem.getFileNameOf(seqName));
                        
                        navButtonsDisabled=false;
                        ActivitySequenceElement ase=project.activitySequence.getElementByTag(seqName, true);
                        
                        // if sequence does no exists, get existing sequence by number
                        if(ase==null){
                            int i=StrUtils.getAbsIntValueOf(seqName);
                            if(i>=0)
                                ase=project.activitySequence.getElement(i, true);
                        }
                        
                        // at this point, if ase==null the sequence was not found in project.
                        // try load new sequence (only with Clic3 files)
                        if(ase==null){
                            boolean firstPac=(project.activitySequence.getSize()==0);
                            boolean isPcc=seqName.endsWith(".pcc");
                            boolean isPac=seqName.endsWith(".pac");
                            if(isPcc || isPac){
                                if(isPcc){
                                    String path=fileSystem.root+seqName;
                                    fileSystem=FileSystem.createFileSystem(path, thisPlayer);
                                    if(firstPac){
                                        project.setFileSystem(fileSystem);
                                        project.setFullPath(path);
                                    }
                                    else
                                        setProject(new JClicProject(thisPlayer, fileSystem, path));
                                    firstPac=true;
                                    Clic3.readPccFile(project);
                                    ase=project.activitySequence.getCurrentAct();
                                }
                                else if(isPac){
                                    Clic3.addPacToSequence(project, seqName);
                                    ase=project.activitySequence.getElementByTag(seqName, true);
                                }
                                
                                if(firstPac){
                                    project.setName(seqName);
                                    if(reporter!=null)
                                        reporter.newSession(project, thisPlayer, messages);
                                }
                            }
                        }
                        
                        if(ase!=null){
                            if(reporter!=null)
                                reporter.newSequence(ase);
                            activityName=ase.getActivityName();
                        }
                    }
                    
                    // step 3: load ActivityBagElement abe
                    if(activityName!=null){
                        String actName=FileSystem.stdFn(activityName);
                        abe=project.activityBag.getElement(actName);
                    }
                    
                    // step 4: load Activity act
                    if(abe!=null){
                        setSystemMessage(messages.get("msg_loading_activity"), abe.getName());
                        act=Activity.getActivity(abe.getData(), project);
                    }
                    
                    // step 5: Load activity
                    if(act!=null){
                        setSystemMessage(null, messages.get("msg_preparing_media"));
                        if(project.settings.eventSounds!=null)
                            act.eventSounds.setParent(project.settings.eventSounds);
                        project.mediaBag.waitForAllImages();
                        act.prepareMedia(thisPlayer);
                        activeMediaBag.realizeAll();
                        project.activitySequence.checkCurrentActivity(abe.getName());
                        setSystemMessage(null, messages.get("msg_initializing"));
                        actp=act.getActivityPanel(thisPlayer);
                        actp.buildVisualComponents();
                    }
                }
                catch(Exception ex){
                    exception=ex;
                    if(project==null)
                        setProject(null);
                    act=null;
                    actp=null;
                }
                return actp;
            }
            
            public void finished(){
                
                setWaitCursor(false);
                
                if(actPanel!=null){
                    actPanel.end();
                    remove(actPanel);
                    actPanel=null;
                    setCounterValue(TIME_COUNTER, 0);
                }
                
                if(actp!=null && worker!=null){
                    // moved to thread
                    setBackgroundSettings(actp.getActivity());
                    add(actPanel=actp);
                    actPanel.setCursor(null);
                    splashImg=null;
                    
                    // set skin
                    if(skin!=null)
                        skin.resetAllCounters(false);
                    
                    if(actp.skin!=null)
                        setSkin(actp.skin);
                    else if(project.skin!=null)
                        setSkin(project.skin);
                    else
                        setSkin(defaultSkin);
                    
                    if(skin!=null){
                        boolean hasReturn=(history.storedElementsCount()>0);
                        int navBtnFlag
                        = navButtonsAlways ? ActivitySequenceElement.NAV_BOTH
                        : navButtonsDisabled ? ActivitySequenceElement.NAV_NONE
                        : project.activitySequence.getNavButtonsFlag();
                        
                        if(actions!=null){
                            actions[ACTION_NEXT].setEnabled((navBtnFlag & ActivitySequenceElement.NAV_FWD)!=0
                            && project.activitySequence.hasNextAct(hasReturn));
                            actions[ACTION_PREV].setEnabled((navBtnFlag & ActivitySequenceElement.NAV_BACK)!=0
                            && project.activitySequence.hasPrevAct(hasReturn));
                            actions[ACTION_RETURN].setEnabled(history.storedElementsCount()>0);
                            actions[ACTION_HELP].setEnabled(actp.getActivity().helpWindowAllowed());
                            actions[ACTION_RESET].setEnabled(actp.getActivity().canReinit());
                            actions[ACTION_INFO].setEnabled(actp.getActivity().hasInfo());
                        }
                    }
                    // place activity on screen
                    setSystemMessage(messages.get("msg_ready"), null);
                    initActivity();
                }
                else if(exception!=null){
                    String sType=null;
                    Vector v=new Vector();
                    if(sFullPath!=null){
                        v.add(sFullPath);
                        sType="msg_error_loading_project";
                    }
                    if(sSequence!=null){
                        v.add(sSequence);
                        if(sType==null)
                            sType="msg_error_loading_sequence";
                    }
                    if(sActivity!=null){
                        v.add(sActivity);
                        if(sType==null)
                            sType="msg_error_loading_activity";
                    }
                    if(sAbe!=null){
                        v.add(sAbe.getName());
                        if(sType==null)
                            sType="msg_error_loading_activity";
                    }
                    if(sType==null)
                        sType=Messages.ERROR;
                    
                    setSystemMessage(messages.get(sType), null);
                    messages.showErrorWarning(thisPlayer, "err_reading_data", v, exception, null);
                    
                    validate();
                }
                else{
                    setSystemMessage(messages.get("msg_ready"), null);
                }
                
                // unlock events
                setWindowTitle();
                worker=null;
                if(skin!=null){
                    skin.stopAnimation();
                    skin.setEnabled(true);
                }
                setEnabled(true);
            }
        };
        
        // Main thread, after SwingWorker was build:
        forceFinishActivity();
        if(skin!=null)
            skin.setEnabled(false);
        setEnabled(false);
        worker.start();
    }
    
    public void forceFinishActivity(){
        if(timer!=null){
            timer.stop();
            delayedTimer.stop();
            if(actPanel!=null){
                closeHelpWindow();
                actPanel.forceFinishActivity();
                stopMedia();
                activeMediaBag.removeAll();
                if(Runtime.getRuntime().freeMemory()<0x100000L){
                    if(trace)
                        System.out.println(">>> LOW MEMORY! cleaning...");
                    project.mediaBag.clearData();
                    System.runFinalization();
                    System.gc();
                }
            }
            setCursor(null);
        }
    }
    
    public void removeActivity(){
        forceFinishActivity();
        if(actPanel!=null){
            actPanel.end();
            remove(actPanel);
            setMsg(null);
            setBackgroundSettings(null);
            actPanel=null;
        }
    }
    
    public void initActivity(){
        
        setWaitCursor(true);
        setCursor(null);
        timer.stop();
        delayedTimer.stop();
        setCounterValue(TIME_COUNTER, 0);
        stopMedia();
        try{
            if(actPanel!=null){
                actPanel.initActivity();
                timer.start();
                if(!actPanel.getActivity().mustPauseSequence())
                    startAutoPassTimer();
                setSystemMessage(messages.get("msg_activity_running"), null);
            }
            if(skin!=null)
                skin.setMem(Runtime.getRuntime().freeMemory());
        } catch(Exception ex){
            messages.showErrorWarning(this, "msg_error_starting_activity", ex);
            setSystemMessage(messages.get("ERROR"), null);
        } finally{
            setWaitCursor(false);
            validate();
            repaint();//
        }
    }
    
00931     public void startActivity(Activity.Panel ap){
        setWaitCursor(true);
        try{
            ap.startActivity();
        }
        catch(Exception ex){
            messages.showErrorWarning(this, "msg_error_starting_activity", ex);
            setSystemMessage(messages.get("ERROR"), null);
        }
        finally{
            setWaitCursor(false);
        }
    }
    
    public void doLayout(){
        if(trace)
            System.out.println(">>> layout!");
        if(actPanel!=null){
            BoxBase.resetAllFonts();
            Rectangle bounds=getBounds();
            Rectangle proposedRect=new Rectangle(AC_MARGIN, AC_MARGIN,
            bounds.width-2*AC_MARGIN, bounds.height-2*AC_MARGIN);
            if(actPanel.bgImage!=null && !actPanel.getActivity().tiledBgImg){
                bgImageOrigin.x=(getWidth()-actPanel.bgImage.getWidth(this))/2;
                bgImageOrigin.y=(getHeight()-actPanel.bgImage.getHeight(this))/2;
                if(actPanel.getActivity().absolutePositioned){
                    proposedRect.x=bgImageOrigin.x;
                    proposedRect.y=bgImageOrigin.y;
                    proposedRect.width-=(bgImageOrigin.x-AC_MARGIN);
                    proposedRect.height-=(bgImageOrigin.y-AC_MARGIN);
                    proposedRect.width=Math.min(proposedRect.width, bounds.width);
                    proposedRect.height=Math.min(proposedRect.height, bounds.height);
                }
            }
            actPanel.fitTo(proposedRect, bounds);
        }
    }
    
    public void paintComponent(Graphics g){
        Graphics2D g2=(Graphics2D)g;
        
        if(splashImg!=null){
            int x, y, imgW, imgH;
            g2.setColor(BG_COLOR);
            g2.fill(g2.getClip());
            imgW=splashImg.getWidth(this);
            imgH=splashImg.getHeight(this);
            x=(getBounds().width-imgW)/2;
            y=(getBounds().height-imgH)/2;
            g2.drawImage(splashImg, x, y, this);
            return;
        }
        
        Rectangle rBounds=new Rectangle(0, 0, getWidth(), getHeight());
        
        if(actPanel==null || actPanel.getActivity().bgGradient==null ||
        actPanel.getActivity().bgGradient.hasTransparency())
            super.paintComponent(g);
        
        if(actPanel!=null && (actPanel.getActivity().bgGradient!=null || actPanel.bgImage!=null)){
            RenderingHints rh=g2.getRenderingHints();
            g2.setRenderingHints(DEFAULT_RENDERING_HINTS);
            
            if(actPanel.getActivity().bgGradient!=null)
                actPanel.getActivity().bgGradient.paint(g2, rBounds);
            
            if(actPanel.bgImage!=null){
                Rectangle r=new Rectangle(0, 0, actPanel.bgImage.getWidth(this),
                actPanel.bgImage.getHeight(this));
                Rectangle gBounds=g2.getClipBounds();
                
                if(!actPanel.getActivity().tiledBgImg){
                    r.setLocation(bgImageOrigin);
                    if(r.intersects(gBounds)){
                        g2.drawImage(actPanel.bgImage, bgImageOrigin.x, bgImageOrigin.y, this);
                    }
                }
                else{
                    Utils.tileImage(g2, actPanel.bgImage, rBounds, r, this);
                }
            }
            g2.setRenderingHints(rh);
        }
    }
    
    // Methods inherited from interface ActionListener
    public void actionPerformed(ActionEvent e){
        String ac=null;
        if(timer!=null && e.getSource().equals(timer)){
            incCounterValue(TIME_COUNTER);
            if(actPanel!=null && actPanel.getActivity().maxTime>0 &&
            actPanel.isPlaying() &&
            counterVal[TIME_COUNTER]>=actPanel.getActivity().maxTime){
                actPanel.finishActivity(false);
            }
            return;
        }
        
        if(delayedTimer!=null && e.getSource().equals(delayedTimer)){
            delayedTimer.stop();
            if(delayedAction!=null){
                delayedAction.actionPerformed(null);
            }
        }
        
        if(ac==null && (ac=e.getActionCommand())==null)
            return;
        delayedAction=null;
        
        processActionEvent(ac);
    }
    
    protected int getNumActions(){
        return NUM_ACTIONS;
    }
    
    protected void buildActions(){
        
        actions=new Action[getNumActions()];
        
        actions[ACTION_NEXT]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                history.processJump(project.activitySequence.getJump(false, reporter), false);
            }
        };
        
        actions[ACTION_PREV]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                history.processJump(project.activitySequence.getJump(true, reporter), false);
            }
        };
        
        actions[ACTION_RETURN]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                history.pop();
            }
        };
        
        actions[ACTION_RESET]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                if(actPanel!=null && actPanel.getActivity().canReinit())
                    initActivity();
            }
        };
        
        actions[ACTION_HELP]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                if(actPanel!=null)
                    actPanel.showHelp();
            }
        };
        
        actions[ACTION_INFO]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                if(actPanel!=null && actPanel.getActivity().hasInfo()){
                    if(actPanel.getActivity().infoUrl!=null){
                        displayUrl(actPanel.getActivity().infoUrl, true);
                    }
                    else if(actPanel.getActivity().infoCmd!=null){
                        runCmd(actPanel.getActivity().infoCmd);
                    }
                }
            }
        };
        
        actions[ACTION_REPORTS]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                showAbout(true);
            }
        };
        
        actions[ACTION_AUDIO]=new AbstractAction(){
            public void actionPerformed(ActionEvent ev){
                Object vBack=getValue(AbstractAction.DEFAULT);
                audioEnabled=!audioEnabled;
                Object vNew=audioEnabled ? Boolean.TRUE : Boolean.FALSE;
                if(!audioEnabled){
                    stopMedia();
                    EventSounds.globalEnabled=false;
                }
                else{
                    EventSounds.globalEnabled=options.getBoolean(SYSTEM_SOUNDS, true);
                }
                putValue(AbstractAction.DEFAULT, vNew);
                if(changeSupport!=null){
                    PropertyChangeEvent evt=new PropertyChangeEvent(this, "selected", vBack, vNew);
                    changeSupport.firePropertyChange(evt);
                }
            }
        };
        actions[ACTION_AUDIO].putValue(AbstractAction.DEFAULT, audioEnabled ? Boolean.TRUE : Boolean.FALSE);
        
        for(int i=0; i<DYNAMIC_ACTIONS.length; i++){
            actions[DYNAMIC_ACTIONS[i]].setEnabled(false);
        }
        actions[ACTION_AUDIO].setEnabled(true);
    }
    
    protected void setActionsText(){
        if(actions!=null){
            for(int i=0; i<actions.length; i++){
                if(actions[i]!=null){
                    String s=messages.get("action_"+getActionName(i)+"_caption");
                    if(!s.equals(actions[i].getValue(Action.NAME)))
                        actions[i].putValue(Action.NAME, s);
                    s=messages.get("action_"+getActionName(i)+"_tooltip");
                    if(!s.equals(actions[i].getValue(Action.SHORT_DESCRIPTION)))
                        actions[i].putValue(Action.SHORT_DESCRIPTION, s);
                    s=messages.get("action_"+getActionName(i)+"_keys");
                    if(s!=null && s.length()==2){
                        actions[i].putValue(Action.MNEMONIC_KEY, new Integer(s.charAt(0)));
                        char c=s.charAt(1);
                        int kk=-1;
                        if(c=='*'){
                            switch(i){
                                case ACTION_NEXT:
                                    kk=KeyEvent.VK_RIGHT;
                                    break;
                                    
                                case ACTION_PREV:
                                    kk=KeyEvent.VK_LEFT;
                                    break;
                                    
                                case ACTION_RETURN:
                                    kk=KeyEvent.VK_UP;
                                    break;
                                    
                                case ACTION_RESET:
                                    kk=KeyEvent.VK_ENTER;
                                    break;
                                    
                                default:
                                    break;
                            }
                        }
                        else
                            kk=(int)c;
                        
                        if(kk>=0)
                            actions[i].putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(kk, KeyEvent.CTRL_MASK));
                    }
                    Icon icon=getActionIcon(i);
                    if(icon!=null && !icon.equals(actions[i].getValue(Action.SMALL_ICON)))
                        actions[i].putValue(Action.SMALL_ICON, icon);
                }
            }
        }
    }
    
    protected String getActionName(int actionId){
        if(actionId<0 || actionId>=ACTION_NAME.length)
            return null;
        return ACTION_NAME[actionId];
    }
    
    protected Icon getActionIcon(int actionId){
        if(actionId<0 || actionId>=ACTION_ICONS.length)
            return null;
        return ResourceManager.getImageIcon(ACTION_ICONS[actionId]);
    }
    
01192     public Action getAction(int id) {
        if(actions==null || id<0 || id>=actions.length)
            return null;
        return actions[id];
    }
    
    protected boolean processActionEvent(String ac){
        return !isEnabled();
    }
    
    protected void showAbout(boolean selectReportPane){
        if(skin!=null){
            AboutWindow aw=skin.buildAboutWindow();
            try{
                aw.buildAboutTab("JClic", getMsg("JCLIC_VERSION"), null, null, null, null, null);
                aw.buildStandardTab(aw.getHtmlSystemInfo(),
                "about_window_systemInfo",
                "about_window_lb_system", "icons/system_small.gif");
                if(project!=null){
                    StringBuffer sb=new StringBuffer(4096);
                    sb.append(project.settings.toHtmlString(messages));
                    if(actPanel!=null){
                        sb.append(Html.BR).append(actPanel.getActivity().toHtmlString(this));
                    }
                    aw.buildStandardTab(sb.substring(0),
                    "about_window_projectInfo",
                    "about_window_lb_project", "icons/info_small.gif");
                }
                if(reporter!=null){
                    aw.buildStandardTab(reporter.toHtmlString(messages),
                    "about_window_reportInfo",
                    "about_window_lb_report", "icons/report_small.gif");
                    if(selectReportPane)
                        aw.getTabbedPane().setSelectedIndex(3);
                }
                skin.showAboutWindow(aw);
                
            } catch(Exception ex){
                System.err.println("Error building about window!\n"+ex);
            }
        }
    }
    
    // Methods inherited from interface ActivityContainer
    public void playMedia(final MediaContent mediaContent, final ActiveBox mediaPlacement) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                String s=mediaContent.mediaFileName;
                JumpInfo ji=null;
                
                switch(mediaContent.mediaType){
                    case MediaContent.RUN_CLIC_PACKAGE:
                        ji=new JumpInfo(JumpInfo.JUMP, FileSystem.stdFn(s));
                        ji.projectPath=mediaContent.externalParam;
                        history.processJump(ji, true);
                        break;
                    case MediaContent.RUN_CLIC_ACTIVITY:
                        history.push();
                        if(!navButtonsAlways)
                            navButtonsDisabled=true;
                        load(null, null, s, null);
                        break;
                    case MediaContent.RETURN:
                        history.pop();
                        break;
                    case MediaContent.EXIT:
                        String exitUrl=mediaContent.mediaFileName;
                        if(exitUrl!=null)
                            exitUrl=project.getFileSystem().getUrl(exitUrl);
                        ji=new JumpInfo(JumpInfo.EXIT, exitUrl);
                        history.processJump(ji, false);
                        break;
                    case MediaContent.RUN_EXTERNAL:
                        if(mediaContent.mediaFileName!=null){
                            StringBuffer sb=new StringBuffer(mediaContent.mediaFileName);
                            if(mediaContent.externalParam!=null)
                                sb.append(" ").append(mediaContent.externalParam);
                            runCmd(sb.substring(0));
                        }
                        break;
                    case MediaContent.URL:
                        if(mediaContent.mediaFileName!=null){
                            displayUrl(mediaContent.mediaFileName, true);
                        }
                        break;
                    case MediaContent.PLAY_AUDIO:
                    case MediaContent.PLAY_MIDI:
                    case MediaContent.PLAY_VIDEO:
                    case MediaContent.RECORD_AUDIO:
                    case MediaContent.PLAY_RECORDED_AUDIO:
                        if(audioEnabled){
                            ActiveMediaPlayer amp=activeMediaBag.getActiveMediaPlayer(mediaContent, project.mediaBag, Player.this);
                            if(amp!=null){
                                amp.play(mediaPlacement);
                            }
                        }
                        break;
                    default:
                        break;
                }
                
            }
        });
    }
    
    protected void runCmd(String cmd){
        if(options.get(Options.APPLET)!=null){
            messages.showAlert(this, "msg_warn_no_exec_in_applets");
            return;
        }
        
        try{
            Runtime.getRuntime().exec(cmd, null, new File(project.getFileSystem().root));
        } catch(Exception ex){
            messages.showErrorWarning(this, "msg_error_executing_external", cmd, ex, null);
        }
    }
    
    public void stopMedia(){
        stopMedia(-1);
    }
    
01314     public void stopMedia(int level){
        activeMediaBag.stopAll(level);
    }
    
01318     public void activityFinished(boolean completedOk) {
        closeHelpWindow();
        if(completedOk){
            setCursor(getCustomCursor(OK_CURSOR));
            actPanel.setCursor(null);
        }
        setSystemMessage(messages.get("msg_activity_finished"), null);
        timer.stop();
        startAutoPassTimer();
    }
    
    public void startAutoPassTimer(){
        ActivitySequenceElement ase=project.activitySequence.getCurrentAct();
        if(ase!=null && ase.delay>0 && !delayedTimer.isRunning() && !navButtonsDisabled){
            delayedAction=actions[ACTION_NEXT];
            delayedTimer.setInitialDelay(ase.delay * 1000);
            delayedTimer.start();
        }
    }
    
    protected void setBackgroundSettings(Activity act){
        setBackground(act!=null ? act.bgColor : Color.lightGray);
        bgImageOrigin.setLocation(0, 0);
        repaint();
    }
    
    public void setMsg(ActiveBoxContent abc) {
        ActiveBox ab=null;
        if(skin!=null)
            ab=skin.getMsgBox();
        if(ab!=null){
            ab.clear();
            ab.setContent(abc==null ? ActiveBoxContent.getEmptyContent() : abc);
        }
    }
    
01354     public void playMsg() {
        if(skin!=null && skin.getMsgBox()!=null){
            skin.getMsgBox().playMedia(this);
        }
    }
    
01360     public void incCounterValue(int counterId){
        counterVal[counterId]++;
        Counter c=null;
        if(skin!=null && (c=skin.getCounter(counterId))!=null)
            c.setValue(counterVal[counterId]);
        if(counterId==ACTIONS_COUNTER && actPanel!=null
        && actPanel.getActivity().maxActions>0 && actPanel.isPlaying()
        && counterVal[ACTIONS_COUNTER]>=actPanel.getActivity().maxActions){
            actPanel.finishActivity(false);
        }
    }
    
01372     public void setCountDown(int counterId, int maxValue){
        Counter c=null;
        if(skin!=null && (c=skin.getCounter(counterId))!=null)
            c.setCountDown(maxValue);
    }
    
01378     public void setCounterValue(int counterId, int newValue) {
        counterVal[counterId]=newValue;
        Counter c=null;
        if(skin!=null && (c=skin.getCounter(counterId))!=null)
            c.setValue(newValue);
    }
    
01385     public int getCounterValue(int counterId) {
        return counterVal[counterId];
    }
    
01389     public void setCounterEnabled(int counterId, boolean bEnabled) {
        if(skin!=null){
            skin.enableCounter(counterId, bEnabled);
            setCountDown(counterId, 0);
        }
    }
    
    public Messages getMessages(){
        return (messages==null ? setMessages() : messages);
    }
    
    
01401     public void setWaitCursor(boolean state) {
        if(skin!=null){
            skin.setWaitCursor(state);
        }
    }
    
01407     public void setSystemMessage(String msg1, String msg2) {
        
        if(skin!=null)
            skin.setSystemMessage(msg1, msg2);
        
        if(trace)
            System.out.println("MSG "+(msg1==null ? "" : msg1 + " ")+(msg2==null ? "" : msg2));
    }
    
    public JComponent getComponent(){
        return this;
    }
    
    public ActiveMediaPlayer getActiveMediaPlayer(MediaContent mediaContent){
        if(activeMediaBag!=null && mediaContent!=null)
            return activeMediaBag.getActiveMediaPlayer(mediaContent, project.mediaBag, this);
        else
            return null;
    }
    
    /** Gets the custom cursor corresponding to the indicated type
     * @param type Type of cursor.
     * @return The requested cursor, or the default system cursor if not found.
     */
01431     public Cursor getCustomCursor(int type) {
        if(type>=0 && type<cursors.length)
            return cursors[type];
        else
            return null;
    }
    
01438     public void reportNewActivity(Activity act, int currentScore){
        ActivitySequenceElement ase=project.activitySequence.getCurrentAct();
        if(reporter!=null){
            if(ase.getTag()!=null && !ase.getTag().equals(reporter.getCurrentSequenceTag()))
                reporter.newSequence(ase);
            if(act.includeInReports)
                reporter.newActivity(act);
        }
        setCounterValue(ACTIONS_COUNTER, 0);
        setCounterValue(SCORE_COUNTER, 0);
    }
    
01450     public void reportNewAction(Activity act, String type, String source,
    String dest, boolean ok, int currentScore){
        if(reporter!=null && act.includeInReports && act.reportActions)
            reporter.newAction(type, source, dest, ok);
        
        if(currentScore>=0){
            incCounterValue(ACTIONS_COUNTER);
            setCounterValue(SCORE_COUNTER, currentScore);
        }
    }
    
01461     public void reportEndActivity(Activity act, boolean solved){
        if(reporter!=null && act.includeInReports)
            reporter.endActivity(counterVal[SCORE_COUNTER], counterVal[ACTIONS_COUNTER], solved);
    }
    
    public boolean showHelp(JComponent hlpComponent, String hlpMsg) {
        if(skin!=null){
            skin.showHelp(hlpComponent, hlpMsg);
            return true;
        }
        return false;
    }
    
    public InputStream getProgressInputStream(InputStream is, int expectedLength, String name){
        if(skin!=null && is!=null && !(is instanceof ByteArrayInputStream)){
            is=skin.getProgressInputStream(is, expectedLength, name);
        }
        return is;
    }
    
    public Options getOptions(){
        return options;
    }
    
    public PlayerHistory getHistory(){
        return history;
    }
    
    public void displayUrl(String url, boolean inFrame){
        if(url!=null){
            url=project.getFileSystem().getUrl(url);
            try{
                displayUrl(new URL(url), inFrame);
            } catch(Exception ex){
                System.err.println("Unable to invoque URL "+url+"\n"+ex);
            }
        }
    }
    
    public void displayUrl(URL url, boolean inFrame){
        if(url==null) return;
        Applet applet=options.getApplet();
        try{
            if(applet!=null){
                if(inFrame){
                    String frame=(String)options.get(INFO_URL_FRAME);
                    if(frame==null)
                        frame="_BLANK";
                    applet.getAppletContext().showDocument(url, frame);
                }
                else{
                    end();
                    applet.getAppletContext().showDocument(url);
                }
            }
            else{
                BrowserLauncher.openURL(url.toExternalForm());
            }
        }catch(Exception ex){
            System.err.println("Unable to invoque URL "+url+"\n"+ex);
        }
    }
    
    public void exit(){
        exit(null);
    }
    
    public void exit(String url){
        final String sUrl=(url==null ? options.getString(EXIT_URL) : url);
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                if(sUrl!=null){
                    displayUrl(sUrl, false);
                }
                if(options.getApplet()==null){
                    try{
                        end();
                        Frame fr=JOptionPane.getFrameForComponent(getTopComponent());
                        if(fr!=null)
                            fr.dispose();
                        else
                            System.exit(0);
                    } catch(Exception ex){
                        System.err.println("Unable to exit!\n"+ex);
                    }
                }
            }
        });
    }
    
    public void requestFocus(){
        if(actPanel!=null)
            actPanel.requestFocus();
    }
    
    public String getMsg(String key) {
        return messages.get(key);
    }
    
    public void doAutoStart() {
    }
    
01563     public boolean newInstanceRequest(final String param1, final String param2) {
        boolean result=false;
        if(param1!=null){
            SwingUtilities.invokeLater(new Runnable(){
                public void run(){
                    Frame frame=JOptionPane.getFrameForComponent(Player.this);
                    if(frame!=null)
                        frame.toFront();
                    load(param1, param2);
                }
            });
            result=true;;
        }
        return result;
    }
    
01579     public boolean windowCloseRequested() {
        return true;
    }
    
    public void setWindowTitle(String docTitle){
        Window w=Options.getWindowForComponent(this);
        if(w!=null){
            StringBuffer sb=new StringBuffer();
            String s=StrUtils.nullableString(docTitle);
            if(s!=null)
                sb.append(s).append(" - ");
            sb.append(appName);
            if(w instanceof Frame)
                ((Frame)w).setTitle(sb.substring(0));
            else if(w instanceof Dialog)
                ((Dialog)w).setTitle(sb.substring(0));
        }
    }
    
    public void setWindowTitle(){
        StringBuffer sb=new StringBuffer();
        String prjName=project==null ? null : StrUtils.nullableString(project.getPublicName());
        String actName=actPanel==null ? null : StrUtils.nullableString(actPanel.getActivity().getPublicName());
        if(actName!=null){
            sb.append(actName);
            if(prjName!=null)
                sb.append(" [");
        }
        if(prjName!=null){
            sb.append(prjName);
            if(actName!=null)
                sb.append("]");
        }
        setWindowTitle(sb.substring(0));
    }
}

Generated by  Doxygen 1.6.0   Back to index