Feature: Show progress bar in systray icon
This commit is contained in:
committed by
Laurent Clouet
parent
cffd34708f
commit
07525f101e
BIN
resources/icon-sprites.png
Normal file
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 |
@@ -25,7 +25,9 @@ public interface Gui {
|
|||||||
public void stop();
|
public void stop();
|
||||||
|
|
||||||
public void status(String msg_);
|
public void status(String msg_);
|
||||||
|
|
||||||
|
public void updateTrayIcon(Integer percentage_);
|
||||||
|
|
||||||
public void setRenderingProjectName(String name_);
|
public void setRenderingProjectName(String name_);
|
||||||
|
|
||||||
public void setRemainingTime(String time_);
|
public void setRemainingTime(String time_);
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ import java.util.Observer;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
import com.sheepit.client.Configuration.ComputeType;
|
import com.sheepit.client.Configuration.ComputeType;
|
||||||
import com.sheepit.client.Error.Type;
|
import com.sheepit.client.Error.Type;
|
||||||
@@ -54,7 +56,9 @@ public class Job {
|
|||||||
public static final String UPDATE_METHOD_BY_REMAINING_TIME = "remainingtime";
|
public static final String UPDATE_METHOD_BY_REMAINING_TIME = "remainingtime";
|
||||||
public static final String UPDATE_METHOD_BLENDER_INTERNAL_BY_PART = "blenderinternal";
|
public static final String UPDATE_METHOD_BLENDER_INTERNAL_BY_PART = "blenderinternal";
|
||||||
public static final String UPDATE_METHOD_BY_TILE = "by_tile";
|
public static final String UPDATE_METHOD_BY_TILE = "by_tile";
|
||||||
|
|
||||||
|
public static final int SHOW_BASE_ICON = -1;
|
||||||
|
|
||||||
private String frameNumber;
|
private String frameNumber;
|
||||||
private String sceneMD5;
|
private String sceneMD5;
|
||||||
private String rendererMD5;
|
private String rendererMD5;
|
||||||
@@ -271,9 +275,18 @@ public class Job {
|
|||||||
|
|
||||||
log.debug("renderer output");
|
log.debug("renderer output");
|
||||||
try {
|
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) {
|
while ((line = input.readLine()) != null) {
|
||||||
log.debug(line);
|
log.debug(line);
|
||||||
|
|
||||||
|
progress = computeRenderingProgress(line, tilePattern, progress);
|
||||||
|
|
||||||
updateRenderingMemoryPeak(line);
|
updateRenderingMemoryPeak(line);
|
||||||
if (configuration.getMaxMemory() != -1 && process.getMemoryUsed() > configuration.getMaxMemory()) {
|
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)");
|
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) {
|
if (script_file != null) {
|
||||||
script_file.delete();
|
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;
|
return Error.Type.RENDERER_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +309,10 @@ public class Job {
|
|||||||
if (script_file != null) {
|
if (script_file != null) {
|
||||||
script_file.delete();
|
script_file.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put back base icon
|
||||||
|
gui.updateTrayIcon(Job.SHOW_BASE_ICON);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +326,10 @@ public class Job {
|
|||||||
// most likely The handle is invalid
|
// most likely The handle is invalid
|
||||||
log.error("Job::render exception(B) (silent error) " + err1);
|
log.error("Job::render exception(B) (silent error) " + err1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put back base icon
|
||||||
|
gui.updateTrayIcon(Job.SHOW_BASE_ICON);
|
||||||
|
|
||||||
log.debug("end of rendering");
|
log.debug("end of rendering");
|
||||||
}
|
}
|
||||||
catch (Exception err) {
|
catch (Exception err) {
|
||||||
@@ -397,7 +423,26 @@ public class Job {
|
|||||||
|
|
||||||
return Error.Type.OK;
|
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) {
|
private void updateRenderingStatus(String line) {
|
||||||
if (getUpdateRenderingStatusMethod() != null && getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BLENDER_INTERNAL_BY_PART)) {
|
if (getUpdateRenderingStatusMethod() != null && getUpdateRenderingStatusMethod().equals(Job.UPDATE_METHOD_BLENDER_INTERNAL_BY_PART)) {
|
||||||
String search = " Part ";
|
String search = " Part ";
|
||||||
|
|||||||
@@ -31,16 +31,21 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.event.WindowStateListener;
|
import java.awt.event.WindowStateListener;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.Buffer;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UnsupportedLookAndFeelException;
|
import javax.swing.UnsupportedLookAndFeelException;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import com.sheepit.client.Client;
|
import com.sheepit.client.Client;
|
||||||
import com.sheepit.client.Configuration;
|
import com.sheepit.client.Configuration;
|
||||||
@@ -72,6 +77,9 @@ public class GuiSwing extends JFrame implements Gui {
|
|||||||
private boolean waitingForAuthentication;
|
private boolean waitingForAuthentication;
|
||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
|
private BufferedImage iconSprites;
|
||||||
|
private BufferedImage[] trayIconSprites;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private SettingsLoader settingsLoader;
|
private SettingsLoader settingsLoader;
|
||||||
@@ -120,13 +128,21 @@ public class GuiSwing extends JFrame implements Gui {
|
|||||||
sysTray = null;
|
sysTray = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
URL iconUrl = getClass().getResource("/icon.png");
|
// load the images sprite and split into individual images
|
||||||
if (iconUrl != null) {
|
URL spriteSequenceUrl = getClass().getResource("/icon-sprites.png");
|
||||||
ImageIcon img = new ImageIcon(iconUrl);
|
|
||||||
setIconImage(img.getImage());
|
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);
|
setTitle(title);
|
||||||
setSize(520, 760);
|
setSize(520, 760);
|
||||||
|
|
||||||
@@ -303,9 +319,9 @@ public class GuiSwing extends JFrame implements Gui {
|
|||||||
|
|
||||||
public TrayIcon getTrayIcon() {
|
public TrayIcon getTrayIcon() {
|
||||||
final PopupMenu trayMenu = new PopupMenu();
|
final PopupMenu trayMenu = new PopupMenu();
|
||||||
|
|
||||||
URL iconUrl = getClass().getResource("/icon.png");
|
// on start, show the base icon
|
||||||
Image img = Toolkit.getDefaultToolkit().getImage(iconUrl);
|
Image img = extractImageFromSprite(-1);
|
||||||
final TrayIcon icon = new TrayIcon(img);
|
final TrayIcon icon = new TrayIcon(img);
|
||||||
|
|
||||||
MenuItem exit = new MenuItem("Exit");
|
MenuItem exit = new MenuItem("Exit");
|
||||||
@@ -350,7 +366,36 @@ public class GuiSwing extends JFrame implements Gui {
|
|||||||
return icon;
|
return icon;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
public class ThreadClient extends Thread {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
@@ -88,7 +88,11 @@ public class GuiText implements Gui {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
Runtime.getRuntime().halt(0);
|
Runtime.getRuntime().halt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTrayIcon(Integer percentage) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void status(String msg_) {
|
public void status(String msg_) {
|
||||||
System.out.println(msg_);
|
System.out.println(msg_);
|
||||||
|
|||||||
@@ -94,7 +94,11 @@ public class GuiTextOneLine implements Gui {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
Runtime.getRuntime().halt(0);
|
Runtime.getRuntime().halt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTrayIcon(Integer percentage) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void status(String msg_) {
|
public void status(String msg_) {
|
||||||
status = msg_;
|
status = msg_;
|
||||||
|
|||||||
Reference in New Issue
Block a user