/* * File : AuthorSingleFrame.java * Created : 16-sep-2002 10:01 * 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.*; import edu.xtec.jclic.boxes.*; import edu.xtec.jclic.clic3.Clic3; import edu.xtec.jclic.edit.*; import edu.xtec.jclic.fileSystem.*; import edu.xtec.jclic.media.*; import edu.xtec.jclic.misc.Utils; import edu.xtec.jclic.project.*; import edu.xtec.jclic.skins.AboutWindow; import edu.xtec.util.*; import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.*; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.17 */ public class AuthorSingleFrame extends JPanel implements ResourceBridge, TestPlayerContainer, RunnableComponent, Constants, ActionListener { protected Options options; protected Messages messages; protected JClicProject project; protected JFrame debugFrame=null; protected int recentFilesOffset; protected JMenuBar menuBar; protected JMenu fileMenu, recentFilesMenu, toolsMenu, helpMenu, editMenu, insertMenu, viewMenu; protected AuthorSettings settings; protected Player player; protected JTabbedPane tabbedPane; protected Action[] actions; protected Action[] projectActions; private edu.xtec.util.SwingWorker worker=null; //protected JInternalFrame mediaBagFrame, activityBagFrame, activitySequenceFrame, playerFrame; protected JDialog playerDlg; protected JClicProjectEditor projectEditor; protected EditorPanel mediaBagEditorPanel; //protected ActivityBagTreePanel activityBagTreePanel; protected EditorPanel activityBagEditorPanel; protected EditorPanel activitySequenceEditorPanel; protected EditorPanel projectSettingsEditorPanel; //protected boolean trace; protected ProgressDialog progressDialog; public static final String MESSAGES_BUNDLE="messages.AuthorMessages"; /** Creates a new instance of Author */ public AuthorSingleFrame(Options options) { this.options=options; setLayout(new BorderLayout()); init(); } protected final void init(){ //setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); settings=AuthorSettings.loadAuthorSettings(this); options.setLookAndFeel(); Utils.checkRenderingHints(options); CheckMediaSystem.check(options, false); setMessages(); buildActions(); setActionsText(); progressDialog=new ProgressDialog(this, options); //trace=options.getBoolean(TRACE); ActiveBox.compressImages=options.getBoolean(COMPRESS_IMAGES, true); createFrames(); } public void activate() { focusListener.focusGained(null); } // Methods inherited from ResourceBridge interface: public java.io.InputStream getProgressInputStream(java.io.InputStream is, int expectedLength, String name){ return progressDialog==null ? is : progressDialog.getProgressInputStream(is, expectedLength, name); } public edu.xtec.util.Options getOptions(){ return options; } public String getMsg(String key){ return messages.get(key); } public javax.swing.JComponent getComponent(){ return this; } // Methods inherited from interface RunnableComponent: public void addTo(javax.swing.RootPaneContainer cont, Object constraints){ cont.setContentPane(this); //cont.add(this, constraints); checkMenu(false); } public boolean start(String fullPath, String sequence){ boolean result=false; if(fullPath!=null) result=load(fullPath, sequence); return result; } public void stop(){ } public void end(){ } public Messages setMessages(){ messages=Messages.getMessages(options, DEFAULT_BUNDLE); messages.addBundle(COMMON_SETTINGS); messages.addBundle(ExtendedPlayer.MESSAGES_BUNDLE); messages.addBundle(MESSAGES_BUNDLE); setLocale(messages.getLocale()); return messages; } public boolean load(String fullPath, String sequence){ load(fullPath, sequence, null); return true; } public void load(final String sFullPath, final String sSequence, final String sActivity){ if(worker!=null){ return; } if(sFullPath!=null && project!=null){ if(project!=null) project.mediaBag.clearData(); if(player!=null){ player.activeMediaBag.removeAll(); } System.gc(); } worker=new edu.xtec.util.SwingWorker(){ ActivityBagElement abe=null; Exception exception=null; AuthorSingleFrame thisAuthor=AuthorSingleFrame.this; String fullPath=null; String sequence=null; String activityName=null; boolean imported=false; @Override public Object construct(){ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try{ fullPath=Clic3.pacNameToLowerCase(sFullPath); sequence=Clic3.pacNameToLowerCase(sSequence); activityName=sActivity; boolean prompted=false; //boolean exit=false; //while(!exit && !isCancelled()){ while(!isCancelled()){ String dn=fullPath != null ? fullPath : sequence!=null ? sequence : activityName; progressDialog.setText(messages.get("msg_loading")+" "+dn); FileSystem fileSystem = project==null ? createFileSystem() : project.getFileSystem(); // Step 1: load project if(fullPath!=null){ if(fileSystem!=null){ fullPath=fileSystem.getUrl(fullPath); if(fullPath.startsWith("file://")) fullPath=fullPath.substring(7); // Added 03-Feb-2011 // Remove trailing parameters of URLs else if(fullPath.indexOf('?')>0) fullPath=fullPath.substring(0, fullPath.indexOf('?')); // ---------- } if(sequence==null) sequence="0"; String projectName; if(fullPath.endsWith(".jclic.zip")){ fileSystem=FileSystem.createFileSystem(fullPath, thisAuthor); 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), thisAuthor); projectName=FileSystem.getFileNameOf(fullPath); } if(projectName.endsWith(".jclic")){ org.jdom.Document doc=fileSystem.getXMLDocument(projectName); System.gc(); setProject(JClicProject.getJClicProject(doc.getRootElement(), thisAuthor, fileSystem, fullPath)); } else{ sequence=projectName; setProject(new JClicProject(thisAuthor, fileSystem, fullPath)); } } // load sequence if(sequence!=null){ ActivitySequenceElement ase=null; String seqName=FileSystem.stdFn(sequence); // get existing sequence by name if(project!=null) ase=project.activitySequence.getElementByTag(seqName, true); // get existing sequence by number if(ase==null && project!=null){ int i=StrUtils.getAbsIntValueOf(seqName); if(i>=0) ase=project.activitySequence.getElement(i, true); } // load new sequence (only with Clic3 files) if(ase==null && project!=null){ boolean firstPac=(project.activitySequence.getSize()==0); boolean isPcc=seqName.endsWith(".pcc"); boolean isPac=seqName.endsWith(".pac"); if(isPcc || isPac){ imported=true; if(isPcc){ String path=fileSystem.root+seqName; fileSystem=FileSystem.createFileSystem(path, thisAuthor); if(firstPac){ project.setFileSystem(fileSystem); project.setFullPath(path); } else setProject(new JClicProject(thisAuthor, 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(ase==null) // throw new Exception("Unable to load sequence: "+seqName); if(ase!=null) activityName=ase.getActivityName(); } // load activity if(activityName!=null && project!=null){ String actName=FileSystem.stdFn(activityName); abe=project.activityBag.getElement(actName); } //if(abe==null) // throw new Exception("Unable to load activity: "+activityName); fullPath=null; sequence=null; activityName=null; if(project!=null) project.activitySequence.checkAllElements(); if(project!=null){ Map<String, String> hm=new HashMap<String, String>(); //project.activitySequence.listReferences(null, hm); project.activityBag.listReferences(SEQUENCE_OBJECT, hm); project.activityBag.listReferences(ACTIVITY_OBJECT, hm); project.activitySequence.listReferences(null, hm); java.util.Iterator it=hm.keySet().iterator(); while(it.hasNext() && !isCancelled()){ String s=(String)it.next(); if(SEQUENCE_OBJECT.equals(hm.get(s))){ if(project.activitySequence.getElementByTag(s, false)==null){ sequence=Clic3.pacNameToLowerCase(s); break; } } else if(!project.activityBag.activityExists(s)){ activityName=s; break; } } } if(fullPath==null && sequence==null && activityName==null){ //exit=true; break; } else{ if(!prompted){ prompted=(messages.showQuestionDlg(progressDialog, "msg_prompt_loadReferences", null, "yn")==Messages.YES); if(!prompted){ //exit=true; break; } } abe=null; } } if(project!=null && !isCancelled()) project.mediaBag.waitForAllImages(); //System.gc(); } catch(Exception ex){ exception=ex; System.err.println("Exception:"+ex); //if(project==null) //setProject(new JClicProject(thisAuthor, createFileSystem(), null)); } attachProject(); if(imported && projectEditor!=null) projectEditor.setModified(true); return abe; } @Override public void finished(){ progressDialog.setVisible(false); setCursor(null); if(/*abe==null || */ worker==null || exception!=null){ //String sType=null; List<Object> v=new ArrayList<Object>(); if(fullPath!=null){ v.add(fullPath); //sType="msg_error_loading_project"; } if(sequence!=null){ v.add(sequence); //if(sType==null) // sType="msg_error_loading_sequence"; } if(activityName!=null){ v.add(activityName); //if(sType==null) // sType="msg_error_loading_activity"; } //if(sType==null) // sType=Messages.ERROR; messages.showErrorWarning(thisAuthor, "err_reading_data", v, exception, null); } // unlock events worker=null; setEnabled(true); } }; // finalization process setCursor(null); // lock events setEnabled(false); // Done by progressDialog! //worker.start(); progressDialog.start("WORKING", "msg_loading_project", worker, true, true, false); } protected void setProject(JClicProject p) { if(project!=null) project.end(); project=p; setFrameTitle(null); checkActions(); } protected void setFrameTitle(String s){ java.awt.Frame fr=JOptionPane.getFrameForComponent(AuthorSingleFrame.this); if(fr!=null){ StringBuilder sb=new StringBuilder("JClic author"); if(s!=null && s.length()>0) sb.append(" - ").append(s); else if(project != null) sb.append(" - ").append(project.getName()); fr.setTitle(sb.substring(0)); } } protected void checkActions(){ if(projectActions!=null) for(int i=0; i<projectActions.length; i++) projectActions[i].setEnabled(project!=null); } protected FileSystem createFileSystem(){ return settings.fileSystem; } protected void createMenu(){ Editor.createBasicActions(options); MediaBagEditor.createActions(options); ActivityBagEditor.createBasicActions(options); ActivitySequenceEditor.createActions(options); 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_NEW_PROJECT))); fileMenu.addSeparator(); fileMenu.add(new KJMenuItem(getAction(ACTION_OPEN_FILE))); fileMenu.add(new KJMenuItem(getAction(ACTION_OPEN_URL))); fileMenu.addSeparator(); fileMenu.add(new KJMenuItem(getAction(ACTION_SAVE_FILE))); fileMenu.add(new KJMenuItem(getAction(ACTION_SAVE_FILE_AS))); menuBar.add(fileMenu); editMenu=new JMenu(messages.get("m_Edit")); editMenu.setMnemonic(messages.get("m_Edit_Mnemonic").charAt(0)); editMenu.add(new KJMenuItem(Editor.cutAction)); editMenu.add(new KJMenuItem(Editor.copyAction)); editMenu.add(new KJMenuItem(Editor.pasteAction)); editMenu.add(new KJMenuItem(Editor.deleteAction)); editMenu.addSeparator(); editMenu.add(ActivityBagEditor.copyActivityAttributesAction); editMenu.addSeparator(); editMenu.add(new KJMenuItem(Editor.moveUpAction)); editMenu.add(new KJMenuItem(Editor.moveDownAction)); menuBar.add(editMenu); insertMenu=new JMenu(messages.get("m_Insert")); insertMenu.setMnemonic(messages.get("m_Insert_Mnemonic").charAt(0)); insertMenu.add(MediaBagEditor.newMediaBagElementAction); insertMenu.add(ActivityBagEditor.newActivityBagElementAction); insertMenu.add(ActivitySequenceEditor.newActivitySequenceElementAction); insertMenu.addSeparator(); insertMenu.add(new KJMenuItem(getAction(ACTION_IMPORT_ACTIVITIES))); menuBar.add(insertMenu); toolsMenu=new JMenu(messages.get("m_Tools")); toolsMenu.setMnemonic(messages.get("m_Tools_Mnemonic").charAt(0)); toolsMenu.add(new KJMenuItem(getAction(ACTION_SETTINGS))); toolsMenu.addSeparator(); toolsMenu.add(new KJMenuItem(getAction(ACTION_DOCTREE))); toolsMenu.addSeparator(); toolsMenu.add(new KJMenuItem(getAction(ACTION_EXPORT_HTML5))); toolsMenu.addSeparator(); toolsMenu.add(new KJMenuItem(getAction(ACTION_CREATE_HTML))); toolsMenu.add(new KJMenuItem(getAction(ACTION_CREATE_INSTALLER))); menuBar.add(toolsMenu); viewMenu=new JMenu(messages.get("m_View")); viewMenu.setMnemonic(messages.get("m_View_Mnemonic").charAt(0)); viewMenu.add(new KJMenuItem(getAction(ACTION_EDIT_PROJECT))); viewMenu.add(new KJMenuItem(getAction(ACTION_EDIT_MEDIA))); viewMenu.add(new KJMenuItem(getAction(ACTION_EDIT_ACTIVITIES))); viewMenu.add(new KJMenuItem(getAction(ACTION_EDIT_SEQ))); viewMenu.addSeparator(); viewMenu.add(ActivityBagElementEditor.testActivityAction); viewMenu.add(MediaBagElementEditor.testMediaBagElementAction); menuBar.add(viewMenu); 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(); } 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=0, ACTION_OPEN_URL=1, ACTION_SAVE_FILE=2, ACTION_SAVE_FILE_AS=3, ACTION_EXIT=4, ACTION_SETTINGS=5, ACTION_DOCTREE=6, ACTION_ABOUT=7, ACTION_NEW_PROJECT=8, ACTION_EDIT_PROJECT=9, ACTION_EDIT_MEDIA=10, ACTION_EDIT_ACTIVITIES=11, ACTION_EDIT_SEQ=12, ACTION_CREATE_HTML=13, ACTION_CREATE_INSTALLER=14, ACTION_IMPORT_ACTIVITIES=15, ACTION_EXPORT_HTML5=16, AUTHOR_NUM_ACTIONS=17; public static final String[] ACTION_NAMES={ "openFile", "openUrl", "saveFile", "saveFileAs", "exit", "settings", "docTree", "helpAbout", "newProject", "editProject", "editMedia", "editActivities", "editSeq", "createHTML", "createInstaller", "importActivities", "exportProject" }; public static final String[] ACTION_ICONS={ "icons/file_open.gif", "icons/world.gif", "icons/file_save.gif", "icons/file_save_as.gif", "icons/exit_small.gif", "icons/settings.gif", "icons/tree.gif", "icons/help.gif", "icons/project_new.gif", "icons/project_settings.gif", "icons/media_bag.gif", "icons/miniclic.png", "icons/sequence.gif", "icons/html_doc.gif", "icons/installer.gif", "icons/import_act.png", "icons/html_doc.gif" }; protected int getNumActions(){ return AUTHOR_NUM_ACTIONS; } protected void buildActions(){ actions=new Action[getNumActions()]; actions[ACTION_OPEN_FILE]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(checkSaveChanges()){ int[] filters={Utils.ALL_CLIC_FF, Utils.INSTALL_FF, Utils.ALL_JCLIC_FF}; FileSystem fs=settings.fileSystem; String result=fs.chooseFile(null, false, filters, options, null, AuthorSingleFrame.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){ if(checkSaveChanges()){ String url=messages.showInputDlg(AuthorSingleFrame.this, "URL_OPEN", "URL", "http://", "URL_OPEN", false); if(url!=null){ url=url.trim(); if(url.startsWith("http://http://")) url=url.substring(7); if(url.length()>0 && !url.equals("http://")){ if(load(url, null)) addRecentFile(url); } } } } }; actions[ACTION_SAVE_FILE]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ saveFile(false); } }; actions[ACTION_SAVE_FILE_AS]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ saveFile(true); } }; 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 currentMediaSystem=settings.mediaSystem; if(settings.edit(AuthorSingleFrame.this)){ settings.save(); options.syncProperties(settings.getProperties(), false); 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(!currentMediaSystem.equals(settings.mediaSystem)){ options.put(MEDIA_SYSTEM, settings.mediaSystem); edu.xtec.jclic.media.CheckMediaSystem.check(options, false); } } } }; actions[ACTION_DOCTREE]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(project!=null){ org.jdom.Element e=JDomTreePanel.editElement(AuthorSingleFrame.this, project.getJDomElement(), AuthorSingleFrame.this, project.getFileSystem(), project.getName(), "edit_docTree_title"); if(e!=null){ try{ //JClicProject prj=JClicProject.getJClicProject(e, Author.this, project.getFileSystem(), project.getFullPath()); String fullPath=project.getFullPath(); JClicProject prj=JClicProject.getJClicProject(e, AuthorSingleFrame.this, FileSystem.createFileSystem(fullPath, AuthorSingleFrame.this), fullPath); if(prj!=null){ setProject(prj); attachProject(); projectEditor.setModified(true); } } catch(Exception ex){ messages.showErrorWarning(AuthorSingleFrame.this, "edit_tree_badFormat", ex); } } } } }; actions[ACTION_IMPORT_ACTIVITIES]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(project!=null){ int[] filters={Utils.ALL_JCLIC_FF}; FileSystem fs=settings.fileSystem; String result=fs.chooseFile(null, false, filters, options, "import_selectProject", AuthorSingleFrame.this, false); if(result!=null){ String fullPath=fs.getFullFileNamePath(result); if((new File(project.getFileSystem().getFullRoot())).equals(new File(fullPath))){ messages.showAlert(AuthorSingleFrame.this, "import_warn_samefile"); } else{ doImportActivities(fullPath); } } } } }; actions[ACTION_ABOUT]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ AboutWindow aw=new AboutWindow(AuthorSingleFrame.this, AuthorSingleFrame.this, new Dimension(500, 400)); try{ aw.buildAboutTab("JClic author", getMsg("AUTHOR_VERSION"), "logo_author_small.png", null, null, null, null); aw.buildStandardTab(aw.getHtmlSystemInfo(), "about_window_systemInfo", "about_window_lb_system", "icons/system_small.gif"); aw.setVisible(true); } catch(Exception ex){ System.err.println("Error building about window: "+ex); } } }; actions[ACTION_NEW_PROJECT]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(checkSaveChanges()){ JClicProject prj=NewProjectDlg.prompt(AuthorSingleFrame.this, AuthorSingleFrame.this, createFileSystem()); if(prj!=null){ setProject(prj); attachProject(); } } } }; actions[ACTION_EXPORT_HTML5]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(checkSaveChanges()){ String inputPath=project.getFileSystem().getFullFileNamePath(""); String[] folders=ExportToJSDlg.prompt(AuthorSingleFrame.this, AuthorSingleFrame.this, inputPath, AuthorSingleFrame.this.settings.rootExportPath, AuthorSingleFrame.this.settings.rootScormPath); if(folders!=null){ boolean exportAll = folders[2].equals("true"); String scormFile = folders[3]; if(!exportAll) inputPath = project.getFileSystem().getFullRoot(); String mainFile = project.getFileSystem().getRelativeFileNamePath(project.getFullPath()); if(mainFile.endsWith(".zip")) mainFile = mainFile.substring(0, mainFile.length()-4); ExportTaskDlg.doTask(AuthorSingleFrame.this, settings, AuthorSingleFrame.this, inputPath, folders[0], mainFile, project, exportAll, scormFile); } } } }; actions[ACTION_EDIT_PROJECT]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(tabbedPane!=null) tabbedPane.setSelectedComponent(projectSettingsEditorPanel); } }; actions[ACTION_EDIT_MEDIA]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(tabbedPane!=null) tabbedPane.setSelectedComponent(mediaBagEditorPanel); } }; actions[ACTION_EDIT_ACTIVITIES]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(tabbedPane!=null) tabbedPane.setSelectedComponent(activityBagEditorPanel); } }; actions[ACTION_EDIT_SEQ]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(tabbedPane!=null) tabbedPane.setSelectedComponent(activitySequenceEditorPanel); } }; actions[ACTION_CREATE_HTML]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(checkSaveChanges()) AppletHtmlCreator.createHtml(project, settings, AuthorSingleFrame.this); } }; actions[ACTION_CREATE_INSTALLER]=new AbstractAction(){ public void actionPerformed(ActionEvent ev){ if(checkSaveChanges()) ProjectInstallerEditPanel.createInstaller(project, AuthorSingleFrame.this); } }; projectActions=new Action[]{actions[ACTION_SAVE_FILE], actions[ACTION_SAVE_FILE_AS], actions[ACTION_DOCTREE], actions[ACTION_EDIT_SEQ], actions[ACTION_EDIT_ACTIVITIES], actions[ACTION_EDIT_MEDIA], actions[ACTION_EDIT_PROJECT], actions[ACTION_CREATE_HTML], actions[ACTION_CREATE_INSTALLER], actions[ACTION_IMPORT_ACTIVITIES], actions[ACTION_EXPORT_HTML5]}; checkActions(); } protected boolean saveFile(boolean saveAs){ boolean ok=false; if(project!=null && projectEditor.checkProject(options, this, true)){ int[] filters={Utils.JCLIC_ZIP_FF}; FileSystem fs=project.getFileSystem(); String path=StrUtils.secureString(project.getFullPath(), project.getName()+".jclic.zip"); String pLower=path.toLowerCase(); if(!pLower.endsWith(".jclic.zip")){ if(pLower.endsWith(".jclic")) path=path+".zip"; else if(pLower.endsWith(".pac") || pLower.endsWith(".pcc")){ int dot=path.lastIndexOf('.'); if(dot>=1){ path=path.substring(0, dot); } path=path+".jclic.zip"; } } String result; File f=new File(path); if(!saveAs && f.exists() && f.canWrite()) result=path; else result=fs.chooseFile(path, true, filters, options, null, AuthorSingleFrame.this, false); if(result!=null){ ok=doSaveFile(result); // 03-Feb-2011 // Correction of bug #53 setFrameTitle(null); } } return ok; } static boolean saveResult; protected boolean doSaveFile(final String fName){ if(worker!=null){ return false; } saveResult=false; //System.gc(); worker=new edu.xtec.util.SwingWorker(){ Exception exception=null; AuthorSingleFrame thisAuthor=AuthorSingleFrame.this; @Override public Object construct(){ Object o=null; setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try{ projectEditor.saveProject(fName); saveResult=true; addRecentFile(project.getFullPath()); o=true; } catch(Exception ex){ exception=ex; } return o; } @Override public void finished(){ progressDialog.setVisible(false); setCursor(null); if(worker==null || exception!=null){ messages.showErrorWarning(thisAuthor, "FILE_ERR_SAVING", fName, exception, null); } // unlock events worker=null; setEnabled(true); } }; setCursor(null); setEnabled(false); progressDialog.start("WORKING", "msg_saving_project", worker, true, false, true); return saveResult; } protected void doImportActivities(final String fullPath){ if(worker!=null){ return; } System.gc(); worker=new edu.xtec.util.SwingWorker(){ Exception exception=null; AuthorSingleFrame thisAuthor=AuthorSingleFrame.this; @Override public Object construct(){ Object o=null; setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try{ JClicProject jcp=JClicProject.getJClicProject(thisAuthor, fullPath, progressDialog); if(jcp!=null){ progressDialog.setText(messages.get("import_importing")); // Select activities to import JClicProjectEditor jcped=(JClicProjectEditor)jcp.getEditor(null); javax.swing.JList actList=new javax.swing.JList(jcp.activityBag.getElements()); // Error: setpreferedSize must be called on the JScrollPane, not on the JList //actList.setPreferredSize(new java.awt.Dimension(200, 300)); javax.swing.JScrollPane pane=new javax.swing.JScrollPane(actList); pane.setPreferredSize(new java.awt.Dimension(300, 300)); if(messages.showInputDlg(thisAuthor, new String[]{"import_selectActivities"}, new String[]{}, new JComponent[]{pane}, "action_importActivities_caption") && actList.getSelectedIndices().length>0){ progressDialog.setText(messages.get("import_checkdep")); Object[] selection=actList.getSelectedValues(); // check media elements to import List<String> mediaNames=new ArrayList<String>(); for(int i=0; i<selection.length; i++){ ActivityBagElement abe=(ActivityBagElement)selection[i]; Map map=abe.getReferences(); Iterator it=map.keySet().iterator(); while(it.hasNext()){ String media=(String)it.next(); Object mediaType=map.get(media); if(Constants.MEDIA_OBJECT.equals(mediaType) && !mediaNames.contains(media)) mediaNames.add(media); // Todo: process also objects of type Constants.EXTERNAL_OBJECT } } // get the list of media bag elements ArrayList<MediaBagElement> mediaBagElements=new ArrayList<MediaBagElement>(); for(int i=0; i<mediaNames.size(); i++){ MediaBagElement mb=jcp.mediaBag.getElement((String)mediaNames.get(i)); if(mb!=null) mediaBagElements.add(mb); } //check for repeated media names and import media for(MediaBagElement mbe : mediaBagElements){ String name=mbe.getName(); String rootName=name; progressDialog.setText(messages.get("import_impmedia")+" "+name); int prefix=0; while(project.mediaBag.getElement(name)!=null){ name="i0"+Integer.toString(++prefix)+"-"+rootName; } String fName=mbe.getFileName(); String rootFName=fName; prefix=0; while(project.getFileSystem().fileExists(fName)){ fName="i0"+Integer.toString(++prefix)+"-"+rootFName; } File outFile=new File(project.getFileSystem().getFullFileNamePath(fName)); outFile.getParentFile().mkdirs(); java.io.FileOutputStream fos=new java.io.FileOutputStream(outFile); edu.xtec.util.StreamIO.writeStreamTo(jcp.mediaBag.getInputStream(mbe.getName()), fos); if(!name.equals(rootName)){ jcped.getActivityBagEditor().nameChanged(Constants.T_MEDIA, rootName, name); mbe.setName(name); } if(!fName.equals(rootFName)){ mbe.setFileName(fName); } mbe.setData(null); projectEditor.getMediaBagEditor().addMediaBagElement(mbe); } // Import activities for(int i=0; i<selection.length; i++){ ActivityBagElement abe=(ActivityBagElement)selection[i]; String actName=abe.toString(); String rootName=actName; progressDialog.setText(messages.get("import_impact")+" "+actName); int prefix=0; while(project.activityBag.getElementByName(actName)!=null){ actName="i0"+Integer.toString(++prefix)+rootName; } if(!actName.equals(rootName)){ jcped.nameChanged(Constants.T_ACTIVITY, rootName, actName); } ActivityBagElementEditor abeed=(ActivityBagElementEditor)abe.getEditor(null); projectEditor.getActivityBagEditor().insertEditor(abeed, true, -1, false); } o=true; } } } catch(Exception ex){ exception=ex; } return o; } @Override public void finished(){ progressDialog.setVisible(false); setCursor(null); if(worker==null || exception!=null){ messages.showErrorWarning(thisAuthor, "FILE_ERR_OPENING", fullPath, exception, null); } // unlock events worker=null; setEnabled(true); } }; setCursor(null); setEnabled(false); progressDialog.start("WORKING", "import_importing", worker, true, false, 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))); if(s.charAt(1)!='*') actions[i].putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke((int)s.charAt(1), 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_NAMES.length) return null; return ACTION_NAMES[actionId]; } protected Icon getActionIcon(int actionId){ if(actionId<0 || actionId>=ACTION_ICONS.length) return null; return ResourceManager.getImageIcon(ACTION_ICONS[actionId]); } public Action getAction(int id) { if(actions==null || id<0 || id>=actions.length) return null; return actions[id]; } 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 && checkSaveChanges()) load(settings.recentFiles[i], null); } catch(Exception ex){ System.err.println("invalid command: "+ac); } } else return !isEnabled(); return true; } protected void addRecentFile(String fName){ settings.addRecentFile(fName); updateRecentFilesMenu(); settings.save(); } public void actionPerformed(java.awt.event.ActionEvent actionEvent) { String cmd=actionEvent.getActionCommand(); if(cmd!=null) processActionEvent(cmd); } public void exit(){ if(checkSaveChanges()){ SwingUtilities.invokeLater(new Runnable(){ public void run(){ if(options.getApplet()==null){ try{ end(); java.awt.Frame fr=JOptionPane.getFrameForComponent(AuthorSingleFrame.this); if(fr!=null){ fr.dispose(); } else System.exit(0); } catch(Exception ex){ System.err.println("Unable to exit!\n"+ex); } } } }); } } protected void attachProject(){ lastFocusedPanel=null; //if(mediaBagFrame!=null && activityBagFrame!=null && activitySequenceFrame!=null){ if(projectSettingsEditorPanel!=null && mediaBagEditorPanel!=null && activityBagEditorPanel!=null && activitySequenceEditorPanel!=null){ if(project!=null) project.activityBag.sortByName(); projectEditor=project==null ? null : (JClicProjectEditor)project.getEditor(null); projectSettingsEditorPanel.attachEditor(projectEditor==null ? null : projectEditor.getProjectSettingsEditor(), true); mediaBagEditorPanel.attachEditor(projectEditor==null ? null : projectEditor.getMediaBagEditor(), true); activityBagEditorPanel.attachEditor(projectEditor==null ? null : projectEditor.getActivityBagEditor(), true); activitySequenceEditorPanel.attachEditor(projectEditor==null ? null : projectEditor.getActivitySequenceEditor(), true); if(project!=null){ player.setProject(project); player.getHistory().clearHistory(); } // 22-Jan-2013: JClicAuthor hangs when an I/O error occurs if(projectEditor!=null) projectEditor.setTestPlayerContainer(this); } actions[ACTION_DOCTREE].setEnabled(project!=null); } private EditorPanel lastFocusedPanel; protected void checkTabbedPaneFocus(boolean focusLost){ if(tabbedPane!=null){ Object o=tabbedPane.getSelectedComponent(); if(!focusLost && (o instanceof EditorPanel)){ if(lastFocusedPanel!=null){ lastFocusedPanel.focusLost(null); } lastFocusedPanel=(EditorPanel)o; lastFocusedPanel.focusGained(null); } else{ Editor.clearBasicActionsOwner(); } } } protected java.awt.event.FocusListener focusListener=new java.awt.event.FocusListener(){ public void focusGained(java.awt.event.FocusEvent ev){ if(playerDlg!=null && playerDlg.isShowing()){ playerDlg.requestFocus(); } else checkTabbedPaneFocus(false); } public void focusLost(java.awt.event.FocusEvent ev){ checkTabbedPaneFocus(true); } }; protected void createFrames(){ tabbedPane=new JTabbedPane(); tabbedPane.addChangeListener(new javax.swing.event.ChangeListener(){ public void stateChanged(javax.swing.event.ChangeEvent ev){ checkTabbedPaneFocus(false); } }); JClicProject newProject=new JClicProject(this, new FileSystem(this), ""); projectEditor=(JClicProjectEditor)newProject.getEditor(null); ProjectSettingsEditor psed=projectEditor.getProjectSettingsEditor(); projectSettingsEditorPanel=psed.createEditorPanel(options); tabbedPane.addTab(messages.get("edit_project"), JClicProjectEditor.getIcon(), projectSettingsEditorPanel, messages.get("edit_project_tooltip")); mediaBagEditorPanel=new MediaBagMultiEditorPanel(options); tabbedPane.addTab(messages.get("edit_media"), MediaBagEditor.getIcon(), mediaBagEditorPanel, messages.get("edit_media_tooltip")); ActivityBagEditor abe=projectEditor.getActivityBagEditor(); activityBagEditorPanel=abe.createEditorPanel(options); tabbedPane.addTab(messages.get("edit_activities"), ActivityEditor.getIcon(), activityBagEditorPanel, messages.get("edit_activities_tooltip")); activitySequenceEditorPanel=projectEditor.getActivitySequenceEditor().createEditorPanel(options); tabbedPane.addTab(messages.get("edit_sequences"), ActivitySequenceEditor.getIcon(), activitySequenceEditorPanel, messages.get("edit_sequences_tooltip")); playerDlg=new JDialog(JOptionPane.getFrameForComponent(this), "test player", true); player=new Player(options, newProject); player.getHistory().setTestMode(true); player.appName="JClic test player"; player.addTo(playerDlg, null); playerDlg.addWindowListener(new WindowAdapter(){ //public void windowClosing(WindowEvent e){ @Override public void windowClosed(WindowEvent e){ player.closeHelpWindow(); //player.stopMedia(-1); player.removeActivity(); } }); playerDlg.pack(); add(tabbedPane, BorderLayout.CENTER); } public Player getTestPlayer() { return player; } public void test() { if(playerDlg!=null && player!=null){ player.initReporter(); if(player.reporter!=null && project!=null) player.reporter.newSession(project, player, messages); playerDlg.setVisible(true); } } public boolean newInstanceRequest(final String param1, final String param2) { SwingUtilities.invokeLater(new Runnable(){ public void run(){ Frame frame=JOptionPane.getFrameForComponent(AuthorSingleFrame.this); if(frame!=null) frame.toFront(); messages.showAlert(AuthorSingleFrame.this, new String[]{"new instance request", param1, param2}); } }); return true; } protected boolean checkSaveChanges(){ boolean result=true; if(projectEditor!=null){ projectEditor.collectData(); if(projectEditor.isModified()){ //switch(JOptionPane.showConfirmDialog(this, messages.get("warn_project_modified"), messages.get("CONFIRM"), JOptionPane.YES_NO_CANCEL_OPTION)){ switch(messages.showQuestionDlg(this, "warn_project_modified", "CONFIRM", "ync")){ case Messages.YES: result=saveFile(false); break; case Messages.CANCEL: result=false; break; case Messages.NO: break; } } } return result; } public boolean windowCloseRequested() { return checkSaveChanges(); } public void displayUrl(String url, boolean inFrame){ try{ edu.xtec.util.BrowserLauncher.openURL(url); } catch(Exception ex){ System.err.println("Unable to invoque URL "+url+"\n"+ex); } } public void editActivity(String activityName) { if(tabbedPane!=null && activityBagEditorPanel!=null){ if(((ActivityBagEditorPanel)activityBagEditorPanel).editActivity(activityName)) tabbedPane.setSelectedComponent(activityBagEditorPanel); } } }