All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy