mirror of
https://gitlab.com/biskuteri-cafe/JKomasto2.git
synced 2025-01-06 19:34:45 +01:00
Added attempt at using AttributedString.
Somewhat works now, but I think we'll abandon it..
This commit is contained in:
parent
71b9c496c4
commit
e4f13ad8c8
@ -15,10 +15,10 @@ BasicHTMLParser {
|
||||
{
|
||||
List<String> segments;
|
||||
segments = distinguishTagsFromPcdata(html);
|
||||
segments = evaluateHtmlEscapes(segments);
|
||||
|
||||
|
||||
Tree<String> document;
|
||||
document = toNodes(segments);
|
||||
document = evaluateHtmlEscapes(document);
|
||||
document = distinguishEmojisFromText(document);
|
||||
document = hierarchise(document);
|
||||
|
||||
@ -61,51 +61,6 @@ BasicHTMLParser {
|
||||
return returnee;
|
||||
}
|
||||
|
||||
private static List<String>
|
||||
evaluateHtmlEscapes(List<String> strings)
|
||||
{
|
||||
List<String> returnee = new ArrayList<>();
|
||||
|
||||
for (String string: strings)
|
||||
{
|
||||
StringBuilder whole = new StringBuilder();
|
||||
StringBuilder part = new StringBuilder();
|
||||
boolean inEscape = false;
|
||||
for (char c: string.toCharArray())
|
||||
{
|
||||
if (inEscape && c == ';')
|
||||
{
|
||||
part.append(c);
|
||||
inEscape = false;
|
||||
String v = empty(part);
|
||||
if (v.equals("<")) part.append('<');
|
||||
if (v.equals(">")) part.append('>');
|
||||
if (v.equals("&")) part.append('&');
|
||||
if (v.equals(""")) part.append('"');
|
||||
if (v.equals("'")) part.append('\'');
|
||||
if (v.equals("'")) part.append('\'');
|
||||
}
|
||||
else if (!inEscape && c == '&')
|
||||
{
|
||||
String v = empty(part);
|
||||
if (!v.isEmpty()) whole.append(v);
|
||||
part.append(c);
|
||||
inEscape = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
part.append(c);
|
||||
}
|
||||
}
|
||||
String v = empty(part);
|
||||
if (!v.isEmpty()) whole.append(v);
|
||||
|
||||
returnee.add(empty(whole));
|
||||
}
|
||||
|
||||
return returnee;
|
||||
}
|
||||
|
||||
private static Tree<String>
|
||||
toNodes(List<String> segments)
|
||||
{
|
||||
@ -181,6 +136,22 @@ BasicHTMLParser {
|
||||
return returnee;
|
||||
}
|
||||
|
||||
private static Tree<String>
|
||||
evaluateHtmlEscapes(Tree<String> nodes)
|
||||
{
|
||||
for (Tree<String> node: nodes)
|
||||
{
|
||||
node.value = evaluateHtmlEscapes(node.value);
|
||||
for (Tree<String> attr: node)
|
||||
{
|
||||
attr.key = evaluateHtmlEscapes(attr.key);
|
||||
attr.value = evaluateHtmlEscapes(attr.value);
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static Tree<String>
|
||||
distinguishEmojisFromText(Tree<String> nodes)
|
||||
{
|
||||
@ -233,10 +204,10 @@ BasicHTMLParser {
|
||||
hierarchise(Tree<String> nodes)
|
||||
{
|
||||
Tree<String> root = new Tree<String>();
|
||||
root.add(new Tree<>("attributes", null));
|
||||
root.get(0).add(new Tree<>("html", null));
|
||||
root.key = "tag";
|
||||
root.add(new Tree<>("html", null));
|
||||
root.add(new Tree<>("children", null));
|
||||
|
||||
|
||||
Deque<Tree<String>> parents = new LinkedList<>();
|
||||
parents.push(root);
|
||||
for (Tree<String> node: nodes)
|
||||
@ -246,6 +217,9 @@ BasicHTMLParser {
|
||||
assert node.size() > 0;
|
||||
String tagName = node.get(0).key;
|
||||
|
||||
assert node.get("children") == null;
|
||||
node.add(new Tree<>("children", null));
|
||||
|
||||
boolean isClosing, selfClosing;
|
||||
isClosing = tagName.startsWith("/");
|
||||
selfClosing = node.get("/") != null;
|
||||
@ -258,30 +232,18 @@ BasicHTMLParser {
|
||||
parent = parents.pop();
|
||||
grandparent = parents.peek();
|
||||
|
||||
assert tagName.equals(
|
||||
"/"
|
||||
+ parent.get("attributes").get(0).key
|
||||
);
|
||||
String pTagName = parent.get(0).key;
|
||||
assert tagName.equals("/" + pTagName);
|
||||
|
||||
grandparent.get("children").add(parent);
|
||||
}
|
||||
else if (selfClosing)
|
||||
{
|
||||
Tree<String> elem = new Tree<String>();
|
||||
node.key = "attributes";
|
||||
elem.add(node);
|
||||
elem.add(new Tree<>("children", null));
|
||||
|
||||
parents.peek().get("children").add(elem);
|
||||
parents.peek().get("children").add(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tree<String> elem = new Tree<String>();
|
||||
node.key = "attributes";
|
||||
elem.add(node);
|
||||
elem.add(new Tree<>("children", null));
|
||||
|
||||
parents.push(elem);
|
||||
parents.push(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -325,4 +287,42 @@ BasicHTMLParser {
|
||||
return returnee;
|
||||
}
|
||||
|
||||
private static String
|
||||
evaluateHtmlEscapes(String string)
|
||||
{
|
||||
if (string == null) return string;
|
||||
|
||||
StringBuilder whole = new StringBuilder();
|
||||
StringBuilder part = new StringBuilder();
|
||||
boolean inEscape = false;
|
||||
for (char c: string.toCharArray())
|
||||
{
|
||||
if (inEscape && c == ';')
|
||||
{
|
||||
part.append(c);
|
||||
inEscape = false;
|
||||
String v = empty(part);
|
||||
if (v.equals("<")) part.append('<');
|
||||
if (v.equals(">")) part.append('>');
|
||||
if (v.equals("&")) part.append('&');
|
||||
if (v.equals(""")) part.append('"');
|
||||
if (v.equals("'")) part.append('\'');
|
||||
if (v.equals("'")) part.append('\'');
|
||||
}
|
||||
else if (!inEscape && c == '&')
|
||||
{
|
||||
String v = empty(part);
|
||||
if (!v.isEmpty()) whole.append(v);
|
||||
part.append(c);
|
||||
inEscape = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
part.append(c);
|
||||
}
|
||||
}
|
||||
String v = empty(part);
|
||||
if (!v.isEmpty()) whole.append(v);
|
||||
return whole.toString();
|
||||
}
|
||||
}
|
0
ClipboardApi.java
Executable file → Normal file
0
ClipboardApi.java
Executable file → Normal file
0
ComposeWindow.java
Executable file → Normal file
0
ComposeWindow.java
Executable file → Normal file
0
ImageApi.java
Executable file → Normal file
0
ImageApi.java
Executable file → Normal file
0
ImageWindow.java
Executable file → Normal file
0
ImageWindow.java
Executable file → Normal file
0
JKomasto.java
Executable file → Normal file
0
JKomasto.java
Executable file → Normal file
0
KDE_Dialog_Appear.wav
Executable file → Normal file
0
KDE_Dialog_Appear.wav
Executable file → Normal file
0
LoginWindow.java
Executable file → Normal file
0
LoginWindow.java
Executable file → Normal file
12
MastodonApi.java
Executable file → Normal file
12
MastodonApi.java
Executable file → Normal file
@ -581,15 +581,23 @@ MastodonApi {
|
||||
debugPrint(Tree<String> tree, String prefix)
|
||||
{
|
||||
System.err.print(prefix);
|
||||
System.err.print(tree.key);
|
||||
System.err.print(deescape(tree.key));
|
||||
System.err.print(": ");
|
||||
System.err.println(tree.value);
|
||||
System.err.println(deescape(tree.value));
|
||||
for (Tree<String> child: tree)
|
||||
debugPrint(child, prefix + " ");
|
||||
}
|
||||
|
||||
// - -%- -
|
||||
|
||||
private static String
|
||||
deescape(String string)
|
||||
{
|
||||
if (string == null) return string;
|
||||
string = string.replaceAll("\n", "\\\\n");
|
||||
return string;
|
||||
}
|
||||
|
||||
private static Tree<String>
|
||||
fromPlain(Reader r)
|
||||
throws IOException
|
||||
|
0
NotificationsWindow.java
Executable file → Normal file
0
NotificationsWindow.java
Executable file → Normal file
27
PostWindow.java
Executable file → Normal file
27
PostWindow.java
Executable file → Normal file
@ -58,6 +58,9 @@ PostWindow extends JFrame {
|
||||
private PostComponent
|
||||
display;
|
||||
|
||||
private static JFrame
|
||||
temp;
|
||||
|
||||
// - -%- -
|
||||
|
||||
private static final DateTimeFormatter
|
||||
@ -98,6 +101,28 @@ PostWindow extends JFrame {
|
||||
|
||||
display.setEmojiUrls(post.emojiUrls);
|
||||
|
||||
{
|
||||
Tree<String> html = BasicHTMLParser.parse(post.text);
|
||||
Tree<String> emojiMap = new Tree<>();
|
||||
for (String[] m: post.emojiUrls)
|
||||
{
|
||||
emojiMap.add(new Tree<>(m[0], m[1]));
|
||||
}
|
||||
|
||||
if (temp == null)
|
||||
{
|
||||
temp = new JFrame();
|
||||
temp.setSize(256, 256);
|
||||
temp.setLocationByPlatform(true);
|
||||
temp.setVisible(true);
|
||||
RichTextPane2 pane = new RichTextPane2();
|
||||
pane.setFont(new Font("Dialog", Font.PLAIN, 18));
|
||||
temp.setContentPane(pane);
|
||||
}
|
||||
((RichTextPane2)temp.getContentPane())
|
||||
.setText(html, emojiMap);
|
||||
}
|
||||
|
||||
display.setHtml(post.text);
|
||||
display.setFavourited(post.favourited);
|
||||
display.setBoosted(post.boosted);
|
||||
@ -428,8 +453,6 @@ implements ActionListener {
|
||||
public void
|
||||
setHtml(String n)
|
||||
{
|
||||
BasicHTMLParser.parse(n);
|
||||
|
||||
RichTextPane.Builder b = new RichTextPane.Builder();
|
||||
Tree<String> nodes = RudimentaryHTMLParser.depthlessRead(n);
|
||||
for (Tree<String> node: nodes)
|
||||
|
0
ProfileWindow.java
Executable file → Normal file
0
ProfileWindow.java
Executable file → Normal file
0
RepliesWindow.java
Executable file → Normal file
0
RepliesWindow.java
Executable file → Normal file
0
RequestListener.java
Executable file → Normal file
0
RequestListener.java
Executable file → Normal file
0
RichTextPane.java
Executable file → Normal file
0
RichTextPane.java
Executable file → Normal file
480
RichTextPane2.java
Normal file
480
RichTextPane2.java
Normal file
@ -0,0 +1,480 @@
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import java.text.AttributedString;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Image;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import cafe.biskuteri.hinoki.Tree;
|
||||
|
||||
class
|
||||
RichTextPane2 extends JComponent
|
||||
implements ComponentListener {
|
||||
|
||||
private AttributedString
|
||||
text;
|
||||
|
||||
// ---%-@-%---
|
||||
|
||||
public void
|
||||
setText(Tree<String> html, Tree<String> emojiMap)
|
||||
{
|
||||
Tree<String> commands = turnIntoCommands(html);
|
||||
|
||||
class AStrSegment {
|
||||
String text;
|
||||
int offset;
|
||||
Object[] values = new Object[Attribute.COUNT];
|
||||
/*
|
||||
{
|
||||
values[3] = (Boolean)true;
|
||||
values[4] = (Integer)0;
|
||||
values[5] = (Boolean)true;
|
||||
values[6] = (Boolean)false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
List<AStrSegment> segments = new ArrayList<>();
|
||||
|
||||
int offset = 0;
|
||||
for (Tree<String> command: commands)
|
||||
{
|
||||
if (command.key.equals("text"))
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Boolean cibl = null;
|
||||
Boolean cwhi = null;
|
||||
for (char c: command.value.toCharArray())
|
||||
{
|
||||
Boolean ibl = isBasicLatin(c);
|
||||
Boolean whi = Character.isWhitespace(c);
|
||||
if (!ibl.equals(cibl) || !whi.equals(cwhi))
|
||||
{
|
||||
if (b.length() > 0)
|
||||
{
|
||||
assert cibl != null && cwhi != null;
|
||||
AStrSegment s = new AStrSegment();
|
||||
s.offset = offset;
|
||||
s.text = b.toString();
|
||||
s.values[3] = cibl;
|
||||
s.values[6] = cwhi;
|
||||
segments.add(s);
|
||||
offset += s.text.length();
|
||||
b.delete(0, b.length());
|
||||
}
|
||||
cibl = ibl;
|
||||
cwhi = whi;
|
||||
}
|
||||
|
||||
b.append(c);
|
||||
}
|
||||
if (b.length() > 0)
|
||||
{
|
||||
AStrSegment s = new AStrSegment();
|
||||
s.offset = offset;
|
||||
s.text = b.toString();
|
||||
s.values[3] = cibl;
|
||||
s.values[6] = cwhi;
|
||||
segments.add(s);
|
||||
offset += s.text.length();
|
||||
}
|
||||
}
|
||||
else if (command.key.equals("emoji"))
|
||||
{
|
||||
AStrSegment s = new AStrSegment();
|
||||
s.offset = offset;
|
||||
s.values[3] = true;
|
||||
s.values[6] = false;
|
||||
|
||||
String shortcode = command.value;
|
||||
String url = null;
|
||||
Tree<String> m = emojiMap.get(shortcode);
|
||||
if (m != null) url = m.value;
|
||||
Image img = ImageApi.remote(url);
|
||||
if (img != null)
|
||||
{
|
||||
s.text = " ";
|
||||
s.values[0] = img;
|
||||
s.values[1] = shortcode;
|
||||
segments.add(s);
|
||||
offset += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.text = shortcode;
|
||||
s.values[0] = null;
|
||||
s.values[1] = null;
|
||||
segments.add(s);
|
||||
offset += shortcode.length();
|
||||
}
|
||||
}
|
||||
else if (command.key.equals("link"))
|
||||
{
|
||||
AStrSegment s = new AStrSegment();
|
||||
s.offset = offset;
|
||||
s.text = command.value;
|
||||
s.values[2] = command.get("url").value;
|
||||
s.values[3] = true;
|
||||
s.values[6] = false;
|
||||
/*
|
||||
* Technically we're supposed to treat
|
||||
* the anchor text like a text node.
|
||||
* As in, it could be non-Basic-Latin..
|
||||
* I'll be Mastodon-specific again, and
|
||||
* assume it's a URL or some @ string.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
AttributedString astr;
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (AStrSegment segment: segments)
|
||||
{
|
||||
b.append(segment.text);
|
||||
}
|
||||
astr = new AttributedString(b.toString());
|
||||
for (AStrSegment segment: segments)
|
||||
{
|
||||
Object[] v = segment.values;
|
||||
astr.addAttribute(
|
||||
Attribute.IMAGE, segment.values[0],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.ALT, segment.values[1],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.LINK, segment.values[2],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.BASICLATIN, segment.values[3],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.Y, segment.values[4],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.OFFSCREEN, segment.values[5],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
astr.addAttribute(
|
||||
Attribute.WHITESPACE, segment.values[6],
|
||||
segment.offset,
|
||||
segment.offset + segment.text.length()
|
||||
);
|
||||
}
|
||||
|
||||
this.text = astr;
|
||||
componentResized(null);
|
||||
}
|
||||
|
||||
// - -%- -
|
||||
|
||||
public void
|
||||
componentResized(ComponentEvent eC)
|
||||
{
|
||||
int w = getWidth(), h = getHeight();
|
||||
|
||||
// We're going to evaluate the
|
||||
// line and off-screen attributes.
|
||||
|
||||
FontMetrics fm = getFontMetrics(getFont());
|
||||
Graphics g = getGraphics();
|
||||
int x = 0, y = fm.getAscent();
|
||||
|
||||
AttributedCharacterIterator it;
|
||||
it = text.getIterator();
|
||||
|
||||
while (it.getIndex() < it.getEndIndex())
|
||||
{
|
||||
int start = it.getIndex();
|
||||
int end = it.getRunLimit();
|
||||
|
||||
Image img = (Image)
|
||||
it.getAttribute(Attribute.IMAGE);
|
||||
Boolean ibl = (Boolean)
|
||||
it.getAttribute(Attribute.BASICLATIN);
|
||||
Boolean whi = (Boolean)
|
||||
it.getAttribute(Attribute.WHITESPACE);
|
||||
|
||||
assert ibl != null;
|
||||
assert whi != null;
|
||||
|
||||
if (img != null)
|
||||
{
|
||||
int ow = img.getWidth(this);
|
||||
int oh = img.getHeight(this);
|
||||
int nh = fm.getAscent() + fm.getDescent();
|
||||
int nw = ow * nh/oh;
|
||||
if (x + nw > w)
|
||||
{
|
||||
y += fm.getAscent() + fm.getDescent();
|
||||
x = nw;
|
||||
}
|
||||
text.addAttribute(
|
||||
Attribute.Y, (Integer)y,
|
||||
start, end
|
||||
);
|
||||
text.addAttribute(
|
||||
Attribute.OFFSCREEN, (Boolean)(y > h),
|
||||
start, end
|
||||
);
|
||||
it.setIndex(end);
|
||||
}
|
||||
else
|
||||
{
|
||||
int p, xOff = 0;
|
||||
for (p = end; p > start; --p)
|
||||
{
|
||||
Rectangle2D r;
|
||||
r = fm.getStringBounds(it, start, p, g);
|
||||
xOff = (int)r.getWidth();
|
||||
if (x + xOff < w) break;
|
||||
}
|
||||
if (p == end || whi)
|
||||
{
|
||||
x += xOff;
|
||||
text.addAttribute(
|
||||
Attribute.Y, (Integer)y,
|
||||
start, end
|
||||
);
|
||||
text.addAttribute(
|
||||
Attribute.OFFSCREEN, (Boolean)(y > h),
|
||||
start, end
|
||||
);
|
||||
it.setIndex(end);
|
||||
}
|
||||
else if (p <= start)
|
||||
{
|
||||
y += fm.getAscent() + fm.getDescent();
|
||||
x = xOff;
|
||||
text.addAttribute(
|
||||
Attribute.Y, (Integer)y,
|
||||
start, end
|
||||
);
|
||||
text.addAttribute(
|
||||
Attribute.OFFSCREEN, (Boolean)(y > h),
|
||||
start, end
|
||||
);
|
||||
it.setIndex(end);
|
||||
}
|
||||
else
|
||||
{
|
||||
text.addAttribute(
|
||||
Attribute.Y, (Integer)y,
|
||||
start, p
|
||||
);
|
||||
text.addAttribute(
|
||||
Attribute.OFFSCREEN, (Boolean)(y > h),
|
||||
start, p
|
||||
);
|
||||
y += fm.getAscent() + fm.getDescent();
|
||||
x = 0;
|
||||
it.setIndex(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text.addAttribute(TextAttribute.FONT, getFont());
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
protected void
|
||||
paintComponent(Graphics g)
|
||||
{
|
||||
int w = getWidth(), h = getHeight();
|
||||
g.clearRect(0, 0, w, h);
|
||||
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
|
||||
AttributedCharacterIterator it;
|
||||
it = text.getIterator();
|
||||
|
||||
((java.awt.Graphics2D)g).setRenderingHint(
|
||||
java.awt.RenderingHints.KEY_ANTIALIASING,
|
||||
java.awt.RenderingHints.VALUE_ANTIALIAS_ON
|
||||
);
|
||||
|
||||
int x = 0, y = fm.getAscent();
|
||||
while (it.getIndex() < it.getEndIndex())
|
||||
{
|
||||
int start = it.getIndex();
|
||||
int end = it.getRunLimit();
|
||||
|
||||
Image img = (Image)
|
||||
it.getAttribute(Attribute.IMAGE);
|
||||
Boolean ibl = (Boolean)
|
||||
it.getAttribute(Attribute.BASICLATIN);
|
||||
Integer ny = (Integer)
|
||||
it.getAttribute(Attribute.Y);
|
||||
|
||||
if (ny > y)
|
||||
{
|
||||
y = ny;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (img != null)
|
||||
{
|
||||
int ow = img.getWidth(this);
|
||||
int oh = img.getHeight(this);
|
||||
int nh = fm.getAscent() + fm.getDescent();
|
||||
int nw = ow * nh/oh;
|
||||
int iy = y + fm.getDescent() - nh;
|
||||
g.drawImage(img, x, iy, nw, nh, this);
|
||||
x += nw;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle2D r;
|
||||
r = fm.getStringBounds(it, start, end, g);
|
||||
AttributedCharacterIterator sit;
|
||||
sit = text.getIterator(null, start, end);
|
||||
g.drawString(sit, x, y);
|
||||
x += (int)r.getWidth();
|
||||
}
|
||||
it.setIndex(end);
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
componentMoved(ComponentEvent eC) { }
|
||||
|
||||
public void
|
||||
componentShown(ComponentEvent eC) { }
|
||||
|
||||
public void
|
||||
componentHidden(ComponentEvent eC) { }
|
||||
|
||||
// - -%- -
|
||||
|
||||
private static Boolean
|
||||
isBasicLatin(char c)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String
|
||||
toText(Tree<String> node)
|
||||
{
|
||||
Tree<String> children = node.get("children");
|
||||
if (children == null)
|
||||
{
|
||||
boolean text = node.key.equals("text");
|
||||
boolean emoji = node.key.equals("emoji");
|
||||
assert text || emoji;
|
||||
return node.value;
|
||||
}
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (Tree<String> child: children)
|
||||
{
|
||||
b.append(toText(child));
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private static Tree<String>
|
||||
turnIntoCommands(Tree<String> tag)
|
||||
{
|
||||
assert tag.key.equals("tag");
|
||||
Tree<String> returnee = new Tree<String>();
|
||||
|
||||
String tagName = tag.get(0).key;
|
||||
Tree<String> children = tag.get("children");
|
||||
|
||||
if (tagName.equals("a"))
|
||||
{
|
||||
String url = tag.get("href").value;
|
||||
Tree<String> addee = new Tree<>();
|
||||
addee.key = "link";
|
||||
addee.value = toText(tag);
|
||||
addee.add(new Tree<>("url", url));
|
||||
returnee.add(addee);
|
||||
}
|
||||
else if (tagName.equals("span"))
|
||||
{
|
||||
Tree<String> addee = new Tree<>();
|
||||
addee.key = "text";
|
||||
addee.value = toText(tag);
|
||||
returnee.add(addee);
|
||||
}
|
||||
else if (tagName.equals("br"))
|
||||
{
|
||||
returnee.add(new Tree<>("text", "\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Tree<String> child: children)
|
||||
{
|
||||
if (!child.key.equals("tag"))
|
||||
{
|
||||
returnee.add(child);
|
||||
continue;
|
||||
}
|
||||
child = turnIntoCommands(child);
|
||||
for (Tree<String> command: child)
|
||||
{
|
||||
returnee.add(command);
|
||||
}
|
||||
}
|
||||
if (tagName.equals("p"))
|
||||
{
|
||||
returnee.add(new Tree<>("text", "\n"));
|
||||
returnee.add(new Tree<>("text", "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
return returnee;
|
||||
}
|
||||
|
||||
// ---%-@-%---
|
||||
|
||||
public static class
|
||||
Attribute extends AttributedCharacterIterator.Attribute {
|
||||
|
||||
public static final Attribute
|
||||
IMAGE = new Attribute("IMAGE"),
|
||||
ALT = new Attribute("ALT"),
|
||||
LINK = new Attribute("LINK"),
|
||||
BASICLATIN = new Attribute("BASICLATIN"),
|
||||
Y = new Attribute("Y"),
|
||||
OFFSCREEN = new Attribute("OFFSCREEN"),
|
||||
WHITESPACE = new Attribute("WHITESPACE");
|
||||
|
||||
public static final int
|
||||
COUNT = 7;
|
||||
|
||||
// -=%=-
|
||||
|
||||
private
|
||||
Attribute(String name) { super(name); }
|
||||
|
||||
}
|
||||
|
||||
// ---%-@-%---
|
||||
|
||||
RichTextPane2()
|
||||
{
|
||||
this.addComponentListener(this);
|
||||
text = new AttributedString("");
|
||||
}
|
||||
|
||||
}
|
0
RudimentaryHTMLParser.java
Executable file → Normal file
0
RudimentaryHTMLParser.java
Executable file → Normal file
0
TimelineWindow.java
Executable file → Normal file
0
TimelineWindow.java
Executable file → Normal file
0
TwoToggleButton.java
Executable file → Normal file
0
TwoToggleButton.java
Executable file → Normal file
0
WindowUpdater.java
Executable file → Normal file
0
WindowUpdater.java
Executable file → Normal file
0
notifOptions.txt
Executable file → Normal file
0
notifOptions.txt
Executable file → Normal file
0
notifOptions.txt~
Executable file → Normal file
0
notifOptions.txt~
Executable file → Normal file
7
run
7
run
@ -1,13 +1,14 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
CLASSPATH=.:../Hinoki:/usr/share/java/javax.json.jar
|
||||
OPTIONS=
|
||||
COMPILE_OPTIONS=-Xlint:deprecation
|
||||
RUNTIME_OPTIONS=-ea
|
||||
|
||||
c:
|
||||
javac -cp $(CLASSPATH) $(OPTIONS) *.java
|
||||
javac -cp $(CLASSPATH) $(COMPILE_OPTIONS) *.java
|
||||
|
||||
r:
|
||||
java -cp $(CLASSPATH) $(OPTIONS) -ea JKomasto
|
||||
java -cp $(CLASSPATH) $(RUNTIME_OPTIONS) JKomasto
|
||||
|
||||
cr: c r
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user