Package se.llbit.chunky.renderer.ui

Source Code of se.llbit.chunky.renderer.ui.SceneSelector

/* Copyright (c) 2010-2014 Jesper Öqvist <jesper@llbit.se>
*
* This file is part of Chunky.
*
* Chunky 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 3 of the License, or
* (at your option) any later version.
*
* Chunky 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.
* You should have received a copy of the GNU General Public License
* along with Chunky.  If not, see <http://www.gnu.org/licenses/>.
*/
package se.llbit.chunky.renderer.ui;

import java.awt.Dialog;
import java.awt.FileDialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import se.llbit.chunky.renderer.RenderContext;
import se.llbit.chunky.renderer.scene.SceneDescription;
import se.llbit.chunky.ui.CenteredFileDialog;

/**
* The scene selector dialog.
* @author Jesper Öqvist <jesper@llbit.se>
*/
@SuppressWarnings("serial")
public class SceneSelector extends JDialog {

  private final DefaultTableModel tableModel;
  private final JTable sceneTable;
  private final RenderControls controls;
  private final List<SceneDescription> scenes =
      new ArrayList<SceneDescription>();
  protected boolean sceneLoaded = false;
  private final RenderContext context;
  private boolean accepted = false;
  private SceneDescription selectedScene;
  protected final JButton loadSelectedBtn =
      new JButton("Load Selected Scene");
  protected final JButton deleteSelectedBtn = new JButton("Delete Scene");
  protected final JButton exportSelectedBtn = new JButton("Export Scene");

  /**
   * Creates a new scene selector dialog.
   * If the controls parameter is <code>null</code> the dialog
   * will be application modal.
   * @param controls
   * @param context
   */
  public SceneSelector(RenderControls controls, RenderContext context) {
    super(controls, "Load Scene");

    this.controls = controls;
    this.context = context;

    tableModel = new DefaultTableModel(0, 3);
    tableModel.setColumnIdentifiers(new String[] {
        "Name", "Size", "Current SPP", "Render Time" });
    sceneTable = new JTable(tableModel) {
      @Override
      public boolean isCellEditable(int row, int column) {
        return false;
      }
    };

    initComponents();

    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    if (controls != null) {
      setModalityType(Dialog.ModalityType.MODELESS);
    } else {
      setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
    }

    pack();
    setLocationRelativeTo(controls);
    setVisible(true);
    requestFocus();
  }

  private void initComponents() {

    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
        KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Close Dialog");
    getRootPane().getActionMap().put("Close Dialog", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent e) {
        closeDialog();
      }
    });

    JLabel listDescription = new JLabel();
    JButton cancelBtn = new JButton("Cancel");
    loadSelectedBtn.setEnabled(false);
    loadSelectedBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        selectScene(sceneTable.getSelectedRow());
      }
    });

    deleteSelectedBtn.setEnabled(false);
    deleteSelectedBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        deleteScene(sceneTable.getSelectedRow());
      }
    });

    exportSelectedBtn.setEnabled(false);
    exportSelectedBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        exportScene(sceneTable.getSelectedRow());
      }
    });

    List<File> fileList = getAvailableSceneFiles(context.getSceneDirectory());
    Collections.sort(fileList);
    for (File sceneFile : fileList) {
      String fileName = sceneFile.getName();
      try {
        SceneDescription desc = new SceneDescription();
        desc.loadDescription(context.getSceneFileInputStream(fileName));
        scenes.add(desc);
        int seconds = (int) ((desc.renderTime / 1000) % 60);
        int minutes = (int) ((desc.renderTime / 60000) % 60);
        int hours = (int) (desc.renderTime / 3600000);
        String renderTime = String.format("%d:%d:%d", hours, minutes, seconds);
        Object[] row = {
            desc.name,
            ""+desc.width+"x"+desc.height,
            ""+desc.spp, renderTime };
        tableModel.addRow(row);
      } catch (IOException e) {
        System.err.println("Warning: could not load scene description: " + fileName);
      }
    }

    sceneTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    sceneTable.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
          JTable source = (JTable) e.getSource();
          selectScene(source.getSelectedRow());
        }
      }
    });
    sceneTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        loadSelectedBtn.setEnabled(true);
        deleteSelectedBtn.setEnabled(true);
        exportSelectedBtn.setEnabled(true);
      }
    });
    JScrollPane scrollPane = new JScrollPane(sceneTable);

    listDescription.setText("Select 3D scene to load:");

    cancelBtn.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        SceneSelector.this.dispose();
      }
    });

    GroupLayout layout = new GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup()
          .addComponent(listDescription, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
          .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
          .addComponent(loadSelectedBtn, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
          .addGroup(layout.createSequentialGroup()
            .addComponent(deleteSelectedBtn)
            .addPreferredGap(ComponentPlacement.UNRELATED)
            .addComponent(exportSelectedBtn)
            .addPreferredGap(ComponentPlacement.UNRELATED)
            .addComponent(cancelBtn, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
          )
        )
        .addContainerGap())
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(listDescription)
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
        .addPreferredGap(ComponentPlacement.RELATED)
        .addComponent(loadSelectedBtn, GroupLayout.DEFAULT_SIZE, 40, 40)
        .addPreferredGap(ComponentPlacement.UNRELATED)
        .addGroup(layout.createParallelGroup()
          .addComponent(deleteSelectedBtn, GroupLayout.DEFAULT_SIZE, 35, 35)
          .addComponent(exportSelectedBtn, GroupLayout.DEFAULT_SIZE, 35, 35)
          .addComponent(cancelBtn, GroupLayout.DEFAULT_SIZE, 35, 35)
        )
        .addContainerGap())
    );

    pack();
  }

  /**
   * Load the selected scene
   * @param selected index of scene to be loaded
   */
  protected void selectScene(int selected) {
    if (selected >= 0 && selected < scenes.size()) {
      selectedScene = scenes.get(selected);
      accepted = true;
      setVisible(false);
      dispose();
      if (controls != null) {
        controls.loadScene(selectedScene.name);
      }
    }
  }

  /**
   * Delete the selected scene
   * @param selected index of scene to be deleted
   */
  protected void deleteScene(int selected) {
    if (selected >= 0 && selected < scenes.size()) {
      SceneDescription scene = scenes.get(selected);
      Object[] options = {
          "Cancel",
          "Delete Scene \"" + scene.name + "\""
      };
      int n = JOptionPane.showOptionDialog(null,
          "<html>Are you sure you wish to delete the scene \"" + scene.name + "\"?<br>"
              + "All files for the scene, except snapshot images, will be irreversibly deleted!",
          "Delete Scene?",
          JOptionPane.YES_NO_OPTION,
          JOptionPane.WARNING_MESSAGE,
          null,
          options,
          options[0]);
      if (n == 1) {
        scene.delete();
        // remove scene from table
        tableModel.removeRow(selected);
        scenes.remove(selected);
        loadSelectedBtn.setEnabled(false);
        deleteSelectedBtn.setEnabled(false);
        exportSelectedBtn.setEnabled(false);
      }
    }
  }

  /**
   * Export the selected scene to a Zip archive
   * @param selected index of scene to be deleted
   */
  protected void exportScene(int selected) {
    if (selected >= 0 && selected < scenes.size()) {
      SceneDescription scene = scenes.get(selected);
      CenteredFileDialog fileDialog =
          new CenteredFileDialog(null, "Export to ZIP", FileDialog.SAVE);
      fileDialog.setDirectory(System.getProperty("user.dir"));
      fileDialog.setFile(scene.name+".zip");
      fileDialog.setFilenameFilter(
        new FilenameFilter() {
          @Override
          public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".zip");
          }
        }
      );
      fileDialog.setVisible(true);
      File selectedFile = fileDialog.getSelectedFile(".zip");
      if (selectedFile != null) {
        scene.exportToZip(selectedFile);
      }
    }
  }

  /**
   * @return <code>true</code> if a scene was selected
   */
  public boolean isAccepted() {
    return accepted;
  }

  /**
   * @return The selected scene name
   */
  public String getSelectedScene() {
    return selectedScene.name;
  }

  protected void closeDialog() {
    setVisible(false);
    dispose();
  }

  /**
   * @param sceneDir
   * @return a list of available scene description files in the given scene
   * directory
   */
  public static final List<File> getAvailableSceneFiles(File sceneDir) {
    File[] sceneFiles = sceneDir.listFiles(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        return name.endsWith(SceneDescription.SCENE_DESCRIPTION_EXTENSION);
      }
    });
    List<File> fileList = new ArrayList<File>(sceneFiles.length);
    for (File file: sceneFiles) {
      fileList.add(file);
    }
    return fileList;
  }
}
TOP

Related Classes of se.llbit.chunky.renderer.ui.SceneSelector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.