/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jpcsp.GUI; import static jpcsp.HLE.modules.sceAudiocodec.PSP_CODEC_AT3PLUS; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Insets; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.DataInputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.border.AbstractBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import org.apache.log4j.Logger; import jpcsp.Emulator; import jpcsp.MainGUI; import jpcsp.Memory; import jpcsp.WindowPropSaver; import jpcsp.HLE.VFS.IVirtualFile; import jpcsp.HLE.VFS.iso.UmdIsoVirtualFile; import jpcsp.HLE.modules.sceMpeg; import jpcsp.HLE.modules.sceAtrac3plus.AtracFileInfo; import jpcsp.HLE.modules.sceMpeg.PSMFHeader; import jpcsp.filesystems.umdiso.UmdIsoFile; import jpcsp.filesystems.umdiso.UmdIsoReader; import jpcsp.format.PSF; import jpcsp.format.psmf.PsmfAudioDemuxVirtualFile; import jpcsp.settings.Settings; import jpcsp.util.Constants; /** * @author Orphis, gid15 */ public class UmdBrowser extends javax.swing.JDialog { private static final long serialVersionUID = 7788144302296106541L; private static Logger log = Emulator.log; public static class UmdFileFilter implements FileFilter { @Override public boolean accept(File file) { String lower = file.getName().toLowerCase(); if (lower.endsWith(".cso") || lower.endsWith(".iso")) { return true; } if (file.isDirectory()) { File eboot[] = file.listFiles(new FileFilter() { @Override public boolean accept(File file) { return file.getName().equalsIgnoreCase("eboot.pbp"); } }); if (eboot.length != 1) { return false; } // Basic sanity checks on EBOOT.PBP DataInputStream is = null; try { is = new DataInputStream(new FileInputStream(eboot[0])); byte[] header = new byte[0x24]; int length = is.read(header); if (length != header.length) { return false; } // PBP header? if (header[0] != 0 || header[1] != 'P' || header[2] != 'B' || header[3] != 'P') { return false; } } catch (IOException e) { return false; } finally { if (is != null) { try { is.close(); } catch (IOException e) { // Ignore exception } } } // Valid EBOOT.PBP return true; } return false; } } private final class MemStickTableModel extends AbstractTableModel { private static final long serialVersionUID = -1675488447176776560L; private UmdInfoLoader umdInfoLoader; public MemStickTableModel(File[] paths) { // Default values in case we return an error umdInfoLoaded = new boolean[0]; // Collect all the programs for all the given paths List<File> programList = new ArrayList<File>(); for (File path : paths) { if (!path.isDirectory()) { log.error("'" + path + "' is not a directory."); return; } try { pathPrefix = path.getCanonicalPath(); } catch (IOException e) { pathPrefix = path.getPath(); } File[] pathPrograms = path.listFiles(new UmdFileFilter()); programList.addAll(Arrays.asList(pathPrograms)); } // Sort the programs based on their file name Collections.sort(programList, new Comparator<File>() { @Override public int compare(File file1, File file2) { if (file1 == null) { return (file2 == null ? 0 : 1); } else if (file2 == null) { return -1; } String name1 = file1.getName().toLowerCase(); String name2 = file2.getName().toLowerCase(); if (name1.equals(name2)) { return compare(file1.getParentFile(), file2.getParentFile()); } return name1.compareTo(name2); } }); programs = programList.toArray(new File[programList.size()]); // The UMD informations are loaded asynchronously // to provide a faster loading time for the UmdBrowser. // Prepare the containers for the information and // start the async loader thread as a daemon running at low priority. icons = new ImageIcon[programs.length]; psfs = new PSF[programs.length]; umdInfoLoaded = new boolean[programs.length]; filteredItems = new int[programs.length]; numberFilteredItems = programs.length; for (int i = 0; i < programs.length; ++i) { umdInfoLoaded[i] = false; filteredItems[i] = i; } // load the first row: its size is used to compute the table size loadUmdInfo(0); umdInfoLoader = new UmdInfoLoader(); umdInfoLoader.setName("Umd Browser - Umd Info Loader"); umdInfoLoader.setPriority(Thread.MIN_PRIORITY); umdInfoLoader.setDaemon(true); umdInfoLoader.start(); } @Override public Class<?> getColumnClass(int columnIndex) { switch (columnIndex) { case 0: return Icon.class; case 1: return String.class; default: throw new IndexOutOfBoundsException("column index out of range"); } } @Override public String getColumnName(int column) { java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); // NOI18N switch (column) { case 0: return bundle.getString("MemStickBrowser.column.icon.text"); case 1: return bundle.getString("MemStickBrowser.column.title.text"); default: throw new IndexOutOfBoundsException("column index out of range"); } } @Override public int getColumnCount() { return 2; } @Override public int getRowCount() { if (programs == null) { return 0; } if (numberFilteredItems >= 0) { return numberFilteredItems; } return programs.length; } @Override public Object getValueAt(int rowIndex, int columnIndex) { if (rowIndex >= numberFilteredItems) { return null; } rowIndex = filteredItems[rowIndex]; if (rowIndex >= umdInfoLoaded.length) { return null; } try { waitForUmdInfoLoaded(rowIndex); switch (columnIndex) { case 0: return icons[rowIndex]; case 1: String title = getTitle(rowIndex); String discid = getDiscId(rowIndex); String firmware = getFirmware(rowIndex); String prgPath = getProgramPath(rowIndex); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); // NOI18N String text = String.format( "%s\n%s: %s\n%s: %s\n%s", title, bundle.getString("UmdBrowser.strDiscID.text"), discid, bundle.getString("UmdBrowser.strFirmware.text"), firmware, prgPath); return text; } } catch (IOException e) { log.error(e); } return null; } } private File[] programs; private ImageIcon[] icons; private PSF[] psfs; private volatile boolean[] umdInfoLoaded; private UmdBrowserPmf umdBrowserPmf; private UmdBrowserSound umdBrowserSound; private int lastRowIndex = -1; private boolean isSwitchingUmd; private MainGUI gui; private File[] paths; private int[] filteredItems; private int numberFilteredItems = -1; private String pathPrefix; /** * Creates new form UmdBrowser */ public UmdBrowser(MainGUI gui, File[] paths) { super(gui); this.gui = gui; this.paths = paths; initPNG(); initComponents(); // set blinking border for ICON0 icon0Label.setBorder(new PmfBorder()); // restrict icon column width manually table.getColumnModel().getColumn(0).setMinWidth(Constants.ICON0_WIDTH); table.getColumnModel().getColumn(0).setMaxWidth(Constants.ICON0_WIDTH); // set custom renderers table.setDefaultRenderer(Icon.class, new DefaultTableCellRenderer() { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(""); // NOI18N setIcon((Icon) value); return this; } }); table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() { private static final long serialVersionUID = 1L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JTextArea textArea = new JTextArea((String) value); textArea.setFont(getFont()); if (isSelected) { textArea.setForeground(table.getSelectionForeground()); textArea.setBackground(table.getSelectionBackground()); } else { textArea.setForeground(table.getForeground()); textArea.setBackground(table.getBackground()); } return textArea; } }); // update icons on selection change table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent event) { onSelectionChanged(event); } }); // update the filtering on filter change filterField.getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent e) { onFilterChanged(); } @Override public void insertUpdate(DocumentEvent e) { onFilterChanged(); } @Override public void changedUpdate(DocumentEvent e) { onFilterChanged(); } }); filterField.requestFocus(); WindowPropSaver.loadWindowProperties(this); } private void waitForUmdInfoLoaded(int rowIndex) { // The UMD info is loaded asynchronously. // Wait for the information to be loaded. while (!umdInfoLoaded[rowIndex]) { sleep(1); } } private void initPNG() { // Invoke // sun.awt.image.PNGImageDecoder.setCheckCRC(false) // to avoid an exception "PNGImageDecoder$PNGException: crc corruption" when reading incorrect PNG files. // As this is a class in the "sun" package, be careful as this class could disappear in a later JDK version: // do not statically reference this class and invoke the method using reflection. try { getClass().getClassLoader().loadClass("sun.awt.image.PNGImageDecoder").getMethod("setCheckCRC", boolean.class).invoke(null, false); } catch (Throwable e) { log.info(e); } } private String getUmdBrowseCacheDirectory(String name) { // Return "tmp/UmdBrowserCache/<name>/" return String.format("%1$s%2$cUmdBrowserCache%2$c%3$s%2$c", Settings.getInstance().readString("emu.tmppath"), File.separatorChar, name); } private void writeUmdBrowseCacheFile(String cacheDirectory, String name, byte[] content) { try { OutputStream os = new FileOutputStream(cacheDirectory + name); os.write(content); os.close(); } catch (FileNotFoundException e) { log.error(e); } catch (IOException e) { log.error(e); } } private void loadUmdInfo(int rowIndex) { if (rowIndex >= umdInfoLoaded.length || umdInfoLoaded[rowIndex]) { return; } try { boolean cacheEntry = true; String entryName = programs[rowIndex].getName(); if (programs[rowIndex].isDirectory()) { File eboot[] = programs[rowIndex].listFiles(new FileFilter() { @Override public boolean accept(File file) { return file.getName().equalsIgnoreCase("eboot.pbp"); } }); if (eboot.length > 0) { programs[rowIndex] = eboot[0]; } else { cacheEntry = false; } } if (cacheEntry) { String cacheDirectory = getUmdBrowseCacheDirectory(entryName); File sfoFile = new File(cacheDirectory + "param.sfo"); if (sfoFile.canRead()) { // Read the param.sfo and ICON0.PNG from the UmdBrowserCache byte[] sfo = new byte[(int) sfoFile.length()]; InputStream is = new FileInputStream(sfoFile); is.read(sfo); is.close(); psfs[rowIndex] = new PSF(); psfs[rowIndex].read(ByteBuffer.wrap(sfo)); File icon0File = new File(cacheDirectory + "ICON0.PNG"); if (icon0File.canRead()) { icons[rowIndex] = new ImageIcon(icon0File.getPath()); } else { icons[rowIndex] = new ImageIcon(getClass().getResource("/jpcsp/images/icon0.png")); } } else { // Read the param.sfo and ICON0.PNG from the ISO and // store them in the UmdBrowserCache. // Create the UmdBrowse Cache directories new File(cacheDirectory).mkdirs(); UmdIsoReader iso = new UmdIsoReader(programs[rowIndex].getPath()); byte[] sfo = iso.readParamSFO(); if (sfo == null) { throw new FileNotFoundException(); } writeUmdBrowseCacheFile(cacheDirectory, "param.sfo", sfo); ByteBuffer buf = ByteBuffer.wrap(sfo); psfs[rowIndex] = new PSF(); psfs[rowIndex].read(buf); byte[] icon0 = iso.readIcon0(); if (icon0 == null) { // default icon icons[rowIndex] = new ImageIcon(getClass().getResource("/jpcsp/images/icon0.png")); } else { writeUmdBrowseCacheFile(cacheDirectory, "ICON0.PNG", icon0); icons[rowIndex] = new ImageIcon(icon0); } } } } catch (FileNotFoundException e) { // Check if we're dealing with a UMD_VIDEO. try { UmdIsoReader iso = new UmdIsoReader(programs[rowIndex].getPath()); UmdIsoFile paramSfo = iso.getFile("UMD_VIDEO/param.sfo"); UmdIsoFile umdDataFile = iso.getFile("UMD_DATA.BIN"); // Manually fetch the DISC ID from the UMD_DATA.BIN (video ISO files lack // this param in their param.sfo). byte[] umdDataId = new byte[10]; umdDataFile.readFully(umdDataId, 0, 9); String umdDataIdString = new String(umdDataId); byte[] sfo = new byte[(int) paramSfo.length()]; paramSfo.read(sfo); paramSfo.close(); ByteBuffer buf = ByteBuffer.wrap(sfo); psfs[rowIndex] = new PSF(); psfs[rowIndex].read(buf); psfs[rowIndex].put("DISC_ID", umdDataIdString); UmdIsoFile icon0umd = iso.getFile("UMD_VIDEO/ICON0.PNG"); byte[] icon0 = new byte[(int) icon0umd.length()]; icon0umd.read(icon0); icon0umd.close(); icons[rowIndex] = new ImageIcon(icon0); } catch (FileNotFoundException ve) { // default icon icons[rowIndex] = new ImageIcon(getClass().getResource("/jpcsp/images/icon0.png")); } catch (IOException ve) { log.error(ve); } } catch (IOException e) { log.error(e); } umdInfoLoaded[rowIndex] = true; updateFilteredItem(rowIndex); } private void onSelectionChanged(ListSelectionEvent event) { loadButton.setEnabled(!((ListSelectionModel) event.getSource()).isSelectionEmpty()); ImageIcon pic0Icon = null; ImageIcon pic1Icon = null; ImageIcon icon0Icon = null; try { int rowIndex = getSelectedRowIndex(); UmdIsoReader iso = new UmdIsoReader(programs[rowIndex].getPath()); // Read PIC0.PNG try { byte[] pic0 = iso.readPic0(); if (pic0 != null) { pic0Icon = new ImageIcon(pic0); } } catch (IOException e) { log.error(e); } // Read PIC1.PNG try { byte[] pic1 = iso.readPic1(); if (pic1 != null) { pic1Icon = new ImageIcon(pic1); } else { // Check if we're dealing with a UMD_VIDEO. try { UmdIsoFile pic1umd = iso.getFile("UMD_VIDEO/PIC1.PNG"); pic1 = new byte[(int) pic1umd.length()]; pic1umd.read(pic1); pic1umd.close(); pic1Icon = new ImageIcon(pic1); } catch (FileNotFoundException ve) { // Generate an empty image pic1Icon = new ImageIcon(); BufferedImage image = new BufferedImage(Constants.PSPSCREEN_WIDTH, Constants.PSPSCREEN_HEIGHT, BufferedImage.TYPE_INT_ARGB); pic1Icon.setImage(image); } } } catch (IOException e) { log.error(e); } icon0Icon = icons[rowIndex]; if (lastRowIndex != rowIndex) { stopVideo(); umdBrowserPmf = new UmdBrowserPmf(iso, "PSP_GAME/ICON1.PMF", icon0Label); if (iso.hasFile("PSP_GAME/SND0.AT3")) { umdBrowserSound = new UmdBrowserSound(Memory.getInstance(), iso.readSnd0()); } else { IVirtualFile pmf = new UmdIsoVirtualFile(iso.getFile("PSP_GAME/ICON1.PMF")); byte mpegHeader[] = new byte[sceMpeg.MPEG_HEADER_BUFFER_MINIMUM_SIZE]; if (pmf.ioRead(mpegHeader, 0, mpegHeader.length) == mpegHeader.length) { PSMFHeader psmfHeader = new PSMFHeader(0, mpegHeader); if (psmfHeader.getSpecificStreamNum(sceMpeg.PSMF_ATRAC_STREAM) > 0) { IVirtualFile audio = new PsmfAudioDemuxVirtualFile(pmf, psmfHeader.mpegOffset, 0); AtracFileInfo atracFileInfo = new AtracFileInfo(); atracFileInfo.inputFileDataOffset = 0; atracFileInfo.atracChannels = 2; atracFileInfo.atracCodingMode = 0; umdBrowserSound = new UmdBrowserSound(Memory.getInstance(), audio, PSP_CODEC_AT3PLUS, atracFileInfo); audio.ioClose(); } } pmf.ioClose(); } } lastRowIndex = rowIndex; } catch (FileNotFoundException e) { // Ignore exception } catch (IOException e) { log.error(e); } pic0Label.setIcon(pic0Icon); pic1Label.setIcon(pic1Icon); icon0Label.setIcon(icon0Icon); } private String getTitle(int rowIndex) { String title; if (psfs[rowIndex] == null || (title = psfs[rowIndex].getString("TITLE")) == null) { // No PSF TITLE, get the parent directory name title = programs[rowIndex].getParentFile().getName(); } return title; } private String getDiscId(int rowIndex) { String discId; if (psfs[rowIndex] == null || (discId = psfs[rowIndex].getString("DISC_ID")) == null) { discId = "No ID"; } return discId; } private String getProgramPath(int rowIndex) throws IOException { String programPath = programs[rowIndex].getCanonicalPath(); if (programPath.startsWith(pathPrefix)) { programPath = programPath.substring(pathPrefix.length() + 1); } else { String cwdPath = new File(".").getCanonicalPath(); if (programPath.startsWith(cwdPath)) { programPath = programPath.substring(cwdPath.length() + 1); } } return programPath; } private String getFirmware(int rowIndex) { String firmware; if (psfs[rowIndex] == null || (firmware = psfs[rowIndex].getString("PSP_SYSTEM_VER")) == null) { firmware = "Not found"; } return firmware; } private void scrollTo(char c) { c = Character.toLowerCase(c); int scrollToRow = -1; for (int rowIndex = 0; rowIndex < programs.length; rowIndex++) { String title = getTitle(rowIndex); if (title != null && title.length() > 0) { char firstChar = Character.toLowerCase(title.charAt(0)); if (firstChar == c) { scrollToRow = rowIndex; break; } } } if (scrollToRow >= 0) { table.scrollRectToVisible(table.getCellRect(scrollToRow, 0, true)); } } private void stopVideo() { if (umdBrowserPmf != null) { umdBrowserPmf.stopVideo(); umdBrowserPmf = null; } if (umdBrowserSound != null) { umdBrowserSound.stopSound(); umdBrowserSound = null; } } private boolean filter(String filter, String text) { text = text.toLowerCase(); return text.contains(filter); } private boolean filterItems(String filter) { synchronized (filteredItems) { numberFilteredItems = 0; for (int rowIndex = 0; rowIndex < programs.length; rowIndex++) { filterItem(filter, rowIndex); } } return true; } private String getFilter() { String filter = filterField.getText(); filter = filter.trim().toLowerCase(); return filter; } private void updateFilteredItem(int rowIndex) { boolean alreadyPresent = false; for (int i = 0; i < numberFilteredItems; i++) { if (filteredItems[i] == rowIndex) { alreadyPresent = true; break; } } boolean modified = false; if (!alreadyPresent) { String filter = getFilter(); synchronized (filteredItems) { modified = filterItem(filter, rowIndex); } } if (modified) { ((AbstractTableModel) table.getModel()).fireTableDataChanged(); } } private boolean filterItem(String filter, int rowIndex) { boolean show = false; if (umdInfoLoaded[rowIndex]) { try { String title = getTitle(rowIndex); String discId = getDiscId(rowIndex); String programPath = getProgramPath(rowIndex); String firmware = getFirmware(rowIndex); if (filter(filter, title) || filter(filter, discId) || filter(filter, programPath) || filter(filter, firmware)) { show = true; } } catch (IOException e) { show = true; } } if (show) { filteredItems[numberFilteredItems] = rowIndex; numberFilteredItems++; } return show; } private void onFilterChanged() { String filter = getFilter(); if (log.isDebugEnabled()) { log.debug(String.format("onFilterChanged '%s'", filter)); } if (filterItems(filter)) { ((AbstractTableModel) table.getModel()).fireTableDataChanged(); } } private int getSelectedRowIndex() { int rowIndex = table.getSelectedRow(); if (rowIndex < numberFilteredItems) { rowIndex = filteredItems[rowIndex]; } return rowIndex; } private void loadSelectedfile() { stopVideo(); File selectedFile = programs[getSelectedRowIndex()]; if (isSwitchingUmd()) { gui.switchUMD(selectedFile); setVisible(false); dispose(); } else { gui.loadAndRunUMD(selectedFile); dispose(); } } @Override public void dispose() { // Stop the PMF video and sound before closing the UMD Browser stopVideo(); super.dispose(); } private static void sleep(long millis) { if (millis > 0) { try { Thread.sleep(millis); } catch (InterruptedException e) { // Ignore exception } } } /** * Load asynchronously all the UMD information (icon, PSF). */ private class UmdInfoLoader extends Thread { @Override public void run() { for (int i = 0; i < umdInfoLoaded.length; i++) { loadUmdInfo(i); } } } public boolean isSwitchingUmd() { return isSwitchingUmd; } public void setSwitchingUmd(boolean isSwitchingUmd) { this.isSwitchingUmd = isSwitchingUmd; loadButton.setText(java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp").getString(isSwitchingUmd() ? "UmdBrowser.loadButtonSwitch.text" : "UmdBrowser.loadButton.text")); } private class PmfBorder extends AbstractBorder { private static final long serialVersionUID = -700510222853542503L; private static final int leftSpace = 20; private static final int topSpace = 8; private static final int borderWidth = 8; private static final int millisPerBeat = 1500; @Override public Insets getBorderInsets(Component c, Insets insets) { insets.set(topSpace, leftSpace, borderWidth, borderWidth); return insets; } @Override public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0, 0, 0, 0)); } @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { if (icon0Label.getIcon() == null) { return; } long now = System.currentTimeMillis(); float beat = (now % millisPerBeat) / (float) millisPerBeat; float noBeat = 0.5f; // Draw border lines for (int i = 0; i < borderWidth; i++) { int alpha = getAlpha(noBeat, i); setColor(g, beat, alpha); // Vertical line on the right side g.drawLine(x + width - borderWidth + i, y + topSpace, x + width - borderWidth + i, y + height - borderWidth); // Horizontal line at the bottom g.drawLine(x + leftSpace, y + height - borderWidth + i, x + width - borderWidth, y + height - borderWidth + i); alpha = getAlpha(beat, i); setColor(g, noBeat, alpha); // Vertical line on the left side g.drawLine(x + leftSpace - i, y + topSpace, x + leftSpace - i, y + height - borderWidth); // Horizontal line at the top g.drawLine(x + leftSpace, y + topSpace - i, x + width - borderWidth, y + topSpace - i); } // Top left corner drawCorner(g, beat, noBeat, x + leftSpace - borderWidth, y + topSpace - borderWidth, borderWidth, borderWidth); // Top right corner drawCorner(g, beat, noBeat, x + width - borderWidth, y + topSpace - borderWidth, 0, borderWidth); // Bottom left corner drawCorner(g, beat, noBeat, x + leftSpace - borderWidth, y + height - borderWidth, borderWidth, 0); // Bottom right corner drawCorner(g, noBeat, beat, x + width - borderWidth, y + height - borderWidth, 0, 0); } private void drawCorner(Graphics g, float alphaBeat, float colorBeat, int x, int y, int centerX, int centerY) { for (int ix = 1; ix < borderWidth; ix++) { for (int iy = 1; iy < borderWidth; iy++) { int alpha = getAlpha(alphaBeat, ix - centerX, iy - centerY); setColor(g, colorBeat, alpha); drawPoint(g, x + ix, y + iy); } } } private int getAlpha(float beat, int distanceX, int distanceY) { float distance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY); return getAlpha(beat, distance); } private int getAlpha(float beat, float distance) { final float maxDistance = borderWidth; int maxAlpha = 0xF0; if (beat < 0.5f) { // beat 0.0 -> 0.5: increase alpha from 0 to max maxAlpha = (int) (maxAlpha * beat * 2); } else { // beat 0.5 -> 1.0: decrease alpha from max to 0 maxAlpha = (int) (maxAlpha * (1 - beat) * 2); } distance = Math.abs(distance); distance = Math.min(distance, maxDistance); return maxAlpha - (int) ((distance * maxAlpha) / maxDistance); } private void setColor(Graphics g, float beat, int alpha) { int color = 0xA0; if (beat < 0.5f) { // beat 0.0 -> 0.5: increase color from 0 to max color = (int) (color * beat * 2); } else { // beat 0.5 -> 1.0: decrease alpha from max to 0 color = (int) (color * (1 - beat) * 2); } g.setColor(new Color(color, color, color, alpha)); } private void drawPoint(Graphics g, int x, int y) { g.drawLine(x, y, x, y); } } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; filterLabel = new javax.swing.JLabel(); filterField = new javax.swing.JTextField(); loadButton = new javax.swing.JButton(); cancelButton = new jpcsp.GUI.CancelButton(); jScrollPane1 = new javax.swing.JScrollPane(); table = new javax.swing.JTable(); imagePanel = new javax.swing.JPanel(); icon0Label = new javax.swing.JLabel(); pic0Label = new javax.swing.JLabel(); pic1Label = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); // NOI18N setTitle(bundle.getString("UmdBrowser.title")); // NOI18N setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL); filterLabel.setText(bundle.getString("FilterLabel.text")); // NOI18N filterField.setText(""); // NOI18N loadButton.setText(bundle.getString("LoadButton.text")); // NOI18N loadButton.setEnabled(false); loadButton.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { loadButtonActionPerformed(evt); } }); cancelButton.setText(bundle.getString("CancelButton.text")); // NOI18N cancelButton.setParent(this); table.setModel(new MemStickTableModel(paths)); table.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN); table.setRowHeight(Constants.ICON0_HEIGHT); table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); table.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mouseClicked(java.awt.event.MouseEvent evt) { tableMouseClicked(evt); } }); table.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyTyped(java.awt.event.KeyEvent evt) { tableKeyTyped(evt); } @Override public void keyPressed(java.awt.event.KeyEvent evt) { tableKeyPressed(evt); } @Override public void keyReleased(java.awt.event.KeyEvent evt) { tableKeyReleased(evt); } }); jScrollPane1.setViewportView(table); imagePanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); imagePanel.setPreferredSize(new java.awt.Dimension(480, 272)); imagePanel.setLayout(new java.awt.GridBagLayout()); icon0Label.setBackground(new java.awt.Color(255, 255, 255)); icon0Label.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 22, 0, 0)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; imagePanel.add(icon0Label, gridBagConstraints); pic0Label.setBackground(new java.awt.Color(204, 204, 204)); pic0Label.setMaximumSize(new java.awt.Dimension(310, 180)); pic0Label.setMinimumSize(new java.awt.Dimension(310, 180)); pic0Label.setPreferredSize(new java.awt.Dimension(310, 180)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; imagePanel.add(pic0Label, gridBagConstraints); pic1Label.setBackground(new java.awt.Color(153, 153, 153)); pic1Label.setMaximumSize(new java.awt.Dimension(480, 272)); pic1Label.setMinimumSize(new java.awt.Dimension(480, 272)); pic1Label.setPreferredSize(new java.awt.Dimension(480, 272)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; imagePanel.add(pic1Label, gridBagConstraints); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(filterLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(filterField, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(loadButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(filterLabel) .addComponent(filterField) .addComponent(loadButton) .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void tableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseClicked if (evt.getClickCount() == 2 && evt.getButton() == MouseEvent.BUTTON1) { loadSelectedfile(); } }//GEN-LAST:event_tableMouseClicked private void tableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableKeyPressed // do nothing }//GEN-LAST:event_tableKeyPressed private void tableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableKeyReleased // do nothing }//GEN-LAST:event_tableKeyReleased private void tableKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableKeyTyped scrollTo(evt.getKeyChar()); }//GEN-LAST:event_tableKeyTyped private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadButtonActionPerformed loadSelectedfile(); }//GEN-LAST:event_loadButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private jpcsp.GUI.CancelButton cancelButton; private javax.swing.JLabel icon0Label; private javax.swing.JPanel imagePanel; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JLabel filterLabel; private javax.swing.JTextField filterField; private javax.swing.JButton loadButton; private javax.swing.JLabel pic0Label; private javax.swing.JLabel pic1Label; private javax.swing.JTable table; // End of variables declaration//GEN-END:variables }