/*
* This file is part of The Technic Launcher Version 3.
* Copyright ©2015 Syndicate, LLC
*
* The Technic Launcher 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.
*
* The Technic Launcher 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 the Technic Launcher. If not, see <http://www.gnu.org/licenses/>.
*/
package net.technicpack.launcher.ui.components.modpacks;
import net.technicpack.discord.IDiscordApi;
import net.technicpack.discord.IDiscordCallback;
import net.technicpack.discord.io.Server;
import net.technicpack.ui.lang.ResourceLoader;
import net.technicpack.launcher.ui.LauncherFrame;
import net.technicpack.ui.controls.list.SimpleScrollbarUI;
import net.technicpack.ui.controls.feeds.StatBox;
import net.technicpack.launchercore.image.IImageJobListener;
import net.technicpack.launchercore.image.ImageJob;
import net.technicpack.launchercore.image.ImageRepository;
import net.technicpack.launchercore.modpacks.ModpackModel;
import net.technicpack.utilslib.DesktopUtils;
import net.technicpack.utilslib.ImageUtils;
import javax.swing.*;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class ModpackDataDisplay extends JPanel implements IImageJobListener<ModpackModel>, IDiscordCallback {
private ResourceLoader resources;
private ImageRepository<ModpackModel> logoRepo;
private IDiscordApi discordApi;
private JPanel statBoxes;
private JLabel titleLabel;
private JTextPane description;
private JButton packImage;
private StatBox ratings;
private StatBox runs;
private StatBox downloads;
private JPanel discordPanel;
private JButton discordLabel;
private JButton countLabel;
private java.util.List<JButton> discordButtons = new ArrayList<JButton>(3);
private String packSiteUrl;
private ModpackModel currentModpack;
public ModpackDataDisplay(ResourceLoader resources, ImageRepository<ModpackModel> logoRepo, IDiscordApi api) {
this.resources = resources;
this.logoRepo = logoRepo;
this.discordApi = api;
initComponents();
}
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
return new Dimension(size.width, 225);
}
public void setModpack(ModpackModel modpack) {
this.currentModpack = modpack;
this.packSiteUrl = modpack.getWebSite();
if (this.packSiteUrl == null)
this.packSiteUrl = "http://www.technicpack.net/";
titleLabel.setText(resources.getString("launcher.packstats.title", modpack.getDisplayName()));
description.setText(modpack.getDescription());
boolean wasVisible = ratings.isVisible();
ratings.setVisible(!modpack.isOfficial());
statBoxes.setVisible(!modpack.isOfficial());
if (wasVisible == modpack.isOfficial()) {
if (wasVisible)
statBoxes.remove(ratings);
else
statBoxes.add(ratings, 0);
}
ratings.setValue(modpack.getLikes());
downloads.setValue(modpack.getDownloads());
runs.setValue(modpack.getRuns());
ImageJob<ModpackModel> job = logoRepo.startImageJob(modpack);
job.addJobListener(this);
packImage.setIcon(new ImageIcon(ImageUtils.scaleImage(job.getImage(), 370, 220)));
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
description.scrollRectToVisible(new Rectangle(new Dimension(1, 1)));
repaint();
}
});
discordPanel.setVisible(false);
if (modpack.getDiscordId() != null && !modpack.getDiscordId().isEmpty())
discordApi.retrieveServer(modpack, modpack.getDiscordId(), this);
}
private void initComponents() {
BorderLayout packFeatureLayout = new BorderLayout();
packFeatureLayout.setHgap(10);
this.setLayout(packFeatureLayout);
this.setOpaque(false);
JPanel imagePanel = new JPanel();
imagePanel.setOpaque(false);
imagePanel.setAlignmentX(RIGHT_ALIGNMENT);
imagePanel.setAlignmentY(TOP_ALIGNMENT);
imagePanel.setBorder(BorderFactory.createEmptyBorder());
imagePanel.setPreferredSize(new Dimension(370, 220));
this.add(imagePanel, BorderLayout.LINE_START);
packImage = new JButton(resources.getIcon("modpack/ModImageFiller.png"));
packImage.setIcon(resources.getIcon("modpack/ModImageFiller.png"));
packImage.setAlignmentX(RIGHT_ALIGNMENT);
packImage.setPreferredSize(new Dimension(370, 220));
packImage.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
packImage.setBorder(BorderFactory.createEmptyBorder());
packImage.setContentAreaFilled(false);
packImage.setFocusPainted(false);
packImage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesktopUtils.browseUrl(packSiteUrl);
}
});
imagePanel.add(packImage);
JPanel packInfoPanel = new JPanel();
packInfoPanel.setLayout(new GridBagLayout());
packInfoPanel.setOpaque(false);
packInfoPanel.setAlignmentY(TOP_ALIGNMENT);
packInfoPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
this.add(packInfoPanel, BorderLayout.CENTER);
statBoxes = new JPanel();
statBoxes.setLayout(new GridLayout(1, 3, 5, 0));
statBoxes.setOpaque(false);
statBoxes.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesktopUtils.browseUrl(packSiteUrl);
}
};
ratings = new StatBox(resources, resources.getString("launcher.packstats.ratings"), null);
ratings.setBackground(LauncherFrame.COLOR_LIKES_BACK);
ratings.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
ratings.addActionListener(listener);
statBoxes.add(ratings);
downloads = new StatBox(resources, resources.getString("launcher.packstats.downloads"), null);
downloads.setBackground(LauncherFrame.COLOR_FEEDITEM_BACK);
downloads.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
downloads.addActionListener(listener);
statBoxes.add(downloads);
runs = new StatBox(resources, resources.getString("launcher.packstats.runs"), null);
runs.setBackground(LauncherFrame.COLOR_FEEDITEM_BACK);
runs.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
runs.addActionListener(listener);
statBoxes.add(runs);
packInfoPanel.add(statBoxes, new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
packInfoPanel.add(Box.createHorizontalGlue(), new GridBagConstraints(2, 2, 1, 1, 1.0, 0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
discordPanel = new JPanel();
discordPanel.setOpaque(false);
discordPanel.setLayout(new GridBagLayout());
JButton discordImage = new JButton(resources.getIcon("discord.png"));
discordImage.setContentAreaFilled(false);
discordImage.setFocusPainted(false);
discordImage.setBorder(BorderFactory.createEmptyBorder());
discordImage.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
discordPanel.add(discordImage, new GridBagConstraints(0, 0, 1, 2, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 0, 0, 3), 0, 0));
discordButtons.add(discordImage);
discordLabel = new JButton(resources.getString("launcher.discord.join"));
discordLabel.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
discordLabel.setFont(resources.getFont(ResourceLoader.FONT_OPENSANS, 20));
discordLabel.setContentAreaFilled(false);
discordLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
discordLabel.setFocusPainted(false);
discordLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
discordPanel.add(discordLabel, new GridBagConstraints(1, 0, 1, 1, 1, 0.5, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
discordButtons.add(discordLabel);
countLabel = new JButton(resources.getString("launcher.discord.count", Integer.toString(0)));
countLabel.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
countLabel.setFont(resources.getFont(ResourceLoader.FONT_OPENSANS, 14));
countLabel.setContentAreaFilled(false);
countLabel.setBorder(BorderFactory.createEmptyBorder());
countLabel.setFocusPainted(false);
countLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
discordPanel.add(countLabel, new GridBagConstraints(1, 1, 1, 1, 1, 0.5, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
discordButtons.add(countLabel);
packInfoPanel.add(discordPanel, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 4), 0, 0));
discordPanel.setVisible(false);
titleLabel = new JLabel(resources.getString("launcher.packstats.title", "Modpack"));
titleLabel.setFont(resources.getFont(ResourceLoader.FONT_RALEWAY, 24, Font.BOLD));
titleLabel.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
titleLabel.setHorizontalAlignment(SwingConstants.LEFT);
titleLabel.setHorizontalTextPosition(SwingConstants.LEFT);
titleLabel.setAlignmentX(LEFT_ALIGNMENT);
titleLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
titleLabel.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
DesktopUtils.browseUrl(packSiteUrl+"/about");
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
packInfoPanel.add(titleLabel, new GridBagConstraints(0,0,4,1,1.0,0.0,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),0,0));
description = new JTextPane();
description.setFont(resources.getFont(ResourceLoader.FONT_OPENSANS, 14));
description.setOpaque(false);
description.setEditable(false);
description.setHighlighter(null);
description.setAlignmentX(LEFT_ALIGNMENT);
description.setForeground(LauncherFrame.COLOR_WHITE_TEXT);
description.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
MutableAttributeSet attributes = new SimpleAttributeSet(description.getParagraphAttributes());
StyleConstants.setLineSpacing(attributes, StyleConstants.getLineSpacing(attributes)*1.3f);
description.setParagraphAttributes(attributes, true);
description.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
DesktopUtils.browseUrl(packSiteUrl+"/about");
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
description.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
JScrollPane scrollPane = new JScrollPane(description, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.getVerticalScrollBar().setUI(new SimpleScrollbarUI(LauncherFrame.COLOR_SCROLL_TRACK, LauncherFrame.COLOR_SCROLL_THUMB));
scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(10,10));
JPanel scrollHostPanel = new JPanel();
scrollHostPanel.setBackground(LauncherFrame.COLOR_FEED_BACK);
scrollHostPanel.setLayout(new BorderLayout());
scrollHostPanel.add(scrollPane, BorderLayout.CENTER);
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(final AdjustmentEvent e) {
ModpackDataDisplay.this.repaint();
}
});
packInfoPanel.add(scrollHostPanel, new GridBagConstraints(0,1,4,1,1.0,1.0,GridBagConstraints.NORTH,GridBagConstraints.BOTH, new Insets(5,0,0,0),0,0));
}
@Override
public void jobComplete(ImageJob<ModpackModel> job) {
if (job.getJobData() == currentModpack) {
packImage.setIcon(new ImageIcon(ImageUtils.scaleImage(job.getImage(), 370, 220)));
}
}
@Override
public void serverGetCallback(ModpackModel pack, final Server server) {
if (this.currentModpack == pack) {
if (server != null && server.getInviteLink() != null && !server.getInviteLink().isEmpty()) {
this.discordPanel.setVisible(true);
this.countLabel.setText(resources.getString("launcher.discord.count", Integer.toString(server.getMemberCount())));
if (pack.isOfficial())
this.discordLabel.setText(resources.getString("launcher.discord.official"));
else
this.discordLabel.setText(resources.getString("launcher.discord.join"));
for (JButton discordButton : discordButtons) {
int actionListenerCount = discordButton.getActionListeners().length;
for (int i = 0; i < actionListenerCount; i++) {
discordButton.removeActionListener(discordButton.getActionListeners()[0]);
}
discordButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesktopUtils.browseUrl(server.getInviteLink());
}
});
}
} else {
this.discordPanel.setVisible(false);
}
}
}
}