// Copyright (C) 2014 Josh Ventura
// Code is part of LateralGM <lateralgm.org> and is released under the terms of
// the GNU General Public License as published by the Free Software Foundation;
// version 3 of the license, or any later version.
interface NodeMatcher {
ResNode makeMatchNode(ResNode node, Pattern criterion);
};
/** Matcher used to filter by name. */
static class NameMatcher implements NodeMatcher {
@Override
ResNode makeMatchNode(ResNode node, Pattern name) {
// If the name of this node matches, just return the node.
return name.matcher(node.name).matches()? node : null;
}
}
/** Matcher based on node's full-text content. */
static class NameMatcher implements NodeMatcher {
static Map<Class, NodeMatcher> fullTextMatchers = new HashMap<>();
static {
fullTextMatchers.put(GmObject.class, new ObjectMatcher());
fullTextMatchers.put(Timeline.class, new TimelineMatcher());
// ...
}
@Override
ResNode makeMatchNode(ResNode node, Pattern content) {
if (!fullTextMatchers.containsKey(node.type)) {
return null;
}
return fullTextMatchers.makeMatchNode(node, content);
}
}
static class ObjectMatcher implements NodeMatcher {
@Override
makeMatchNode(ResNode node, Pattern content) {
ResNode rnode = null;
int numMatchingEvents = 0;
// for (Event event : ((GmObject)node.getResource).getEvents()) {
// LineMatch[] lines = getMatchingLines(event.getCode(), content);
// if (lines.length == 0) {
// continue;
// }
// int ind = 0;
// if (rnode == null) {
// rnode = node.clone();
// }
// MutableTreeNode evnode = buildEventNode(event);
// for (LineMatch line : lines) {
// evnode.insert(new MatchNode(line, ind++);
// }
// rnode.addChild(evnode, numMatchingEvents++);
// }
return rnode;
}
}
class LineMatch {
class Block {
String content;
boolean highlighted;
Block(String content, boolean highlighted) {
this.content = content;
this.highlighted = highlighted;
}
}
int lineNum;
List<Block> matchedText;
}
class MatchNode extends DefaultMutableTreeNode {
MatchNode(LineMatch match) {
// Set icon to red arrow
// Assemble rich text from line number and matched text;
// concatenate match.matchedText, highlighting highlighted blocks
}
}
private static final Pattern newline = Pattern.compile("\r\n|\r|\n");
LineMatch[] getMatchingLines(String code, Pattern content) {
List<LineMatch> res = new ArrayList<>();
Matcher m = content.matcher(code), nl = newline.matcher(code);
int lineNum = 1, lineAt = 0, lastEnd = -1;
LineMatch lastMatch = null;
while (m.find()) {
nl.region(lineAt, m.start());
int firstSkippedLineAt = lineAt;
if (nl.find() {
firstSkippedLineAt = nl.start();
lineAt = nl.end();
while (nl.find()) {
++lineNum;
lineAt = nl.end();
}
}
if (lastMatch != null) {
// We have to add the rest of the line to the old match, either way.
// And if we're matching on the same line, we add that match, too.
if (lineNum == lastMatch.lineNum) {
lastMatch.matchedText.add(new LineMatch.Block(code.substring(lastEnd, m.start()), false);
lastMatch.matchedText.add(new LineMatch.Block(code.substring(m.start(), m.end()), true);
} else {
lastMatch.matchedText.add(
new LineMatch.Block(code.substring(lastEnd, firstSkippedLineAt), false);
}
}
if (lastMatch == null || lineNum == lastMatch.lineNum) {
lastMatch = new LineMatch();
lastMatch.lineNum = lineNum;
if (m.start() > lineAt) {
lastMatch.add(new Block(code.substring(lineAt, m.start()), false));
}
lastMatch.add(new Block(code.substring(m.start(), m.end()), false));
res.add(lastMatch);
}
lastEnd = m.end();
}
return res.toArray(new LineMatch[] {});
}
void buildTree(DefaultMutableTreeNode node, DefaultMutableTreeNode newNode,
NodeMatcher matcher, Pattern pattern) {
int numChildren = node.getChildCount();
for (int i = 0; i < numChildren; ++i) {
DefaultMutableTreeNode child = node.getChildAt(i);
if (child instanceof ResNode) {
ResNode resNode = (ResNode)child;
if (child.status == ResNode.STATUS_GROUP) {
ResNode copy = resNode.clone();
buildTree(resNode, copy, matcher);
if (copy.getChildCount() > 0) {
node.add(copy);
}
} else {
ResNode add = matcher.makeMatchNode(node, pattern);
if (add != null) {
node.add(copy);
}
}
}
}
}
Comments
0 B
|👍
/👎