/*
* Copyright (C) 2010-2016 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.gui.abc;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.timeline.AS3Package;
import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem;
import com.jpexs.decompiler.graph.DottedChain;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
*
* @author JPEXS
*/
public class ClassesListTreeModel extends AS3ClassTreeItem implements TreeModel {
private final SWF swf;
private List<ScriptPack> list;
private final AS3Package root;
private final List<TreeModelListener> listeners = new ArrayList<>();
public List<ScriptPack> getList() {
return list;
}
public ClassesListTreeModel(SWF swf) {
super(null, null, null);
root = new AS3Package(null, swf);
this.swf = swf;
this.list = swf.getAS3Packs();
setFilter(null);
}
@Override
public SWF getSwf() {
return swf;
}
public final void update() {
this.list = swf.getAS3Packs();
TreeModelEvent event = new TreeModelEvent(this, new TreePath(root));
for (TreeModelListener listener : listeners) {
listener.treeStructureChanged(event);
}
}
public final void setFilter(String filter) {
root.clear();
List<String> ignoredClasses = new ArrayList<>();
List<String> ignoredNss = new ArrayList<>();
if (Configuration._ignoreAdditionalFlexClasses.get()) {
getSwf().getFlexMainClass(ignoredClasses, ignoredNss);
}
filter = (filter == null || filter.isEmpty()) ? null : filter.toLowerCase();
loop:
for (ScriptPack item : list) {
if (filter != null) {
if (!item.getClassPath().toString().toLowerCase().contains(filter)) {
continue;
}
}
if (!item.isSimple && Configuration.ignoreCLikePackages.get()) {
continue;
}
if (Configuration._ignoreAdditionalFlexClasses.get()) {
String fullName = item.getClassPath().packageStr.add(item.getClassPath().className, item.getClassPath().namespaceSuffix).toRawString();
if (ignoredClasses.contains(fullName)) {
continue;
}
for (String ns : ignoredNss) {
if (fullName.startsWith(ns + ".")) {
continue loop;
}
}
}
DottedChain packageStr = item.getClassPath().packageStr;
AS3Package pkg = ensurePackage(packageStr);
pkg.addScriptPack(item);
}
}
private AS3Package ensurePackage(DottedChain packageStr) {
AS3Package parent = root;
for (int i = 0; i < packageStr.size(); i++) {
String pathElement = packageStr.get(i);
AS3Package pkg = parent.getSubPackage(pathElement);
if (pkg == null) {
pkg = new AS3Package(pathElement, swf);
parent.addSubPackage(pkg);
}
parent = pkg;
}
return parent;
}
public ScriptPack getElementByClassIndex(int classIndex) {
return getElementByClassIndexRecursive(root, classIndex);
}
private ScriptPack getElementByClassIndexRecursive(AS3Package item, int classIndex) {
for (AS3Package pkg : item.getSubPackages()) {
ScriptPack result = getElementByClassIndexRecursive(pkg, classIndex);
if (result != null) {
return result;
}
}
for (ScriptPack sc : item.getScriptPacks()) {
for (Trait t : sc.abc.script_info.get(sc.scriptIndex).traits.traits) {
if (t instanceof TraitClass) {
if (((TraitClass) t).class_info == classIndex) {
return sc;
}
}
}
}
return null;
}
@Override
public AS3ClassTreeItem getRoot() {
return root;
}
public List<AS3ClassTreeItem> getAllChildren(Object parent) {
AS3Package pkg = (AS3Package) parent;
return pkg.getAllChildren();
}
@Override
public AS3ClassTreeItem getChild(Object parent, int index) {
AS3Package pkg = (AS3Package) parent;
return pkg.getChild(index);
}
@Override
public int getChildCount(Object parent) {
AS3ClassTreeItem parentItem = (AS3ClassTreeItem) parent;
if (parentItem instanceof ScriptPack) {
return 0;
}
AS3Package pkg = (AS3Package) parentItem;
return pkg.getChildCount();
}
@Override
public boolean isLeaf(Object node) {
AS3ClassTreeItem te = (AS3ClassTreeItem) node;
return te instanceof ScriptPack;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
AS3Package pkg = (AS3Package) parent;
return pkg.getIndexOfChild((AS3ClassTreeItem) child);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
@Override
public String toString() {
return AppStrings.translate("node.scripts");
}
@Override
public boolean isModified() {
return root.isModified();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ClassesListTreeModel)) {
return false;
}
return swf.equals(((ClassesListTreeModel) obj).swf);
}
@Override
public int hashCode() {
return ClassesListTreeModel.class.hashCode() ^ swf.hashCode();
}
}