diff --git a/src/com/t_oster/liblasercut/LibInfo.java b/src/com/t_oster/liblasercut/LibInfo.java
index 2b7bcb40bcd8f3f25aafb7cb4b44aea944eebc86..1da3a5de245b9363e42443da4c2956bfb509a1c3 100644
--- a/src/com/t_oster/liblasercut/LibInfo.java
+++ b/src/com/t_oster/liblasercut/LibInfo.java
@@ -46,6 +46,7 @@ public class LibInfo
       IModelaMill.class,
       SampleDriver.class,
       ExportSVG.class,
+      MakeBlockXYPlotter.class,
       GenericGcodeDriver.class,
       SmoothieBoard.class,
       Marlin.class
diff --git a/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotter.java b/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotter.java
new file mode 100644
index 0000000000000000000000000000000000000000..3390f22e4a06f9c1ac1ce3f011fffc9edc6f3f04
--- /dev/null
+++ b/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotter.java
@@ -0,0 +1,586 @@
+/**
+ * This file is part of LibLaserCut.
+ * Copyright (C) 2011 - 2014 Thomas Oster <mail@thomas-oster.de>
+ *
+ * LibLaserCut is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LibLaserCut 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with LibLaserCut. If not, see <http://www.gnu.org/licenses/>.
+ *
+ **/
+
+/**
+ * Author: Sven Jung <sven.jung@rwth-aachen.de>
+ */
+
+package com.t_oster.liblasercut.drivers;
+
+import com.t_oster.liblasercut.IllegalJobException;
+import com.t_oster.liblasercut.*;
+import com.t_oster.liblasercut.LaserJob;
+import com.t_oster.liblasercut.ProgressListener;
+import com.t_oster.liblasercut.platform.Point;
+import com.t_oster.liblasercut.platform.Util;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import purejavacomm.CommPortIdentifier;
+import purejavacomm.NoSuchPortException;
+import purejavacomm.PortInUseException;
+import purejavacomm.SerialPort;
+
+/**
+ *
+ * @author Sven Jung
+ */
+public class MakeBlockXYPlotter extends LaserCutter
+{
+  private enum ToolState {
+    ON, OFF
+  }
+  
+  /*
+   * Internal Settings
+  */
+  private final boolean debug = false; // print to command line
+  private static final String MODELNAME = "MakeBlockXYPlotter";
+  private double addSpacePerRasterLine = 0.5;
+  private String hostname = ""; 
+  private double bedWidth = 300;
+  private double bedHeight = 210;
+  private int delayRate = 5000;
+  private int powerRate = 255;
+  private String usedTool = "PEN"; // PEN, Laser
+  private List<Double> resolutions = Arrays.asList(new Double[]{
+                64d // fine liner
+              });
+  
+  private int chosenDelay;
+  private int chosenPower;
+  private ToolState toolState;
+  
+  private PrintWriter w = null;
+  BufferedReader portReader = null;
+  private BufferedOutputStream out = null;
+  private SerialPort port = null;
+    
+  /*
+   * Global Settings
+  */
+  private static final String SETTING_HOSTNAME = "Target port:// or file://";
+  private static final String SETTING_RASTER_WHITESPACE = "Additional space per Raster line (mm)";
+  private static final String SETTING_BEDWIDTH = "Laserbed width (mm)";
+  private static final String SETTING_BEDHEIGHT = "Laserbed height (mm)";
+  private static final String SETTING_DELAY_RATE = "Max. Delay Rate (abs. us)";
+  private static final String SETTING_POWER_RATE = "Max. Power Rate (abs. pwm)";
+  private static final String SETTING_TOOL = "Tool (PEN, LASER)";
+  private static String[] settingAttributes = new String[]{
+    SETTING_HOSTNAME,
+    SETTING_RASTER_WHITESPACE,
+    SETTING_BEDWIDTH,
+    SETTING_BEDHEIGHT,
+    SETTING_DELAY_RATE,
+    SETTING_POWER_RATE,
+    SETTING_TOOL
+  };
+  
+  
+  /**
+   * Get the value of MODELNAME
+   * 
+   * @return the value of MODELNAME
+   */
+  @Override
+  public String getModelName() {
+    return MODELNAME;
+  }
+  
+  @Override
+  public List<Double> getResolutions() {
+    return resolutions;
+  }
+  
+  @Override
+  public MakeBlockXYPlotterProperty getLaserPropertyForVectorPart() {
+    return new MakeBlockXYPlotterProperty(this.usedTool.equals("LASER")); // show power and speed only if laser
+  }
+
+  @Override
+  public MakeBlockXYPlotterProperty getLaserPropertyForRasterPart()
+  {
+    return new MakeBlockXYPlotterProperty(this.usedTool.equals("LASER")); // show power and speed only if laser
+  }
+  
+  /**
+   * Get the value of bedWidth
+   *
+   * @return the value of bedWidth
+   */
+  @Override
+  public double getBedWidth()
+  {
+    return bedWidth;
+  }
+
+  /**
+   * Get the value of bedHeight
+   *
+   * @return the value of bedHeight
+   */
+  @Override
+  public double getBedHeight()
+  {
+    return bedHeight;
+  }
+
+  
+  private void generateInitializationGCode() throws Exception {
+    toolOff();
+    this.sendCommand("G28 X Y");//move to 0 0
+  }
+
+  private void generateShutdownGCode() throws Exception {
+    //back to origin and shutdown
+    toolOff();
+    this.sendCommand("G28 X Y");//move to 0 0
+  }
+  
+  private void toolOff() throws Exception {
+    if(toolState != ToolState.OFF) {
+      if(usedTool.equals("PEN")) {
+        this.sendCommand("M1 90");
+        this.sendCommand(String.format("M3 %d", 0)); // to ensure fastest speed
+      } else if(usedTool.equals("LASER")) {
+        this.sendCommand(String.format("M4 %d", 0));
+        this.sendCommand(String.format("M3 %d", 0)); // to move faster with tool off
+      } else {
+        throw new Exception("Tool " + this.usedTool + " not supported!");
+      }
+      toolState = ToolState.OFF;
+    }
+  }
+  
+  private void toolOn() throws Exception {
+    if(toolState != ToolState.ON) {
+      if(usedTool.equals("PEN")) {
+        this.sendCommand(String.format("M3 %d", 0)); // to ensure fastest speed
+        this.sendCommand("M1 130");
+      } else if(usedTool.equals("LASER")) {
+        this.sendCommand(String.format("M3 %d", (int) ((double) delayRate * this.chosenDelay / 100)));
+        this.sendCommand(String.format("M4 %d", (int) ((double) powerRate * this.chosenPower / 100)));
+      } else {
+        throw new Exception("Tool " + this.usedTool + " not supported!");
+      }
+      toolState = ToolState.ON;
+    }
+  }
+  
+  private void setDelay(int value) throws Exception{
+    // saves just the chosen delay value
+    // delay of the plotter really set on toolOn(), to move faster with tool off
+    if(usedTool.equals("LASER")) { // property option only supported if laser
+      if (value != chosenDelay) {
+        chosenDelay = value;
+      }
+    }
+  }
+  
+  private void setPower(int value) throws Exception{
+    // saves just the chosen power value
+    // power of the laser really set on toolOn()
+    if(usedTool.equals("LASER")) { // property option only supported if laser
+      if (value != chosenPower) {
+        chosenPower = value;
+      }
+    }
+  }
+  
+  private void move(int x, int y, double resolution) throws Exception{
+    toolOff();
+    this.sendCommand(String.format(Locale.US, "G0 X%f Y%f", Util.px2mm(x, resolution), Util.px2mm(y, resolution)));
+  }
+
+  private void line(int x, int y, double resolution) throws Exception{
+    toolOn();
+    this.sendCommand(String.format(Locale.US, "G1 X%f Y%f", Util.px2mm(x, resolution), Util.px2mm(y, resolution)));
+  }
+  
+  private void generateVectorGCode(VectorPart vp, double resolution, ProgressListener pl, int startProgress, int maxProgress) throws UnsupportedEncodingException, Exception {
+    int i = 0;
+    int progress;
+    int max = vp.getCommandList().length;
+    for (VectorCommand cmd : vp.getCommandList()) {
+      switch (cmd.getType()) {
+        case MOVETO:
+          int x = cmd.getX();
+          int y = cmd.getY();
+          this.move(x, y, resolution);
+          break;
+        case LINETO:
+          x = cmd.getX();
+          y = cmd.getY();
+          this.line(x, y, resolution);
+          break;
+        case SETPROPERTY: // called once per part to set chosen properties
+          MakeBlockXYPlotterProperty p = (MakeBlockXYPlotterProperty) cmd.getProperty(); // only set with LASER tool
+          // ensure percent power
+          int pPercent = p.getPower();
+          pPercent = pPercent<0?0:pPercent;
+          pPercent = pPercent>100?100:pPercent;
+          this.setPower(pPercent);
+          // ensure percent speed
+          int sPercent = p.getSpeed();
+          sPercent = sPercent<0?0:sPercent;
+          sPercent = sPercent>100?100:sPercent;
+          int dPercent = 100-sPercent; // convert speed to delay
+          this.setDelay(dPercent);
+          break;
+      }
+      i++;
+      progress = (startProgress + (int) (i*(double) maxProgress/max));
+      pl.progressChanged(this, progress);
+    }
+  }
+  
+  private void generatePseudoRasterGCode(RasterPart rp, double resolution, ProgressListener pl, int startProgress, int maxProgress) throws UnsupportedEncodingException, Exception {
+    int i = 0;
+    int progress;
+    int max = rp.getRasterHeight();
+    
+    boolean dirRight = true;
+    Point rasterStart = rp.getRasterStart();
+    
+    // called once per part to set chosen properties
+    PowerSpeedFocusProperty prop = (PowerSpeedFocusProperty) rp.getLaserProperty();
+    this.setDelay(prop.getSpeed());
+    this.setPower(prop.getPower());
+    
+    for (int line = 0; line < rp.getRasterHeight(); line++) {
+      Point lineStart = rasterStart.clone();
+      lineStart.y += line;
+      List<Byte> bytes = new LinkedList<Byte>();
+      boolean lookForStart = true;
+      for (int x = 0; x < rp.getRasterWidth(); x++) {
+        if (lookForStart) {
+          if (rp.isBlack(x, line)) {
+            lookForStart = false;
+            bytes.add((byte) 255);
+          } else {
+            lineStart.x += 1;
+          }
+        } else {
+          bytes.add(rp.isBlack(x, line) ? (byte) 255 : (byte) 0);
+        }
+      }
+      //remove trailing zeroes
+      while (bytes.size() > 0 && bytes.get(bytes.size() - 1) == 0) {
+        bytes.remove(bytes.size() - 1);
+      }
+      if (bytes.size() > 0) {
+        if (dirRight) {
+          //add some space to the left
+          this.move(Math.max(0, (int) (lineStart.x - Util.mm2px(this.addSpacePerRasterLine, resolution))), lineStart.y, resolution);
+          //move to the first nonempyt point of the line
+          this.move(lineStart.x, lineStart.y, resolution);
+          byte old = bytes.get(0);
+          for (int pix = 0; pix < bytes.size(); pix++) {
+            if (bytes.get(pix) != old) {
+              if (old == 0) {
+                this.move(lineStart.x + pix, lineStart.y, resolution);
+              } else {
+                this.setPower(prop.getPower() * (0xFF & old) / 255);
+                this.line(lineStart.x + pix - 1, lineStart.y, resolution);
+                this.move(lineStart.x + pix, lineStart.y, resolution);
+              }
+              old = bytes.get(pix);
+            }
+          }
+          //last point is also not "white"
+          this.setPower(prop.getPower() * (0xFF & bytes.get(bytes.size() - 1)) / 255);
+          this.line(lineStart.x + bytes.size() - 1, lineStart.y, resolution);
+          //add some space to the right
+          this.move(Math.min((int) Util.mm2px(bedWidth, resolution), (int) (lineStart.x + bytes.size() - 1 + Util.mm2px(this.addSpacePerRasterLine, resolution))), lineStart.y, resolution);
+        } else {
+          //add some space to the right
+          this.move(Math.min((int) Util.mm2px(bedWidth, resolution), (int) (lineStart.x + bytes.size() - 1 + Util.mm2px(this.addSpacePerRasterLine, resolution))), lineStart.y, resolution);
+          //move to the last nonempty point of the line
+          this.move(lineStart.x + bytes.size() - 1, lineStart.y, resolution);
+          byte old = bytes.get(bytes.size() - 1);
+          for (int pix = bytes.size() - 1; pix >= 0; pix--) {
+            if (bytes.get(pix) != old || pix == 0) {
+              if (old == 0) {
+                this.move(lineStart.x + pix, lineStart.y, resolution);
+              } else {
+                this.setPower(prop.getPower() * (0xFF & old) / 255);
+                this.line(lineStart.x + pix + 1, lineStart.y, resolution);
+                this.move(lineStart.x + pix, lineStart.y, resolution);
+              }
+              old = bytes.get(pix);
+            }
+          }
+          //last point is also not "white"
+          this.setPower(prop.getPower() * (0xFF & bytes.get(0)) / 255);
+          this.line(lineStart.x, lineStart.y, resolution);
+          //add some space to the left
+          this.move(Math.max(0, (int) (lineStart.x - Util.mm2px(this.addSpacePerRasterLine, resolution))), lineStart.y, resolution);
+        }
+      }
+      dirRight = !dirRight;
+      
+      i = line + 1;
+      progress = (startProgress + (int) (i*(double) maxProgress/max));
+      pl.progressChanged(this, progress);
+    }
+  }
+  
+  private void connect() throws NoSuchPortException, PortInUseException, Exception {
+    if(!this.debug){
+      if (this.hostname.startsWith("port://")) {
+        String portString = this.hostname.replace("port://", "");
+        
+        try{
+          CommPortIdentifier cpi = CommPortIdentifier.getPortIdentifier(portString);
+          port = (SerialPort) cpi.open("VisiCut", 2000);
+        }
+        catch(Exception e) {
+          throw new Exception("Port '"+portString+"' is not available.");
+        }
+        
+        if (port == null)
+        {
+          throw new Exception("Error: Could not Open COM-Port '"+portString+"'");
+        }
+        if (!(port instanceof SerialPort))
+        {
+          throw new Exception("Port '"+portString+"' is not a serial port.");
+        }
+        port.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+        out = new BufferedOutputStream(port.getOutputStream());
+        portReader = new BufferedReader(new InputStreamReader(port.getInputStream()));
+        
+        // wake up firmware
+        String command = "\r\n\r\n";
+        out.write(command.getBytes("US-ASCII"));
+        out.flush();
+        Thread.sleep(2000);
+        portReader.readLine(); // "ok"
+        portReader.readLine(); // "ok"
+        
+        this.checkVersion();
+      }
+      else if (hostname.startsWith("file://")) {
+        String filename = this.hostname.replace("file://", "");
+        try {
+          w = new PrintWriter(filename);
+        }
+        catch(Exception e) {
+          throw new Exception(String.format("No correct absolute file path: %s Exception %s", this.hostname, e));
+        }
+      }
+      else {
+        throw new Exception(String.format("Unknown hostname: %s", this.hostname));
+      }
+    }
+  }
+  
+  private void disconnect() throws Exception{
+    if(w != null) {
+      w.close();
+      w = null;
+    }
+    
+    if(out != null) {
+      out.close();
+      out = null;
+    }
+    
+    if(port != null){
+      port.close();
+      port = null;
+    }
+  }
+  
+  private void checkResponse(String command, String response, String expectedAnswer) throws Exception {
+    if(!response.toLowerCase().contains(expectedAnswer.toLowerCase())) {
+        throw new Exception(String.format("Got wrong response to command \"%s\":\n\"%s\" instead of \"%s\"", command, response, expectedAnswer));
+      }
+  }
+  private void sendCommand(String command) throws Exception {
+    this.send(command);
+    
+    if(!debug) {
+      if (this.hostname.startsWith("port://")) {
+        String resp = this.receive();
+        this.checkResponse(command, resp, "ok");
+      }    
+    }
+  }
+  
+  private void checkVersion() throws Exception {
+    // check if firmware matches implemented protocol
+    this.send("M115");
+    
+    if(!debug) {
+      if (this.hostname.startsWith("port://")) {
+        String resp = this.receive();
+        this.checkResponse("Version", resp, "Version");
+        String resp2 = this.receive();
+        this.checkResponse("Version", resp2, "ok");
+      }    
+    }
+  }
+  
+  private void send(String command) throws Exception {
+    if(!debug) {
+      if (this.hostname.startsWith("port://")) {
+        // send
+        String sendString = command + "\n";
+        out.write(sendString.getBytes("US-ASCII"));
+        out.flush();
+      }
+      else if (hostname.startsWith("file://")) {
+        w.println(command);
+      }
+      else {
+        throw new Exception(String.format("Unknown hostname: %s", this.hostname));
+      }
+      
+    } else {
+      System.out.println(command);
+    }
+  }
+  
+  private String receive() throws Exception{
+    if(!debug) {
+      if (this.hostname.startsWith("port://")) {
+            String line;
+        try {
+          line = portReader.readLine();
+          line = line.replace("\n", "").replace("\r", "");
+          return line;
+        } catch(IOException e) { 
+          throw new IOException("IO Exception, e.g. timeout");
+        }
+      }
+    }
+    return "";
+  }
+
+  @Override
+  public void sendJob(LaserJob job, ProgressListener pl, List<String> warnings) throws IllegalJobException, Exception
+  {
+    this.chosenPower = 0;
+    this.chosenDelay = 0;
+    this.toolState = ToolState.ON; // assume worst case, set to OFF in initialization code
+    pl.progressChanged(this, 0); 
+    pl.taskChanged(this, "checking job");
+    checkJob(job);
+    job.applyStartPoint();
+    pl.taskChanged(this, "connecting");
+    this.connect();
+    pl.taskChanged(this, "sending");
+    this.generateInitializationGCode();
+    int startProgress = 20;
+    pl.progressChanged(this, startProgress);
+    int i = 0;
+    int progress = startProgress;
+    int max = job.getParts().size();
+    for (JobPart p : job.getParts())
+    {
+      if (p instanceof Raster3dPart)
+      {
+        throw new Exception("Raster 3D parts are not implemented for " + this.getModelName());
+      }
+      else if (p instanceof RasterPart)
+      {
+        this.generatePseudoRasterGCode((RasterPart) p, p.getDPI(), pl, progress, ((int) ((i+1)*(double) 80/max)));
+      }
+      else if (p instanceof VectorPart)
+      {
+        this.generateVectorGCode((VectorPart) p, p.getDPI(), pl, progress, ((int) ((i+1)*(double) 80/max)));
+      }
+      i++;
+      progress = (startProgress + (int) (i*(double) 80/max));
+      pl.progressChanged(this, progress);
+    }
+    this.generateShutdownGCode();
+    pl.taskChanged(this, "disconnecting");
+    this.disconnect();
+    pl.taskChanged(this, "sent");
+    pl.progressChanged(this, 100);
+  }
+
+  @Override
+  public LaserCutter clone()
+  {
+    MakeBlockXYPlotter clone = new MakeBlockXYPlotter();
+    clone.addSpacePerRasterLine = addSpacePerRasterLine;
+    clone.hostname = hostname;
+    clone.bedWidth = bedWidth;
+    clone.bedHeight = bedHeight;
+    clone.delayRate = delayRate;
+    clone.powerRate = powerRate;
+    clone.usedTool = usedTool;
+    return clone;
+  }
+
+  @Override
+  public String[] getPropertyKeys() {
+    return settingAttributes;
+  }
+
+  @Override
+  public Object getProperty(String attribute) {
+    if (SETTING_HOSTNAME.equals(attribute)) {
+      return this.hostname;
+    } else if (SETTING_RASTER_WHITESPACE.equals(attribute)) {
+      return this.addSpacePerRasterLine;
+    } else if (SETTING_BEDWIDTH.equals(attribute)) {
+      return this.bedWidth;
+    } else if (SETTING_BEDHEIGHT.equals(attribute)) {
+      return this.bedHeight;
+    } else if (SETTING_DELAY_RATE.equals(attribute)) {
+      return this.delayRate;
+    } else if (SETTING_POWER_RATE.equals(attribute)) {
+      return this.powerRate;
+    } else if (SETTING_TOOL.equals(attribute)) {
+      return this.usedTool;
+    } 
+    return null;
+  }
+
+  @Override
+  public void setProperty(String attribute, Object value) {
+    if (SETTING_HOSTNAME.equals(attribute)) {
+      this.hostname = (String) value;
+    } else if (SETTING_RASTER_WHITESPACE.equals(attribute)) {
+      this.addSpacePerRasterLine = (Double) value;
+    } else if (SETTING_BEDWIDTH.equals(attribute)) {
+      this.bedWidth = (Double) value;
+    } else if (SETTING_BEDHEIGHT.equals(attribute)) {
+      this.bedHeight = (Double) value;
+    } else if (SETTING_DELAY_RATE.equals(attribute)) {
+      this.delayRate = (Integer) value;
+    } else if (SETTING_POWER_RATE.equals(attribute)) {
+      this.powerRate = (Integer) value;
+    } else if (SETTING_TOOL.equals(attribute)) {
+      this.usedTool = (String) value;
+    }  
+  }
+  
+}
diff --git a/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotterProperty.java b/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotterProperty.java
new file mode 100644
index 0000000000000000000000000000000000000000..497313ead9be138746605acfd443b8f4ef1c81c2
--- /dev/null
+++ b/src/com/t_oster/liblasercut/drivers/MakeBlockXYPlotterProperty.java
@@ -0,0 +1,107 @@
+/**
+ * This file is part of LibLaserCut.
+ * Copyright (C) 2011 - 2014 Thomas Oster <mail@thomas-oster.de>
+ *
+ * LibLaserCut is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LibLaserCut 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with LibLaserCut. If not, see <http://www.gnu.org/licenses/>.
+ *
+ **/
+
+/**
+ * Author: Sven Jung <sven.jung@rwth-aachen.de>
+ */
+
+package com.t_oster.liblasercut.drivers;
+
+import com.t_oster.liblasercut.PowerSpeedFocusFrequencyProperty;
+import java.util.Arrays;
+import java.util.LinkedList;
+
+/**
+ *
+ * @author Sven
+ */
+public class MakeBlockXYPlotterProperty extends PowerSpeedFocusFrequencyProperty
+{
+  private boolean showPowerAndSpeed;
+  
+  public MakeBlockXYPlotterProperty(boolean showPowerAndSpeed) {
+    this.showPowerAndSpeed = showPowerAndSpeed;
+  }
+  
+  public MakeBlockXYPlotterProperty() {
+    this(false);
+  }
+  
+  @Override
+  public String[] getPropertyKeys()
+  {
+    LinkedList<String> result = new LinkedList<String>();
+    result.addAll(Arrays.asList(super.getPropertyKeys()));
+    result.remove("focus");
+    result.remove("frequency");
+    
+    if(!showPowerAndSpeed) {
+      result.remove("power");
+      result.remove("speed");
+    }
+    
+    return result.toArray(new String[0]);
+  }
+
+  @Override
+  public Object getProperty(String name)
+  {
+    return super.getProperty(name);
+  }
+
+  @Override
+  public void setProperty(String name, Object value)
+  {
+    super.setProperty(name, value);
+  }
+
+  @Override
+  public MakeBlockXYPlotterProperty clone()
+  {
+    MakeBlockXYPlotterProperty result = new MakeBlockXYPlotterProperty();
+    for (String s:this.getPropertyKeys())
+    {
+      result.setProperty(s, this.getProperty(s));
+    }
+    return result;
+  }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final MakeBlockXYPlotterProperty other = (MakeBlockXYPlotterProperty) obj;
+        if (this.showPowerAndSpeed != other.showPowerAndSpeed) {
+            return false;
+        }
+        return super.equals(other);
+    }
+
+  @Override
+  public int hashCode()
+  {
+    int hash = 7;
+    hash = 59 * hash + (this.showPowerAndSpeed ? 1 : 0);
+    return hash;
+  }
+}