diff --git a/.gitignore b/.gitignore index 9522c5824..b562aac77 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,7 @@ hs_err_pid*.log /libsrc/jpproxy/build/ /libsrc/LZMA/nbproject/private/ /libsrc/ttf/nbproject/private/ -/libsrc/ttf/build/ \ No newline at end of file +/libsrc/ttf/build/ +/libsrc/tablelayout/nbproject/private/ +/libsrc/tablelayout/build/ +/libsrc/tablelayout/dist/ \ No newline at end of file diff --git a/lib/tablelayout.jar b/lib/tablelayout.jar new file mode 100644 index 000000000..0c109eb37 Binary files /dev/null and b/lib/tablelayout.jar differ diff --git a/lib/ttf.jar b/lib/ttf.jar index 651b36145..9f4e7edcc 100644 Binary files a/lib/ttf.jar and b/lib/ttf.jar differ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index a172d5ad0..ba3616327 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -271,7 +271,8 @@ public final class SWF implements TreeItem, Timelined { public Map characters = new HashMap<>(); public List abcList; public JPEGTablesTag jtt; - public Map sourceFontsMap = new HashMap<>(); + public Map sourceFontFamiliesMap = new HashMap<>(); + public Map sourceFontFacesMap = new HashMap<>(); public static final double unitDivisor = 20; private static final Logger logger = Logger.getLogger(SWF.class.getName()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 0ffd95b6f..33258aaad 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -452,7 +452,7 @@ public class Configuration { recentFiles.set(Helper.joinStrings(recentFilesArray, "::")); } - public static Map getFontPairs() { + public static Map getFontIdToFamilyMap() { String fonts = fontPairing.get(); if (fonts == null) { return new HashMap<>(); @@ -467,19 +467,39 @@ public class Configuration { } return result; } + + public static Map getFontIdToFaceMap() { + String fonts = fontPairing.get(); + if (fonts == null) { + return new HashMap<>(); + } - public static void addFontPair(String fileName, int fontId, String fontName, String systemFontName) { + Map result = new HashMap<>(); + for (String pair : fonts.split("::")) { + if (!pair.isEmpty()) { + String[] splittedPair = pair.split("="); + result.put(splittedPair[0], splittedPair.length<3?"":splittedPair[2]); + } + } + return result; + } + + public static void addFontPair(String fileName, int fontId, String fontName, String installedFontFamily, String installedFontFace) { String key = fileName + "_" + fontId + "_" + fontName; - Map fontPairs = getFontPairs(); - fontPairs.put(key, systemFontName); - fontPairs.put(fontName, systemFontName); + Map fontPairs = getFontIdToFamilyMap(); + fontPairs.put(key, installedFontFamily); + fontPairs.put(fontName, installedFontFamily); + + Map facePairs = getFontIdToFaceMap(); + facePairs.put(key, installedFontFace); + facePairs.put(fontName, installedFontFace); StringBuilder sb = new StringBuilder(); int i = 0; for (Entry pair : fontPairs.entrySet()) { if (i != 0) { sb.append("::"); } - sb.append(pair.getKey()).append("=").append(pair.getValue()); + sb.append(pair.getKey()).append("=").append(pair.getValue()).append("=").append(facePairs.containsKey(pair.getKey())?facePairs.get(pair.getKey()):""); i++; } fontPairing.set(sb.toString()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/FontHelper.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/FontHelper.java index 7a55e8240..1340df6c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/FontHelper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/FontHelper.java @@ -12,34 +12,84 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.helpers; -import com.sun.jna.Platform; +import com.jpexs.decompiler.flash.AppResources; +import java.awt.Font; import java.awt.GraphicsEnvironment; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.Map; /** * * @author JPEXS */ public class FontHelper { + + /** + * Gets all available fonts in the system + * @return Map> + */ + public static Map> getInstalledFonts(){ + Map> ret = new HashMap<>(); + Font fonts[] = null; + + try { + Class clFmFactory = Class.forName("sun.font.FontManagerFactory"); + Object fm = clFmFactory.getDeclaredMethod("getInstance").invoke(null); + Class clFm = Class.forName("sun.font.SunFontManager"); - public static String[] getInstalledFontFamilyNames() { - // todo: cannot load newly installed fonts, so this feature is disabled until i find a solution for font loading problem - if (Platform.isWindows()) { - try { - Class clW32Fm = Class.forName("sun.awt.Win32FontManager"); - Class clSunFm = Class.forName("sun.font.SunFontManager"); - Object fm = clW32Fm.newInstance(); - return (String[]) clSunFm.getDeclaredMethod("getInstalledFontFamilyNames", Locale.class).invoke(fm, Locale.getDefault()); - } catch (Throwable ex) { - // catch everything to avoid class not found problems, because Win32FontManager is an internal proprietary API - Logger.getLogger(FontHelper.class.getName()).log(Level.SEVERE, null, ex); - } + //Delete cached installed names + Field inField = clFm.getDeclaredField("installedNames"); + inField.setAccessible(true); + inField.set(null, null); + + //Delete cached family names + Field allFamField = clFm.getDeclaredField("allFamilies"); + allFamField.setAccessible(true); + allFamField.set(fm,null); + + //Delete cached fonts + Field allFonField = clFm.getDeclaredField("allFonts"); + allFonField.setAccessible(true); + allFonField.set(fm, null); + + fonts = (Font[]) clFm.getDeclaredMethod("getAllInstalledFonts").invoke(fm); + } catch (Throwable ex) { + //ignore } - return GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + if(fonts == null){ + fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); + } + for(Font f:fonts){ + String fam = f.getFamily(Locale.getDefault()); + //Do not want Java logical fonts + if(Arrays.asList("Dialog","DialogInput","Monospaced","Serif","SansSerif").contains(fam)){ + continue; + } + if(!ret.containsKey(fam)){ + ret.put(fam, new HashMap()); + } + String face = getFontFace(f); + ret.get(f.getFamily()).put(face, f); + } + return ret; + } + + public static String getFontFace(Font f){ + String fam = f.getFamily(Locale.getDefault()); + String face = f.getFontName(Locale.getDefault()); + if(face.startsWith(fam)){ + face = face.substring(fam.length()).trim(); + } + if(face.startsWith(".")){ + face = face.substring(1); + } + return face; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java index 866557b4c..1875fa534 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/FontTag.java @@ -120,9 +120,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable public abstract int getLeading(); - public static String[] fontNamesArray; - - public static List fontNames; + public static Map> installedFonts; public static String defaultFontName; @@ -168,7 +166,7 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable } public String getSystemFontName() { - Map fontPairs = Configuration.getFontPairs(); + Map fontPairs = Configuration.getFontIdToFamilyMap(); String key = swf.getShortFileName() + "_" + getFontId() + "_" + getFontName(); if (fontPairs.containsKey(key)) { return fontPairs.get(key); @@ -224,51 +222,52 @@ public abstract class FontTag extends CharacterTag implements AloneTag, Drawable } public static void reload() { - fontNamesArray = FontHelper.getInstalledFontFamilyNames(); - fontNames = Arrays.asList(fontNamesArray); - if (fontNames.contains("Times New Roman")) { + installedFonts = FontHelper.getInstalledFonts(); + + if (installedFonts.containsKey("Times New Roman")) { defaultFontName = "Times New Roman"; - } else if (fontNames.contains("Arial")) { + } else if (installedFonts.containsKey("Arial")) { defaultFontName = "Arial"; } else { - defaultFontName = fontNames.get(0); + defaultFontName = installedFonts.keySet().iterator().next(); } } public static String getFontNameWithFallback(String fontName) { - if (fontNames.contains(fontName)) { + if (installedFonts.containsKey(fontName)) { return fontName; } - if (fontNames.contains("Times New Roman")) { + if (installedFonts.containsKey("Times New Roman")) { return "Times New Roman"; } - if (fontNames.contains("Arial")) { + if (installedFonts.containsKey("Arial")) { return "Arial"; } - //Fallback to DIALOG - return "Dialog"; + + //First font + return installedFonts.keySet().iterator().next(); } - public static String isFontInstalled(String fontName) { - if (fontNames.contains(fontName)) { - return fontName; + public static String isFontFamilyInstalled(String fontFamily) { + if (installedFonts.containsKey(fontFamily)) { + return fontFamily; } - if (fontName.contains("_")) { - String beforeUnderscore = fontName.substring(0, fontName.indexOf('_')); - if (fontNames.contains(beforeUnderscore)) { + if (fontFamily.contains("_")) { + String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_')); + if (installedFonts.containsKey(beforeUnderscore)) { return beforeUnderscore; } } return null; } - public static String findInstalledFontName(String fontName) { - if (fontNames.contains(fontName)) { - return fontName; + public static String findInstalledFontFamily(String fontFamily) { + if (installedFonts.containsKey(fontFamily)) { + return fontFamily; } - if (fontName.contains("_")) { - String beforeUnderscore = fontName.substring(0, fontName.indexOf('_')); - if (fontNames.contains(beforeUnderscore)) { + if (fontFamily.contains("_")) { + String beforeUnderscore = fontFamily.substring(0, fontFamily.indexOf('_')); + if (installedFonts.containsKey(beforeUnderscore)) { return beforeUnderscore; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java index c21fe14aa..2853eb8f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/MissingCharacterHandler.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.tags.base; import java.awt.Font; +import java.util.Map; /** * @@ -26,10 +27,22 @@ public class MissingCharacterHandler { public boolean handle(FontTag font, char character) { String fontName = font.getFontName(); - if (!FontTag.fontNames.contains(fontName)) { + if (!FontTag.installedFonts.containsKey(fontName)) { return false; } - Font f = new Font(fontName, font.getFontStyle(), 18); + Map faces = FontTag.installedFonts.get(fontName); + + Font f = null; + for (String face : faces.keySet()) { + Font ff = faces.get(face); + if (ff.isBold() == font.isBold() && ff.isItalic() == font.isItalic()) { + f = ff; + break; + } + } + if (f == null) { + f = faces.get(faces.keySet().iterator().next()); + } if (!f.canDisplay(character)) { return false; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index db8839fda..ac00684ae 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1954,7 +1954,7 @@ public class XFLConverter { } int fontStyle = font.getFontStyle(); String installedFont; - if ((installedFont = FontTag.isFontInstalled(fontName)) != null) { + if ((installedFont = FontTag.isFontFamilyInstalled(fontName)) != null) { fontName = new Font(installedFont, fontStyle, 10).getPSName(); } String embedRanges = ""; @@ -2458,7 +2458,7 @@ public class XFLConverter { fontStyle = font.getFontStyle(); } String installedFont; - if ((installedFont = FontTag.isFontInstalled(fontName)) != null) { + if ((installedFont = FontTag.isFontFamilyInstalled(fontName)) != null) { psFontName = new Font(installedFont, fontStyle, 10).getPSName(); } else { psFontName = fontName; @@ -2616,7 +2616,7 @@ public class XFLConverter { size = det.fontHeight; fontFace = fontName; String installedFont = null; - if ((installedFont = FontTag.isFontInstalled(fontName)) != null) { + if ((installedFont = FontTag.isFontFamilyInstalled(fontName)) != null) { fontName = installedFont; fontFace = new Font(installedFont, (italic ? Font.ITALIC : 0) | (bold ? Font.BOLD : 0) | (!italic && !bold ? Font.PLAIN : 0), size < 0 ? 10 : size).getPSName(); } @@ -3355,7 +3355,7 @@ public class XFLConverter { fontName = ft.getFontName(); } String installedFont; - if ((installedFont = FontTag.isFontInstalled(fontName)) != null) { + if ((installedFont = FontTag.isFontFamilyInstalled(fontName)) != null) { fontFace = new Font(installedFont, (italic ? Font.ITALIC : 0) | (bold ? Font.BOLD : 0) | (!italic && !bold ? Font.PLAIN : 0), size < 0 ? 10 : size).getPSName(); } else { fontFace = fontName; diff --git a/libsrc/tablelayout/build.xml b/libsrc/tablelayout/build.xml deleted file mode 100644 index ae1a49d7b..000000000 --- a/libsrc/tablelayout/build.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - Builds, tests, and runs the project tablelayout. - - - diff --git a/libsrc/tablelayout/nbproject/build-impl.xml b/libsrc/tablelayout/nbproject/build-impl.xml deleted file mode 100644 index bc8c6ee04..000000000 --- a/libsrc/tablelayout/nbproject/build-impl.xml +++ /dev/null @@ -1,1413 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set src.dir - Must set test.src.dir - Must set build.dir - Must set dist.dir - Must set build.classes.dir - Must set dist.javadoc.dir - Must set build.test.classes.dir - Must set build.test.results.dir - Must set build.classes.excludes - Must set dist.jar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No tests executed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set JVM to use for profiling in profiler.info.jvm - Must set profiler agent JVM arguments in profiler.info.jvmargs.agent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To run this application from the command line without Ant, try: - - java -jar "${dist.jar.resolved}" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - Must select one file in the IDE or set run.class - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set debug.class - - - - - Must select one file in the IDE or set debug.class - - - - - Must set fix.includes - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - Must select one file in the IDE or set profile.class - This target only works when run from inside the NetBeans IDE. - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - This target only works when run from inside the NetBeans IDE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select one file in the IDE or set run.class - - - - - - Must select some files in the IDE or set test.includes - - - - - Must select one file in the IDE or set run.class - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must select some files in the IDE or set javac.includes - - - - - - - - - - - - - - - - - - - - Some tests failed; see details above. - - - - - - - - - Must select some files in the IDE or set test.includes - - - - Some tests failed; see details above. - - - - Must select some files in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - Some tests failed; see details above. - - - - - Must select one file in the IDE or set test.class - - - - Must select one file in the IDE or set test.class - Must select some method in the IDE or set test.method - - - - - - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - Must select one file in the IDE or set applet.url - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libsrc/tablelayout/nbproject/genfiles.properties b/libsrc/tablelayout/nbproject/genfiles.properties deleted file mode 100644 index 72e23fc4c..000000000 --- a/libsrc/tablelayout/nbproject/genfiles.properties +++ /dev/null @@ -1,8 +0,0 @@ -build.xml.data.CRC32=e5124a5d -build.xml.script.CRC32=4efcaf5c -build.xml.stylesheet.CRC32=8064a381@1.74.2.48 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=e5124a5d -nbproject/build-impl.xml.script.CRC32=1a6f89d0 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.2.48 diff --git a/libsrc/tablelayout/nbproject/project.properties b/libsrc/tablelayout/nbproject/project.properties deleted file mode 100644 index 4a19a9a31..000000000 --- a/libsrc/tablelayout/nbproject/project.properties +++ /dev/null @@ -1,73 +0,0 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=tablelayout -application.vendor=Jindra -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=../../lib/tablelayout.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -excludes= -includes=** -jar.compress=false -javac.classpath= -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath} -javac.source=1.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -javac.test.processorpath=\ - ${javac.test.classpath} -javadoc.additionalparam= -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle= -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -platform.active=default_platform -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -# Space-separated list of JVM arguments used when running the project. -# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test diff --git a/libsrc/tablelayout/nbproject/project.xml b/libsrc/tablelayout/nbproject/project.xml deleted file mode 100644 index 4aca3d912..000000000 --- a/libsrc/tablelayout/nbproject/project.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - org.netbeans.modules.java.j2seproject - - - tablelayout - - - - - - - - - diff --git a/libsrc/tablelayout/src/org/xito/dialog/LayoutParser.java b/libsrc/tablelayout/src/org/xito/dialog/LayoutParser.java deleted file mode 100644 index 7e47d791e..000000000 --- a/libsrc/tablelayout/src/org/xito/dialog/LayoutParser.java +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright 2007 Xito.org -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package org.xito.dialog; - -import java.awt.*; -import java.io.*; -import java.net.*; -import java.text.*; -import java.util.Locale; - -import javax.xml.parsers.*; -import org.w3c.dom.*; -import org.xml.sax.SAXException; - -/** - * The Layout Parser will parse well-formed HTML for the first Table declaration and generate a TableLayout - * based on the HTML described Table - * - * @author Deane Richan - */ -public class LayoutParser { - - private static final String TABLE_TAG = "table"; - private static final String TR_TAG = "tr"; - private static final String TD_TAG = "td"; - private static final String WIDTH_ATTR = "width"; - private static final String MIN_WIDTH_ATTR = "min-width"; - private static final String MAX_WIDTH_ATTR = "max-width"; - private static final String HEIGHT_ATTR = "height"; - private static final String MIN_HEIGHT_ATTR = "min-height"; - private static final String MAX_HEIGHT_ATTR = "max-height"; - private static final String ANCHOR_ATTR = "anchor"; - private static final String CELL_SPACING_ATTR = "cellspacing"; - private static final String CELL_PADDING_ATTR = "cellpadding"; - private static final String ALIGN_ATTR = "align"; - private static final String VALIGN_ATTR = "valign"; - private static final String COLSPAN_ATTR = "colspan"; - private static final String ROWSPAN_ATTR = "rowspan"; - private static final String PADDING_ATTR = "padding"; - private static final String ID_ATTR = "id"; - private static final String PREFERRED = "preferred"; - private static final String LEFT = "left"; - private static final String RIGHT = "right"; - private static final String TOP = "top"; - private static final String BOTTOM = "bottom"; - private static final String CENTER = "center"; - private static final String MIDDLE = "middle"; - private static final String FULL = "full"; - private static final String NW = "nw"; - private static final String N = "n"; - private static final String NE = "ne"; - private static final String E = "e"; - private static final String SE = "se"; - private static final String S = "s"; - private static final String SW = "sw"; - private static final String W = "w"; - - //percent values need to be in English style - private static final DecimalFormat percentFormat = new DecimalFormat("###.##%", new DecimalFormatSymbols(Locale.ENGLISH)); - - - /** Creates a new instance of LayoutParser */ - public LayoutParser() { - } - - public TableLayout parse(String htmlTable) throws IOException { - - return parse(new StringBufferInputStream(htmlTable)); - } - - public TableLayout parse(URL url) throws IOException { - - try { - DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = fact.newDocumentBuilder(); - return parse(docBuilder.parse(url.openStream())); - } catch (ParserConfigurationException configExp) { - configExp.printStackTrace(); - throw new IOException(configExp.getMessage()); - } catch (SAXException saxExp) { - saxExp.printStackTrace(); - throw new IOException(saxExp.getMessage()); - } - } - - public TableLayout parse(InputStream in) throws IOException { - - try { - DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = fact.newDocumentBuilder(); - return parse(docBuilder.parse(in)); - } catch (ParserConfigurationException configExp) { - configExp.printStackTrace(); - throw new IOException(configExp.getMessage()); - } catch (SAXException saxExp) { - saxExp.printStackTrace(); - throw new IOException(saxExp.getMessage()); - } - } - - /** - * Parse a Document - * @param doc - * @return - * @throws java.io.IOException - */ - public TableLayout parse(Document doc) throws IOException { - - return parse(doc.getDocumentElement()); - } - - /** - * Parse an Element - * @param element - * @return - * @throws java.io.IOException - */ - public TableLayout parse(Element element) throws IOException { - - if (element.getNodeName().equalsIgnoreCase(TABLE_TAG)) { - return processTableElement(element); - } - else { - NodeList children = element.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { - TableLayout layout = parse((Element) children.item(i)); - if (layout != null) { - return layout; - } - } - } - } - - return null; - } - - /** - * Process the Table Element - * @param element - * @return - * @throws java.io.IOException - */ - private TableLayout processTableElement(Element element) throws IOException { - - TableLayout layout = new TableLayout(); - - //Get Width and Height of Table - float width = getFloat(element.getAttribute(WIDTH_ATTR)); - float height = getFloat(element.getAttribute(HEIGHT_ATTR)); - - //default to 100% relative - if (width == 0) { - width = TableLayout.PREFERRED; //TableLayout.PERCENT_100; - } - if (height == 0) { - height = TableLayout.PREFERRED; //TableLayout.PERCENT_100; - } - layout.setWidth(width); - layout.setHeight(height); - - //get min, max width and height of Table - int min_width = getInteger(element.getAttribute(MIN_WIDTH_ATTR), 0); - int max_width = getInteger(element.getAttribute(MAX_WIDTH_ATTR), Integer.MAX_VALUE); - int min_height = getInteger(element.getAttribute(MIN_HEIGHT_ATTR), 0); - int max_height = getInteger(element.getAttribute(MAX_HEIGHT_ATTR), Integer.MAX_VALUE); - layout.setMinWidth(min_width); - layout.setMaxWidth(max_width); - layout.setMinHeight(min_height); - layout.setMaxHeight(max_height); - - //Anchor - layout.setAnchor(processAnchor(element.getAttribute(ANCHOR_ATTR))); - - //Cell Spacing and Padding - int cs = getInteger(element.getAttribute(CELL_SPACING_ATTR), 0); - int cp = getInteger(element.getAttribute(CELL_PADDING_ATTR), 0); - int padding = cs + cp; - layout.setPadding(new Insets(padding, padding, padding, padding)); - - //Process Rows - NodeList possibleRows = element.getChildNodes(); - for (int r = 0; r < possibleRows.getLength(); r++) { - Node n = possibleRows.item(r); - if (n.getNodeName().equalsIgnoreCase(TR_TAG) && n.getNodeType() == Node.ELEMENT_NODE) { - Element rowElement = (Element) n; - String hStr = rowElement.getAttribute(HEIGHT_ATTR); - TableLayout.Row row = new TableLayout.Row(getFloatDimensionValue(hStr)); - processRow(row, rowElement); - layout.addRow(row); - } - } - - //Add additional RowSpan columns. - processRowSpan(layout); - - return layout; - } - - /** - * When HTML uses RowSpan it automatically inserts extra columns where the - * row is spanning over so we need to insert these extra empty columns into the layout - * @param layout - */ - private void processRowSpan(TableLayout layout) { - - - for (int r = 0; r < layout.getRowCount(); r++) { - TableLayout.Row row = layout.getRow(r); - - //check for any row spans in the columns - for (int c = 0; c < row.getColumnCount(); c++) { - TableLayout.Column col = row.getColumn(c); - - if (col.rowSpan > 1) { - int span = col.rowSpan - 1; - //loop through this many rows below and insert - //extra columns - for (int s = 1; s <= span; s++) { - TableLayout.Row spanRow = layout.getRow(r + s); - if (spanRow == null) { - continue; - } - spanRow.insertEmptyColumn(c); - } - } - } - - } - - } - - /** - * Process a Row - * @param row - * @param rowElement - */ - private void processRow(TableLayout.Row row, Element rowElement) { - NodeList possibleColumns = rowElement.getChildNodes(); - for (int c = 0; c < possibleColumns.getLength(); c++) { - Node n = possibleColumns.item(c); - if (n.getNodeName().equalsIgnoreCase(TD_TAG) && n.getNodeType() == Node.ELEMENT_NODE) { - Element td = (Element) n; - row.addCol(processCol(td)); - } - } - } - - /** - * Process a Column - * @param colElement - * @return - */ - private TableLayout.Column processCol(Element colElement) { - - TableLayout.Column col = new TableLayout.Column(); - String width = colElement.getAttribute(WIDTH_ATTR); - String hAlign = colElement.getAttribute(ALIGN_ATTR); - String vAlign = colElement.getAttribute(VALIGN_ATTR); - String colSpan = colElement.getAttribute(COLSPAN_ATTR); - String rowSpan = colElement.getAttribute(ROWSPAN_ATTR); - - col.width = getFloatDimensionValue(width); - - //process col and row spans - try { - if (colSpan != null && !colSpan.equals("")) { - col.colSpan = Integer.parseInt(colSpan); - } - } catch (NumberFormatException badNum) { - System.err.println("Error reading colspan:" + colSpan); - } - - try { - if (rowSpan != null && !rowSpan.equals("")) { - col.rowSpan = Integer.parseInt(rowSpan); - } - } catch (NumberFormatException badNum) { - System.err.println("Error reading rowspan:" + rowSpan); - } - - //Horz Align - if (hAlign != null && hAlign.equalsIgnoreCase(LEFT)) { - col.hAlign = TableLayout.LEFT; - } - else if (hAlign != null && hAlign.equalsIgnoreCase(RIGHT)) { - col.hAlign = TableLayout.RIGHT; - } - else if (hAlign != null && (hAlign.equalsIgnoreCase(MIDDLE) || hAlign.equalsIgnoreCase(CENTER))) { - col.hAlign = TableLayout.CENTER; - } - else if (hAlign != null && hAlign.equalsIgnoreCase(FULL)) { - col.hAlign = TableLayout.FULL; - } - - //Vert Align - if (vAlign.equals(TOP)) { - col.vAlign = TableLayout.TOP; - } - else if (vAlign.equals(BOTTOM)) { - col.vAlign = TableLayout.BOTTOM; - } - else if (vAlign.equals(CENTER) || vAlign.equals(MIDDLE)) { - col.vAlign = TableLayout.CENTER; - } - else if (vAlign.equals(FULL)) { - col.vAlign = TableLayout.FULL; - } - - //Process padding - col.padding = processColPadding(colElement.getAttribute(PADDING_ATTR)); - - //First look for name in ID - col.name = colElement.getAttribute(ID_ATTR); - - //Look for name in Text Node if it wasn't in ID - if (col.name == null || col.name.length() == 0) { - try { - NodeList childNodes = colElement.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - if (childNodes.item(i).getNodeType() == Node.TEXT_NODE) { - col.name = childNodes.item(i).getNodeValue(); - break; - } - } - } catch (DOMException badDOM) { - System.err.println("Error reading col name"); - badDOM.printStackTrace(); - } - } - - return col; - } - - public Insets processColPadding(String s) { - if (s == null || s.equals("")) { - return null; - } - Insets insets = new Insets(0, 0, 0, 0); - String values[] = s.split(","); - for (int i = 0; i < values.length; i++) { - if (i == 0) { - insets.top = getInteger(values[i], 0); - } - if (i == 1) { - insets.left = getInteger(values[i], 0); - } - if (i == 2) { - insets.bottom = getInteger(values[i], 0); - } - if (i == 3) { - insets.right = getInteger(values[i], 0); - } - } - - return insets; - } - - /** - * Returns the integer value or 0 - */ - private int getInteger(String s, int defaultValue) { - if (s == null || s.equals("")) { - return defaultValue; - } - try { - return Integer.parseInt(s); - } catch (NumberFormatException badNum) { - return defaultValue; - } - } - - /** - * Returns the integer value or 0 - */ - private float getFloat(String s) { - try { - if (s.endsWith("%")) { - //JPEXS modified - float p = percentFormat.parse(s).floatValue(); - if(p == 1) - { - return TableLayout.PERCENT_100; - } - return p; - } - else { - return Float.parseFloat(s); - } - } catch (ParseException parseExp) { - return 0; - } catch (NumberFormatException badNum) { - return 0; - } - } - - /** - * Returns the Anchor int value for the specified String - * defaults to NORTH_WEST - */ - public int processAnchor(String s) { - - if (s == null || s.equals("")) { - return TableLayout.NORTH_WEST; - } - if (s.equalsIgnoreCase(NW)) { - return TableLayout.NORTH_WEST; - } - else if (s.equalsIgnoreCase(N)) { - return TableLayout.NORTH; - } - else if (s.equalsIgnoreCase(NE)) { - return TableLayout.NORTH_EAST; - } - else if (s.equalsIgnoreCase(E)) { - return TableLayout.EAST; - } - else if (s.equalsIgnoreCase(SE)) { - return TableLayout.SOUTH_EAST; - } - else if (s.equalsIgnoreCase(S)) { - return TableLayout.SOUTH; - } - else if (s.equalsIgnoreCase(SW)) { - return TableLayout.SOUTH_WEST; - } - else if (s.equalsIgnoreCase(W)) { - return TableLayout.WEST; - } - else if (s.equalsIgnoreCase(CENTER)) { - return TableLayout.CENTER; - } - - return TableLayout.NORTH_WEST; - } - - private float getFloatDimensionValue(String s) { - if (s == null || s.equals("") || s.equalsIgnoreCase(PREFERRED)) { - return TableLayout.PREFERRED; - } - if (s.equals("100%")) { - return TableLayout.PERCENT_100; - } - try { - if (s.endsWith("%")) { - return percentFormat.parse(s).floatValue(); - } - else { - return Float.parseFloat(s); - } - } catch (ParseException parseExp) { - System.err.println("Error parsing Dimension value:" + s); - return TableLayout.PREFERRED; - } catch (NumberFormatException badNum) { - System.err.println("Error parsing Dimension value:" + s); - return TableLayout.PREFERRED; - } - } -} diff --git a/libsrc/tablelayout/src/org/xito/dialog/TableLayout.java b/libsrc/tablelayout/src/org/xito/dialog/TableLayout.java deleted file mode 100644 index c7ac63d29..000000000 --- a/libsrc/tablelayout/src/org/xito/dialog/TableLayout.java +++ /dev/null @@ -1,1725 +0,0 @@ -// Copyright 2007 Xito.org -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package org.xito.dialog; - -import java.awt.*; -import java.net.*; -import java.util.*; -import java.io.*; -import javax.swing.*; - -/** - *

- * The TableLayout provides an easy to use layout manager based on the HTML Table. Layouts can be - * defined programmatically or by suppling a description in a well formed HTML file. This enables Layouts to be - * defined in seperate layout html resource files that can be modified seperately from the codebase. - *

- *

- * Layouts that are defined in seperate HTML files should contain just the tags. These files can - * be used to preview the layout behavior in your browser. For the most case, table layout behavior, as displayed - * in the browser will be duplicate with this layout in your component container. - *

- *

- * The table layout html should be well formed. The Tidy package is used to tidy any invalidate HTML, and therefore results may very. - * It is always best just to use well formed HTML. - *

- *

Table Size

- *

- * Just as in html if no size of the table is specified as in <table>...</table> the - * contents of the container will layout using their preferred sizes. - * Generally this will mean components will pack into the North-West corner of the container. - *

- *

- * If you would like your components to take up the full size of the container use a layout that specifies a percentage - * size such as - * <table min_width="100%" max_height="100%">...</table> - * Of course other percentages will be applied accordingly. - *

- *

- * If you would like your components to take up a specific min_width and max_height you can specify an absolute size using:
- * <table min_width="100" max_height="100">...</table> - *

- *

Minimum and Maximum Table Sizes

- *

- * Although not part of the HTML spec, table layouts can define min-min_width, min-max_height, max-min_width, and max-max_height - * attributes. These should not be percent values but instead maximum or minimum size values in pixels. - *

- *

Anchor

- *

- * Just as HTML table in a web page, TableLayout is anchored to the North-West corner of the parent container. - * However an optional anchor attribute can be added to the table element. This attribute will be ignored if min_width - * and max_height are set to 100%. The supported values are:
- * nw, n, ne, v, e, sw, s, se - *

- *

Rows

- *

- * Rows are defined using the html <tr> element. The max_height attribute has the following behavior: - * (undefined) The table row max_height will take the largest preferred max_height of a component in that row.
- * max_height="50%" the table row max_height will be 50% of the table's max_height.
- * max_height="100" the table row will be set to 100 pixels high.
- *

- *

Columns

- *

- * Columns are defined using the html <td> element. The following attributes are supported:
- * id Used to specify an id of this table cell. This can be used in the program to place a component at this id.
- * min_width Can be undefined, which uses the embedded components preferred min_width, a percentage, or fixed min_width in pixels.
- * padding Used to specify padding space around the component. Best used with an undefined min_width.
- * align Used to specify the horizontal alignment of the component in the cell. values are left, center, right, and full.
- * valign Used to specify the vertical alignment of the component in the cell. values are top, bottom, and full.
- * colspan Used to specify that this cell's component should span this cell and adjacent cells.
- * rowspan Used to specify that this cell's component should span this row and adjacent rows.
- * Note: colspan, and rowspan don't always have the same behavior as these attributes in a browser. These attributes should be used - * carefully. - *

- *

- * Once the Table layout has been processed and added to a container you can use the following to added components to the - * container: - *

- * JPanel panel = new JPanel();
- * panel.setLayout(new TableLayout(html or url));
- * panel.add("id_1", new JButton()); //where id_1 is the id for the table cell you want to place the component in. The border attribute
- * is ignored by the TableLayout.
- * 
- *

- *

- * Tip: In order to help test layouts in a browser set the table border="1". - *

- * @author Deane Richan - * Modified by JPEXS - */ -public class TableLayout implements LayoutManager2 { - - public final static int PREFERRED = -1; - public final static int LEFT = SwingConstants.LEFT; - public final static int RIGHT = SwingConstants.RIGHT; - public final static int CENTER = SwingConstants.CENTER; - public final static int TOP = SwingConstants.TOP; - public final static int BOTTOM = SwingConstants.BOTTOM; - public final static int FULL = -2; - public final static int NORTH_WEST = SwingConstants.NORTH_WEST; - public final static int NORTH = SwingConstants.NORTH; - public final static int NORTH_EAST = SwingConstants.NORTH_EAST; - public final static int EAST = SwingConstants.EAST; - public final static int SOUTH_EAST = SwingConstants.SOUTH_EAST; - public final static int SOUTH = SwingConstants.SOUTH; - public final static int SOUTH_WEST = SwingConstants.SOUTH_WEST; - public final static int WEST = SwingConstants.WEST; - public final static float PERCENT_100 = 0.9999f; - private ArrayList rows = new ArrayList(); - private float rowH[]; - private int rowY[]; - private int colCount = 0; - private float colW[]; - private int colX[]; - private int preferredWidth; - private int preferredHeight; - private int maxCalculatedWidth, maxCalculatedHeight; - private float width = 1.0f; - private float height = 1.0f; - private int anchor = NORTH_WEST; - private Insets padding = null; - private Dimension lastTargetDim; - private int minWidth = 0; - private int maxWidth = Integer.MAX_VALUE; - private int minHeight = 0; - private int maxHeight = Integer.MAX_VALUE; - private URL htmlResourceURL; - - public static final String BORDER_LAYOUT = "border_layout"; - public static final String TITLE_LAYOUT = "title_layout"; - - /** - * Create a layout for the given resource name. Layouts include: - * border_layout - * @param name - * @return - */ - public static TableLayout createLayout(String name) { - return new TableLayout(TableLayout.class.getResource("layouts/" + name + ".html")); - } - - /** - * Creates a new instance of TableLayout - * With min_width of 100%, max_height of 100% and anchor of NORTH_WEST - */ - public TableLayout() { - this(PERCENT_100, PERCENT_100, NORTH_WEST); - } - - /** - * Creates a new instance of TableLayout - * @param width either fixed or percentage of container's min_width - * @param height either fixed or percentage of container's max_height - * @param anchor either NORTH_WEST, NORTH, NORTH_EAST, EAST, SOUTH_EAST, SOUTH, SOUTH_WEST, WEST, or CENTER - */ - public TableLayout(float width, float height, int anchor) { - this.width = width; - this.height = height; - this.anchor = anchor; - } - - /** Creates a new instance of TableLayout */ - public TableLayout(String html) { - try { - LayoutParser parser = new LayoutParser(); - TableLayout layout = parser.parse(html); - copy(layout); - } catch (IOException ioExp) { - ioExp.printStackTrace(); - } - } - - /** Creates a new instance of TableLayout */ - public TableLayout(URL htmlURL) { - - htmlResourceURL = htmlURL; - - try { - LayoutParser parser = new LayoutParser(); - TableLayout layout = parser.parse(htmlURL); - copy(layout); - } catch (IOException ioExp) { - ioExp.printStackTrace(); - } - } - - /** Creates a new instance of TableLayout */ - public TableLayout(ArrayList rows) { - this.rows = rows; - if (this.rows == null) { - rows = new ArrayList(); - } - } - - - private float fix100(float v) - { - if(v==PERCENT_100){ - return 1; - } - return v; - } - - /** - * Copy settings from a layout to this layout - */ - private void copy(TableLayout layout) { - - this.padding = layout.getPadding(); - this.width = layout.getWidth(); - this.minWidth = layout.getMinWidth(); - this.maxWidth = layout.getMaxWidth(); - this.height = layout.getHeight(); - this.minHeight = layout.getMinHeight(); - this.maxHeight = layout.getMaxHeight(); - - this.anchor = layout.anchor; - - //return early if there are no rows in the layout - if (layout.rows == null) { - return; //copy rows - } - for (int i = 0; i < layout.rows.size(); i++) { - Row r = (Row) ((Row) layout.rows.get(i)).clone(); - rows.add(r); - } - } - - public void setWidth(float w) { - width = w; - } - - public float getWidth() { - return width; - } - - public void setHeight(float h) { - height = h; - } - - public float getHeight() { - return height; - } - - public int getMaxHeight() { - return maxHeight; - } - - public void setMaxHeight(int maxHeight) { - this.maxHeight = maxHeight; - } - - public int getMaxWidth() { - return maxWidth; - } - - public void setMaxWidth(int maxWidth) { - this.maxWidth = maxWidth; - } - - public int getMinHeight() { - return minHeight; - } - - public void setMinHeight(int minHeight) { - this.minHeight = minHeight; - } - - public int getMinWidth() { - return minWidth; - } - - public void setMinWidth(int minWidth) { - this.minWidth = minWidth; - } - - public void setAnchor(int a) { - anchor = a; - } - - public int getAnchor() { - return anchor; - } - - public void setPadding(Insets p) { - padding = p; - } - - public Insets getPadding() { - return padding; - } - - /** - * Add a Row to the end of Current Rows - */ - public void addRow(Row r) { - - rows.add(r); - lastTargetDim = null; - } - - /** - * Add a Row - */ - public void addRow(int i, Row r) { - - if (i > rows.size() - 1) { - i = rows.size() - 1; - } - rows.add(i, r); - lastTargetDim = null; - } - - /** - * Remove a Row - */ - public void removeRow(int i) { - - if (i > rows.size() - 1) { - return; - } - rows.remove(i); - lastTargetDim = null; - } - - /** - * Get Row Count - */ - public int getRowCount() { - - return rows.size(); - } - - /** - * Get a Row or null if it doesn't exist - */ - public Row getRow(int r) { - try { - return (Row) rows.get(r); - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - /** - * Adds the specified component to the layout, using the specified - * constraint object. - * @param comp the component to be added - * @param constraints where/how the component is added to the layout. - */ - @Override - public void addLayoutComponent(Component comp, Object constraints) { - addLayoutComponent((String) constraints, comp); - } - - /** - * If the layout manager uses a per-component string, - * adds the component comp to the layout, - * associating it - * with the string specified by name. - * - * @param name the string to be associated with the component - * @param comp the component to be added - */ - @Override - public void addLayoutComponent(String name, Component comp) { - Column c = this.getColumn(name); - if (c != null) { - c.component = comp; - } - } - - /** - * Calculates the preferred size dimensions for the specified - * container, given the components it contains. - * @param target the container to be laid out - * - * @see #minimumLayoutSize - */ - @Override - public Dimension preferredLayoutSize(Container target) { - - if (rows.size() == 0) { - return new Dimension(0, 0); - } - - Insets is=target.getInsets(); - calculatePositions(target); - return new Dimension(preferredWidth+is.left+is.right, preferredHeight+is.top+is.bottom); - } - - /** - * - * Calculates the minimum size dimensions for the specified - * container, given the components it contains. - * @param target the component to be laid out - * @see #preferredLayoutSize - */ - public Dimension minimumLayoutSize(Container target) { - - int min_height = 0; - int min_width = 0; - for (int i = 0; i < rows.size(); i++) { - Row row = (Row) rows.get(i); - float ph = row.getMinimumHeight(); - if (ph < 1) { - min_height = min_height + (int) row.getMinimumHeight(); - } - else { - min_height = min_height + (int) ph; - } - - float pw = row.getMinimumWidth(); - - if (min_width < pw) { - min_width = (int) pw; - } - } - - Insets is=target.getInsets(); - - return new Dimension(min_width+is.left+is.right, min_height+is.top+is.bottom); - } - - /** - * - * Calculates the maximum size dimensions for the specified container, - * given the components it contains. - * @see java.awt.Component#getMaximumSize - * @see LayoutManager - */ - @Override - public Dimension maximumLayoutSize(Container target) { - - if(rows.size() == 0) { - return new Dimension(0,0); - } - - calculatePositions(target); - Insets is = target.getInsets(); - return new Dimension(maxCalculatedWidth+is.left+is.right, maxCalculatedHeight+is.top+is.bottom); - } - - /** - * - * Lays out the specified container. - * @param parent the container to be laid out - */ - @Override - public void layoutContainer(Container parent) { - - if (rows.size() == 0) { - return; //Recalculate the Positions - } - calculatePositions(parent); - - synchronized (parent.getTreeLock()) { - Iterator row_it = rows.iterator(); - int r = 0; - while (row_it.hasNext()) { - Row row = (Row) row_it.next(); - if (row.cols != null) { - - Iterator col_it = row.cols.iterator(); - int c = 0; - while (col_it.hasNext()) { - layoutColumn(row, (Column)col_it.next(), r, c); - - //iterate col index - c++; - } - } - - //iterate row index - r++; - } - - }//End of Synchronize Block - } - - /** - * Layout a Column's component - * @param row - * @param col - * @param r num - * @param c num - */ - private void layoutColumn(Row row, Column col, int r, int c) { - - if (col.component == null) { - return; //no component so we don't care - } - - //get the new x index based on colspan - int x = getColXforColSpan(row, c); - if(x == -1) { - return; //colspan pushed the x past the end of the table - } - - //get the w based on colspan - int w = getColWidthforColSpan(row, c); - - int y = (int) rowY[r]; - int h = (int) rowH[r]; - - //Compute RowSpan - //TODO take this out when new RowSpan is done - if (col.rowSpan > 1) { - int lastRow = r + (col.rowSpan - 1); - if (lastRow >= rowH.length) { - lastRow = rowH.length - 1; - } - - h = (((int) rowY[lastRow] + (int) rowH[lastRow])) - y; - } - - //Compute column Padding - if (col.padding != null) { - x = x + col.padding.left; - y = y + col.padding.top; - w = w - col.padding.right; - h = h - col.padding.bottom; - } - - //TODO this max and min calc has a problem of messing up alignment need to rewrite - //Apply Max or Min Width - - - //Compute Table level Padding - if (padding != null) { - x = x + padding.left; - y = y + padding.top; - w = w - padding.right; - h = h - padding.bottom; - } - - int pw = col.component.getPreferredSize().width; - int ph = col.component.getPreferredSize().height; - - //Compute hAlign - if (col.hAlign != FULL) { - - if (col.hAlign == RIGHT) { - if ((colX[c] + w - pw) >= x) { - x = colX[c] + w - pw; - } - } - else if (col.hAlign == CENTER) { - int col_center = x + (w / 2); - if ((col_center - (pw / 2)) >= x) { - x = col_center - (pw / 2); - } - } - if (pw < w) { - w = pw; - } - } - - //Compute vAlign - if (col.vAlign != FULL) { - - if (col.vAlign == BOTTOM) { - if ((rowY[r] + h - ph) >= y) { - y = rowY[r] + h - ph; - } - } - else if (col.vAlign == CENTER) { - int row_center = y + (h / 2); - if ((row_center - (ph / 2)) >= y) { - y = row_center - (ph / 2); - } - } - if (ph < h) { - h = ph; - } - } - - col.component.setLocation(x, y); - col.component.setSize(w, h); - } - - /** - * return -1 if can't determine columns y location - * @param r - * @param c - * @return - */ - private int getRowYforRowSpan(int r, int c) { - int rowIndex = getRowIndexforRowSpan(r, c); - if(rowIndex > rows.size()-1) { - return -1; - } - else { - return rowY[rowIndex]; - } - } - - /** - * return -1 if can't determine columns X location - * @param row - * @param c - * @return - */ - private int getColXforColSpan(Row row, int c) { - int index = getColIndexforColSpan(row, c); - if(index>colX.length-1) { - return -1; - } - else { - return (int) colX[index]; - } - } - - /** - * Get the column width using colspan - * @param row - * @param c - * @return - */ - private int getColWidthforColSpan(Row row, int c) { - int index = getColIndexforColSpan(row, c); - int colspan = row.cols.get(c).colSpan; - - float w = 0; - for(int i=index;icolW.length-1) { - break; //we moved past the end of the table so we just return now - } - w = w + colW[i]; - } - - return (int)w; - } - - private int getColIndexforColSpan(Row row, int c) { - int index = 0; - for(int i=0;irow.cols.size()-1) { - break; - } - Column col = row.cols.get(colIndex); - index = index + col.rowSpan; - } - - return index; - } - - - - /** - * Invalidates the layout, indicating that if the layout manager - * has cached information it should be discarded. - */ - public void invalidateLayout(Container target) { - - rowH = null; - rowY = null; - - colCount = 0; - colW = null; - colX = null; - } - - /** - * Returns the alignment along the y axis. This specifies how - * the component would like to be aligned relative to other - * components. The value should be a number between 0 and 1 - * where 0 represents alignment along the origin, 1 is aligned - * the furthest away from the origin, 0.5 is centered, etc. - */ - public float getLayoutAlignmentY(Container target) { - return 0f; - } - - /** - * Returns the alignment along the x axis. This specifies how - * the component would like to be aligned relative to other - * components. The value should be a number between 0 and 1 - * where 0 represents alignment along the origin, 1 is aligned - * the furthest away from the origin, 0.5 is centered, etc. - */ - public float getLayoutAlignmentX(Container target) { - return 0f; - } - - /** - * Removes the specified component from the layout. - * @param comp the component to be removed - */ - public void removeLayoutComponent(Component comp) { - Iterator it = rows.iterator(); - while (it.hasNext()) { - Row r = (Row) it.next(); - if (r.cols == null) { - continue; - } - Iterator col_it = r.cols.iterator(); - while (col_it.hasNext()) { - Column c = (Column) col_it.next(); - if (c.component == comp) { - c.component = null; - } - } - } - - lastTargetDim = null; - } - - /** - * Get a Column by a specified name - * The column is a specific Column instance in a specific Row - * @return the Column found or null - */ - public Column getColumn(String name) { - - for (int i = 0; i < rows.size(); i++) { - Row r = (Row) rows.get(i); - Column c = r.getColumn(name); - if (c != null) { - return c; - } - } - - return null; - } - - /** - * Get a Column by row number and col number. 0,0 is the Upper-Left component - * @return the Column or null - */ - public Column getColumn(int r, int c) { - try { - return (Column) ((Row) rows.get(r)).cols.get(c); - } catch (IndexOutOfBoundsException badIndex) { - return null; - } catch (NullPointerException noCols) { - return null; - } - } - - /** - * Paint the Layouts Tablelines using the specified graphics context - */ - public void paintTableLines(Container target, Graphics g) { - - if (rowY == null) { - calculatePositions(target); - } - - Graphics2D g2d = (Graphics2D) g; - Dimension size = getSize(target); - Point origin = getOrigin(size, target); - - //Draw outside border - g2d.setColor(Color.RED); - g2d.drawRect(origin.x, origin.y, size.width, size.height); - - //Draw rows - for (int i = 0; i < rowY.length; i++) { - g2d.drawLine(origin.x, rowY[i], size.width + origin.x, rowY[i]); - } - //draw columns - for (int i = 0; i < colX.length; i++) { - int x = colX[i]; - g2d.drawLine(colX[i], origin.y, colX[i], size.height + origin.y); - x = colX[i] + (int) colW[i]; - g2d.drawLine(x, origin.y, x, size.height + origin.y); - } - - } - - /** - * Get the Size that this layout wants based on its settings and the container - */ - private Dimension getSize(Container target) { - Dimension dim = new Dimension(); - Insets is=target.getInsets(); - int twid = target.getWidth() - is.left - is.right; - int thei = target.getHeight() - is.top - is.bottom; - - //min_width - if (isFixedValue(width)) { - dim.width = (int) width; - } - else { - dim.width = (int) (fix100(width) * twid); - } - - if (dim.width < minWidth) { - dim.width = minWidth; - } - if (dim.width > maxWidth) { - dim.width = maxWidth; //max_height - } - if (isFixedValue(height)) { - dim.height = (int) height; - } - else { - dim.height = (int) (fix100(height) * thei); - } - - if (dim.height < minHeight) { - dim.height = minHeight; - } - if (dim.height > maxHeight) { - dim.height = maxHeight; - } - return dim; - } - - private Point getOrigin(Dimension size, Container target) { - Point origin = new Point(); - Insets is=target.getInsets(); - - int twid = target.getWidth() - is.left - is.right; - int thei = target.getHeight() - is.top - is.bottom; - - origin.x = is.left; - origin.y = is.top; - - if (anchor == NORTH_WEST) { - origin.x = is.left; - origin.y = is.top; - } - else if (anchor == NORTH) { - origin.x = is.left + ((twid - size.width) / 2); - origin.y = is.top; - } - else if (anchor == NORTH_EAST) { - origin.x = is.left + twid - size.width; - origin.y = is.top; - } - else if (anchor == EAST) { - origin.x = is.left + twid - size.width; - origin.y = is.top + ((thei - size.height) / 2); - } - else if (anchor == SOUTH_EAST) { - origin.x = is.left + twid - size.width; - origin.y = is.top + thei - size.height; - } - else if (anchor == SOUTH) { - origin.x = is.left + ((twid - size.width) / 2); - origin.y = is.top + thei - size.height; - } - else if (anchor == SOUTH_WEST) { - origin.x = is.left; - origin.y = is.top + thei - size.height; - } - else if (anchor == WEST) { - origin.x = is.left; - origin.y = is.top + (thei - size.height) / 2; - } - else if (anchor == CENTER) { - origin.x = is.left + ((twid - size.width) / 2); - origin.y = is.top + (thei- size.height) / 2; - } - - return origin; - } - - /** - * Calculate the Positions of each Cell - */ - public void calculatePositions(Container target) { - - if (rows.size() == 0) { - return; - } - - //If we already calculated based on this target size then just return - if (lastTargetDim != null && target.getWidth() > 0 && target.getHeight() > 0) { - if (target.getWidth() == lastTargetDim.width && target.getHeight() == lastTargetDim.height && rowH != null) { - return; - } - } - - Dimension size = getSize(target); - - Point origin = getOrigin(size, target); - - //Calculate Row Heights - calculateRowHeightsAndLocations(size.height, origin.y); - - //Calculate Col Widths - calculateColWidthsAndLocations(size.width, origin.x); - - lastTargetDim = target.getSize(); - } - - private boolean isPreferredValue(float v) { - return (v == PREFERRED); - } - - private boolean isFullValue(float v){ - return v == FULL; - } - - private boolean isRelativeValue(float v) { - return (v > 0 && v < 1.0); - } - - private boolean isFixedValue(float v) { - return (v == 0 || v >= 1.0); - } - - /** - * Calculate the row heights and the row locations - * @param totalHeight - */ - private void calculateRowHeightsAndLocations(int totalHeight, int y) { - - rowH = new float[rows.size()]; - rowY = new int[rows.size()]; - - //we calculate column count while we are processing rows - colCount = 0; - - int[] maxHeights = new int[rows.size()]; - int[] preferredHeights = new int[rows.size()]; - int twocnt=0; - for (int r = 0; r < rows.size(); r++) { - - Row row = getRow(r); - - //Get column counts while we are at it - if (row.cols != null && row.cols.size() > colCount) { - colCount = row.cols.size(); - } - - //check to see if the row height is fixed or relative - if (isFixedValue(row.height)) { - maxHeights[r] = (int) row.height; - preferredHeights[r] = (int) row.height; - rowH[r] = row.height; - } - else if (isRelativeValue(row.height)) { - maxHeights[r] = (int)row.getMaximumHeight(); - preferredHeights[r] = (int)row.getPreferredHeight(); - rowH[r] = row.height; - } - //use the rows preferred height to determine - else { - - twocnt++; - rowH[r] = height==TableLayout.PREFERRED?row.getPreferredHeight():FULL; - preferredHeights[r] = (int)rowH[r]; - - maxHeights[r] = (int)row.getMaximumHeight(); - - /* - for (int c = 0; c < row.cols.size(); c++) { - Column col = row.getColumn(c); - float ph = col.getPreferredHeight(); - if (ph > rowH[r]) { - rowH[r] = ph; - } - - //update preferred, max_height - if (ph > preferredHeights[r]) { - preferredHeights[r] = (int) ph; - } - } - */ - } - } - - preferredHeight = total(preferredHeights); - maxCalculatedHeight = total(maxHeights); - - //our preferred Height shouldn't be lower then our min height - if(preferredHeight < minHeight) { - preferredHeight = minHeight; - } - - if(maxCalculatedHeight < maxHeight) { - maxCalculatedHeight = maxHeight; - } - - //convert relative heights to fixed heights - //add up all the fixed heights - int fixedHeight = 0; - for (int r = 0; r < rowH.length; r++) { - if (isFixedValue(rowH[r])) { - fixedHeight += (int) rowH[r]; - } - } - - //first we fix the percentages to make sure that they add up to 1.0 - float totalPercentage = 0; - for (int r = 0; r < rowH.length; r++) { - if (isRelativeValue(rowH[r])) { - totalPercentage += rowH[r]; - } - } - - //the fixed relative widths get ratios of the total percentage - if (totalPercentage > 1.0) { - for (int r = 0; r < rowH.length; r++) { - if (isRelativeValue(rowH[r])) { - rowH[r] = totalPercentage / rowH[r]; - } - } - totalPercentage = 1.0f; - } - float remPercentage = 1.0f - totalPercentage; - - - int remainingHeight = totalHeight - fixedHeight; - - - - - int rh = remainingHeight; - //convert the relative widths to fixed widths - for (int r = 0; r < rowH.length; r++) { - if (isRelativeValue(rowH[r])) { - int requestedHeight = (int) (remainingHeight * fix100(rowH[r])); - if (requestedHeight < rh) { - rowH[r] = requestedHeight; - rh -= requestedHeight; - } - else { - rowH[r] = rh; - rh = 0; - } - } - } - - float remPrefSize = remPercentage*remainingHeight; - for (int r = 0; r < rowH.length; r++) { - if(rowH[r] == FULL){ - rowH[r] = remPrefSize/twocnt; - } - } - - //Calculate Row Y locations - rowY[0] = y; - for (int i = 1; i < rowY.length; i++) { - y = y + (int) rowH[i - 1]; - rowY[i] = y; - } - } - - /** - * Get the Column Widths - */ - private void calculateColWidthsAndLocations(int totalWidth, int x) { - - colW = new float[colCount]; - colX = new int[colCount]; - - if (colCount == 0) { - return; - } - if (rows.size() == 0) { - return; - } - - int[] maxWidths = new int[colW.length]; - int[] preferredWidths = new int[colW.length]; - int twoCnt = 0; - for (int c = 0; c < colW.length; c++) { - for (int r = 0; r < rows.size(); r++) { - Row row = getRow(r); - if (row.cols.size() < (c + 1)) { - continue; - } - Column col = row.getColumn(c); - float pw = col.getPreferredWidth(); - - int mw = col.getMaximumWidth(); - if(maxWidths[c] 1.0) { - for (int c = 0; c < colW.length; c++) { - if (isRelativeValue(colW[c])) { - colW[c] = 1 / (totalPercentage / colW[c]); - } - } - } - - int remainingWidth = totalWidth - fixedWidth; - //convert the relative widths to fixed widths - for (int c = 0; c < colW.length; c++) { - if (isRelativeValue(colW[c])) { - //if relative min_width is .9999 then they really mean 100% - int requestedWidth = (int) (remainingWidth * fix100(colW[c])); - if (requestedWidth < remainingWidth) { - colW[c] = requestedWidth; - } - else { - colW[c] = remainingWidth; - remainingWidth = 0; - } - } - } - - //Calculate Col X locations - colX[0] = x; - for (int i = 1; i < colX.length; i++) { - x = x + (int) colW[i - 1]; - colX[i] = x; - } - - } - - private float total(float[] values) { - if (values == null) { - return 0; - } - float totalValue = 0; - - for (int i = 0; i < values.length; i++) { - totalValue += values[i]; - } - - return totalValue; - } - - private int total(int[] values) { - if (values == null) { - return 0; - } - int totalValue = 0; - - for (int i = 0; i < values.length; i++) { - totalValue += values[i]; - } - - return totalValue; - } - - /** - * Get the Column Widths - */ - private void calculateColWidthsOLD(int totalWidth, int colCount) { - - colW = new float[colCount]; - - //Get fixed and preferred Widths - for (int r = 0; r < rows.size(); r++) { - Row row = (Row) rows.get(r); - row.updateColWidth(colW); - } - - //calculate fixed Height - int fixedWidth = 0; - for (int i = 0; i < colCount; i++) { - if (colW[i] >= 1) { - fixedWidth = fixedWidth + (int) colW[i]; - } - } - - //calculate relative Widths - int remainingW = totalWidth - fixedWidth; - for (int i = 0; i < colCount; i++) { - if (remainingW == 0) { - continue; - } - else if (colW[i] > 0 && colW[i] < 1 && remainingW > 0) { - //calc relative min_width - int w = 0; - if (isFixedValue(colW[i])) { - w = (int) (totalWidth - fixedWidth); - } - else { - w = (int) (colW[i] * (totalWidth - fixedWidth)); - } - - if (w > remainingW) { - w = remainingW; - } - remainingW = remainingW - w; - colW[i] = w; - } - } - } - - /******************************************************************* - * ROW Class represents Table elements - *******************************************************************/ - public static class Row implements Cloneable { - - public float height = PREFERRED; - private ArrayList cols = new ArrayList(); - - /** - * Create a row with PREFERRED Height - */ - public Row() { - height = PREFERRED; - } - - /** - * Create a row with a specified max_height - */ - public Row(float h) { - height = h; - } - - public int getColumnCount() { - return cols.size(); - } - - /** - * Add a Column to this Row - */ - public void addCol(Column c) { - cols.add(c); - } - - /** - * insert empty column at index. Columns will be added to fill into i - * @param index - */ - public void insertEmptyColumn(int index) { - if (index > cols.size()) { - int count = index - cols.size(); - for (int i = 0; i < count + 1; i++) { - cols.add(new Column()); - } - } - else { - cols.add(index, new Column()); - } - } - - /** - * Copy this row - * @return a copy of this row including a copy of all columns - */ - @Override - public Object clone() { - - Row rowCopy = new Row(); - rowCopy.height = this.height; - if (this.cols != null) { - for (int i = 0; i < this.cols.size(); i++) { - Column colCopy = (Column) ((Column) this.cols.get(i)).clone(); - rowCopy.addCol(colCopy); - } - } - - return rowCopy; - } - - /** - * Returns a Rows Preferred Height. Based on the content components of the row - */ - public int getPreferredHeight() { - - //Must be Preferred Height so check the components - Iterator it = cols.iterator(); - int h = 0; - while (it.hasNext()) { - Column col = it.next(); - Component comp = col.component; - if (comp != null) { - int ph = comp.getPreferredSize().height; - if (col.padding != null) { - ph = ph + col.padding.top + col.padding.bottom; - } - if (ph > h) { - h = ph; - } - } - } - - return h; - } - - /** - * Returns a Rows Maximum Height based on calculating the maximum components height in this row - */ - public int getMaximumHeight() { - - Iterator it = cols.iterator(); - int h = 0; - while (it.hasNext()) { - Column col = it.next(); - Component comp = col.component; - if (comp != null) { - int mh = comp.getMaximumSize().height; - if (col.padding != null) { - mh = mh + col.padding.top + col.padding.bottom; - } - if (mh > h) { - h = mh; - } - } - } - - return h; - } - - /** - * Returns a Rows Maximum Width. If row is PREFERRED then returns the max Width column components - * If row is relative Percentage or fixed then returns 1 - */ - public int getMaximumWidth() { - - if (cols == null) { - return 0; - } - Iterator it = cols.iterator(); - int w = 0; - while (it.hasNext()) { - Column col = (Column) it.next(); - w = w + col.getMaximumWidth(); - } - - return w; - } - - /** - * Returns a Rows Minimum Width. If row is PREFERRED then returns the min Width column components - * If row is relative Percentage or fixed then returns 1 - */ - public int getMinimumWidth() { - - if (cols == null) { - return 0; - } - Iterator it = cols.iterator(); - int w = 0; - while (it.hasNext()) { - Column col = (Column) it.next(); - float pw = col.getMinimumWidth(); - - if (pw > w) { - w = (int) pw; - } - } - - return w; - } - - /** - * Returns a Rows Preferred Width by getting the sum of all columns widths. - */ - public int getPreferredWidth() { - - if (cols == null) { - return 0; - } - Iterator it = cols.iterator(); - int w = 0; - while (it.hasNext()) { - Column col = (Column) it.next(); - float pw = col.getPreferredWidth(); - if (pw < 1) { - pw = col.getMinimumWidth(); - } - - w = w + (int) pw; - - } - - return w; - } - - /** - * Returns a Rows Minimum Height. - * IF row is fixed then returns the fixed row max_height - * If row is PREFERRED or relative Percentage - * then returns the max minimum Height of all column components - */ - public int getMinimumHeight() { - - //If a fixed max_height - if (height >= 1) { - return (int) height; //must be preferred or relative in which case we just return the min max_height - } - if (cols == null) { - return 0; - } - Iterator it = cols.iterator(); - int h = 0; - while (it.hasNext()) { - Column col = (Column) it.next(); - Component comp = col.component; - if (comp != null) { - int mh = comp.getMinimumSize().height; - if (col.padding != null) { - mh = mh + col.padding.top + col.padding.bottom; - } - if (mh > h) { - h = mh; - } - } - } - - return h; - } - - /** - * Calculate the Column Widths that this Row wants. Existing column widths are passed in and - * if this row's columns want widths that are larger then it replaces just those widths with its - * own columns widths - */ - protected float[] updateColWidth(float colW[]) { - - //If we don't have any columns then we can't figure it out - //so just return what we got - if (cols == null) { - return colW; //Walk through each col - } - float relativeWidth = 0; - for (int i = 0; i < colW.length; i++) { - try { - Column col = (Column) cols.get(i); - - //The preferred min_width is either a fixed min_width or a relative min_width - float pw = col.getPreferredWidth(); - - //If a percentage min_width then make sure we have room for it - if (pw > 0 && pw < 1) { - if ((relativeWidth + pw) > 1) { - pw = col.getMinimumWidth(); - relativeWidth = 1.0f; - } - else { - relativeWidth = relativeWidth + pw; - } - } - - //If fixed min_width was based on preferred component min_width then - //use it if its greater then what we have and what we have is not a relative min_width - if ((col.width == PREFERRED) && (pw > colW[i]) && (colW[i] >= 1)) { - colW[i] = pw; - } //Else use the fixed or percentage min_width if we don't have a setting yet - else if (colW[i] == 0) { - colW[i] = pw; - } - } //Cols that we don't have just get skipped - catch (IndexOutOfBoundsException noCol) { - } - } - - return colW; - } - - /** - * Get a Column for a specific Name - */ - public Column getColumn(String name) { - if (cols == null) { - return null; - } - Iterator it = cols.iterator(); - while (it.hasNext()) { - Column c = (Column) it.next(); - if (c.name != null && c.name.equals(name)) { - return c; - } - } - - return null; - } - - public Column getColumn(int index) { - if (index >= cols.size()) { - return null; - } - return (Column) cols.get(index); - } - } - - /******************************************************************* - * Column Class represents Table
elements or Columns in Rows - *******************************************************************/ - public static class Column implements Cloneable { - - public float width = PREFERRED; - public String name; - public Component component; - public int colSpan = 1; - public int rowSpan = 1; - public int hAlign = LEFT; - public int vAlign = CENTER; - Insets padding = null; - - /** - * Create a Column - */ - public Column() { - } - - /** - * Create a Column with a Name - */ - public Column(String n) { - name = n; - } - - /** - * Create a Column with a Width - */ - public Column(float w) { - width = w; - } - - /** - * Create a Column with name and min_width - */ - public Column(String n, float w) { - name = n; - width = w; - } - - /** - * Create a Column with a specific column and row span - */ - public Column(String n, float w, int cspan, int rspan) { - name = n; - width = w; - colSpan = cspan; - rowSpan = rspan; - } - - /** - * Get a copy of this column information - * @return - */ - @Override - public Object clone() { - Column colCopy = new Column(); - - colCopy.width = this.width; - colCopy.name = this.name; - colCopy.component = null; //we are copying the layout not the components in it - colCopy.colSpan = this.colSpan; - colCopy.rowSpan = this.rowSpan; - colCopy.hAlign = this.hAlign; - colCopy.vAlign = this.vAlign; - if (this.padding != null) { - colCopy.padding = (Insets) this.padding.clone(); - } - - return colCopy; - } - - /** - * Returns a Columns Preferred Width. If the column is PREFERRED then returns this column's component preferred min_width - * If the column is a relative percentage then returns that percentage - */ - public float getPreferredWidth() { - float pw = 0; - if (width == PREFERRED && component != null && colSpan <= 1) { - pw = component.getPreferredSize().width; - return pw; - } - else if (width == PREFERRED && (component == null || colSpan > 1)) { - return 0; - } - else if (width >= 1 || width == 0) { - - pw = width; - if (padding != null) { - pw = pw + padding.left + padding.right; - } - - return pw; - } - else { - return width; - } - } - - public int getPreferredHeight() { - if (component == null) { - return 0; - } - else { - return component.getPreferredSize().height; - } - } - - public int getComponentPreferredWidth() { - if (component == null) { - return 0; - } - else { - return component.getPreferredSize().width; - } - } - - /** - * Gets this Columns Components Minimum Width - */ - public int getMinimumWidth() { - - //if its fixed then just return it - if (width > 1) { - return (int) width; //if no component then just 0 - } - if (component == null) { - return 0; - } - return component.getMinimumSize().width; - } - - /** - * Gets this Columns Components Maximum Width - */ - public int getMaximumWidth() { - - //if its fixed then just return it - if (width > 1) { - return (int) width; //if no component then just 0 - } - if (component == null) { - return 0; - } - return component.getMaximumSize().width; - } - } -} - diff --git a/libsrc/ttf/src/fontastic/Fontastic.java b/libsrc/ttf/src/fontastic/Fontastic.java index 717939e92..7dcbc7c11 100644 --- a/libsrc/ttf/src/fontastic/Fontastic.java +++ b/libsrc/ttf/src/fontastic/Fontastic.java @@ -162,7 +162,6 @@ public class Fontastic { */ public void buildFont() throws FileNotFoundException { // Create TTF file with doubletype - m_engine.getTypeface().addRequiredGlyphs(); //m_engine.fireAction(); //m_engine.addDefaultGlyphs(); @@ -202,7 +201,7 @@ public class Fontastic { } glyphFile.saveGlyphFile(); } - + m_engine.getTypeface().addRequiredGlyphs(); m_engine.buildTrueType(false); // End TTF creation diff --git a/nbproject/project.xml b/nbproject/project.xml index ccf7640f3..b019ebf73 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -187,7 +187,7 @@ src - lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/jsyntaxpane-0.9.5.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src;lib/JavactiveX.jar + lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/jsyntaxpane-0.9.5.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src;lib/JavactiveX.jar;lib/tablelayout.jar build javadoc reports diff --git a/src/com/jpexs/decompiler/flash/gui/FontEmbedDialog.java b/src/com/jpexs/decompiler/flash/gui/FontEmbedDialog.java index 25779bbf4..63ce4171a 100644 --- a/src/com/jpexs/decompiler/flash/gui/FontEmbedDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/FontEmbedDialog.java @@ -16,30 +16,44 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.font.CharacterRanges; +import com.jpexs.helpers.Helper; +import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; +import java.awt.FontFormatException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextField; +import javax.swing.filechooser.FileFilter; /** * @@ -49,27 +63,38 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { private static final String ACTION_OK = "OK"; private static final String ACTION_CANCEL = "CANCEL"; + private static final String ACTION_LOAD_FROM_DISK = "LOAD_FROM_DISK"; private static final int SAMPLE_MAX_LENGTH = 50; - private final JComboBox sourceFont; + private final JComboBox familyNamesSelection; + private final JComboBox faceSelection; private final JCheckBox[] rangeCheckboxes; private final String rangeNames[]; private final JLabel[] rangeSamples; private final JTextField individualCharsField; private boolean result = false; - private JLabel individialSample; - private final int style; + private JLabel individialSample; + private Font customFont; + private final JCheckBox allCheckbox; + private final JCheckBox updateTextsCheckbox; - public String getSelectedFont() { - return sourceFont.getSelectedItem().toString(); + public Font getSelectedFont() { + if (ttfFileRadio.isSelected() && customFont != null) { + return customFont; + } + return FontTag.installedFonts.get(familyNamesSelection.getSelectedItem().toString()).get(faceSelection.getSelectedItem().toString()); } + public boolean hasUpdateTexts(){ + return updateTextsCheckbox.isSelected(); + } + public Set getSelectedChars() { Set chars = new TreeSet<>(); - Font f = new Font(getSelectedFont(), style, new JLabel().getFont().getSize()); - for (int i = 0; i < rangeCheckboxes.length; i++) { - if (rangeCheckboxes[i].isSelected()) { + Font f = getSelectedFont(); + if(allCheckbox.isSelected()){ + for (int i = 0; i < rangeCheckboxes.length; i++) { int codes[] = CharacterRanges.rangeCodes(i); for (int c : codes) { if (f.canDisplay(c)) { @@ -77,40 +102,135 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { } } } - } - String indStr = individualCharsField.getText(); - for (int i = 0; i < indStr.length(); i++) { - if (f.canDisplay(indStr.codePointAt(i))) { - chars.add(indStr.codePointAt(i)); + }else{ + for (int i = 0; i < rangeCheckboxes.length; i++) { + if (rangeCheckboxes[i].isSelected()) { + int codes[] = CharacterRanges.rangeCodes(i); + for (int c : codes) { + if (f.canDisplay(c)) { + chars.add(c); + } + } + } + } + String indStr = individualCharsField.getText(); + for (int i = 0; i < indStr.length(); i++) { + if (f.canDisplay(indStr.codePointAt(i))) { + chars.add(indStr.codePointAt(i)); + } } } return chars; } - public FontEmbedDialog(String selectedFont, String selectedChars, int style) { + private JRadioButton ttfFileRadio; + private JRadioButton installedRadio; + + private void updateFaceSelection(){ + faceSelection.setModel( new DefaultComboBoxModel<>(new Vector(FontTag.installedFonts.get(familyNamesSelection.getSelectedItem().toString()).keySet()))); + } + + public FontEmbedDialog(String selectedFamily, String selectedFace, String selectedChars) { setSize(900, 600); - this.style = style; setDefaultCloseOperation(HIDE_ON_CLOSE); setTitle(translate("dialog.title")); Container cnt = getContentPane(); cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS)); + JPanel selFontPanel = new JPanel(new FlowLayout()); + + installedRadio = new JRadioButton(translate("installed")); + ttfFileRadio = new JRadioButton(translate("ttffile.noselection")); + + ButtonGroup bg = new ButtonGroup(); + bg.add(installedRadio); + bg.add(ttfFileRadio); + + installedRadio.setSelected(true); + individialSample = new JLabel(); - sourceFont = new JComboBox<>(new Vector<>(FontTag.fontNames)); - sourceFont.setSelectedItem(selectedFont); - cnt.add(sourceFont); + familyNamesSelection = new JComboBox<>(new Vector(new TreeSet(FontTag.installedFonts.keySet()))); + familyNamesSelection.setSelectedItem(selectedFamily); + faceSelection = new JComboBox<>(); + updateFaceSelection(); + faceSelection.setSelectedItem(selectedFace); + JButton loadFromDiskButton = new JButton(View.getIcon("open16")); + loadFromDiskButton.setToolTipText(translate("button.loadfont")); + loadFromDiskButton.addActionListener(this); + loadFromDiskButton.setActionCommand(ACTION_LOAD_FROM_DISK); + selFontPanel.add(installedRadio); + selFontPanel.add(familyNamesSelection); + selFontPanel.add(faceSelection); + selFontPanel.add(ttfFileRadio); + selFontPanel.add(loadFromDiskButton); + + installedRadio.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + updateCheckboxes(); + } + } + }); + + ttfFileRadio.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + if (ttfFileRadio.isSelected()) { + if (customFont == null) { + if (loadFromDisk()) { + updateCheckboxes(); + } else { + installedRadio.setSelected(true); + } + } else { + updateCheckboxes(); + } + } + } + } + }); + + cnt.add(selFontPanel); JPanel rangesPanel = new JPanel(); rangesPanel.setLayout(new BoxLayout(rangesPanel, BoxLayout.Y_AXIS)); - int rc = CharacterRanges.rangeCount(); + final int rc = CharacterRanges.rangeCount(); rangeCheckboxes = new JCheckBox[rc]; rangeSamples = new JLabel[rc]; rangeNames = new String[rc]; + allCheckbox = new JCheckBox(translate("allcharacters")); + allCheckbox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED){ + for (int i = 0; i < rc; i++) { + rangeCheckboxes[i].setEnabled(false); + } + individualCharsField.setEnabled(false); + }else if(e.getStateChange() == ItemEvent.DESELECTED){ + for (int i = 0; i < rc; i++) { + rangeCheckboxes[i].setEnabled(true); + } + individualCharsField.setEnabled(true); + } + } + }); + JPanel rangeRowPanel = new JPanel(); + rangeRowPanel.setLayout(new BorderLayout()); + rangeRowPanel.add(allCheckbox,BorderLayout.WEST); + rangeRowPanel.setAlignmentX(0); + rangesPanel.add(rangeRowPanel); + for (int i = 0; i < rc; i++) { rangeNames[i] = CharacterRanges.rangeName(i); rangeSamples[i] = new JLabel(""); rangeCheckboxes[i] = new JCheckBox(rangeNames[i]); - JPanel rangeRowPanel = new JPanel(); + rangeRowPanel = new JPanel(); rangeRowPanel.setLayout(new BoxLayout(rangeRowPanel, BoxLayout.X_AXIS)); rangeRowPanel.add(rangeCheckboxes[i]); rangeRowPanel.add(Box.createHorizontalGlue()); @@ -127,8 +247,18 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { individualCharsField.setPreferredSize(new Dimension(100, individualCharsField.getPreferredSize().height)); individialSample = new JLabel(); specialPanel.add(individualCharsField); + + updateTextsCheckbox = new JCheckBox(AppStrings.translate("font.updateTexts")); + + JPanel utPanel = new JPanel(new FlowLayout()); + utPanel.add(updateTextsCheckbox); cnt.add(specialPanel); cnt.add(individialSample); + cnt.add(utPanel); + + + + JPanel buttonsPanel = new JPanel(new FlowLayout()); JButton okButton = new JButton(AppStrings.translate("button.ok")); @@ -145,7 +275,15 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { setModalityType(ModalityType.APPLICATION_MODAL); individualCharsField.setText(selectedChars); getRootPane().setDefaultButton(okButton); - sourceFont.addItemListener(new ItemListener() { + familyNamesSelection.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateFaceSelection(); + updateCheckboxes(); + } + }); + faceSelection.addItemListener(new ItemListener() { + @Override public void itemStateChanged(ItemEvent e) { updateCheckboxes(); @@ -162,7 +300,7 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { private void updateIndividual() { String chars = individualCharsField.getText(); - Font f = new Font(getSelectedFont(), style, new JLabel().getFont().getSize()); + Font f = getSelectedFont(); String visibleChars = ""; for (int i = 0; i < chars.length(); i++) { if (f.canDisplay(chars.codePointAt(i))) { @@ -173,9 +311,10 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { } private void updateCheckboxes() { - String fontStr = sourceFont.getSelectedItem().toString(); - Font f = new Font(fontStr, style, new JLabel().getFont().getSize()); + Font f = getSelectedFont().deriveFont(12f); int rc = CharacterRanges.rangeCount(); + + Set allChars=new HashSet<>(); for (int i = 0; i < rc; i++) { rangeNames[i] = CharacterRanges.rangeName(i); int codes[] = CharacterRanges.rangeCodes(i); @@ -183,6 +322,7 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { String sample = ""; for (int c = 0; c < codes.length; c++) { if (f.canDisplay(codes[c])) { + allChars.add(codes[c]); if (avail < SAMPLE_MAX_LENGTH) { sample += "" + (char) codes[c]; } @@ -193,6 +333,7 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { rangeSamples[i].setFont(f); rangeCheckboxes[i].setText(translate("range.description").replace("%available%", "" + avail).replace("%name%", rangeNames[i]).replace("%total%", "" + codes.length)); } + allCheckbox.setText(translate("allcharacters").replace("%available%", ""+allChars.size())); individialSample.setFont(f); updateIndividual(); } @@ -208,9 +349,52 @@ public class FontEmbedDialog extends AppDialog implements ActionListener { result = false; setVisible(false); break; + case ACTION_LOAD_FROM_DISK: + if (customFont != null) { + if (loadFromDisk()) { + updateCheckboxes(); + } + } + ttfFileRadio.setSelected(true); + break; } } + private boolean loadFromDisk() { + JFileChooser fc = new JFileChooser(); + fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); + FileFilter ttfFilter = new FileFilter() { + @Override + public boolean accept(File f) { + return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory()); + } + + @Override + public String getDescription() { + return translate("filter.ttf"); + } + }; + fc.setFileFilter(ttfFilter); + fc.setAcceptAllFileFilterUsed(true); + JFrame f = new JFrame(); + View.setWindowIcon(f); + int returnVal = fc.showOpenDialog(f); + if (returnVal == JFileChooser.APPROVE_OPTION) { + Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); + File selfile = Helper.fixDialogFile(fc.getSelectedFile()); + try { + customFont = Font.createFont(Font.TRUETYPE_FONT, selfile); + ttfFileRadio.setText(translate("ttffile.selection").replace("%fontname%", customFont.getName()).replace("%filename%", selfile.getName())); + return true; + } catch (FontFormatException ex) { + JOptionPane.showMessageDialog(this, translate("error.invalidfontfile"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } catch (IOException ex) { + JOptionPane.showMessageDialog(this, translate("error.cannotreadfontfile"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + } + } + return false; + } + public boolean display() { result = false; setVisible(true); diff --git a/src/com/jpexs/decompiler/flash/gui/FontPanel.form b/src/com/jpexs/decompiler/flash/gui/FontPanel.form deleted file mode 100644 index 8240f65b8..000000000 --- a/src/com/jpexs/decompiler/flash/gui/FontPanel.form +++ /dev/null @@ -1,607 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/com/jpexs/decompiler/flash/gui/FontPanel.java b/src/com/jpexs/decompiler/flash/gui/FontPanel.java index 9f3b72bc9..3c50fac6a 100644 --- a/src/com/jpexs/decompiler/flash/gui/FontPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/FontPanel.java @@ -18,30 +18,37 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.helpers.FontHelper; import com.jpexs.decompiler.flash.tags.DefineFontNameTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.tags.base.TextTag; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.helpers.Helper; +import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontFormatException; -import java.awt.font.FontRenderContext; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; +import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.BorderFactory; import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.JPanel; import javax.swing.filechooser.FileFilter; +import layout.TableLayout; /** * @@ -70,8 +77,12 @@ public class FontPanel extends javax.swing.JPanel { fontTag = null; } - private ComboBoxModel getModel() { - return new DefaultComboBoxModel<>(FontTag.fontNamesArray); + private ComboBoxModel getFamilyModel() { + return new DefaultComboBoxModel<>(new Vector(new TreeSet(FontTag.installedFonts.keySet()))); + } + + private ComboBoxModel getNameModel(String family) { + return new DefaultComboBoxModel<>(new Vector(FontTag.installedFonts.get(family).keySet())); } private void setEditable(boolean editable) { @@ -119,7 +130,7 @@ public class FontPanel extends javax.swing.JPanel { for (int ic : selChars) { char c = (char) ic; if (oldchars.indexOf((int) c) > -1) { - int opt = 0; //yes + int opt; //yes if (!(yestoall || notoall)) { opt = View.showOptionDialog(null, translate("message.font.add.exists").replace("%char%", "" + c), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, translate("button.yes")); if (opt == 2) { @@ -133,6 +144,8 @@ public class FontPanel extends javax.swing.JPanel { opt = 0; //yes } else if (notoall) { opt = 1; //no + } else { + opt = 1; } if (opt == 1) { @@ -185,35 +198,59 @@ public class FontPanel extends javax.swing.JPanel { fontLeadingLabel.setText(ft.getLeading() == -1 ? translate("value.unknown") : "" + ft.getLeading()); String chars = ft.getCharacters(swf.tags); fontCharactersTextArea.setText(chars); + setAllowSave(false); String key = swf.getShortFileName() + "_" + ft.getFontId() + "_" + ft.getFontName(); - if (swf.sourceFontsMap.containsKey(ft.getFontId())) { - fontSelection.setSelectedItem(swf.sourceFontsMap.get(ft.getFontId())); - } else if (Configuration.getFontPairs().containsKey(key)) { - fontSelection.setSelectedItem(Configuration.getFontPairs().get(key)); - } else if (Configuration.getFontPairs().containsKey(ft.getFontName())) { - fontSelection.setSelectedItem(Configuration.getFontPairs().get(ft.getFontName())); + if (swf.sourceFontFamiliesMap.containsKey(ft.getFontId())) { + fontFamilyNameSelection.setSelectedItem(swf.sourceFontFamiliesMap.get(ft.getFontId())); + } else if (Configuration.getFontIdToFamilyMap().containsKey(key)) { + fontFamilyNameSelection.setSelectedItem(Configuration.getFontIdToFamilyMap().get(key)); + } else if (Configuration.getFontIdToFamilyMap().containsKey(ft.getFontName())) { + fontFamilyNameSelection.setSelectedItem(Configuration.getFontIdToFamilyMap().get(ft.getFontName())); } else { - fontSelection.setSelectedItem(FontTag.findInstalledFontName(ft.getFontName())); + fontFamilyNameSelection.setSelectedItem(FontTag.findInstalledFontFamily(ft.getFontName())); } + + if (swf.sourceFontFacesMap.containsKey(ft.getFontId())) { + fontFaceSelection.setSelectedItem(swf.sourceFontFacesMap.get(ft.getFontId())); + } else if (Configuration.getFontIdToFaceMap().containsKey(key)) { + fontFaceSelection.setSelectedItem(Configuration.getFontIdToFaceMap().get(key)); + } else if (Configuration.getFontIdToFaceMap().containsKey(ft.getFontName())) { + fontFaceSelection.setSelectedItem(Configuration.getFontIdToFaceMap().get(ft.getFontName())); + } else { + java.util.Map faces = FontTag.installedFonts.get(fontFamilyNameSelection.getSelectedItem().toString()); + boolean found = false; + for (String face : faces.keySet()) { + Font f = faces.get(face); + if (f.isBold() == ft.isBold() && f.isItalic() == ft.isItalic()) { + found = true; + fontFaceSelection.setSelectedItem(face); + break; + } + } + if (!found) { + fontFaceSelection.setSelectedItem(""); + } + } + setAllowSave(true); setEditable(false); } - /** - * 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() { - java.awt.GridBagConstraints gridBagConstraints; + private static void addTableSpaces(TableLayout tl, double size) { + int cols = tl.getNumColumn(); + int rows = tl.getNumRow(); + for (int x = 0; x <= cols; x++) { + tl.insertColumn(x * 2, size); + } + for (int y = 0; y <= rows; y++) { + tl.insertRow(y * 2, size); + } + } - jScrollPane1 = new javax.swing.JScrollPane(); - jPanel2 = new javax.swing.JPanel(); - jPanel1 = new javax.swing.JPanel(); - javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); + private void initComponents() { + + addCharsPanel = new javax.swing.JPanel(); + fontParamsPanel = new javax.swing.JPanel(); fontNameLabel = new javax.swing.JLabel(); - javax.swing.JLabel jLabel2 = new javax.swing.JLabel(); javax.swing.JScrollPane fontDisplayNameScrollPane = new javax.swing.JScrollPane(); fontDisplayNameTextArea = new javax.swing.JTextArea(); javax.swing.JLabel jLabel3 = new javax.swing.JLabel(); @@ -232,58 +269,44 @@ public class FontPanel extends javax.swing.JPanel { javax.swing.JLabel jLabel9 = new javax.swing.JLabel(); fontCharactersScrollPane = new javax.swing.JScrollPane(); fontCharactersTextArea = new javax.swing.JTextArea(); - javax.swing.JLabel jLabel10 = new javax.swing.JLabel(); + javax.swing.JLabel fontCharsAddLabel = new javax.swing.JLabel(); fontAddCharactersField = new javax.swing.JTextField(); fontAddCharsButton = new javax.swing.JButton(); updateTextsCheckBox = new javax.swing.JCheckBox(); - jLabel11 = new javax.swing.JLabel(); - fontSelection = new javax.swing.JComboBox(); + fontSourceLabel = new javax.swing.JLabel(); + fontFamilyNameSelection = new javax.swing.JComboBox<>(); + fontFaceSelection = new javax.swing.JComboBox<>(); fontEmbedButton = new javax.swing.JButton(); buttonEdit = new javax.swing.JButton(); buttonSave = new javax.swing.JButton(); buttonCancel = new javax.swing.JButton(); buttonPreviewFont = new javax.swing.JButton(); - importTTFButton = new javax.swing.JButton(); - addComponentListener(new java.awt.event.ComponentAdapter() { + @Override public void componentResized(java.awt.event.ComponentEvent evt) { formComponentResized(evt); } }); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + TableLayout tlFontParamsPanel; + fontParamsPanel.setLayout(tlFontParamsPanel = new TableLayout(new double[][]{ + {TableLayout.PREFERRED, TableLayout.FILL}, + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED,} + })); - jPanel1.setLayout(new java.awt.GridBagLayout()); + JLabel fontNameLabLabel = new JLabel(); + fontNameLabLabel.setText(AppStrings.translate("font.name")); // NOI18N + fontParamsPanel.add(fontNameLabLabel, "0,0,R"); - java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/jpexs/decompiler/flash/gui/locales/MainFrame"); // NOI18N - jLabel1.setText(bundle.getString("font.name")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel1, gridBagConstraints); - - fontNameLabel.setText(bundle.getString("value.unknown")); // NOI18N + fontNameLabel.setText(AppStrings.translate("value.unknown")); // NOI18N fontNameLabel.setMaximumSize(new java.awt.Dimension(250, 14)); fontNameLabel.setMinimumSize(new java.awt.Dimension(250, 14)); fontNameLabel.setPreferredSize(new java.awt.Dimension(250, 14)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontNameLabel, gridBagConstraints); + fontParamsPanel.add(fontNameLabel, "1,0"); - jLabel2.setText(bundle.getString("fontName.name")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.ipadx = 8; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel2, gridBagConstraints); + JLabel fontNameNameLabLabel = new JLabel(); + fontNameNameLabLabel.setText(AppStrings.translate("fontName.name")); // NOI18N + fontParamsPanel.add(fontNameNameLabLabel, "0,1,R"); fontDisplayNameScrollPane.setBorder(null); fontDisplayNameScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -293,27 +316,16 @@ public class FontPanel extends javax.swing.JPanel { fontDisplayNameTextArea.setColumns(20); fontDisplayNameTextArea.setFont(new JLabel().getFont()); fontDisplayNameTextArea.setLineWrap(true); - fontDisplayNameTextArea.setText(bundle.getString("value.unknown")); // NOI18N + fontDisplayNameTextArea.setText(AppStrings.translate("value.unknown")); // NOI18N fontDisplayNameTextArea.setWrapStyleWord(true); fontDisplayNameTextArea.setMinimumSize(new java.awt.Dimension(250, 16)); fontDisplayNameTextArea.setOpaque(false); fontDisplayNameScrollPane.setViewportView(fontDisplayNameTextArea); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontDisplayNameScrollPane, gridBagConstraints); + fontParamsPanel.add(fontDisplayNameScrollPane, "1,1"); - jLabel3.setText(bundle.getString("fontName.copyright")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel3, gridBagConstraints); + jLabel3.setText(AppStrings.translate("fontName.copyright")); // NOI18N + fontParamsPanel.add(jLabel3, "0,2,R"); fontCopyrightScrollPane.setBorder(null); fontCopyrightScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -323,107 +335,48 @@ public class FontPanel extends javax.swing.JPanel { fontCopyrightTextArea.setColumns(20); fontCopyrightTextArea.setFont(new JLabel().getFont()); fontCopyrightTextArea.setLineWrap(true); - fontCopyrightTextArea.setText(bundle.getString("value.unknown")); // NOI18N + fontCopyrightTextArea.setText(AppStrings.translate("value.unknown")); // NOI18N fontCopyrightTextArea.setWrapStyleWord(true); fontCopyrightTextArea.setMinimumSize(new java.awt.Dimension(250, 16)); fontCopyrightTextArea.setOpaque(false); fontCopyrightScrollPane.setViewportView(fontCopyrightTextArea); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontCopyrightScrollPane, gridBagConstraints); + fontParamsPanel.add(fontCopyrightScrollPane, "1,2"); - jLabel4.setText(bundle.getString("font.isbold")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel4, gridBagConstraints); + jLabel4.setText(AppStrings.translate("font.isbold")); // NOI18N + fontParamsPanel.add(jLabel4, "0,3,R"); fontIsBoldCheckBox.setEnabled(false); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontIsBoldCheckBox, gridBagConstraints); - jLabel5.setText(bundle.getString("font.isitalic")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 4; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel5, gridBagConstraints); + fontParamsPanel.add(fontIsBoldCheckBox, "1,3"); + + jLabel5.setText(AppStrings.translate("font.isitalic")); // NOI18N + + fontParamsPanel.add(jLabel5, "0,4,R"); fontIsItalicCheckBox.setEnabled(false); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 4; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontIsItalicCheckBox, gridBagConstraints); + fontParamsPanel.add(fontIsItalicCheckBox, "1,4"); - jLabel6.setText(bundle.getString("font.ascent")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 5; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel6, gridBagConstraints); + jLabel6.setText(AppStrings.translate("font.ascent")); // NOI18N + fontParamsPanel.add(jLabel6, "0,5,R"); - fontAscentLabel.setText(bundle.getString("value.unknown")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 5; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontAscentLabel, gridBagConstraints); + fontAscentLabel.setText(AppStrings.translate("value.unknown")); // NOI18N + fontParamsPanel.add(fontAscentLabel, "1,5"); - jLabel7.setText(bundle.getString("font.descent")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 6; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel7, gridBagConstraints); + jLabel7.setText(AppStrings.translate("font.descent")); // NOI18N + fontParamsPanel.add(jLabel7, "0,6,R"); - fontDescentLabel.setText(bundle.getString("value.unknown")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 6; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontDescentLabel, gridBagConstraints); + fontDescentLabel.setText(AppStrings.translate("value.unknown")); // NOI18N + fontParamsPanel.add(fontDescentLabel, "1,6"); - jLabel8.setText(bundle.getString("font.leading")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 7; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel8, gridBagConstraints); + jLabel8.setText(AppStrings.translate("font.leading")); // NOI18N + fontParamsPanel.add(jLabel8, "0,7,R"); - fontLeadingLabel.setText(bundle.getString("value.unknown")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 7; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontLeadingLabel, gridBagConstraints); + fontLeadingLabel.setText(AppStrings.translate("value.unknown")); // NOI18N + fontParamsPanel.add(fontLeadingLabel, "1,7"); - jLabel9.setText(bundle.getString("font.characters")); // NOI18N - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 8; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jLabel9, gridBagConstraints); + jLabel9.setText(AppStrings.translate("font.characters")); // NOI18N + fontParamsPanel.add(jLabel9, "0,8,R"); fontCharactersScrollPane.setBorder(null); fontCharactersScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -437,173 +390,128 @@ public class FontPanel extends javax.swing.JPanel { fontCharactersTextArea.setMinimumSize(new java.awt.Dimension(250, 16)); fontCharactersTextArea.setOpaque(false); fontCharactersScrollPane.setViewportView(fontCharactersTextArea); + fontParamsPanel.add(fontCharactersScrollPane, "1,8"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 8; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 6); - jPanel1.add(fontCharactersScrollPane, gridBagConstraints); + fontCharsAddLabel.setText(AppStrings.translate("font.characters.add")); // NOI18N - jLabel10.setText(bundle.getString("font.characters.add")); // NOI18N - - fontAddCharsButton.setText(bundle.getString("button.ok")); // NOI18N + fontAddCharsButton.setText(AppStrings.translate("button.ok")); // NOI18N fontAddCharsButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { fontAddCharsButtonActionPerformed(evt); } }); - updateTextsCheckBox.setText(bundle.getString("font.updateTexts")); // NOI18N + updateTextsCheckBox.setText(AppStrings.translate("font.updateTexts")); // NOI18N - jLabel11.setText(bundle.getString("font.source")); // NOI18N + fontSourceLabel.setText(AppStrings.translate("font.source")); // NOI18N - fontSelection.setModel(getModel()); - fontSelection.setSelectedItem(FontTag.defaultFontName); - fontSelection.addItemListener(new java.awt.event.ItemListener() { + fontFamilyNameSelection.setModel(getFamilyModel()); + fontFamilyNameSelection.setSelectedItem(FontTag.defaultFontName); + fontFaceSelection.setModel(getNameModel((String) fontFamilyNameSelection.getSelectedItem())); + fontFamilyNameSelection.addItemListener(new java.awt.event.ItemListener() { + @Override public void itemStateChanged(java.awt.event.ItemEvent evt) { - fontSelectionItemStateChanged(evt); + fontFamilySelectionItemStateChanged(); } }); - fontEmbedButton.setText(bundle.getString("button.font.embed")); // NOI18N + fontFaceSelection.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent evt) { + fontFaceSelectionItemStateChanged(); + } + }); + + fontEmbedButton.setText(AppStrings.translate("button.font.embed")); // NOI18N fontEmbedButton.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(java.awt.event.ActionEvent evt) { fontEmbedButtonActionPerformed(evt); } }); buttonEdit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/edit16.png"))); // NOI18N - buttonEdit.setText(bundle.getString("button.edit")); // NOI18N + buttonEdit.setText(AppStrings.translate("button.edit")); // NOI18N buttonEdit.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(java.awt.event.ActionEvent evt) { buttonEditActionPerformed(evt); } }); buttonSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/save16.png"))); // NOI18N - buttonSave.setText(bundle.getString("button.save")); // NOI18N + buttonSave.setText(AppStrings.translate("button.save")); // NOI18N buttonSave.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(java.awt.event.ActionEvent evt) { buttonSaveActionPerformed(evt); } }); buttonCancel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jpexs/decompiler/flash/gui/graphics/cancel16.png"))); // NOI18N - buttonCancel.setText(bundle.getString("button.cancel")); // NOI18N + buttonCancel.setText(AppStrings.translate("button.cancel")); // NOI18N buttonCancel.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(java.awt.event.ActionEvent evt) { buttonCancelActionPerformed(evt); } }); - buttonPreviewFont.setText(bundle.getString("button.preview")); // NOI18N + buttonPreviewFont.setText(AppStrings.translate("button.preview")); // NOI18N buttonPreviewFont.addActionListener(new java.awt.event.ActionListener() { + @Override public void actionPerformed(java.awt.event.ActionEvent evt) { buttonPreviewFontActionPerformed(evt); } }); - importTTFButton.setText("Import TTF"); - importTTFButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - importTTFButtonActionPerformed(evt); - } - }); + TableLayout tlAddCharsPanel; + addCharsPanel.setLayout(tlAddCharsPanel = new TableLayout(new double[][]{ + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}, + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED} + })); + addCharsPanel.setBorder(BorderFactory.createRaisedBevelBorder()); - javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); - jPanel2.setLayout(jPanel2Layout); - jPanel2Layout.setHorizontalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addComponent(importTTFButton) - .addContainerGap(387, Short.MAX_VALUE)) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addComponent(jLabel11) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(fontSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel2Layout.createSequentialGroup() - .addComponent(jLabel10) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(fontAddCharactersField, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(fontEmbedButton)) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(buttonEdit) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonSave) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(buttonCancel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel2Layout.createSequentialGroup() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addComponent(fontAddCharsButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(updateTextsCheckBox)) - .addComponent(buttonPreviewFont)) - .addGap(315, 315, 315))) - .addContainerGap())) - ); - jPanel2Layout.setVerticalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() - .addContainerGap(341, Short.MAX_VALUE) - .addComponent(importTTFButton) - .addGap(85, 85, 85)) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel10, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(fontAddCharactersField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fontAddCharsButton) - .addComponent(updateTextsCheckBox)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel11) - .addComponent(fontSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(buttonPreviewFont) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fontEmbedButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 78, Short.MAX_VALUE) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonEdit) - .addComponent(buttonSave) - .addComponent(buttonCancel)) - .addContainerGap())) - ); + addCharsPanel.add(fontCharsAddLabel, "0,0,R"); + addCharsPanel.add(fontAddCharactersField, "1,0,2,0"); + addCharsPanel.add(fontAddCharsButton, "3,0"); + addCharsPanel.add(fontEmbedButton, "4,0"); - jScrollPane1.setViewportView(jPanel2); + addCharsPanel.add(fontSourceLabel, "0,1,R"); + addCharsPanel.add(fontFamilyNameSelection, "1,1"); + addCharsPanel.add(fontFaceSelection, "2,1"); + addCharsPanel.add(buttonPreviewFont, "3,1"); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 415, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents + addCharsPanel.add(updateTextsCheckBox, "0,2,2,2"); - private void fontAddCharsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontAddCharsButtonActionPerformed + JPanel buttonsPanel = new JPanel(new FlowLayout()); + buttonsPanel.add(buttonEdit); + buttonsPanel.add(buttonSave); + buttonsPanel.add(buttonCancel); + + TableLayout tlAll; + setLayout(tlAll = new TableLayout(new double[][]{ + {TableLayout.FILL}, + {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED} + })); + + add(fontParamsPanel, "0,0"); + add(buttonsPanel, "0,1"); + add(addCharsPanel, "0,2"); + + addTableSpaces(tlAddCharsPanel, 10); + addTableSpaces(tlFontParamsPanel, 10); + addTableSpaces(tlAll, 10); + + } + + private void labsize(JLabel lab) { + lab.setPreferredSize(new Dimension(lab.getFontMetrics(lab.getFont()).stringWidth(lab.getText()) + 30, lab.getPreferredSize().height)); + lab.setMinimumSize(lab.getPreferredSize()); + } + + private void fontAddCharsButtonActionPerformed(java.awt.event.ActionEvent evt) { String newchars = fontAddCharactersField.getText(); TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); @@ -612,47 +520,69 @@ public class FontPanel extends javax.swing.JPanel { for (int c = 0; c < newchars.length(); c++) { selChars.add(newchars.codePointAt(c)); } - fontAddChars((FontTag) item, selChars, new Font(fontSelection.getSelectedItem().toString(),Font.PLAIN,12)); + fontAddChars((FontTag) item, selChars, FontTag.installedFonts.get(fontFamilyNameSelection.getSelectedItem().toString()).get(fontFaceSelection.getSelectedItem().toString())); fontAddCharactersField.setText(""); mainPanel.reload(true); } - }//GEN-LAST:event_fontAddCharsButtonActionPerformed - - - private void fontEmbedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontEmbedButtonActionPerformed + } + + private void fontEmbedButtonActionPerformed(java.awt.event.ActionEvent evt) { TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); if (item instanceof FontTag) { FontTag ft = (FontTag) item; - FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ft.getFontStyle()); - if (fed.display()) { + FontEmbedDialog fed = new FontEmbedDialog(fontFamilyNameSelection.getSelectedItem().toString(), fontFaceSelection.getSelectedItem().toString(), fontAddCharactersField.getText()); + if (fed.display()) { Set selChars = fed.getSelectedChars(); if (!selChars.isEmpty()) { - String selFont = fed.getSelectedFont(); - fontSelection.setSelectedItem(selFont); - fontAddChars(ft, selChars, new Font(selFont,Font.PLAIN,10)); - fontAddCharactersField.setText(""); - mainPanel.reload(true); + Font selFont = fed.getSelectedFont(); + updateTextsCheckBox.setSelected(fed.hasUpdateTexts()); + fontFamilyNameSelection.setSelectedItem(selFont.getName()); + fontFaceSelection.setSelectedItem(FontHelper.getFontFace(selFont)); + fontAddChars(ft, selChars, selFont); + fontAddCharactersField.setText(""); + mainPanel.reload(true); } } } - }//GEN-LAST:event_fontEmbedButtonActionPerformed + } - private void fontSelectionItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_fontSelectionItemStateChanged + private boolean allowSave = true; + + private synchronized void setAllowSave(boolean v) { + allowSave = v; + } + + private synchronized void savePair() { + if (!allowSave) { + return; + } TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); if (item instanceof FontTag) { FontTag f = (FontTag) item; SWF swf = f.getSwf(); - String selectedSystemFont = (String) fontSelection.getSelectedItem(); - swf.sourceFontsMap.put(f.getFontId(), selectedSystemFont); - Configuration.addFontPair(swf.getShortFileName(), f.getFontId(), f.getFontName(), selectedSystemFont); + String selectedFamily = (String) fontFamilyNameSelection.getSelectedItem(); + String selectedFace = (String) fontFaceSelection.getSelectedItem(); + swf.sourceFontFamiliesMap.put(f.getFontId(), selectedFamily); + swf.sourceFontFacesMap.put(f.getFontId(), selectedFace); + Configuration.addFontPair(swf.getShortFileName(), f.getFontId(), f.getFontName(), selectedFamily, selectedFace); } - }//GEN-LAST:event_fontSelectionItemStateChanged + } - private void buttonEditActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEditActionPerformed + private void fontFamilySelectionItemStateChanged() { + + savePair(); + fontFaceSelection.setModel(getNameModel((String) fontFamilyNameSelection.getSelectedItem())); + } + + private void fontFaceSelectionItemStateChanged() { + savePair(); + } + + private void buttonEditActionPerformed(java.awt.event.ActionEvent evt) { setEditable(true); - }//GEN-LAST:event_buttonEditActionPerformed + } - private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed + private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) { if (fontTag.isBoldEditable()) { fontTag.setBold(fontIsBoldCheckBox.isSelected()); } @@ -660,76 +590,76 @@ public class FontPanel extends javax.swing.JPanel { fontTag.setItalic(fontIsItalicCheckBox.isSelected()); } setEditable(false); - }//GEN-LAST:event_buttonSaveActionPerformed + } - private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed + private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) { showFontTag(fontTag); setEditable(false); - }//GEN-LAST:event_buttonCancelActionPerformed + } - private void buttonPreviewFontActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPreviewFontActionPerformed - String selectedSystemFont = (String) fontSelection.getSelectedItem(); - new FontPreviewDialog(null, true, new Font(selectedSystemFont, fontTag.getFontStyle(), 1024)).setVisible(true); - }//GEN-LAST:event_buttonPreviewFontActionPerformed + private void buttonPreviewFontActionPerformed(java.awt.event.ActionEvent evt) { + String familyName = (String) fontFamilyNameSelection.getSelectedItem(); + String face = (String) fontFaceSelection.getSelectedItem(); + new FontPreviewDialog(null, true, FontTag.installedFonts.get(familyName).get(face)).setVisible(true); + } - private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized - jPanel1.updateUI(); - }//GEN-LAST:event_formComponentResized + private void formComponentResized(java.awt.event.ComponentEvent evt) { + fontParamsPanel.updateUI(); + } - private void importTTFButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importTTFButtonActionPerformed + private void importTTFButtonActionPerformed(java.awt.event.ActionEvent evt) { TreeItem item = mainPanel.tagTree.getCurrentTreeItem(); if (item instanceof FontTag) { - FontTag ft = (FontTag) item; - - - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get())); - FileFilter ttfFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory()); - } + FontTag ft = (FontTag) item; - @Override - public String getDescription() { - return "TTF files"; - } - }; - fc.setFileFilter(ttfFilter); - - fc.setAcceptAllFileFilterUsed(false); - JFrame fr = new JFrame(); - View.setWindowIcon(fr); - int returnVal = fc.showOpenDialog(fr); - if (returnVal == JFileChooser.APPROVE_OPTION) { - Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); - File selfile = Helper.fixDialogFile(fc.getSelectedFile()); - Set selChars = new HashSet<>(); - try { - Font f = Font.createFont(Font.TRUETYPE_FONT, selfile); - int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020}; - loopi:for(char i=0;i selChars = new HashSet<>(); + try { + Font f = Font.createFont(Font.TRUETYPE_FONT, selfile); + int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020}; + loopi: + for (char i = 0; i < Character.MAX_VALUE; i++) { + for (int r : required) { + if (r == i) { + continue loopi; + } + } + if (f.canDisplay((int) i)) { + selChars.add((int) i); + } + } + fontAddChars(ft, selChars, f); + mainPanel.reload(true); + } catch (FontFormatException ex) { + JOptionPane.showMessageDialog(mainPanel, "Invalid TTF font"); + } catch (IOException ex) { + Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + } + private javax.swing.JButton buttonCancel; private javax.swing.JButton buttonEdit; private javax.swing.JButton buttonPreviewFont; @@ -747,12 +677,11 @@ public class FontPanel extends javax.swing.JPanel { private javax.swing.JCheckBox fontIsItalicCheckBox; private javax.swing.JLabel fontLeadingLabel; private javax.swing.JLabel fontNameLabel; - private javax.swing.JComboBox fontSelection; - private javax.swing.JButton importTTFButton; - private javax.swing.JLabel jLabel11; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; + private javax.swing.JComboBox fontFamilyNameSelection; + private javax.swing.JComboBox fontFaceSelection; + private javax.swing.JLabel fontSourceLabel; + private javax.swing.JPanel fontParamsPanel; + private javax.swing.JPanel addCharsPanel; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JCheckBox updateTextsCheckBox; - // End of variables declaration//GEN-END:variables } diff --git a/src/com/jpexs/decompiler/flash/gui/FontPreviewDialog.java b/src/com/jpexs/decompiler/flash/gui/FontPreviewDialog.java index 073c0961b..4e3e7a82f 100644 --- a/src/com/jpexs/decompiler/flash/gui/FontPreviewDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/FontPreviewDialog.java @@ -48,13 +48,13 @@ public class FontPreviewDialog extends AppDialog { initComponents(); View.setWindowIcon(this); - labelSample12.setFont(font.deriveFont(Font.PLAIN, 12)); - labelSample18.setFont(font.deriveFont(Font.PLAIN, 18)); - labelSample24.setFont(font.deriveFont(Font.PLAIN, 24)); - labelSample36.setFont(font.deriveFont(Font.PLAIN, 36)); - labelSample48.setFont(font.deriveFont(Font.PLAIN, 48)); - labelSample60.setFont(font.deriveFont(Font.PLAIN, 60)); - labelSample72.setFont(font.deriveFont(Font.PLAIN, 72)); + labelSample12.setFont(font.deriveFont(12f)); + labelSample18.setFont(font.deriveFont(18f)); + labelSample24.setFont(font.deriveFont(24f)); + labelSample36.setFont(font.deriveFont(36f)); + labelSample48.setFont(font.deriveFont(48f)); + labelSample60.setFont(font.deriveFont(60f)); + labelSample72.setFont(font.deriveFont(72f)); comboBoxSampleTexts.setSelectedIndex(Configuration.guiFontPreviewSampleText.get(0)); if (Configuration.guiFontPreviewWidth.hasValue()) { int width = Configuration.guiFontPreviewWidth.get(); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 66320d72c..f47c59393 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -1906,11 +1906,11 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec if (textTag.setFormattedText(new MissingCharacterHandler() { @Override public boolean handle(FontTag font, char character) { - String fontName = font.getSwf().sourceFontsMap.get(font.getFontId()); + String fontName = font.getSwf().sourceFontFamiliesMap.get(font.getFontId()); if (fontName == null) { fontName = font.getFontName(); } - fontName = FontTag.findInstalledFontName(fontName); + fontName = FontTag.findInstalledFontFamily(fontName); Font f = new Font(fontName, font.getFontStyle(), 18); if (!f.canDisplay(character)) { View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + character), translate("error"), JOptionPane.ERROR_MESSAGE); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/FontEmbedDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/FontEmbedDialog.properties index 71301cdb8..917c9486a 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/FontEmbedDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/FontEmbedDialog.properties @@ -16,3 +16,11 @@ range.description = %name% (%available% of %total% characters) dialog.title = Font embedding label.individual = Individual characters: +button.loadfont = Load font from disk... +filter.ttf = True Type Font files (*.ttf) +error.invalidfontfile = Invalid font file +error.cannotreadfontfile = Cannot read font file +installed = Installed: +ttffile.noselection = TTF file: +ttffile.selection = TTF soubor: %fontname% (%filename%) +allcharacters = V\u0161echny znaky (%available% znak\u016f) \ No newline at end of file