Implement skin inheritance via <% .extends skinname %>. Lookup code is now incredibly convoluted for what it does and needs some streamlining.

This commit is contained in:
hns 2009-04-06 05:54:26 +00:00
parent ea2d20c55f
commit 8b65614827
3 changed files with 54 additions and 14 deletions

View file

@ -341,19 +341,25 @@ public final class Prototype {
skin = Skin.getSkin(res, app); skin = Skin.getSkin(res, app);
if (skin.hasMainskin()) if (skin.hasMainskin())
break; break;
String extendz = skin.getExtends();
if (extendz != null && extendz != skinName)
return getSkin(extendz, null, null);
res = res.getOverloadedResource(); res = res.getOverloadedResource();
} }
if (parentName != null) { if (parentName != null) {
Skin parentSkin = null; Skin parentSkin = null;
Resource parent = skinMap.getResource(parentName); Resource parentResource = skinMap.getResource(parentName);
while (parent != null) { while (parentResource != null) {
parentSkin = Skin.getSkin(parent, app); parentSkin = Skin.getSkin(parentResource, app);
if (parentSkin.hasSubskin(subName)) if (parentSkin.hasSubskin(subName))
break; break;
parent = parent.getOverloadedResource(); String extendz = parentSkin.getExtends();
if (extendz != null && extendz != parentName)
return getSkin(extendz, extendz, subName);
parentResource = parentResource.getOverloadedResource();
} }
if (parent != null) { if (parentResource != null) {
if (res != null && app.getResourceComparator().compare(res, parent) > 0) if (res != null && app.getResourceComparator().compare(res, parentResource) > 0)
return skin; return skin;
else else
return parentSkin.getSubskin(subName); return parentSkin.getSubskin(subName);

View file

@ -42,6 +42,8 @@ public final class Skin {
private HashSet sandbox; private HashSet sandbox;
private HashMap subskins; private HashMap subskins;
private Skin parentSkin = this; private Skin parentSkin = this;
private String extendz = null;
private boolean hasContent = false;
static private final int PARSE_MACRONAME = 0; static private final int PARSE_MACRONAME = 0;
static private final int PARSE_PARAM = 1; static private final int PARSE_PARAM = 1;
@ -157,10 +159,16 @@ public final class Skin {
length = i; length = i;
break; break;
} else { } else {
if (!macro.isCommentMacro) {
hasContent = true;
}
partBuffer.add(macro); partBuffer.add(macro);
} }
i = macro.end - 1; i = macro.end - 1;
} else { } else {
if (!hasContent && !Character.isWhitespace(source[i])){
hasContent = true;
}
escape = source[i] == '\\' && !escape; escape = source[i] == '\\' && !escape;
} }
} }
@ -181,7 +189,7 @@ public final class Skin {
* @return true if this skin contains a main skin * @return true if this skin contains a main skin
*/ */
public boolean hasMainskin() { public boolean hasMainskin() {
return length - offset > 0 || subskins == null; return hasContent;
} }
/** /**
@ -212,6 +220,10 @@ public final class Skin {
(String[]) subskins.keySet().toArray(new String[0]); (String[]) subskins.keySet().toArray(new String[0]);
} }
public String getExtends() {
return extendz;
}
/** /**
* Get the raw source text this skin was parsed from * Get the raw source text this skin was parsed from
*/ */
@ -328,8 +340,6 @@ public final class Skin {
} }
} }
class Macro { class Macro {
final int start, end; final int start, end;
String name; String name;
@ -389,6 +399,18 @@ public final class Skin {
handlerType = HANDLER_PARAM; handlerType = HANDLER_PARAM;
} }
} }
if (".extends".equals(name)) {
if (parentSkin != Skin.this) {
throw new RuntimeException("Found .extends in subskin");
}
if (positionalParams == null || positionalParams.size() < 1
|| !(positionalParams.get(0) instanceof String)) {
throw new RuntimeException(".extends requires an unnamed string parameter");
}
extendz = (String) positionalParams.get(0);
isCommentMacro = true; // don't render
}
} }
private int parse(int macroOffset, boolean lenient) { private int parse(int macroOffset, boolean lenient) {

View file

@ -51,7 +51,7 @@ public final class SkinManager implements FilenameFilter {
Skin skin; Skin skin;
Prototype proto = prototype; Prototype proto = prototype;
// if name contains dot, this might be a substring of some other string // if name contains #, this may be a subskin of some other skin
String parentName = null, subskinName = null; String parentName = null, subskinName = null;
int hash = skinname.indexOf('#'); int hash = skinname.indexOf('#');
if (hash > -1) { if (hash > -1) {
@ -65,15 +65,27 @@ public final class SkinManager implements FilenameFilter {
if (skinpath != null) { if (skinpath != null) {
for (int i = 0; i < skinpath.length; i++) { for (int i = 0; i < skinpath.length; i++) {
skin = getSkinInPath(skinpath[i], proto.getName(), skinname); skin = getSkinInPath(skinpath[i], proto.getName(), skinname);
if (skin != null && skin.hasMainskin()) { if (skin != null) {
// check if skin skin contains main skin // check if skin skin contains main skin
return skin; if (skin.hasMainskin()) {
return skin;
}
String extendz = skin.getExtends();
if (extendz != null && !extendz.equals(skinname)) {
return getSkin(prototype, extendz, skinpath);
}
} else if (parentName != null) { } else if (parentName != null) {
// get parent skin // get parent skin
skin = getSkinInPath(skinpath[i], proto.getName(), parentName); skin = getSkinInPath(skinpath[i], proto.getName(), parentName);
// check if it contains subskin // check if it contains subskin
if (skin != null && skin.hasSubskin(subskinName)) { if (skin != null) {
return skin.getSubskin(subskinName); if (skin.hasSubskin(subskinName)) {
return skin.getSubskin(subskinName);
}
String extendz = skin.getExtends();
if (extendz != null && !extendz.equals(skinname)) {
return getSkin(prototype, extendz + "#" + subskinName, skinpath);
}
} }
} }
} }