package com.elsealabs.xshot.capture;
import java.awt.AWTException;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.ArrayList;
/**
* CaptureDevice.java
*
* Contains all of the information about the local graphical
* environment and holds instances of the user's monitors.
* Screen captures can be taken using Capture Device.
*
*/
public class CaptureDevice
{
private GraphicsEnvironment environment;
private GraphicsDevice[] screenDevices;
private List<Monitor> monitors;
private Robot robot;
/**
* Fires various setup methods to find environment information
* and create needed variables.
*/
public CaptureDevice()
{
setupEnvironment();
setupMonitors();
setupRobot();
}
/**
* This method merges the bounds of two or more monitors together,
* taking into account the offset that may be present in the operating
* system.
*
* @param monitors The monitors whose bounds will be combined
* @return Bounds readjusted for the offset of monitors
*/
public Rectangle mergeBounds(List<Monitor> monitors)
{
if (monitors.size() > 1)
{
Rectangle bounds = new Rectangle();
monitors.stream().forEach(a -> {
Rectangle.union(bounds, a.getBounds(), bounds);
});
return bounds;
}
else
{
return monitors.get(0).getBounds();
}
}
/**
* Creates a capture of the monitor argument's dimensions.
*
* @param monitor A monitor to be captured
* @return A capture of the monitor
*/
public BufferedImage captureMonitor(Monitor monitor)
{
return captureDimension(monitor.getBounds());
}
/**
* Merges the dimensions of multiple monitors allowing
* pictures that span multiple monitors.
*
* @param monitors The list of monitors to be included
* @return One capture containing all specified monitors.
*/
public BufferedImage captureMonitors(List<Monitor> monitors)
{
return captureDimension(mergeBounds(monitors));
}
/**
* Shortcut for capturing all of the available monitors.
*
* @return One capture containing all monitors.
*/
public BufferedImage captureAll()
{
return captureMonitors(getMonitors());
}
/**
* Takes a picture of the portion of the graphical environment
* as defined by the argument-passed dimension. Returns a Capture
* object with this portion as its base image.
*
* @param dimension The dimension to capture of the screen
* @return A capture with original bounds of said dimension
*/
public BufferedImage captureDimension(Rectangle dimension)
{
return robot.createScreenCapture(dimension);
}
/**
* This method loads the robot and handles any robot-related
* failures.
*/
public void setupRobot()
{
try
{
robot = new Robot();
}
catch (AWTException e)
{
e.printStackTrace();
}
}
/**
* This method loads the local graphical environment.
*/
public void setupEnvironment()
{
environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
}
/**
* This method finds all the monitors that are involved with the
* local graphical environment.
*/
public void setupMonitors()
{
monitors = new ArrayList<Monitor>();
screenDevices = environment.getScreenDevices();
for (GraphicsDevice device : screenDevices)
{
for (GraphicsConfiguration cfg : device.getConfigurations())
{
System.out.println(device.getIDstring() + " " + cfg.getBounds());
}
monitors.add(new Monitor(device));
}
}
/**
* Returns a monitor at i position in the array of all
* available monitors.
*
* @param i Position in the monitor array
* @return The monitor at position i in the monitor array.
*/
public Monitor getMonitor(int i)
{
return monitors.get(i);
}
/**
* Returns the default monitor as specified by the Graphics
* Environment.
*
* @return The default monitor
*/
public Monitor getDefaultMonitor()
{
return monitors.stream()
.filter(Monitor::isDefaultMonitor)
.findFirst()
.get();
}
/**
* Returns all of the available monitors in the current
* GraphicsEnvironment. Java does not allow hardware
* changes to be updated when the JVM is on. Changes in
* the graphical environment will be reflected when the
* JVM is restarted.
*
* @return All available monitors at the time of running
* the JVM.
*/
public List<Monitor> getMonitors()
{
return monitors;
}
}