/* * File : MediaBagEditor.java * Created : 17-sep-2002 16:30 * 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.bags; import edu.xtec.jclic.Constants; import edu.xtec.jclic.edit.*; import edu.xtec.jclic.fileSystem.FileSystem; import edu.xtec.jclic.fileSystem.ZipFileSystem; import edu.xtec.jclic.misc.Utils; import edu.xtec.jclic.project.JClicProjectEditor; import edu.xtec.util.Messages; import edu.xtec.util.Options; import edu.xtec.util.ProgressDialog; import edu.xtec.util.StrUtils; import edu.xtec.util.StreamIO; import java.awt.Color; import java.awt.Component; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import javax.swing.Icon; import javax.swing.JComponent; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.16 */ public class MediaBagEditor extends Editor{ public static final int DEFAULT_IMG_MAX_WIDTH=800; public static final int DEFAULT_IMG_MAX_HEIGHT=600; public static final int IMG_MIN_SIZE=10; public static final String RESIZED="resized"; //public static EditorAction newMediaAction; public static boolean actionsCreated; private boolean initializing; public static EditorAction newMediaBagElementAction, updateAllMediaAction, exportAllMediaAction; private static Icon icon; protected static int imgMaxWidth=DEFAULT_IMG_MAX_WIDTH; protected static int imgMaxHeight=DEFAULT_IMG_MAX_HEIGHT; /** Creates a new instance of MediaBagEditor */ public MediaBagEditor(MediaBag mb) { super(mb); } public Options getOptions(){ return getMediaBag().getProject().getBridge().getOptions(); } protected void createChildren() { initializing=true; Iterator it=getMediaBag().getElementsByName().iterator(); while(it.hasNext()){ ((MediaBagElement)it.next()).getEditor(this); } initializing=false; } public EditorPanel createEditorPanel(Options options) { return new MediaBagMultiEditorPanel(options); } public Class getEditorPanelClass() { return MediaBagMultiEditorPanel.class; } @Override public String getTitleKey(){ return "edit_media"; } public MediaBag getMediaBag(){ return (MediaBag)getUserObject(); } public JClicProjectEditor getProjectEditor(){ return (JClicProjectEditor)getFirstParent(JClicProjectEditor.class); } public static String[] selectMediaFiles(MediaBag mediaBag, Options options, Component dlgOwner, int fileFilters, String defaultFile){ String[] result; FileSystem fs=mediaBag.getProject().getFileSystem(); //int[] filters=new int[]{fileFilters}; //if(fileFilters<0){ int[] filters=new int[]{Utils.ALL_IMAGES_FF, Utils.ALL_SOUNDS_FF, Utils.MIDI_FF, Utils.ALL_VIDEO_FF, Utils.ALL_ANIM_FF, Utils.FONTS_FF, Utils.SKINS_FF, Utils.ALL_MEDIA_FF}; //} result=fs.chooseFiles(defaultFile, false, filters, options, "edit_find_media", dlgOwner, true, true); if(result!=null){ for(int i=0; i<result.length; i++){ if(result[i]!=null) result[i]=result[i].replace(File.separatorChar, '/'); } } return result; } public String getValidMediaName(String suggestedName){ String name=suggestedName; int i=1; while(getMediaBag().getElement(name)!=null){ name=name+"_"+i++; } return name; } public MediaBagElementEditor addMediaBagElement(MediaBagElement mbe){ MediaBagElementEditor result=null; if(getMediaBag().addElement(mbe)){ result=(MediaBagElementEditor)mbe.getEditor(this); fireEditorDataChanged(null); } return result; } public MediaBagElementEditor[] createNewMediaBagElements(Options options, Component dlgOwner, int fileFilters){ MediaBagElementEditor[] result=null; Messages msg=options.getMessages(); MediaBag mb=getMediaBag(); FileSystem fs=mb.getProject().getFileSystem(); String[] fNames=selectMediaFiles(getMediaBag(), options, dlgOwner, fileFilters, null); if(fNames!=null){ List<MediaBagElementEditor> v=new ArrayList<MediaBagElementEditor>(); for(int i=0; i<fNames.length; i++){ if(mb.getElementByFileName(fNames[i])!=null){ msg.showAlert(dlgOwner, new String[]{ msg.get("edit_media_exists_1"), fNames[i], msg.get("edit_media_exists_2") }); } else{ MediaBagElement mbe=new MediaBagElement(fNames[i], null, getValidMediaName(fNames[i])); boolean cancel=false; // Check image size if(mbe.isImage()){ Image img=null; try { img=mbe.prepareAndGetImage(fs); if(img==null) throw new Exception("invalid image!"); } catch (Exception ex){ msg.showErrorWarning(dlgOwner, "err_reading_data", fNames[i], ex, null); cancel=true; } if (img != null) { int imgWidth = img.getWidth(null); int imgHeight = img.getHeight(null); if ((imgWidth > imgMaxWidth || imgHeight > imgMaxHeight)) { int answer = msg.showQuestionDlgObj( dlgOwner, new String[]{StrUtils.replace( msg.get("img_resize_prompt"), "%s", new String[]{ fNames[i], "" + imgWidth + "x" + imgHeight, "" + imgMaxWidth + "x" + imgMaxHeight })}, "CONFIRM", "ync"); if (answer == Messages.CANCEL) { cancel = true; } else if (answer == Messages.YES) { // TODO: Process can be long. Display wait cursor String baseName = fNames[i]; int lastDot = baseName.lastIndexOf("."); if (lastDot > 0) { baseName = baseName.substring(0, lastDot); } String newName = baseName + "-" + RESIZED + ".jpg"; File destFile = new File(fs.getFullFileNamePath(newName)); int counter = 0; while (destFile.exists()) { newName = baseName + "-" + RESIZED + Integer.toString(++counter) + ".jpg"; destFile = new File(fs.getFullFileNamePath(newName)); } try { javax.swing.ImageIcon resizedImg = mbe.getThumbNail(imgMaxWidth, imgMaxHeight, fs); BufferedImage bimg=Utils.toBufferedImage(resizedImg.getImage(), Color.white, null); javax.imageio.ImageIO.write(bimg, "jpg", destFile); fNames[i] = newName; mbe = new MediaBagElement(fNames[i], null, getValidMediaName(fNames[i])); } catch (Exception ex) { cancel=true; msg.showErrorWarning(dlgOwner, "err_file_save", ex); } } } } } if(!cancel && mb.addElement(mbe)){ v.add((MediaBagElementEditor)mbe.getEditor(this)); //fireEditorDataChanged(null); } } } if(v.size()>0){ result=v.toArray(new MediaBagElementEditor[v.size()]); fireEditorDataChanged(null); } } return result; } public void updateAllElements(JComponent parent){ final ProgressDialog progressDialog=new ProgressDialog(parent, getOptions()); edu.xtec.util.SwingWorker sw=new edu.xtec.util.SwingWorker(){ @Override public Object construct(){ FileSystem fs=getMediaBag().getProject().getFileSystem(); ZipFileSystem zfs=(fs instanceof ZipFileSystem) ? (ZipFileSystem)fs : null; int count=0; progressDialog.setProgressMax(getChildCount()); progressDialog.setProgressValue(count); Enumeration en=children(); while(en.hasMoreElements() && !isCancelled()){ MediaBagElementEditor mbeled=(MediaBagElementEditor)en.nextElement(); String fName=mbeled.getMediaBagElement().getFileName(); progressDialog.setFileLabel(fName); if(zfs!=null){ ZipFileSystem.ExtendedZipEntry ze=zfs.getEntry(fName); if(ze!=null && zfs.fileExists(fName)){ ze.ignore=true; } } mbeled.updateContent(null); progressDialog.setProgressValue(++count); } setModified(true); progressDialog.setFileLabel(null); fireEditorDataChanged(null); return null; } @Override public void finished(){ progressDialog.setVisible(false); } }; progressDialog.start("edit_media_refreshAll", "edit_media_refreshAll_working", sw, true, true, false); } public void exportAllElements(final JComponent parent){ final Options options=getOptions(); final ProgressDialog progressDialog=new ProgressDialog(parent, options); edu.xtec.util.SwingWorker sw=new edu.xtec.util.SwingWorker(){ @Override public Object construct(){ FileSystem fs=getMediaBag().getProject().getFileSystem(); ZipFileSystem zfs=(fs instanceof ZipFileSystem) ? (ZipFileSystem)fs : null; String dlgMsg=options.getMessages().get("filesystem_copyFile"); int count=0; progressDialog.setProgressMax(getChildCount()); progressDialog.setProgressValue(count); Enumeration en=children(); boolean overwriteAll=false; boolean overwriteNone=false; while(en.hasMoreElements() && !isCancelled()){ MediaBagElementEditor mbeled=(MediaBagElementEditor)en.nextElement(); String fName=mbeled.getMediaBagElement().getFileName(); if(zfs!=null){ ZipFileSystem.ExtendedZipEntry ze=zfs.getEntry(fName); if(ze!=null && !ze.ignore){ progressDialog.setFileLabel(fName); String fNameDest=zfs.getFullFileNamePath(fName); File fileDest=new File(fNameDest); boolean prompt=true; if(fileDest.exists()){ if(overwriteNone) continue; else if(!overwriteAll){ boolean next=false; boolean cancel=false; switch(options.getMessages().confirmOverwriteFile(parent, fileDest, "yYnNc")){ case Messages.NO_TO_ALL: overwriteNone=true; case Messages.NO: next=true; break; case Messages.YES_TO_ALL: overwriteAll=true; case Messages.YES: break; default: cancel=true; } if(next) continue; else if(cancel) break; } } try{ OutputStream os=zfs.createSecureFileOutputStream(fNameDest); //int len=(int)zfs.getFileLength(fName); InputStream is=zfs.getInputStream(fName); StreamIO.writeStreamTo(is, os); //StreamIO.writeStreamDlg(is, os, len, dlgMsg, progressDialog, options); } catch(Exception ex){ options.getMessages().showErrorWarning(progressDialog, "FILE_ERR_SAVING", ex); break; } } progressDialog.setProgressValue(++count); } } progressDialog.setFileLabel(null); return null; } @Override public void finished(){ progressDialog.setVisible(false); } }; progressDialog.start("edit_media_refreshAll", "edit_media_refreshAll_working", sw, true, true, false); } @Override public void setActionsOwner(){ allowDelete = allowCut = allowCopy = allowPaste = false; super.setActionsOwner(); if(actionsCreated){ newMediaBagElementAction.setActionOwner(this); FileSystem fs=getMediaBag().getProject().getFileSystem(); boolean isZipFileSystem=(fs instanceof ZipFileSystem); updateAllMediaAction.setActionOwner(isZipFileSystem ? this : null); exportAllMediaAction.setActionOwner(isZipFileSystem ? this : null); } } @Override public void clearActionsOwner(){ super.clearActionsOwner(); if(actionsCreated){ newMediaBagElementAction.setActionOwner(null); updateAllMediaAction.setActionOwner(null); exportAllMediaAction.setActionOwner(null); } } public static void createActions(Options opt){ createBasicActions(opt); if(!actionsCreated){ newMediaBagElementAction=new EditorAction("edit_media_new", "icons/media_new.gif", "edit_media_new_tooltip", opt){ protected void doAction(Editor e){ Editor ch=null; if(e instanceof MediaBagElementEditor){ ch=e; e=e.getEditorParent(); } if(e instanceof MediaBagEditor){ EditorPanel ep=getEditorPanelSrc(); MediaBagMultiEditorPanel mbep=null; if(ep instanceof MediaBagMultiEditorPanel) mbep=(MediaBagMultiEditorPanel)ep; int filters=(mbep==null ? -1 : mbep.getFilters()); MediaBagElementEditor[] mbed=((MediaBagEditor)e).createNewMediaBagElements(options, getComponentSrc(), filters); if(mbed!=null && mbed.length>0 && mbep!=null){ mbep.setSelected(mbed[0]); } } } }; updateAllMediaAction=new EditorAction("edit_media_refreshAll", "icons/reset_all.gif", "edit_media_refreshAll_tooltip", opt){ protected void doAction(Editor e){ if(e instanceof MediaBagEditor){ ((MediaBagEditor)e).updateAllElements(getJComponentSrc()); } } }; exportAllMediaAction=new EditorAction("edit_media_exportAll", "icons/file_save_all.gif", "edit_media_exportAll_tooltip", opt){ protected void doAction(Editor e){ if(e instanceof MediaBagEditor){ ((MediaBagEditor)e).exportAllElements(getJComponentSrc()); } } }; actionsCreated=true; } } public MediaBagElementEditor getChildFor(MediaBagElement mbe){ MediaBagElementEditor result=null; if(mbe!=null){ Enumeration en=children(); while(en.hasMoreElements()){ Editor e=(Editor)en.nextElement(); if(e.getUserObject()==mbe){ result=(MediaBagElementEditor)e; break; } } } return result; } public List<MediaBagElementEditor> getChildrenList(int filters){ List<MediaBagElementEditor> v=new ArrayList<MediaBagElementEditor>(); Iterator it=getMediaBag().getElementsByName().iterator(); String[] extFilters=Utils.getFileFilterExtensions(filters); while(it.hasNext()){ MediaBagElement mbe=(MediaBagElement)it.next(); int i=0; String s=mbe.getFileName().toLowerCase(); if(extFilters!=null) while(i<extFilters.length && !s.endsWith(extFilters[i])) i++; if(extFilters==null || i<extFilters.length){ MediaBagElementEditor mbed=getChildFor(mbe); if(mbed!=null) v.add(mbed); } } return v; } public boolean nameChanged(int type, String oldName, String newName){ boolean result=false; if((type & Constants.T_MEDIA)!=0){ Enumeration e=children(); while(e.hasMoreElements()) result|=((MediaBagElementEditor)e.nextElement()).nameChanged(type, oldName, newName); } return result; } public static Icon getIcon(){ if(icon==null) icon=edu.xtec.util.ResourceManager.getImageIcon("icons/media_bag.gif"); return icon; } public int checkOrphanElements(Options options, Component parent, boolean prompt){ int result=Messages.YES; List<MediaBagElementEditor> v=new ArrayList<MediaBagElementEditor>(); Enumeration en=children(); while(en.hasMoreElements()){ MediaBagElementEditor mbed=(MediaBagElementEditor)en.nextElement(); if(mbed.listReferences().isEmpty()) v.add(mbed); } if(!v.isEmpty()){ boolean doIt=!prompt; if(!doIt){ //result=options.getMessages().showQuestionDlg(parent, "edit_project_orphanMedia", null, true); Object[] object=new Object[]{ options.getMsg("edit_project_orphanMedia"), v.size()>10 ? (Object)(new javax.swing.JScrollPane(new javax.swing.JList(v.toArray()))) : (Object)v, options.getMsg("edit_project_orphanMedia_prompt"), }; result=options.getMessages().showQuestionDlgObj(parent, object, "edit_project_orphanMedia_title", "ync"); doIt=(result==Messages.YES); } if(doIt){ Iterator<MediaBagElementEditor> it=v.iterator(); while(it.hasNext()){ it.next().delete(true); } } } return result; } public static int getImgMaxWidth(){ return imgMaxWidth; } public static void setImgMaxWidth(int width){ imgMaxWidth=Math.max(IMG_MIN_SIZE, width); } public static int getImgMaxHeight(){ return imgMaxHeight; } public static void setImgMaxHeight(int height){ imgMaxHeight=Math.max(IMG_MIN_SIZE, height); } }