Feature: Show progress bar in systray icon

This commit is contained in:
Luis Uguina
2020-03-19 23:48:06 +01:00
committed by Laurent Clouet
parent cffd34708f
commit 07525f101e
7 changed files with 116 additions and 16 deletions

BIN
resources/icon-sprites.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -26,6 +26,8 @@ public interface Gui {
public void status(String msg_);
public void updateTrayIcon(Integer percentage_);
public void setRenderingProjectName(String name_);
public void setRemainingTime(String time_);

View File

@@ -40,6 +40,8 @@ import java.util.Observer;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import com.sheepit.client.Configuration.ComputeType;
import com.sheepit.client.Error.Type;
@@ -55,6 +57,8 @@ public class Job {
public static final String UPDATE_METHOD_BLENDER_INTERNAL_BY_PART = "blenderinternal";
public static final String UPDATE_METHOD_BY_TILE = "by_tile";
public static final int SHOW_BASE_ICON = -1;
private String frameNumber;
private String sceneMD5;
private String rendererMD5;
@@ -271,9 +275,18 @@ public class Job {
log.debug("renderer output");
try {
int progress = -1;
Pattern tilePattern = Pattern.compile(" ([0-9]+)\\s?\\/\\s?([0-9]+) ");
// Initialise the progress bar in the icon (0% completed at this time)
gui.updateTrayIcon(0);
while ((line = input.readLine()) != null) {
log.debug(line);
progress = computeRenderingProgress(line, tilePattern, progress);
updateRenderingMemoryPeak(line);
if (configuration.getMaxMemory() != -1 && process.getMemoryUsed() > configuration.getMaxMemory()) {
log.debug("Blocking render because process ram used (" + process.getMemoryUsed() + "k) is over user setting (" + configuration.getMaxMemory() + "k)");
@@ -282,6 +295,11 @@ public class Job {
if (script_file != null) {
script_file.delete();
}
// Once the process is finished (either finished successfully or with an error) move back to
// base icon (isolated S with no progress bar)
gui.updateTrayIcon(Job.SHOW_BASE_ICON);
return Error.Type.RENDERER_OUT_OF_MEMORY;
}
@@ -291,6 +309,10 @@ public class Job {
if (script_file != null) {
script_file.delete();
}
// Put back base icon
gui.updateTrayIcon(Job.SHOW_BASE_ICON);
return error;
}
@@ -304,6 +326,10 @@ public class Job {
// most likely The handle is invalid
log.error("Job::render exception(B) (silent error) " + err1);
}
// Put back base icon
gui.updateTrayIcon(Job.SHOW_BASE_ICON);
log.debug("end of rendering");
}
catch (Exception err) {
@@ -398,6 +424,25 @@ public class Job {
return Error.Type.OK;
}
private int computeRenderingProgress(String line, Pattern tilePattern, int currentProgress) {
Matcher standardTileInfo = tilePattern.matcher(line);
int newProgress = currentProgress;
if (standardTileInfo.find()) {
int tileJustProcessed = Integer.parseInt(standardTileInfo.group(1));
int totalTilesInJob = Integer.parseInt(standardTileInfo.group(2));
newProgress = Math.abs((tileJustProcessed * 100) / totalTilesInJob);
}
// Only update the tray icon if percentage has changed
if (newProgress != currentProgress) {
gui.updateTrayIcon(newProgress);
}
return newProgress;
}
private void updateRenderingStatus(String line) {
if (getUpdateRenderingStatusMethod() != null && getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BLENDER_INTERNAL_BY_PART)) {
String search = " Part ";

View File

@@ -31,16 +31,21 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.nio.Buffer;
import java.util.Timer;
import java.util.TimerTask;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.imageio.ImageIO;
import com.sheepit.client.Client;
import com.sheepit.client.Configuration;
@@ -72,6 +77,9 @@ public class GuiSwing extends JFrame implements Gui {
private boolean waitingForAuthentication;
private Client client;
private BufferedImage iconSprites;
private BufferedImage[] trayIconSprites;
@Getter
@Setter
private SettingsLoader settingsLoader;
@@ -121,10 +129,18 @@ public class GuiSwing extends JFrame implements Gui {
}
}
URL iconUrl = getClass().getResource("/icon.png");
if (iconUrl != null) {
ImageIcon img = new ImageIcon(iconUrl);
setIconImage(img.getImage());
// load the images sprite and split into individual images
URL spriteSequenceUrl = getClass().getResource("/icon-sprites.png");
if (spriteSequenceUrl != null) {
try {
iconSprites = ImageIO.read(spriteSequenceUrl);
trayIconSprites = new BufferedImage[101 * 1]; // sprite sheet has 101 images in 1 column
setIconImage(extractImageFromSprite(-1)); // sprite 0 is standard Sheep It! icon
} catch (IOException e) {
e.printStackTrace();
}
}
setTitle(title);
@@ -304,8 +320,8 @@ public class GuiSwing extends JFrame implements Gui {
public TrayIcon getTrayIcon() {
final PopupMenu trayMenu = new PopupMenu();
URL iconUrl = getClass().getResource("/icon.png");
Image img = Toolkit.getDefaultToolkit().getImage(iconUrl);
// on start, show the base icon
Image img = extractImageFromSprite(-1);
final TrayIcon icon = new TrayIcon(img);
MenuItem exit = new MenuItem("Exit");
@@ -351,6 +367,35 @@ public class GuiSwing extends JFrame implements Gui {
}
private Image extractImageFromSprite(int spriteNumber) {
// Sprite structure
// Image 0: base sprite
// Images 1-101: progress bar percentage from 0 to 100
//
// Always add +1 to the icon requested.
// -1 turns into 0 (base sprite with no progress bar)
// 0 to 101 turns into 1 to 101 (progress sequence starts in sprite 1 and ends on sprite 101)
ImageIcon img = new ImageIcon(iconSprites.getSubimage(0, (spriteNumber + 1) * 114, 114, 114));
return img.getImage();
}
@Override
public void updateTrayIcon(Integer percentage) {
// update the app icon on the app bar
Image img = extractImageFromSprite(percentage);
setIconImage(img);
// if the app supports the system tray, update as well
if (sysTray != null && SystemTray.isSupported()) {
if (trayIcon != null) {
trayIcon.setImage(img);
trayIcon.setImageAutoSize(true); // use this method to ensure that icon is refreshed when on
// the tray
}
}
}
public class ThreadClient extends Thread {
@Override
public void run() {

View File

@@ -89,6 +89,10 @@ public class GuiText implements Gui {
Runtime.getRuntime().halt(0);
}
@Override
public void updateTrayIcon(Integer percentage) {
}
@Override
public void status(String msg_) {
System.out.println(msg_);

View File

@@ -95,6 +95,10 @@ public class GuiTextOneLine implements Gui {
Runtime.getRuntime().halt(0);
}
@Override
public void updateTrayIcon(Integer percentage) {
}
@Override
public void status(String msg_) {
status = msg_;