com.codename1.designer.TimelineEditor Maven / Gradle / Ivy
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.designer;
import com.codename1.designer.ResourceEditorView;
import com.codename1.ui.animations.AnimationAccessor;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import javax.swing.JList;
import javax.swing.SpinnerNumberModel;
import com.codename1.ui.animations.Timeline;
import com.codename1.ui.EncodedImage;
import com.codename1.ui.animations.AnimationObject;
import com.codename1.tools.resourcebuilder.AnimationImpl;
import com.codename1.ui.util.EditableResources;
import java.awt.Point;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* @author Shai
*/
public class TimelineEditor extends BaseForm {
private CodenameOneImageRenderer renderer;
private EditableResources res;
private String name;
private javax.swing.Timer refreshTimeline;
/** Creates new form TimelineEditor */
public TimelineEditor(EditableResources res, String name, ResourceEditorView view) {
if(res.isOverrideMode() && !res.isOverridenResource(name)) {
setOverrideMode(true, view.getComponent());
}
initComponents();
animationObjectList.setModel(new AnimationObjectTableModel());
this.res = res;
this.name = name;
animationObjectList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
int i = animationObjectList.getSelectedRow();
removeAnimationObject.setEnabled(i > -1);
duplicateObject.setEnabled(i > -1);
int size = animationObjectList.getModel().getRowCount();
moveUp.setEnabled(i > -1 && i > 0 && size > 1);
moveDown.setEnabled(i > -1 && i < size - 1 && size > 1);
}
});
animationObjectList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2 && animationObjectList.getSelectedRow() > -1) {
Timeline t = (Timeline)TimelineEditor.this.res.getImage(TimelineEditor.this.name);
updatePosition(-1, -1, t.getAnimation(animationObjectList.getSelectedRow()), false);
}
renderer.repaint();
}
});
duration.setModel(new SpinnerNumberModel(20000, 1000, 1000000, 1000));
width.setModel(new SpinnerNumberModel(240, 10, 1000, 10));
height.setModel(new SpinnerNumberModel(320, 10, 1000, 10));
com.codename1.ui.animations.Timeline current = (com.codename1.ui.animations.Timeline)res.getImage(name);
if(current == null) {
current = Timeline.createTimeline(3000, new AnimationObject[0], new com.codename1.ui.geom.Dimension(100, 100));
}
setImage(current);
current.setPause(true);
}
public class AnimationObjectTableModel extends AbstractTableModel {
private List anims = new ArrayList();
private final String[] COLUMNS = {"Start Time", "Duration", "Image", "X", "Y", "Width", "Height", "Orientation", "Opacity"};
public int indexOf(com.codename1.ui.animations.AnimationObject o) {
return anims.indexOf(o);
}
public void setElementAt(com.codename1.ui.animations.AnimationObject o, int index) {
anims.set(index, o);
fireTableRowsUpdated(index, index);
}
public void addElement(com.codename1.ui.animations.AnimationObject o) {
anims.add(o);
fireTableRowsInserted(anims.size() - 1, anims.size() - 1);
}
public void remove(int i) {
anims.remove(i);
fireTableRowsDeleted(i, i);
}
public void updateTimeline(com.codename1.ui.animations.Timeline t) {
anims.clear();
for(int iter = 0 ; iter < t.getAnimationCount() ; iter++) {
anims.add(t.getAnimation(iter));
}
fireTableDataChanged();
}
public int getRowCount() {
return anims.size();
}
public com.codename1.ui.animations.AnimationObject getElementAt(int i) {
return anims.get(i);
}
public int getColumnCount() {
return COLUMNS.length;
}
public String getColumnName(int columnIndex) {
return COLUMNS[columnIndex];
}
public Class> getColumnClass(int columnIndex) {
return String.class;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
private String motionToString(com.codename1.ui.animations.Motion m) {
if(m == null) {
return "";
}
if(m.getSourceValue() != m.getDestinationValue()) {
return "" + m.getSourceValue() + " - " + m.getDestinationValue();
}
return "" + m.getSourceValue();
}
public Object getValueAt(int rowIndex, int columnIndex) {
com.codename1.ui.animations.AnimationObject o = anims.get(rowIndex);
switch(columnIndex) {
case 0:
return "" + o.getStartTime();
case 1:
return "" + (o.getEndTime() - o.getStartTime());
case 2:
if(AnimationAccessor.getImageName(o) != null) {
return AnimationAccessor.getImageName(o);
}
return res.findId(AnimationAccessor.getImage(o));
case 3:
return motionToString(AnimationAccessor.getMotionX(o));
case 4:
return motionToString(AnimationAccessor.getMotionY(o));
case 5:
return motionToString(AnimationAccessor.getWidth(o));
case 6:
return motionToString(AnimationAccessor.getHeight(o));
case 7:
return motionToString(AnimationAccessor.getOrientation(o));
case 8:
return motionToString(AnimationAccessor.getOpacity(o));
}
return null;
}
}
/**
* Selects a gif file using a file chooser and converts it to a timeline
*/
public static void selectFile(ResourceEditorView view, EditableResources res, String timelineName) {
File[] files = ResourceEditorView.showOpenFileChooser("Images", ".gif");
if(files != null) {
File sel = files[0];
if(timelineName == null) {
timelineName = sel.getName();
}
Preferences.userNodeForPackage(view.getClass()).put("lastDir", sel.getParentFile().getAbsolutePath());
ImageReader iReader = ImageIO.getImageReadersBySuffix("gif").next();
try {
iReader.setInput(ImageIO.createImageInputStream(new FileInputStream(sel)));
int frames = iReader.getNumImages(true);
AnimationObject[] anims = new AnimationObject[frames];
int currentTime = 0;
for(int frameIter = 0 ; frameIter < frames ; frameIter++) {
BufferedImage currentImage = iReader.read(frameIter);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ImageIO.write(currentImage, "png", bo);
bo.close();
// create a PNG image in the resource file
String label = sel.getName() + " frame:" + frameIter;
EncodedImage i = EncodedImage.create(bo.toByteArray());
res.setImage(label, i);
int duration = Math.max(40, AnimationImpl.getFrameTime(iReader, frameIter));
Point pos = AnimationImpl.getPixelOffsets(iReader, frameIter);
anims[frameIter] = AnimationObject.createAnimationImage(i, pos.x, pos.y);
anims[frameIter].setStartTime(currentTime);
anims[frameIter].setEndTime(100000000);
String disposeMethod = getDisposalMethod(iReader, frameIter);
if(disposeMethod != null) {
if("restoreToBackgroundColor".equals(disposeMethod)) {
if(frameIter + 1 < frames) {
int t = Math.max(40, AnimationImpl.getFrameTime(iReader, frameIter + 1));
anims[frameIter].setEndTime(currentTime + t);
} else {
anims[frameIter].setEndTime(currentTime + duration);
}
//for(int iter = frameIter ; iter >= 0 ; iter--) {
// anims[iter].setEndTime(currentTime);
//}
}
// "none" |
// "doNotDispose" | "restoreToBackgroundColor" |
// "restoreToPrevious"
}
currentTime += duration;
}
Timeline t = Timeline.createTimeline(currentTime, anims, new com.codename1.ui.geom.Dimension(iReader.getWidth(0), iReader.getHeight(0)));
res.setImage(timelineName, t);
view.setSelectedResource(timelineName);
} catch(IOException err) {
err.printStackTrace();
JOptionPane.showMessageDialog(JFrame.getFrames()[0], "Error reading file " + err, "IO Error", JOptionPane.ERROR_MESSAGE);
}
}
}
static String getDisposalMethod(ImageReader reader, int num) throws IOException {
IIOMetadata meta = reader.getImageMetadata(num);
Node parent = meta.getAsTree("javax_imageio_gif_image_1.0");
//printNodeTree(parent);
NodeList root = parent.getChildNodes();
for(int iter = 0 ; iter < root.getLength() ; iter++) {
Node n = root.item(iter);
if(n.getNodeName().equals("GraphicControlExtension")) {
return n.getAttributes().getNamedItem("disposalMethod").getNodeValue();
}
}
return null;
}
public void updatePosition(int x, int y, AnimationObject o, boolean startingPoint) {
AnimationObjectTableModel dl = (AnimationObjectTableModel)animationObjectList.getModel();
int index = -1;
for(int iter = 0 ; iter < animationObjectList.getModel().getRowCount() ; iter++) {
if(dl.getElementAt(iter) == o) {
index = iter;
break;
}
}
Timeline t = (Timeline)TimelineEditor.this.res.getImage(TimelineEditor.this.name);
AnimationObjectEditor editor = new AnimationObjectEditor(TimelineEditor.this.res, o, t.getDuration());
if(x > -1) {
editor.updatePosition(x, y, startingPoint);
}
int ok = JOptionPane.showConfirmDialog(TimelineEditor.this, editor, "Edit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if(ok == JOptionPane.OK_OPTION) {
if(index < 0) {
return;
}
dl.setElementAt(editor.getAnimationObject(), index);
AnimationObject[] animations = new AnimationObject[t.getAnimationCount()];
for(int iter = 0 ; iter < animations.length ; iter++) {
animations[iter] = t.getAnimation(iter);
}
animations[index] = editor.getAnimationObject();
boolean paused = t.isPause();
int oldTime = t.getTime();
t = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
t.setPause(paused);
t.setTime(oldTime);
setImage(t);
}
}
public void setImage(com.codename1.ui.animations.Timeline image) {
animationPanel.removeAll();
AnimationObjectTableModel model = (AnimationObjectTableModel)animationObjectList.getModel();
model.updateTimeline(image);
/*for(int iter = 0 ; iter < image.getAnimationCount() ; iter++) {
model.addElement(image.getAnimation(iter));
}*/
renderer = new CodenameOneImageRenderer(image);
renderer.setAnimationObjectList(animationObjectList, this);
animationPanel.add(BorderLayout.CENTER, renderer);
animationPanel.revalidate();
if(image != res.getImage(name)) {
res.setImage(name, image);
}
timeline.setMaximum(image.getDuration());
duration.setValue(image.getDuration());
endTime.setText("" + image.getDuration());
width.setValue(image.getWidth());
height.setValue(image.getHeight());
}
/** 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")
// //GEN-BEGIN:initComponents
private void initComponents() {
jSplitPane1 = new javax.swing.JSplitPane();
animationPanel = new javax.swing.JPanel();
jPanel3 = new javax.swing.JPanel();
propertiesTab = new javax.swing.JTabbedPane();
jPanel1 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
duration = new javax.swing.JSpinner();
width = new javax.swing.JSpinner();
jLabel4 = new javax.swing.JLabel();
height = new javax.swing.JSpinner();
jPanel2 = new javax.swing.JPanel();
jScrollPane2 = new javax.swing.JScrollPane();
animationObjectList = new javax.swing.JTable();
addAnimationObject = new javax.swing.JButton();
removeAnimationObject = new javax.swing.JButton();
duplicateObject = new javax.swing.JButton();
moveUp = new javax.swing.JButton();
moveDown = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
help = new javax.swing.JTextPane();
play = new javax.swing.JButton();
pause = new javax.swing.JButton();
timeline = new javax.swing.JSlider();
currentTime = new javax.swing.JLabel();
endTime = new javax.swing.JLabel();
FormListener formListener = new FormListener();
setName("Form"); // NOI18N
setOpaque(false);
jSplitPane1.setName("jSplitPane1"); // NOI18N
animationPanel.setName("animationPanel"); // NOI18N
animationPanel.setLayout(new java.awt.BorderLayout());
jSplitPane1.setLeftComponent(animationPanel);
jPanel3.setName("jPanel3"); // NOI18N
propertiesTab.setName("propertiesTab"); // NOI18N
jPanel1.setName("jPanel1"); // NOI18N
jPanel1.setOpaque(false);
jLabel1.setText("Duration");
jLabel1.setName("jLabel1"); // NOI18N
jLabel2.setText("Width");
jLabel2.setName("jLabel2"); // NOI18N
duration.setName("duration"); // NOI18N
duration.addChangeListener(formListener);
width.setName("width"); // NOI18N
width.addChangeListener(formListener);
jLabel4.setText("Height");
jLabel4.setName("jLabel4"); // NOI18N
height.setName("height"); // NOI18N
height.addChangeListener(formListener);
org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jLabel1)
.add(jLabel2)
.add(jLabel4))
.add(33, 33, 33)
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(width, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE)
.add(duration, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE)
.add(height, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 453, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel1)
.add(duration, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel2)
.add(width, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel4)
.add(height, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addContainerGap(175, Short.MAX_VALUE))
);
propertiesTab.addTab("Timeline", jPanel1);
jPanel2.setName("jPanel2"); // NOI18N
jPanel2.setOpaque(false);
jScrollPane2.setName("jScrollPane2"); // NOI18N
animationObjectList.setName("animationObjectList"); // NOI18N
jScrollPane2.setViewportView(animationObjectList);
addAnimationObject.setText("Add");
addAnimationObject.setName("addAnimationObject"); // NOI18N
addAnimationObject.addActionListener(formListener);
removeAnimationObject.setText("Remove");
removeAnimationObject.setEnabled(false);
removeAnimationObject.setName("removeAnimationObject"); // NOI18N
removeAnimationObject.addActionListener(formListener);
duplicateObject.setText("Duplicate");
duplicateObject.setEnabled(false);
duplicateObject.setName("duplicateObject"); // NOI18N
duplicateObject.addActionListener(formListener);
moveUp.setText("Move Up");
moveUp.setEnabled(false);
moveUp.setName("moveUp"); // NOI18N
moveUp.addActionListener(formListener);
moveDown.setText("Move Down");
moveDown.setEnabled(false);
moveDown.setName("moveDown"); // NOI18N
moveDown.addActionListener(formListener);
org.jdesktop.layout.GroupLayout jPanel2Layout = new org.jdesktop.layout.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.add(addAnimationObject)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(removeAnimationObject)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(duplicateObject)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(moveUp)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(moveDown)
.addContainerGap(68, Short.MAX_VALUE))
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 547, Short.MAX_VALUE))
);
jPanel2Layout.linkSize(new java.awt.Component[] {addAnimationObject, duplicateObject, moveDown, moveUp, removeAnimationObject}, org.jdesktop.layout.GroupLayout.HORIZONTAL);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel2Layout.createSequentialGroup()
.addContainerGap(224, Short.MAX_VALUE)
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(addAnimationObject)
.add(removeAnimationObject)
.add(duplicateObject)
.add(moveUp)
.add(moveDown))
.addContainerGap())
.add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel2Layout.createSequentialGroup()
.add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 214, Short.MAX_VALUE)
.add(44, 44, 44)))
);
propertiesTab.addTab("Objects", jPanel2);
jScrollPane1.setName("jScrollPane1"); // NOI18N
help.setContentType("text/html");
help.setEditable(false);
help.setText("\r\n \r\n\r\n \r\n \r\n \r\n \rA timeline is a simple repeating animation that allows us to create portable visual effects based \non moving/manipulating images (referenced as objects in timeline terminology). A timeline isn't designed for creation of elaborate effects and is mostly designed for simple splash screen/progress indication animations.\n
\n \nA timeline has a size and duration, while the duration is fixed the size is used to calculate the ratio \nto image sizes. When a timeline is scaled it will sclae the images within it as well and position them in\na scaled location (e.g. an image positioned in 50,50 for a 100,100 timeline will be in 160x160 when the timeline is scaled to 320x320 resolution).\n
\r\n \nA timeline is manipuated by adding objects and defining their internal positions/behaviors during a portion of the timeline. \n
\n \r\n\r\n"); // NOI18N
help.setName("help"); // NOI18N
jScrollPane1.setViewportView(help);
propertiesTab.addTab("Help", jScrollPane1);
play.setText("Play");
play.setName("play"); // NOI18N
play.addActionListener(formListener);
pause.setText("Pause");
pause.setEnabled(false);
pause.setName("pause"); // NOI18N
pause.addActionListener(formListener);
org.jdesktop.layout.GroupLayout jPanel3Layout = new org.jdesktop.layout.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.add(play)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(pause)
.addContainerGap(422, Short.MAX_VALUE))
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(propertiesTab, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 552, Short.MAX_VALUE))
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel3Layout.createSequentialGroup()
.addContainerGap(297, Short.MAX_VALUE)
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(play)
.add(pause))
.addContainerGap())
.add(jPanel3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jPanel3Layout.createSequentialGroup()
.add(propertiesTab, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE)
.add(45, 45, 45)))
);
jSplitPane1.setRightComponent(jPanel3);
timeline.setMaximum(20000);
timeline.setValue(0);
timeline.setName("timeline"); // NOI18N
timeline.addChangeListener(formListener);
currentTime.setText("0");
currentTime.setName("currentTime"); // NOI18N
endTime.setText("20000");
endTime.setName("endTime"); // NOI18N
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(org.jdesktop.layout.GroupLayout.LEADING, jSplitPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 559, Short.MAX_VALUE)
.add(layout.createSequentialGroup()
.add(currentTime)
.add(18, 18, 18)
.add(timeline, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 487, Short.MAX_VALUE)
.add(18, 18, 18)
.add(endTime)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.add(jSplitPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(currentTime)
.add(endTime)
.add(timeline, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
}
// Code for dispatching events from components to event handlers.
private class FormListener implements java.awt.event.ActionListener, javax.swing.event.ChangeListener {
FormListener() {}
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (evt.getSource() == addAnimationObject) {
TimelineEditor.this.addAnimationObjectActionPerformed(evt);
}
else if (evt.getSource() == removeAnimationObject) {
TimelineEditor.this.removeAnimationObjectActionPerformed(evt);
}
else if (evt.getSource() == duplicateObject) {
TimelineEditor.this.duplicateObjectActionPerformed(evt);
}
else if (evt.getSource() == moveUp) {
TimelineEditor.this.moveUpActionPerformed(evt);
}
else if (evt.getSource() == moveDown) {
TimelineEditor.this.moveDownActionPerformed(evt);
}
else if (evt.getSource() == play) {
TimelineEditor.this.playActionPerformed(evt);
}
else if (evt.getSource() == pause) {
TimelineEditor.this.pauseActionPerformed(evt);
}
}
public void stateChanged(javax.swing.event.ChangeEvent evt) {
if (evt.getSource() == duration) {
TimelineEditor.this.durationStateChanged(evt);
}
else if (evt.getSource() == width) {
TimelineEditor.this.widthStateChanged(evt);
}
else if (evt.getSource() == height) {
TimelineEditor.this.heightStateChanged(evt);
}
else if (evt.getSource() == timeline) {
TimelineEditor.this.timelineStateChanged(evt);
}
}
}// //GEN-END:initComponents
private Timeline cloneCurrentTimeline() {
Timeline t = (Timeline)res.getImage(name);
AnimationObject[] arr = new AnimationObject[t.getAnimationCount()];
for(int iter = 0 ; iter < arr.length ; iter++) {
arr[iter] = t.getAnimation(iter);
}
Timeline nt = Timeline.createTimeline(getValue(duration), arr,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
nt.setTime(t.getTime());
return nt;
}
private void durationStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_durationStateChanged
int d = getValue(duration);
if(d != ((Timeline)renderer.getImage()).getDuration()) {
com.codename1.ui.animations.Timeline t = cloneCurrentTimeline();
endTime.setText("" + d);
timeline.setMaximum(d);
res.setImage(name, t);
setImage(t);
}
}//GEN-LAST:event_durationStateChanged
private void widthStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_widthStateChanged
int w = getValue(width);
if(w != renderer.getImage().getWidth()) {
com.codename1.ui.animations.Timeline t = cloneCurrentTimeline();
renderer.getImage().scaled(w, renderer.getImage().getHeight());
res.setImage(name, t);
setImage(t);
renderer.revalidate();
renderer.repaint();
}
}//GEN-LAST:event_widthStateChanged
private void heightStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_heightStateChanged
int h = getValue(height);
if(h != renderer.getImage().getHeight()) {
com.codename1.ui.animations.Timeline t = cloneCurrentTimeline();
renderer.getImage().scaled(renderer.getImage().getWidth(), h);
res.setImage(name, t);
setImage(t);
renderer.revalidate();
renderer.repaint();
}
}//GEN-LAST:event_heightStateChanged
private void timelineStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_timelineStateChanged
currentTime.setText("" + timeline.getValue());
if(!refreshingTimelineLock) {
Timeline t = (Timeline)renderer.getImage();
t.setPause(false);
t.setTime(timeline.getValue());
renderer.updateAnimation();
t.setPause(true);
}
}//GEN-LAST:event_timelineStateChanged
private boolean refreshingTimelineLock;
private void playActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playActionPerformed
final Timeline t = (Timeline)renderer.getImage();
t.setPause(false);
play.setEnabled(false);
pause.setEnabled(true);
refreshTimeline = new javax.swing.Timer(500, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(t.isPause()) {
pause.setEnabled(false);
play.setEnabled(true);
refreshTimeline.stop();
refreshTimeline = null;
return;
}
refreshingTimelineLock = true;
timeline.setValue(t.getTime());
refreshingTimelineLock = false;
}
});
refreshTimeline.setRepeats(true);
refreshTimeline.start();
}//GEN-LAST:event_playActionPerformed
private void pauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseActionPerformed
Timeline t = (Timeline)renderer.getImage();
t.setPause(true);
play.setEnabled(true);
pause.setEnabled(false);
if(refreshTimeline != null) {
refreshTimeline.stop();
refreshTimeline = null;
}
}//GEN-LAST:event_pauseActionPerformed
private int getValue(JSpinner s) {
return ((Number)s.getValue()).intValue();
}
private void addAnimationObjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAnimationObjectActionPerformed
AnimationObjectEditor editor = new AnimationObjectEditor(res, null, getValue(duration));
editor.setStartTime(timeline.getValue());
int ok = JOptionPane.showConfirmDialog(this, editor, "Add", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if(ok == JOptionPane.OK_OPTION) {
((AnimationObjectTableModel)animationObjectList.getModel()).addElement(editor.getAnimationObject());
Timeline t = (Timeline)res.getImage(name);
AnimationObject[] animations = new AnimationObject[t.getAnimationCount() + 1];
for(int iter = 0 ; iter < animations.length - 1 ; iter++) {
animations[iter] = t.getAnimation(iter);
}
animations[animations.length - 1] = editor.getAnimationObject();
Timeline nt = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
nt.setTime(t.getTime());
setImage(nt);
}
}//GEN-LAST:event_addAnimationObjectActionPerformed
private void removeAnimationObjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeAnimationObjectActionPerformed
Timeline t = (Timeline)res.getImage(name);
AnimationObject[] animations = new AnimationObject[t.getAnimationCount() - 1];
int offset = 0;
for(int iter = 0 ; iter < t.getAnimationCount() ; iter++) {
if(iter != animationObjectList.getSelectedRow()) {
animations[offset] = t.getAnimation(iter);
offset++;
}
}
((AnimationObjectTableModel)animationObjectList.getModel()).remove(animationObjectList.getSelectedRow());
Timeline nt = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
setImage(nt);
animationObjectList.clearSelection();
duplicateObject.setEnabled(false);
moveDown.setEnabled(false);
moveUp.setEnabled(false);
removeAnimationObject.setEnabled(false);
}//GEN-LAST:event_removeAnimationObjectActionPerformed
private void duplicateObjectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_duplicateObjectActionPerformed
Timeline t = cloneCurrentTimeline();
AnimationObject o = AnimationAccessor.clone((AnimationObject)((AnimationObjectTableModel)animationObjectList.getModel()).getElementAt(animationObjectList.getSelectedRow()));
((AnimationObjectTableModel)animationObjectList.getModel()).addElement(o);
AnimationObject[] animations = new AnimationObject[t.getAnimationCount() + 1];
for(int iter = 0 ; iter < animations.length - 1 ; iter++) {
animations[iter] = t.getAnimation(iter);
}
animations[animations.length - 1] = o;
Timeline nt = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
setImage(nt);
animationObjectList.clearSelection();
duplicateObject.setEnabled(false);
moveDown.setEnabled(false);
moveUp.setEnabled(false);
removeAnimationObject.setEnabled(false);
}//GEN-LAST:event_duplicateObjectActionPerformed
private void moveUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpActionPerformed
int i = animationObjectList.getSelectedRow();
Timeline t = cloneCurrentTimeline();
AnimationObject[] animations = new AnimationObject[t.getAnimationCount()];
for(int iter = 0 ; iter < animations.length ; iter++) {
animations[iter] = t.getAnimation(iter);
}
AnimationObject o = animations[i - 1];
animations[i - 1] = animations[i];
animations[i] = o;
Timeline nt = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
setImage(nt);
moveUp.setEnabled(i > 1);
moveDown.setEnabled(true);
animationObjectList.getSelectionModel().setSelectionInterval(i - 1, i -1);
}//GEN-LAST:event_moveUpActionPerformed
private void moveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownActionPerformed
int i = animationObjectList.getSelectedRow();
Timeline t = cloneCurrentTimeline();
AnimationObject[] animations = new AnimationObject[t.getAnimationCount()];
for(int iter = 0 ; iter < animations.length ; iter++) {
animations[iter] = t.getAnimation(iter);
}
AnimationObject o = animations[i + 1];
animations[i + 1] = animations[i];
animations[i] = o;
Timeline nt = Timeline.createTimeline(getValue(duration), animations,
new com.codename1.ui.geom.Dimension(getValue(width), getValue(height)));
nt.setPause(t.isPause());
setImage(nt);
moveDown.setEnabled(i < animations.length - 1);
moveUp.setEnabled(true);
animationObjectList.getSelectionModel().setSelectionInterval(i + 1, i + 1);
}//GEN-LAST:event_moveDownActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addAnimationObject;
private javax.swing.JTable animationObjectList;
private javax.swing.JPanel animationPanel;
private javax.swing.JLabel currentTime;
private javax.swing.JButton duplicateObject;
private javax.swing.JSpinner duration;
private javax.swing.JLabel endTime;
private javax.swing.JSpinner height;
private javax.swing.JTextPane help;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel4;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JSplitPane jSplitPane1;
private javax.swing.JButton moveDown;
private javax.swing.JButton moveUp;
private javax.swing.JButton pause;
private javax.swing.JButton play;
private javax.swing.JTabbedPane propertiesTab;
private javax.swing.JButton removeAnimationObject;
private javax.swing.JSlider timeline;
private javax.swing.JSpinner width;
// End of variables declaration//GEN-END:variables
}