Properties panel. Document properties. Color effect instance property.

This commit is contained in:
Jindra Petřík
2024-10-12 23:08:14 +02:00
parent 97ac81c05c
commit 3b055802a7
17 changed files with 1597 additions and 4 deletions

View File

@@ -489,4 +489,10 @@ public class PlaceObject2Tag extends PlaceObjectTypeTag implements ASMSourceCont
public boolean hasImage() {
return false;
}
@Override
public void setColorTransform(ColorTransform colorTransform) {
this.colorTransform = new CXFORMWITHALPHA(colorTransform);
placeFlagHasColorTransform = true;
}
}

View File

@@ -698,5 +698,10 @@ public class PlaceObject3Tag extends PlaceObjectTypeTag implements ASMSourceCont
public boolean hasImage() {
return placeFlagHasImage;
}
@Override
public void setColorTransform(ColorTransform colorTransform) {
this.colorTransform = new CXFORMWITHALPHA(colorTransform);
placeFlagHasColorTransform = true;
}
}

View File

@@ -719,4 +719,10 @@ public class PlaceObject4Tag extends PlaceObjectTypeTag implements ASMSourceCont
public boolean hasImage() {
return placeFlagHasImage;
}
@Override
public void setColorTransform(ColorTransform colorTransform) {
this.colorTransform = new CXFORMWITHALPHA(colorTransform);
placeFlagHasColorTransform = true;
}
}

View File

@@ -301,4 +301,9 @@ public class PlaceObjectTag extends PlaceObjectTypeTag {
public boolean hasImage() {
return false;
}
@Override
public void setColorTransform(ColorTransform colorTransform) {
this.colorTransform = new CXFORM(colorTransform);
}
}

View File

@@ -208,6 +208,12 @@ public abstract class PlaceObjectTypeTag extends Tag implements CharacterIdTag,
* @param placeFlagMove Place flag move
*/
public abstract void setPlaceFlagMove(boolean placeFlagMove);
/**
* Sets color transform.
* @param colorTransform Color transform
*/
public abstract void setColorTransform(ColorTransform colorTransform);
/**
* Checks if place equals.

View File

@@ -146,6 +146,10 @@ public class CXFORMWITHALPHA extends ColorTransform implements Serializable {
* Constructor.
*/
public CXFORMWITHALPHA() {
alphaMultTerm = 256;
redMultTerm = 256;
greenMultTerm = 256;
blueMultTerm = 256;
}
/**
@@ -160,7 +164,7 @@ public class CXFORMWITHALPHA extends ColorTransform implements Serializable {
greenAddTerm = cxform.greenAddTerm;
blueAddTerm = cxform.blueAddTerm;
alphaAddTerm = 0;
alphaMultTerm = 255;
alphaMultTerm = 256;
}
/**

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui;
/**
*
* @author JPEXS
*/
public abstract class ChangeDoableOperation implements DoableOperation {
private final String itemIdentifier;
public ChangeDoableOperation(String itemIdentifier) {
this.itemIdentifier = itemIdentifier;
}
@Override
public String getDescription() {
return EasyStrings.translate("action.change").replace("%item%", EasyStrings.translate("action.change." + itemIdentifier));
}
}

View File

@@ -16,10 +16,14 @@
*/
package com.jpexs.decompiler.flash.easygui;
import com.jpexs.decompiler.flash.easygui.properties.IntegerPropertyField;
import com.jpexs.decompiler.flash.easygui.properties.FloatPropertyField;
import com.jpexs.decompiler.flash.DefineBeforeUsageFixer;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.easygui.properties.panels.DocumentPropertiesPanel;
import com.jpexs.decompiler.flash.easygui.properties.panels.GeneralPropertiesPanel;
import com.jpexs.decompiler.flash.gui.FasterScrollPane;
import com.jpexs.decompiler.flash.gui.ImagePanel;
import com.jpexs.decompiler.flash.gui.Main;
@@ -45,6 +49,7 @@ import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.treeitems.Openable;
import com.jpexs.decompiler.flash.types.MATRIX;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
@@ -91,6 +96,12 @@ public class EasySwfPanel extends JPanel {
private Timelined timelined;
private JLabel timelineLabel;
private JButton closeTimelineButton;
private JPanel propertiesPanel;
private static final String PROPERTIES_DOCUMENT = "Document";
private static final String PROPERTIES_GENERAL = "General";
private DocumentPropertiesPanel documentPropertiesPanel;
private GeneralPropertiesPanel generalPropertiesPanel;
public EasySwfPanel() {
setLayout(new BorderLayout());
@@ -107,6 +118,7 @@ public class EasySwfPanel extends JPanel {
timelinePanel.setDepth(pl.getDepth());
}
transformPanel.setVisible(pl != null);
updatePropertiesPanel();
}
});
@@ -384,6 +396,7 @@ public class EasySwfPanel extends JPanel {
}
}
transformPanel.setVisible(depth != -1);
updatePropertiesPanel();
}
});
@@ -403,6 +416,19 @@ public class EasySwfPanel extends JPanel {
libraryPreviewPanel.setPreferredSize(new Dimension(200, 200));
rightTabbedPane = new JTabbedPane();
propertiesPanel = new JPanel();
documentPropertiesPanel = new DocumentPropertiesPanel(undoManager);
propertiesPanel.setLayout(new CardLayout());
generalPropertiesPanel = new GeneralPropertiesPanel(this, undoManager);
propertiesPanel.add(documentPropertiesPanel, PROPERTIES_DOCUMENT);
propertiesPanel.add(generalPropertiesPanel, PROPERTIES_GENERAL);
rightTabbedPane.addTab(EasyStrings.translate("properties"), propertiesPanel);
rightTabbedPane.addTab(EasyStrings.translate("library"), libraryPanel);
JPanel transformTab = new JPanel(new BorderLayout());
@@ -473,8 +499,19 @@ public class EasySwfPanel extends JPanel {
});
}
private void updatePropertiesPanel() {
CardLayout cl = (CardLayout) propertiesPanel.getLayout();
PlaceObjectTypeTag place = getSelectedPlaceTag();
if (place == null) {
cl.show(propertiesPanel, PROPERTIES_DOCUMENT);
return;
}
generalPropertiesPanel.update();
cl.show(propertiesPanel, PROPERTIES_GENERAL);
}
private boolean transformEnabled() {
return rightTabbedPane.getSelectedIndex() == 1;
return rightTabbedPane.getSelectedIndex() == 2;
}
public void setTimelined(Timelined timelined) {
@@ -486,8 +523,11 @@ public class EasySwfPanel extends JPanel {
libraryPreviewPanel.clearAll();
closeTimelineButton.setVisible(false);
timelineLabel.setText("");
documentPropertiesPanel.setSwf(null);
generalPropertiesPanel.update();
} else {
SWF swf = timelined.getSwf();
documentPropertiesPanel.setSwf(swf);
libraryTreeTable.setSwf(swf);
libraryPreviewPanel.clearAll();
stagePanel.setTimelined(timelined, swf, 0, true, true, true, true, true, false, true);
@@ -502,6 +542,7 @@ public class EasySwfPanel extends JPanel {
timelineLabel.setText(EasyStrings.translate("timeline.item").replace("%item%", nameResolver.getTagName((Tag) timelined)));
closeTimelineButton.setVisible(true);
}
generalPropertiesPanel.update();
}
updateUndos();
}
@@ -537,4 +578,37 @@ public class EasySwfPanel extends JPanel {
setTimelined(null);
undoManager.clear();
}
public int getDepth() {
return stagePanel.getSelectedDepth();
}
public int getFrame() {
return stagePanel.getFrame();
}
public ImagePanel getStagePanel() {
return stagePanel;
}
public SWF getSwf() {
return timelined == null ? null : timelined.getSwf();
}
public DepthState getSelectedDepthState() {
if (timelined == null) {
return null;
}
int frame = stagePanel.getFrame();
int depth = stagePanel.getSelectedDepth();
DepthState ds = timelined.getTimeline().getDepthState(frame, depth);
return ds;
}
public PlaceObjectTypeTag getSelectedPlaceTag() {
DepthState ds = getSelectedDepthState();
if (ds == null) {
return null;
}
return ds.placeObjectTag;
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties;
import java.awt.AWTEvent;
import java.awt.BasicStroke;
import java.awt.CardLayout;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
*
* @author JPEXS
*/
public abstract class AbstractPropertyField<E> extends JPanel {
private static final String CARD_READ = "Read";
private static final String CARD_WRITE = "Write";
protected JLabel readLabel;
protected JTextField writeField;
private final List<PropertyValidationInteface<E>> validations = new ArrayList<>();
private final List<ChangeListener> changeListeners = new ArrayList<>();
private AWTEventListener aeListener;
public void addValidation(PropertyValidationInteface<E> validation) {
validations.add(validation);
}
public void removeValidation(PropertyValidationInteface<E> validation) {
validations.remove(validation);
}
public void addChangeListener(ChangeListener changeListener) {
changeListeners.add(changeListener);
}
public void removeChangeListener(ChangeListener changeListener) {
changeListeners.remove(changeListener);
}
private void fireChange() {
for (ChangeListener listener : changeListeners) {
listener.stateChanged(new ChangeEvent(this));
}
}
@SuppressWarnings("unchecked")
public AbstractPropertyField(String text) {
setLayout(new CardLayout());
readLabel = new DottedUnderlineLabel(text);
readLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
writeField = new JTextField(text);
add(readLabel, CARD_READ);
add(writeField, CARD_WRITE);
readLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1) {
((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_WRITE);
writeField.requestFocus();
writeField.selectAll();
Toolkit.getDefaultToolkit().addAWTEventListener(aeListener, AWTEvent.MOUSE_EVENT_MASK);
}
}
});
writeField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
finishEdit();
}
});
writeField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
e.consume();
finishEdit();
}
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
e.consume();
cancelEdit();
}
}
});
aeListener = new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent me = (MouseEvent) event;
if (!SwingUtilities.isDescendingFrom(me.getComponent(), writeField)) {
if (me.getClickCount() > 0) {
finishEdit();
}
}
}
}
};
}
protected abstract E textToValue(String text);
protected abstract String valueToText(E value);
private void finishEdit() {
String textBefore = readLabel.getText();
String textAfter = writeField.getText();
if (textBefore.equals(textAfter)) {
cancelEdit();
return;
}
Toolkit.getDefaultToolkit().removeAWTEventListener(aeListener);
boolean ok = true;
E value = textToValue(textAfter);
if (value == null) {
ok = false;
} else {
for (PropertyValidationInteface<E> validation : validations) {
if (!validation.validate(value)) {
ok = false;
break;
}
}
}
if (!ok) {
cancelEdit();
return;
}
readLabel.setText(valueToText(value));
((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_READ);
fireChange();
}
private void cancelEdit() {
Toolkit.getDefaultToolkit().removeAWTEventListener(aeListener);
writeField.setText(readLabel.getText());
((CardLayout)AbstractPropertyField.this.getLayout()).show(AbstractPropertyField.this, CARD_READ);
}
public E getValue() {
return textToValue(writeField.getText());
}
public void setValue(E value) {
String text = valueToText(value);
readLabel.setText(text);
writeField.setText(text);
fireChange();
}
}
class DottedUnderlineLabel extends JLabel {
public DottedUnderlineLabel(String text) {
super(text);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Font font = getFont();
FontMetrics metrics = getFontMetrics(font);
String text = getText();
int x = 0;
int y = metrics.getAscent();
g2d.setPaint(getForeground());
int textWidth = metrics.stringWidth(text);
int underlineY = y + 6;
float[] dash = {1f, 1f};
Stroke dotted = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1f, dash, 0f);
g2d.setStroke(dotted);
g2d.draw(new Line2D.Float(x, underlineY, x + textWidth, underlineY));
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties;
/**
*
* @author JPEXS
*/
public class FloatPropertyField extends AbstractPropertyField<Float> {
private PropertyValidationInteface<Float> minValidation = null;
private PropertyValidationInteface<Float> maxValidation = null;
public FloatPropertyField(float value, float min, float max) {
super("" + value);
setMin(min);
setMax(max);
}
public FloatPropertyField(float value) {
super("" + value);
}
public void setMax(float max) {
if (maxValidation != null) {
removeValidation(maxValidation);
}
maxValidation = new PropertyValidationInteface<Float>() {
@Override
public boolean validate(Float value) {
return value <= max;
}
};
addValidation(maxValidation);
}
public void setMin(float min) {
if (minValidation != null) {
removeValidation(minValidation);
}
minValidation = new PropertyValidationInteface<Float>() {
@Override
public boolean validate(Float value) {
return value >= min;
}
};
addValidation(minValidation);
}
@Override
protected Float textToValue(String text) {
try{
return Float.parseFloat(text);
}catch(NumberFormatException nfe){
return null;
}
}
@Override
protected String valueToText(Float value) {
return "" + value;
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties;
/**
*
* @author JPEXS
*/
public class IntegerPropertyField extends AbstractPropertyField<Integer> {
private PropertyValidationInteface<Integer> minValidation = null;
private PropertyValidationInteface<Integer> maxValidation = null;
public IntegerPropertyField(int value, int min, int max) {
super("" + value);
setMin(min);
setMax(max);
writeField.setColumns(("" + max).length());
}
public IntegerPropertyField(int value) {
super("" + value);
}
public void setMax(int max) {
if (maxValidation != null) {
removeValidation(maxValidation);
}
maxValidation = new PropertyValidationInteface<Integer>() {
@Override
public boolean validate(Integer value) {
return value <= max;
}
};
addValidation(maxValidation);
}
public void setMin(int min) {
if (minValidation != null) {
removeValidation(minValidation);
}
minValidation = new PropertyValidationInteface<Integer>() {
@Override
public boolean validate(Integer value) {
return value >= min;
}
};
addValidation(minValidation);
}
@Override
protected Integer textToValue(String text) {
try {
return Integer.valueOf(text);
} catch (NumberFormatException nfe) {
return null;
}
}
@Override
protected String valueToText(Integer value) {
return "" + value;
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties;
/**
*
* @author JPEXS
* @param <E>
*/
public interface PropertyValidationInteface<E> {
public boolean validate(E value);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties;
/**
*
* @author JPEXS
*/
public class TextPropertyField extends AbstractPropertyField<String> {
public TextPropertyField(String text, int maxLength) {
super(text);
writeField.setColumns(maxLength);
addValidation(new PropertyValidationInteface<String>(){
@Override
public boolean validate(String value) {
return value.length() <= maxLength;
}
});
}
@Override
protected String textToValue(String text) {
return text;
}
@Override
protected String valueToText(String value) {
return value;
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties.panels;
import com.jpexs.decompiler.flash.easygui.EasyStrings;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
/**
*
* @author JPEXS
*/
public abstract class AbstractPropertiesPanel extends JPanel {
protected String titleIdentifier;
private final Map<String, JPanel> cardContents = new LinkedHashMap<>();
private final Map<String, JLabel> cardPlusMinusLabels = new LinkedHashMap<>();
public AbstractPropertiesPanel(String titleIdentifier) {
setLayout(new BorderLayout());
JLabel documentLabel = new JLabel(EasyStrings.translate("properties." + titleIdentifier));
add(documentLabel, BorderLayout.NORTH);
this.titleIdentifier = titleIdentifier;
}
protected String formatPropertyName(String id) {
String item = EasyStrings.translate("property."+titleIdentifier+"." + id);
return EasyStrings.translate("property.label").replace("%item%", item);
}
protected JPanel makeCard(String id, String icon, JPanel contents) {
JPanel cardPanel = new JPanel();
JPanel headerPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel(EasyStrings.translate("properties." + titleIdentifier + ".header." + id));
if (icon != null) {
label.setIcon(View.getIcon(icon));
}
label.setHorizontalAlignment(JLabel.CENTER);
headerPanel.add(label, BorderLayout.CENTER);
JLabel plusMinusLabel = new JLabel("+");
plusMinusLabel.setFont(plusMinusLabel.getFont().deriveFont(plusMinusLabel.getFont().getSize2D() * 1.8f));
plusMinusLabel.setHorizontalAlignment(JLabel.CENTER);
plusMinusLabel.setPreferredSize(new Dimension(30, 30));
headerPanel.add(plusMinusLabel, BorderLayout.WEST);
headerPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
headerPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
headerPanel.setMinimumSize(new Dimension(0, 40));
headerPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
cardPanel.setLayout(new BoxLayout(cardPanel, BoxLayout.Y_AXIS));
headerPanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
setCardOpened(id, !isCardOpened(id));
cardPanel.revalidate();
cardPanel.repaint();
}
}
});
contents.setAlignmentX(Component.LEFT_ALIGNMENT);
contents.setVisible(false);
cardPanel.add(headerPanel);
cardPanel.add(contents);
contents.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
//contents.setMaximumSize(new Dimension(getPreferredSize().width, contents.getPreferredSize().height + 10));
cardPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
cardPanel.setAlignmentY(Component.TOP_ALIGNMENT);
cardContents.put(id, contents);
cardPlusMinusLabels.put(id, plusMinusLabel);
return cardPanel;
}
private boolean isCardOpened(String id) {
return cardContents.get(id).isVisible();
}
private void setCardOpened(String id, boolean opened) {
JPanel contents = cardContents.get(id);
contents.setVisible(opened);
contents.setMaximumSize(new Dimension(Integer.MAX_VALUE, contents.getPreferredSize().height));
JLabel plusMinusLabel = cardPlusMinusLabels.get(id);
if (opened) {
plusMinusLabel.setText("-");
} else {
plusMinusLabel.setText("+");
}
}
protected void addToGrid(GridBagLayout layout, Container parent, Component component, int x, int y) {
addToGrid(layout, parent, component, x, y, 1, 1);
}
protected void addToGrid(GridBagLayout layout, Container parent, Component component, int x, int y, int w, int h) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(3, 3, 3, 3);
gbc.weightx = 0;
if (x == 0 && w == 1) {
gbc.anchor = GridBagConstraints.EAST;
}
parent.add(component, gbc);
}
}

View File

@@ -0,0 +1,448 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties.panels;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFCompression;
import static com.jpexs.decompiler.flash.SWFCompression.LZMA;
import static com.jpexs.decompiler.flash.SWFCompression.NONE;
import static com.jpexs.decompiler.flash.SWFCompression.ZLIB;
import com.jpexs.decompiler.flash.easygui.ChangeDoableOperation;
import com.jpexs.decompiler.flash.easygui.DoableOperation;
import com.jpexs.decompiler.flash.easygui.EasyStrings;
import com.jpexs.decompiler.flash.easygui.UndoManager;
import com.jpexs.decompiler.flash.easygui.properties.FloatPropertyField;
import com.jpexs.decompiler.flash.easygui.properties.IntegerPropertyField;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.ComboBoxItem;
import com.jpexs.decompiler.flash.gui.View;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
/**
*
* @author JPEXS
*/
public class DocumentPropertiesPanel extends AbstractPropertiesPanel {
private final JLabel displayRectPixelsLabel = new JLabel();
private final JPanel compressionEditorPanel = new JPanel();
private final JComboBox<ComboBoxItem<SWFCompression>> compressionComboBox = new JComboBox<>();
private final JPanel versionEditorPanel = new JPanel();
private final IntegerPropertyField versionEditor = new IntegerPropertyField(SWF.DEFAULT_VERSION, 1, 255);
private final JCheckBox gfxCheckBox = new JCheckBox();
private final JCheckBox encryptedCheckBox = new JCheckBox();
private final JPanel frameRateEditorPanel = new JPanel();
private final FloatPropertyField frameRateEditor = new FloatPropertyField(24f, 0.01f, 120f);
private final JPanel propertiesPanel = new JPanel();
private final JPanel displayRectEditorPanel = new JPanel();
private final IntegerPropertyField widthEditor = new IntegerPropertyField(550, 1, 8192);
private final IntegerPropertyField heightEditor = new IntegerPropertyField(400, 1, 8192);
private final JPanel warningPanel = new JPanel();
private final JLabel warningLabel = new JLabel();
private SWF swf;
private boolean modifying = false;
public DocumentPropertiesPanel(UndoManager undoManager) {
super("document");
FlowLayout layout = new FlowLayout(SwingConstants.WEST);
layout.setHgap(0);
layout.setVgap(0);
compressionEditorPanel.setLayout(layout);
compressionComboBox.addItem(new ComboBoxItem<>(AppStrings.translate("header.uncompressed"), SWFCompression.NONE));
compressionComboBox.addItem(new ComboBoxItem<>("Zlib", SWFCompression.ZLIB));
compressionComboBox.addItem(new ComboBoxItem<>("LZMA", SWFCompression.LZMA));
compressionComboBox.addActionListener((ActionEvent e) -> {
validateHeader();
});
compressionEditorPanel.add(compressionComboBox);
versionEditorPanel.setLayout(layout);
versionEditor.setPreferredSize(new Dimension(80, versionEditor.getPreferredSize().height));
versionEditor.addChangeListener((ChangeEvent e) -> {
validateHeader();
});
versionEditorPanel.add(versionEditor);
encryptedCheckBox.addChangeListener((ChangeEvent e) -> {
validateHeader();
});
gfxCheckBox.addChangeListener((ChangeEvent e) -> {
validateHeader();
});
frameRateEditorPanel.setLayout(layout);
frameRateEditor.setPreferredSize(new Dimension(80, frameRateEditor.getPreferredSize().height));
frameRateEditorPanel.add(frameRateEditor);
displayRectEditorPanel.setLayout(layout);
//displayRectEditorPanel.setMinimumSize(new Dimension(10, displayRectEditorPanel.getMinimumSize().height));
//widthEditor.setPreferredSize(new Dimension(80, widthEditor.getPreferredSize().height));
//heightEditor.setPreferredSize(new Dimension(80, heightEditor.getPreferredSize().height));
displayRectEditorPanel.add(widthEditor);
displayRectEditorPanel.add(new JLabel("\u00D7 "));
displayRectEditorPanel.add(heightEditor);
displayRectEditorPanel.add(new JLabel(" px"));
warningLabel.setIcon(View.getIcon("warning16"));
warningPanel.setLayout(layout);
warningPanel.setBackground(new Color(255, 213, 29));
warningPanel.add(warningLabel);
GridBagLayout gridBag = new GridBagLayout();
propertiesPanel.setLayout(gridBag);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.compression")), 0, 1);
addToGrid(gridBag, propertiesPanel, compressionEditorPanel, 1, 1);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.version")), 0, 2);
addToGrid(gridBag, propertiesPanel, versionEditorPanel, 1, 2);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.encrypted")), 0, 3);
addToGrid(gridBag, propertiesPanel, encryptedCheckBox, 1, 3);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.gfx")), 0, 4);
addToGrid(gridBag, propertiesPanel, gfxCheckBox, 1, 4);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.framerate")), 0, 6);
addToGrid(gridBag, propertiesPanel, frameRateEditorPanel, 1, 6);
addToGrid(gridBag, propertiesPanel, new JLabel(AppStrings.translate("header.displayrect")), 0, 7);
addToGrid(gridBag, propertiesPanel, displayRectEditorPanel, 1, 7);
addToGrid(gridBag, propertiesPanel, new JLabel(""), 0, 8);
addToGrid(gridBag, propertiesPanel, displayRectPixelsLabel, 1, 8);
addToGrid(gridBag, propertiesPanel, warningPanel, 0, 9, 2, 1);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 10;
gbc.gridwidth = 3;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
propertiesPanel.add(new JPanel(), gbc);
gbc = new GridBagConstraints();
gbc.gridx = 2;
gbc.gridy = 0;
gbc.gridheight = 10;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
propertiesPanel.add(new JPanel(), gbc);
add(propertiesPanel, BorderLayout.CENTER);
warningPanel.setVisible(false);
compressionComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (modifying) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("compression") {
SWFCompression itemBefore = swf.compression;
SWFCompression itemAfter = getCompression();
@Override
public void doHeaderOperation() {
swf.compression = itemAfter;
}
@Override
public void undoHeaderOperation() {
swf.compression = itemBefore;
}
}, swf);
}
});
versionEditor.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("swfVersion") {
int itemBefore = swf.version;
int itemAfter = versionEditor.getValue();
@Override
public void doHeaderOperation() {
swf.version = itemAfter;
}
@Override
public void undoHeaderOperation() {
swf.version = itemBefore;
}
}, swf);
});
encryptedCheckBox.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
if (encryptedCheckBox.isSelected() == swf.encrypted) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("encrypted") {
boolean itemBefore = swf.encrypted;
boolean itemAfter = encryptedCheckBox.isSelected();
@Override
public void doHeaderOperation() {
swf.encrypted = itemAfter;
}
@Override
public void undoHeaderOperation() {
swf.encrypted = itemBefore;
}
}, swf);
});
gfxCheckBox.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
if (gfxCheckBox.isSelected() == swf.gfx) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("gfx") {
boolean itemBefore = swf.gfx;
boolean itemAfter = gfxCheckBox.isSelected();
@Override
public void doHeaderOperation() {
swf.gfx = itemAfter;
}
@Override
public void undoHeaderOperation() {
swf.gfx = itemBefore;
}
}, swf);
});
frameRateEditor.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("frameRate") {
float itemBefore = swf.frameRate;
float itemAfter = frameRateEditor.getValue();
@Override
public void doHeaderOperation() {
swf.frameRate = itemAfter;
}
@Override
public void undoHeaderOperation() {
swf.frameRate = itemBefore;
}
}, swf);
});
widthEditor.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("width") {
int xMinBefore = swf.displayRect.Xmin;
int xMaxBefore = swf.displayRect.Xmax;
int xMaxAfter = widthEditor.getValue() * 20;
@Override
public void doHeaderOperation() {
swf.displayRect.Xmin = 0;
swf.displayRect.Xmax = xMaxAfter;
}
@Override
public void undoHeaderOperation() {
swf.displayRect.Xmin = xMinBefore;
swf.displayRect.Xmax = xMaxBefore;
}
}, swf);
});
heightEditor.addChangeListener((ChangeEvent e) -> {
if (modifying) {
return;
}
undoManager.doOperation(new HeaderChangeDoableOperation("height") {
int yMinBefore = swf.displayRect.Ymin;
int yMaxBefore = swf.displayRect.Ymax;
int yMaxAfter = heightEditor.getValue() * 20;
@Override
public void doHeaderOperation() {
swf.displayRect.Ymin = 0;
swf.displayRect.Ymax = yMaxAfter;
}
@Override
public void undoHeaderOperation() {
swf.displayRect.Ymin = yMinBefore;
swf.displayRect.Ymax = yMaxBefore;
}
}, swf);
});
}
private boolean validateHeader() {
int version = getVersionNumber();
boolean gfx = gfxCheckBox.isSelected();
boolean encrypted = encryptedCheckBox.isSelected();
SWFCompression compression = getCompression();
List<String> results = new ArrayList<>();
if (gfx && !(compression == SWFCompression.NONE || compression == SWFCompression.ZLIB)) {
results.add(AppStrings.translate("header.warning.unsupportedGfxCompression"));
}
if (gfx && encrypted) {
results.add(AppStrings.translate("header.warning.unsupportedGfxEncryption"));
}
if (compression == SWFCompression.ZLIB && version < 6) {
results.add(AppStrings.translate("header.warning.minimumZlibVersion"));
}
if (compression == SWFCompression.LZMA && version < 13) {
results.add(AppStrings.translate("header.warning.minimumLzmaVersion"));
}
warningPanel.setVisible(!results.isEmpty());
if (!results.isEmpty()) {
warningLabel.setText("<html>" + String.join("<br>", results) + "</html>");
}
return results.isEmpty();
}
private int getVersionNumber() {
return versionEditor.getValue();
}
private SWFCompression getCompression() {
@SuppressWarnings("unchecked")
ComboBoxItem<SWFCompression> item = (ComboBoxItem<SWFCompression>) compressionComboBox.getSelectedItem();
return item.getValue();
}
private void refresh() {
modifying = true;
propertiesPanel.setVisible(swf != null);
if (swf == null) {
modifying = false;
return;
}
switch (swf.compression) {
case LZMA:
compressionComboBox.setSelectedIndex(2);
break;
case ZLIB:
compressionComboBox.setSelectedIndex(1);
break;
case NONE:
compressionComboBox.setSelectedIndex(0);
break;
}
versionEditor.setValue(swf.version);
encryptedCheckBox.setSelected(swf.encrypted);
gfxCheckBox.setSelected(swf.gfx);
frameRateEditor.setValue(swf.frameRate);
widthEditor.setValue(swf.displayRect.getWidth() / 20);
heightEditor.setValue(swf.displayRect.getHeight() / 20);
modifying = false;
}
public void setSwf(SWF swf) {
this.swf = swf;
refresh();
}
abstract class HeaderChangeDoableOperation extends ChangeDoableOperation {
private boolean modifiedBefore = swf.isHeaderModified();
public HeaderChangeDoableOperation(String itemIdentifier) {
super(itemIdentifier);
}
@Override
public final void doOperation() {
modifying = true;
doHeaderOperation();
swf.setHeaderModified(true);
refresh();
validateHeader();
modifying = false;
}
@Override
public final void undoOperation() {
modifying = true;
undoHeaderOperation();
swf.setHeaderModified(modifiedBefore);
refresh();
validateHeader();
modifying = false;
}
public abstract void doHeaderOperation();
public abstract void undoHeaderOperation();
}
}

View File

@@ -0,0 +1,370 @@
/*
* Copyright (C) 2024 JPEXS
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.easygui.properties.panels;
import com.jpexs.decompiler.flash.easygui.ChangeDoableOperation;
import com.jpexs.decompiler.flash.easygui.EasyStrings;
import com.jpexs.decompiler.flash.easygui.EasySwfPanel;
import com.jpexs.decompiler.flash.easygui.UndoManager;
import com.jpexs.decompiler.flash.easygui.properties.IntegerPropertyField;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.ImagePanel;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.converters.PlaceObjectTypeConverter;
import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
import com.jpexs.decompiler.flash.types.ColorTransform;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
*
* @author JPEXS
*/
public class GeneralPropertiesPanel extends AbstractPropertiesPanel {
private final IntegerPropertyField alphaPercentPropertyField = new IntegerPropertyField(100, -100, 100);
private final IntegerPropertyField redPercentPropertyField = new IntegerPropertyField(100, -100, 100);
private final IntegerPropertyField greenPercentPropertyField = new IntegerPropertyField(100, -100, 100);
private final IntegerPropertyField bluePercentPropertyField = new IntegerPropertyField(100, -100, 100);
private final IntegerPropertyField alphaAddPropertyField = new IntegerPropertyField(0, -255, 255);
private final IntegerPropertyField redAddPropertyField = new IntegerPropertyField(0, -255, 255);
private final IntegerPropertyField greenAddPropertyField = new IntegerPropertyField(0, -255, 255);
private final IntegerPropertyField blueAddPropertyField = new IntegerPropertyField(0, -255, 255);
private final EasySwfPanel swfPanel;
private final JPanel propertiesPanel;
private boolean updating = false;
public GeneralPropertiesPanel(EasySwfPanel swfPanel, UndoManager undoManager) {
super("general");
JPanel colorEffectPanel = new JPanel();
GridBagLayout gridBag = new GridBagLayout();
colorEffectPanel.setLayout(gridBag);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 0;
gbc.insets = new Insets(3, 3, 3, 3);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
colorEffectPanel.add(new JLabel(formatPropertyName("colorEffect.alpha")), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
colorEffectPanel.add(alphaPercentPropertyField, gbc);
gbc.gridx++;
colorEffectPanel.add(new JLabel("% \u00D7 A + "), gbc);
gbc.gridx++;
colorEffectPanel.add(alphaAddPropertyField, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
colorEffectPanel.add(new JLabel(formatPropertyName("colorEffect.red")), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
colorEffectPanel.add(redPercentPropertyField, gbc);
gbc.gridx++;
colorEffectPanel.add(new JLabel("% \u00D7 R + "), gbc);
gbc.gridx++;
colorEffectPanel.add(redAddPropertyField, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
colorEffectPanel.add(new JLabel(formatPropertyName("colorEffect.green")), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
colorEffectPanel.add(greenPercentPropertyField, gbc);
gbc.gridx++;
colorEffectPanel.add(new JLabel("% \u00D7 G + "), gbc);
gbc.gridx++;
colorEffectPanel.add(greenAddPropertyField, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
colorEffectPanel.add(new JLabel(formatPropertyName("colorEffect.blue")), gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx++;
colorEffectPanel.add(bluePercentPropertyField, gbc);
gbc.gridx++;
colorEffectPanel.add(new JLabel("% \u00D7 B + "), gbc);
gbc.gridx++;
colorEffectPanel.add(blueAddPropertyField, gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.gridheight = 4;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
colorEffectPanel.add(new JPanel(), gbc);
propertiesPanel = new JPanel();
propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS));
propertiesPanel.add(makeCard("colorEffect", null, colorEffectPanel));
this.swfPanel = swfPanel;
alphaPercentPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = alphaPercentPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.alphaMultTerm = value * 256 / 100;
colorTransform.hasMultTerms = true;
}
}, swfPanel.getSwf());
}
});
alphaAddPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = alphaAddPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.alphaAddTerm = value;
colorTransform.hasAddTerms = true;
}
}, swfPanel.getSwf());
}
});
redPercentPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = redPercentPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.redMultTerm = value * 256 / 100;
colorTransform.hasMultTerms = true;
}
}, swfPanel.getSwf());
}
});
redAddPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = redAddPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.redAddTerm = value;
colorTransform.hasAddTerms = true;
}
}, swfPanel.getSwf());
}
});
greenPercentPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = greenPercentPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.greenMultTerm = value * 256 / 100;
colorTransform.hasMultTerms = true;
}
}, swfPanel.getSwf());
}
});
greenAddPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = greenAddPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.greenAddTerm = value;
colorTransform.hasAddTerms = true;
}
}, swfPanel.getSwf());
}
});
bluePercentPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = bluePercentPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.blueMultTerm = value * 256 / 100;
colorTransform.hasMultTerms = true;
}
}, swfPanel.getSwf());
}
});
blueAddPropertyField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (updating) {
return;
}
undoManager.doOperation(new ColorEffectChangeDoableOperation() {
int value = blueAddPropertyField.getValue();
@Override
public void doColorEffectOperation(CXFORMWITHALPHA colorTransform) {
colorTransform.blueAddTerm = value;
colorTransform.hasAddTerms = true;
}
}, swfPanel.getSwf());
}
});
add(propertiesPanel, BorderLayout.CENTER);;
}
public void update() {
updating = true;
DepthState ds = swfPanel.getSelectedDepthState();
if (ds == null || ds.placeObjectTag == null) {
propertiesPanel.setVisible(false);
return;
}
propertiesPanel.setVisible(true);
ColorTransform colorTransform = ds.colorTransForm;
if (colorTransform == null) {
alphaPercentPropertyField.setValue(100);
alphaAddPropertyField.setValue(0);
redPercentPropertyField.setValue(100);
redAddPropertyField.setValue(0);
greenPercentPropertyField.setValue(100);
greenAddPropertyField.setValue(0);
bluePercentPropertyField.setValue(100);
blueAddPropertyField.setValue(0);
} else {
alphaPercentPropertyField.setValue(colorTransform.getAlphaMulti() * 100 / 256);
alphaAddPropertyField.setValue(colorTransform.getAlphaAdd());
redPercentPropertyField.setValue(colorTransform.getRedMulti() * 100 / 256);
redAddPropertyField.setValue(colorTransform.getRedAdd());
greenPercentPropertyField.setValue(colorTransform.getGreenMulti() * 100 / 256);
greenAddPropertyField.setValue(colorTransform.getGreenAdd());
bluePercentPropertyField.setValue(colorTransform.getBlueMulti() * 100 / 256);
blueAddPropertyField.setValue(colorTransform.getBlueAdd());
}
updating = false;
}
abstract class PlaceChangeDoableOperation extends ChangeDoableOperation {
int fdepth = swfPanel.getDepth();
int fframe = swfPanel.getFrame();
DepthState depthStateBefore = swfPanel.getSelectedDepthState();
PlaceObjectTypeTag placeObjectBefore = depthStateBefore.placeObjectTag;
PlaceObjectTypeTag placeObjectAfter = null;
private final int minPlace;
private final boolean timelinedModifiedBefore = placeObjectBefore.getTimelined().isModified();
public PlaceChangeDoableOperation(String itemIdentifier, int minPlace) {
super(itemIdentifier);
this.minPlace = minPlace;
}
@Override
public final void doOperation() {
swfPanel.getStagePanel().gotoFrame(fframe + 1);
swfPanel.getStagePanel().selectDepth(fdepth);
int convNum = placeObjectBefore.getPlaceObjectNum() < minPlace ? minPlace : placeObjectBefore.getPlaceObjectNum();
PlaceObjectTypeConverter conv = new PlaceObjectTypeConverter();
placeObjectAfter = conv.convertTagType(placeObjectBefore, convNum);
doPlaceOperation(placeObjectAfter, depthStateBefore);
placeObjectAfter.getTimelined().resetTimeline();
update();
}
@Override
public final void undoOperation() {
swfPanel.getStagePanel().gotoFrame(fframe + 1);
swfPanel.getStagePanel().selectDepth(fdepth);
int index = placeObjectAfter.getTimelined().indexOfTag(placeObjectAfter);
Timelined timelined = placeObjectAfter.getTimelined();
timelined.removeTag(index);
timelined.addTag(index, placeObjectBefore);
if (!timelinedModifiedBefore) {
timelined.setModified(false);
}
timelined.resetTimeline();
update();
}
public abstract void doPlaceOperation(PlaceObjectTypeTag placeObject, DepthState depthState);
}
abstract class ColorEffectChangeDoableOperation extends PlaceChangeDoableOperation {
CXFORMWITHALPHA colorTransformAfter;
public ColorEffectChangeDoableOperation() {
super("colorEffect", 2);
}
@Override
public final void doPlaceOperation(PlaceObjectTypeTag placeObject, DepthState depthState) {
colorTransformAfter = depthState.colorTransForm == null ? new CXFORMWITHALPHA() : new CXFORMWITHALPHA(depthState.colorTransForm);
doColorEffectOperation(colorTransformAfter);
placeObject.setColorTransform(colorTransformAfter);
}
public abstract void doColorEffectOperation(CXFORMWITHALPHA colorTransform);
}
}

View File

@@ -53,7 +53,36 @@ action.removeFrame = Remove frame
action.transform = Transform
action.move = Move
action.addToStage = Add to stage
action.change = Change %item%
action.change.compression = Compression
action.change.swfVersion = SWF version
action.change.encrypted = Encrypted
action.change.swfVersion = SWF version
action.change.gfx = GFX
action.change.frameRate = Frame rate
action.change.width = Width
action.change.height = Height
action.change.colorEffect = Color effect
timeline.main = Main timeline
timeline.item = Timeline of %item%
timeline.item.cancel = Cancel - Click to go to main timeline
timeline.item.cancel = Cancel - Click to go to main timeline
properties = Properties
properties.document = Document
properties.general = General
properties.general.header.colorEffect = Color effect
property.label = %item%:
property.general.item = Item
property.general.colorEffect.alpha = Alpha
property.general.colorEffect.red = Red
property.general.colorEffect.green = Green
property.general.colorEffect.blue = Blue