biskuteri-cafe-JKomasto2/ProfileWindow.java

447 lines
12 KiB
Java

/* copyright
This file is part of JKomasto2.
Written in 2022 by Usawashi <usawashi16@yahoo.co.jp>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
copyright */
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.Graphics;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Shape;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.geom.Ellipse2D;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
class
ProfileWindow extends JFrame {
private JKomasto
primaire;
private MastodonApi
api;
private Account
account;
// - -%- -
private ProfileComponent
display;
// ---%-@-%---
public void
use(Account account)
{
this.account = account;
account.resolveAvatar();
display.setAvatar(account.avatar);
display.setAccountID(account.id);
display.setDisplayName(account.name);
int n1 = account.followedCount;
int n2 = account.followerCount;
display.setFollowedAndFollowers(n1 + " & " + n2);
int n3 = account.postCount;
String hs;
if (n3 >= 1000) hs = "~" + (n3 / 1000) + "K";
else if (n3 >= 300) hs = "~" + (n3 / 100) + "00";
else hs = Integer.toString(n3);
hs += " posts since ";
switch (account.creationDate.getMonth())
{
case JANUARY: hs += "Jan"; break;
case FEBRUARY: hs += "Feb"; break;
case MARCH: hs += "Mar"; break;
case APRIL: hs += "Apr"; break;
case MAY: hs += "May"; break;
case JUNE: hs += "Jun"; break;
case JULY: hs += "Jul"; break;
case AUGUST: hs += "Aug"; break;
case SEPTEMBER: hs += "Sept"; break;
case OCTOBER: hs += "Oct"; break;
case NOVEMBER: hs += "Nov"; break;
case DECEMBER: hs += "Dec"; break;
/*
* (悪) We're hardcoding for English right now,
* but later we need to localise properly using
* Month#getDisplayName. Right now I'm just
* finishing this component ASAP for English.
*/
}
hs += " " + account.creationDate.getYear();
display.setHistory(hs);
for (int i = 1; i <= 4; ++i)
{
if (i > account.fields.length)
{
display.setField(i, "", "");
continue;
}
String[] field = account.fields[i - 1];
display.setField(i, field[0], field[1]);
}
display.setDescription(account.description);
setTitle(account.name + " - JKomasto");
}
// - -%- -
public void
seePosts()
{
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
TimelineWindow w = new TimelineWindow(primaire);
w.showAuthorPosts(account.numId);
w.showLatestPage();
w.setLocationRelativeTo(this);
w.setVisible(true);
display.setCursor(null);
}
// ---%-@-%---
ProfileWindow(JKomasto primaire)
{
super("Profile window - JKomasto");
this.primaire = primaire;
this.api = primaire.getMastodonApi();
this.display = new ProfileComponent(this);
add(display);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
}
class
ProfileComponent extends JPanel
implements ActionListener {
private ProfileWindow
primaire;
// - -5- -
private Image
avatar;
private JLabel
accountIdLabel,
accountId,
displayNameLabel,
displayName,
followedLabel,
followed,
historyLabel,
history,
field1Label,
field1,
field2Label,
field2,
field3Label,
field3,
field4Label,
field4;
private JTextArea
description;
private JScrollPane
scroll;
private JButton
seePosts;
private int
dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4;
// ---%-@-%---
public void
setAvatar(Image avatar)
{
this.avatar = avatar;
}
public void
setAccountID(String id)
{
accountId.setText(id);
}
public void
setDisplayName(String name)
{
displayName.setText(name);
}
public void
setFollowedAndFollowers(String text)
{
followed.setText(text);
}
public void
setHistory(String text)
{
history.setText(text);
}
public void
setField(int index, String name, String value)
{
assert index >= 1 && index <= 4;
JLabel label = null, field = null;
switch (index)
{
case 1: label = field1Label; field = field1; break;
case 2: label = field2Label; field = field2; break;
case 3: label = field3Label; field = field3; break;
case 4: label = field4Label; field = field4; break;
}
label.setText(name);
field.setText(value);
}
public void
setDescription(String html)
{
description.setText(html);
}
// - -%- -
public void
actionPerformed(ActionEvent eA)
{
assert eA.getSource() == seePosts;
primaire.seePosts();
}
protected void
paintComponent(Graphics g)
{
g.clearRect(0, 0, getWidth(), getHeight());
int w = getWidth(), h = getHeight();
int aw = 256;
int ah = 256;
int ax = (w - aw) / 2;
int ay = 10;
int acx = ax + (aw / 2);
int acy = ay + (ah / 2);
Shape defaultClip = g.getClip();
g.setClip(new Ellipse2D.Float(ax, ay, aw, ah));
g.drawImage(avatar, ax, ay, aw, ah, this);
g.setClip(defaultClip);
g.setColor(new Color(0, 0, 0, 50));
g.fillRect(0, acy - dy1, acx - dx1, 2);
g.fillRect(0, acy - dy2, acx - dx2, 2);
g.fillRect(0, acy + dy3, acx - dx3, 2);
g.fillRect(0, acy + dy4, acx - dx4, 2);
g.fillRect(acx + dx1, acy - dy1, w - (acx + dx1), 2);
g.fillRect(acx + dx2, acy - dy2, w - (acx + dx2), 2);
g.fillRect(acx + dx3, acy + dy3, w - (acx + dx3), 2);
g.fillRect(acx + dx4, acy + dy4, w - (acx + dx4), 2);
((java.awt.Graphics2D)g).setRenderingHint(
java.awt.RenderingHints.KEY_ANTIALIASING,
java.awt.RenderingHints.VALUE_ANTIALIAS_ON
);
}
public void
doLayout()
{
final double TAU = 2 * Math.PI;
int w = getWidth(), h = getHeight();
int aw = 256;
int ah = 256;
int ax = (w - aw) / 2;
int ay = 10;
int acx = ax + (aw / 2);
int acy = ay + (ah / 2);
dx1 = (int)((aw * 11/20) * Math.cos(TAU * 45 / 360));
dx2 = (int)((aw * 11/20) * Math.cos(TAU * 15 / 360));
dx3 = dx2;
dx4 = dx1;
dy1 = (int)((ah / 2) * Math.sin(TAU * 45 / 360));
dy2 = (int)((ah / 2) * Math.sin(TAU * 15 / 360));
dy3 = dy2;
dy4 = dy1;
FontMetrics fm = getFontMetrics(field1.getFont());
int lh = fm.getAscent() * 9 / 8;
accountIdLabel.setLocation(10, acy - dy1 - lh - 1);
accountId.setLocation(10, acy - dy1 + 1);
accountIdLabel.setSize(acx - dx1 - 16, lh);
accountId.setSize(acx - dx1 - 24, lh);
displayNameLabel.setLocation(10, acy - dy2 - lh - 1);
displayName.setLocation(10, acy - dy2 + 1);
displayNameLabel.setSize(acx - dx2 - 16, lh);
displayName.setSize(acx - dx2 - 24, lh);
followedLabel.setLocation(10, acy + dy3 - lh - 1);
followed.setLocation(10, acy + dy3 + 1);
followedLabel.setSize(acx - dx3 - 24, lh);
followed.setSize(acx - dx3 - 16, lh);
historyLabel.setLocation(10, acy + dy4 - lh - 1);
history.setLocation(10, acy + dy4 + 1);
historyLabel.setSize(acx - dx4 - 24, lh);
history.setSize(acx - dx4 - 16, lh);
field1Label.setLocation(acx + dx1 + 16, acy - dy1 - lh - 1);
field1.setLocation(acx + dx1 + 24, acy - dy1 + 1);
field1Label.setSize(w - 10 - (acy + dx1 + 16), lh);
field1.setSize(w - 10 - (acy + dx1 + 24), lh);
field2Label.setLocation(acx + dx2 + 16, acy - dy2 - lh - 1);
field2.setLocation(acx + dx2 + 24, acy - dy2 + 1);
field2Label.setSize((w - 10) - (acy + dx2 + 16), lh);
field2.setSize((w - 10) - (acy + dx2 + 24), lh);
field3Label.setLocation(acx + dx3 + 24, acy + dy3 - lh - 1);
field3.setLocation(acx + dx3 + 16, acy + dy3 + 1);
field3Label.setSize((w - 10) - (acy + dx3 + 24), lh);
field3.setSize((w - 10) - (acy + dx3 + 16), lh);
field4Label.setLocation(acx + dx4 + 24, acy + dy4 - lh - 1);
field4.setLocation(acx + dx4 + 16, acy + dy4 + 1);
field4Label.setSize((w - 10) - (acy + dx4 + 24), lh);
field4.setSize((w - 10) - (acy + dx4 + 16), lh);
seePosts.setLocation(10, h - 10 - 24);
seePosts.setSize((w - 40) / 4, 24);
scroll.setLocation(10, (ay + ah) + 10);
scroll.setSize(w - 20, seePosts.getY() - 10 - scroll.getY());
}
// ---%-@-%---
ProfileComponent(ProfileWindow primaire)
{
this.primaire = primaire;
Font f1 = new Font("VL Gothic", Font.PLAIN, 16);
Font f2 = new Font("VL Gothic", Font.PLAIN, 14);
int a = JLabel.RIGHT;
accountIdLabel = new JLabel("Account ID", a);
accountId = new JLabel("", a);
displayNameLabel = new JLabel("Display name", a);
displayName = new JLabel("", a);
followedLabel = new JLabel("Followed & followers", a);
followed = new JLabel("", a);
historyLabel = new JLabel("History", a);
history = new JLabel("", a);
field1Label = new JLabel("");
field1 = new JLabel("");
field2Label = new JLabel("");
field2 = new JLabel("");
field3Label = new JLabel("");
field3 = new JLabel("");
field4Label = new JLabel("");
field4 = new JLabel("");
accountIdLabel.setFont(f1);
accountId.setFont(f1);
displayNameLabel.setFont(f1);
displayName.setFont(f1);
followedLabel.setFont(f1);
followed.setFont(f1);
historyLabel.setFont(f1);
history.setFont(f2);
field1Label.setFont(f1);
field1.setFont(f2);
field2Label.setFont(f1);
field2.setFont(f2);
field3Label.setFont(f1);
field3.setFont(f2);
field4Label.setFont(f1);
field4.setFont(f2);
description = new JTextArea();
description.setEditable(false);
description.setLineWrap(true);
description.setBackground(null);
description.setFont(f1);
scroll = new JScrollPane(
description,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
scroll.setBorder(null);
seePosts = new JButton("See posts");
seePosts.addActionListener(this);
setLayout(null);
add(accountIdLabel);
add(accountId);
add(displayNameLabel);
add(displayName);
add(followedLabel);
add(followed);
add(historyLabel);
add(history);
add(field1Label);
add(field1);
add(field2Label);
add(field2);
add(field3Label);
add(field3);
add(field4Label);
add(field4);
add(scroll);
add(seePosts);
setPreferredSize(new Dimension(640, 480));
}
}