diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form index 4a7db3ca7..7e56b8a94 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form @@ -277,5 +277,16 @@ + + + + + + + + + + + diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java index c621b7ba7..91f6ba280 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java @@ -61,7 +61,7 @@ public class MainPagePanel extends AnimatedPanel { void initGui() { initComponents(); - + pnlButtons = new javax.swing.JPanel(); pnlButtons.setLayout(null); @@ -84,6 +84,9 @@ public class MainPagePanel extends AnimatedPanel { pnlMore.setBounds(0, 0, pnlMore.getWidth(), DEFAULT_HEIGHT); pnlMore.setBackground(GraphicsUtils.getWebColorWithAlpha("FFFFFF7F")); pnlMore.setOpaque(true); + + recommendPanel = new RecommendPanel(); + contentPanel.add(recommendPanel); Settings.getInstance().authChangedEvent.register(onAuthChanged); Settings.profileLoadingEvent.register(onLoadingProfiles); @@ -122,6 +125,7 @@ public class MainPagePanel extends AnimatedPanel { btnLogout = new javax.swing.JButton(); btnImportModpack = new javax.swing.JButton(); btnExportModpack = new javax.swing.JButton(); + contentPanel = new javax.swing.JPanel(); setLayout(null); @@ -262,7 +266,7 @@ public class MainPagePanel extends AnimatedPanel { .addComponent(lblVersion, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboProfiles, 0, 128, Short.MAX_VALUE) + .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGroup(pnlMoreLayout.createSequentialGroup() .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -306,6 +310,10 @@ public class MainPagePanel extends AnimatedPanel { add(pnlMore); pnlMore.setBounds(0, 0, 190, 480); + + contentPanel.setLayout(null); + add(contentPanel); + contentPanel.setBounds(220, 40, 540, 320); }// //GEN-END:initComponents private void txtPlayerNameFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusGained @@ -426,6 +434,8 @@ public class MainPagePanel extends AnimatedPanel { super.onCreate(); Settings.onProfileLoading(); } + + private RecommendPanel recommendPanel; // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnExportModpack; @@ -434,6 +444,7 @@ public class MainPagePanel extends AnimatedPanel { private javax.swing.JComboBox cboLoginMode; private javax.swing.JComboBox cboProfiles; private javax.swing.JComboBox cboVersions; + private javax.swing.JPanel contentPanel; private javax.swing.JLabel jLabel10; private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel9; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/RecommendPanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/RecommendPanel.java new file mode 100644 index 000000000..a4cfc5855 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/RecommendPanel.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2016 evilwk + * + * 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 . + */ +package org.jackhuang.hellominecraft.launcher.ui; + +import java.awt.Graphics; +import java.awt.Image; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import javax.imageio.ImageIO; +import javax.swing.JPanel; +import javax.swing.SwingWorker; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.swing.SwingUtilities; +import org.jackhuang.hellominecraft.util.NetUtils; +import org.jackhuang.hellominecraft.util.ui.SwingUtils; + +/** + * + * @author evilwk + */ +public class RecommendPanel extends JPanel { + + private static final int SWITCH_INTERVAL = 10; + + private Image currImage; + private String imageKey = null; + private List recommends; + public ScheduledExecutorService scheduledexec = Executors.newScheduledThreadPool(1); + + public RecommendPanel() { + recommends = new ArrayList(); + new LoadImages().execute(); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + MouseClicked(e); + } + }); + } + + private void MouseClicked(MouseEvent evt) { + if (imageKey == null) { + return; + } + RecommendInfo info = recommends.get(getCurrentImageIndex()); + if (info.link != null && !info.link.equals("")) { + SwingUtils.openLink(info.link); + } + } + + public void showImages() { + if (recommends.isEmpty()) { + return; + } + + new Thread(new Runnable() { + @Override + public void run() { + for (RecommendInfo info : recommends) { + try { + File tempFile = File.createTempFile("hmcl", "png"); + String tempPath = tempFile.getCanonicalPath(); + if (NetUtils.download(info.url, tempPath)) { + info.image = ImageIO.read(tempFile); + } + } catch (IOException ex) { + } + } + + if (getImagesSize() == 0 || showIfOnly()) { + return; + } + scheduledexec.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + int showIndex = getNextImageIndex(); + RecommendInfo info = recommends.get(showIndex); + RecommendPanel.this.setImage(info.url, info.image); + } + }); + } + }, 0, SWITCH_INTERVAL, TimeUnit.SECONDS); + } + }).start(); + } + + public int getImagesSize() { + int imageCount = 0; + for (RecommendInfo recommend : recommends) { + if (recommend.image != null) { + imageCount++; + } + } + return imageCount; + } + + public boolean showIfOnly() { + if (getImagesSize() != 1) { + return false; + } + for (RecommendInfo recommend : recommends) { + if (recommend.image != null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + RecommendPanel.this.setImage(recommend.url, recommend.image); + } + }); + } + } + return true; + } + + public int getNextImageIndex(int showIndex) { + if (showIndex >= recommends.size()) { + showIndex = 0; + } + RecommendInfo info = recommends.get(showIndex); + if (info.image == null) { + showIndex = getNextImageIndex(++showIndex); + } + return showIndex; + } + + public int getNextImageIndex() { + int showIndex = 0; + if (imageKey != null) { + showIndex = getCurrentImageIndex(); + showIndex++; + } + if (showIndex >= recommends.size()) { + showIndex = 0; + } + showIndex = getNextImageIndex(showIndex); + return showIndex >= recommends.size() ? 0 : showIndex; + } + + public int getCurrentImageIndex() { + int currIndex = 0; + for (int i = 0; i < recommends.size(); i++) { + RecommendInfo info = recommends.get(i); + if (imageKey != null && info.url.equals(imageKey)) { + currIndex = i; + break; + } + } + return currIndex; + } + + public void setImage(String key, Image image) { + this.imageKey = key; + this.currImage = image; + setSize(image.getWidth(this), image.getHeight(this)); + SwingUtilities.updateComponentTreeUI(this.getRootPane()); + } + + @Override + public void paintComponent(Graphics g) { + if (null == currImage) { + return; + } + g.drawImage(currImage, 0, 0, currImage.getWidth(this), currImage.getHeight(this), this); + } + + static class RecommendInfo { + String url; + String link; + Image image; + } + + class LoadImages extends SwingWorker>, Void> { + + private static final String RECOMMEND_URL = "http://client.api.mcgogogo.com:81/recommend.php"; + + @Override + protected List> doInBackground() throws Exception { + List> infos = null; + do { + String content = NetUtils.get(RECOMMEND_URL); + if (content == null || content.equals("")) { + break; + } + + Map data = new Gson().fromJson(content, + new TypeToken>() { + }.getType()); + if (data == null) { + break; + } + + infos = (List>) data.get("data"); + } while (false); + return infos; + } + + @Override + protected void done() { + try { + List> infos = this.get(); + if (infos == null) { + return; + } + for (Map info : infos) { + RecommendInfo recommend = new RecommendInfo(); + recommend.url = info.get("url"); + recommend.link = info.get("link"); + recommend.image = null; + recommends.add(recommend); + } + RecommendPanel.this.showImages(); + } catch (InterruptedException | ExecutionException ex) { + } + } + } + +} diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/NetUtils.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/NetUtils.java index adc12fd31..e3b03744e 100755 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/NetUtils.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/NetUtils.java @@ -19,6 +19,8 @@ package org.jackhuang.hellominecraft.util; import org.jackhuang.hellominecraft.util.logging.HMCLog; import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -129,6 +131,23 @@ public final class NetUtils { con.disconnect(); return result; } + + public static boolean download(String url, String saveFile) { + try { + int readCount = 0; + byte[] buffer = new byte[1204]; + InputStream inputStream = new URL(url).openConnection().getInputStream(); + FileOutputStream fs = new FileOutputStream(saveFile); + while ((readCount = inputStream.read(buffer)) != -1) { + fs.write(buffer, 0, readCount); + } + return true; + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } + } private static final String DEFAULT_CHARSET = "UTF-8";