/**
* Created : July 4, 2012
*
* @author pquiring
*/
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javaforce.*;
public class TrackPanel extends javax.swing.JPanel {
/**
* Creates new form TrackPanel
*/
public TrackPanel(ProjectPanel project) {
initComponents();
this.project = project;
initDND();
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
formMousePressed(evt);
}
public void mouseReleased(java.awt.event.MouseEvent evt) {
formMouseReleased(evt);
}
});
addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
formMouseDragged(evt);
}
public void mouseMoved(java.awt.event.MouseEvent evt) {
formMouseMoved(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 619, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 87, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
private void formMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMousePressed
project.selectTrack(this);
selectedOffset = project.offset + evt.getX() / 16 * project.scale;
repaint();
}//GEN-LAST:event_formMousePressed
private void formMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseDragged
project.drag(evt, this);
}//GEN-LAST:event_formMouseDragged
private void formMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseReleased
if (project.dragTrack != null) {
project.stopDrag();
}
}//GEN-LAST:event_formMouseReleased
private void formMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseMoved
}//GEN-LAST:event_formMouseMoved
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
private ProjectPanel project;
public boolean selected = false;
public int selectedOffset = -1;
public ArrayList<Element> list = new ArrayList<Element>();
public void paint(Graphics g) {
g.setColor(Color.GRAY);
g.fillRect(0,0,getWidth(),getHeight());
if (selected)
g.setColor(Color.YELLOW);
else
g.setColor(Color.BLUE);
g.drawRect(0,0,getWidth()-1,getHeight()-1);
int offset = project.offset;
int px = 0;
int width = getWidth();
g.setColor(Color.BLACK);
while (px < width) {
if (selectedOffset >= offset && selectedOffset <= (offset + project.scale-1)) {
if (project.dragTrack == this) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.RED);
}
} else {
g.setColor(Color.BLACK);
}
g.drawRect(px,1,15,61);
drawElements(g, px, offset, project.scale);
px += 16;
offset += project.scale;
}
}
public void drawElements(Graphics g, int px, int offset, int length) {
int len = list.size();
int d1 = offset;
int d2 = offset + length - 1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
int off = offset - e.offset;
if (off < 0) off = 0;
drawElement(g, e, px, off);
}
}
}
public void drawElement(Graphics g, Element e, int px, int offset) {
g.drawImage(e.getPreview(offset, project.scale), px, 2, null);
}
public Dimension getPreferredSize() {
return new Dimension(project.getTracksWidth(), 64);
}
public int totalLength() {
int max = 0;
for(int a=0;a<list.size();a++) {
Element e = list.get(a);
int len = e.offset + e.length;
if (len > max) max = len;
}
return max;
}
public boolean used(int offset, int length) {
int len = list.size();
int d1 = offset;
int d2 = offset + length - 1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
return true;
}
}
return false;
}
public void addElement(String file[], int type) {
if (type == 0) {
JFLog.log("Error:TrackPanel.addElement() : type == 0");
return;
}
Element e;
int len = list.size();
for(int a=0;a<len;a++) {
e = list.get(a);
if (e.offset == selectedOffset) {
if (!JF.showConfirm("Warning", "Replace element?")) return;
list.remove(a);
break;
}
}
e = new Element();
e.path = file;
e.offset = selectedOffset;
e.type = type;
if (type == Element.TYPE_SPECIAL_TEXT) {
e.fx = "center,center,Arial,0,16,Enter your text here...";
e.clr = 0xffffff; //white
}
if (type == Element.TYPE_IMAGE || type == Element.TYPE_SPECIAL_CUT || type == Element.TYPE_SPECIAL_BLUR || type == Element.TYPE_SPECIAL_TEXT) {
if (file.length == 1)
e.length = 1;
else
e.length = (file.length + (project.config.videoRate-1)) / project.config.videoRate;
} else {
//audio / video
String fullfile = JF.getUserPath() + "/" + file[0];
if (!new File(fullfile).exists()) return;
if (!e.start(project.config)) return;
e.length = (int)e.getDuration();
e.stop();
JFLog.log("length = " + e.length);
}
if (used(e.offset, e.length)) {
JF.showError("Error", "That will overlap another element, try another track");
return;
}
list.add(e);
repaint();
if (project.config.preview) {
JFTask task = new JFTask() {
public boolean work() {
this.setTitle("Creating Preview");
this.setLabel("Creating Preview");
Element e = (Element)getProperty("element");
e.createPreview(this);
return true;
}
};
task.setProperty("element", e);
ProgressDialog dialog = new ProgressDialog(null, true, task);
dialog.setAutoClose(true);
dialog.setVisible(true);
repaint();
}
}
public void deleteElement() {
//delete element at selectedOffset
int len = list.size();
int d1 = selectedOffset;
int d2 = selectedOffset + project.scale - 1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
list.remove(a);
break;
}
}
repaint();
}
public void editElement() {
//edit element properties at selectedOffset
int len = list.size();
int d1 = selectedOffset;
int d2 = selectedOffset + project.scale - 1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
EditElementProperties dialog = new EditElementProperties(null, true, e, 0);
dialog.setVisible(true);
if (dialog.saved) {
if (project.config.preview && e.type == Element.TYPE_IMAGE) {
//redo preview for images since length may have changed
e.createPreview(null); //this is usually very fast, no need for JFTask/ProgressDialog
}
}
break;
}
}
repaint();
}
public void deleteElement(Element e) {
list.remove(e);
repaint();
}
public void addElement(Element e, boolean updateOffset) {
if (updateOffset) e.offset = selectedOffset;
list.add(e);
repaint();
}
public void drag(MouseEvent evt) {
if (project.dragElement == null) {
startDrag();
}
selectedOffset = project.offset + evt.getX() / 16 * project.scale;
repaint();
}
public void undrag() {}
public void startDrag() {
//delete element at selectedOffset
int len = list.size();
int d1 = selectedOffset;
int d2 = selectedOffset + project.scale - 1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
project.dragElement = e;
break;
}
}
}
public void stopDrag() {
project.dragElement = null;
}
public void stop() {
//unload all elements
for(int a=0;a<list.size();a++) {
list.get(a).stop();
}
}
private boolean isCut;
public boolean isCut() {
return isCut;
}
public void renderVideo(final ProjectPanel.GLData gldata, final JFImage image, final int second, final int frame) {
int len = list.size();
int d1 = second;
int d2 = d1;
isCut = false;
for(int a=0;a<len;a++) {
final Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
if (!e.isReady()) e.start(project.config);
isCut = e.isCut();
if (e.use3d) {
MainPanel.runGL(new Runnable() {
public void run() {
MainPanel.gl.pollEvents();
gldata.image3d.clear();
e.preRenderVideo();
e.renderVideo(gldata.image3d, second, frame);
//render image3d and put into image
gldata.scene.setTexture("0", gldata.image3d.getBuffer(), project.config.width, project.config.height, 0);
gldata.model.setIdentity();
// gldata.model.translate(0,0,-20.f); //base translate : TODO : based on width/height/fov
gldata.model.translate(e.tx, e.ty, e.tz);
gldata.model.rotate(e.rx, 1.0f, 0, 0);
gldata.model.rotate(e.ry, 0, 1.0f, 0);
gldata.model.rotate(e.rz, 0, 0, 1.0f);
MainPanel.gl.setCurrent();
gldata.render.render();
gldata.image3d.putPixels(gldata.off.getOffscreenPixels(), 0, 0
, project.config.width, project.config.height, 0);
e.applyAlpha(gldata.image3d);
image.putPixelsBlend(gldata.image3d.getBuffer(), 0, 0
, project.config.width, project.config.height, 0, true);
}
});
} else {
e.preRenderVideo();
e.applyAlpha();
e.renderVideo(image, second, frame);
}
}
if (frame == 0 && d2 == e2+1) {
e.stop();
}
}
}
public void renderAudio(short audio[], int offset, int frame) {
int len = list.size();
int d1 = offset;
int d2 = d1;
for(int a=0;a<len;a++) {
Element e = list.get(a);
int e1 = e.offset;
int e2 = e.offset + e.length - 1;
if ((d1 >= e1 && d1 <= e2) || (d2 >= e1 && d2 <= e2) || (d1 <= e1 && d2 >= e2))
{
if (!e.isReady()) e.start(project.config);
e.renderAudio(audio);
}
if (frame ==0 && d2 == e2+1) {
e.stop();
}
}
}
private void initDND() {
setTransferHandler(new TransferHandler() {
public boolean canImport(TransferHandler.TransferSupport info) {
// we only import Files
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
/*
TransferHandler.DropLocation dl = (TransferHandler.DropLocation) info.getDropLocation();
Point pt = dl.getDropPoint();
JComponent c = (JComponent)getComponentAt(pt);
*/
return true;
}
public boolean importData(TransferHandler.TransferSupport info) {
if (!info.isDrop()) {
return false;
}
// Check for file flavor
if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
TransferHandler.DropLocation dl = info.getDropLocation();
Point pt = dl.getDropPoint();
project.selectTrack(TrackPanel.this);
selectedOffset = project.offset + pt.x / 16 * project.scale;
repaint();
// Get the file(s) that are being dropped.
Transferable t = info.getTransferable();
java.util.List<File> data;
try {
data = (java.util.List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
} catch (Exception e) {
JFLog.log(e);
return false;
}
ArrayList<String> files = new ArrayList<String>();
// Perform the actual import.
for(int a=0;a<data.size();a++) {
switch (info.getDropAction()) {
case COPY:
case MOVE:
files.add(data.get(a).getAbsolutePath());
break;
case LINK:
return false; //BUG : not supported : ???
}
}
project.addElement(project.prepFiles(files));
project.calcMaxLength();
return true;
}
public int getSourceActions(JComponent c) {
return NONE;
}
protected Transferable createTransferable(JComponent c) {
return null;
}
protected void exportDone(JComponent source, Transferable data, int action) {
}
});
}
}