class Rectangle implements SelectionArea {

    private static final float[] POINT_RECT = {1, 1};
    private final GraphDrawable drawable;
    private final VizConfig config;
    private final float[] color;
    private final float[] rectangle = new float[2];
    private final float[] rectangle3d = new float[2];
    private final float[] center = new float[2];
    private final float[] rectangleSize = new float[2];
    //Variables
    private float[] startPosition;
    private float[] startPosition3d;
    private boolean stop = true;
    private boolean blocking = true;
    private boolean ctrl = false;

    public Rectangle() {
        drawable = VizController.getInstance().getDrawable();
        config = VizController.getInstance().getVizConfig();
        color = config.getRectangleSelectionColor().getRGBComponents(null);
    }

    @Override
    public float[] getSelectionAreaRectancle() {
        if (stop) {
            return POINT_RECT;
        }
        rectangleSize[0] = Math.abs(rectangle[0] - startPosition[0]);
        rectangleSize[1] = Math.abs(rectangle[1] - startPosition[1]);
        if (rectangleSize[0] < 1f) {
            rectangleSize[0] = 1f;
        }
        if (rectangleSize[1] < 1f) {
            rectangleSize[1] = 1f;
        }
        return rectangleSize;
    }

    @Override
    public float[] getSelectionAreaCenter() {
        if (stop) {
            return null;
        }
        center[0] = -(rectangle[0] - startPosition[0]) / 2f;
        center[1] = -(rectangle[1] - startPosition[1]) / 2f;
        return center;
    }

    @Override
    public boolean mouseTest(Vecf distanceFromMouse, NodeModel nodeModel) {
        if (stop) {
            return nodeModel.selectionTest(distanceFromMouse, 0);
        }

        float x = nodeModel.getX();
        float y = nodeModel.getY();
        float rad = nodeModel.getNode().size();

        boolean res = true;
        if (startPosition3d[0] > rectangle3d[0]) {
            if (x - rad > startPosition3d[0] || x + rad < rectangle3d[0]) {
                res = false;
            }
        } else if (x + rad < startPosition3d[0] || x - rad > rectangle3d[0]) {
            res = false;
        }
        if (startPosition3d[1] < rectangle3d[1]) {
            if (y + rad < startPosition3d[1] || y - rad > rectangle3d[1]) {
                res = false;
            }
        } else if (y - rad > startPosition3d[1] || y + rad < rectangle3d[1]) {
            res = false;
        }
        return res;
    }

    public void start(float[] mousePosition, float[] mousePosition3d) {<FILL_FUNCTION_BODY>}

    public void stop() {
        stop = true;
        blocking = true;
    }

    public void setMousePosition(float[] mousePosition, float[] mousePosition3d) {
        if (!stop) {
            rectangle[0] = mousePosition[0];
            rectangle[1] = mousePosition[1];
            rectangle3d[0] = mousePosition3d[0];
            rectangle3d[1] = mousePosition3d[1];
        }
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public boolean blockSelection() {
        return blocking;
    }

    public void setBlocking(boolean blocking) {
        this.blocking = blocking;
    }

    @Override
    public void drawArea(GL2 gl, GLU glu) {
        if (!stop) {
            float x = startPosition[0];
            float y = startPosition[1];
            float w = rectangle[0] - startPosition[0];
            float h = rectangle[1] - startPosition[1];

            gl.glMatrixMode(GL2.GL_PROJECTION);
            gl.glPushMatrix();
            gl.glLoadIdentity();
            glu.gluOrtho2D(0, drawable.getViewportWidth(), 0, drawable.getViewportHeight());
            gl.glMatrixMode(GL2.GL_MODELVIEW);
            gl.glPushMatrix();
            gl.glLoadIdentity();

            gl.glColor4f(color[0], color[1], color[2], color[3]);

            gl.glBegin(GL2.GL_QUADS);
            gl.glVertex3f(x + w, y, 0);
            gl.glVertex3f(x, y, 0);
            gl.glVertex3f(x, y + h, 0);
            gl.glVertex3f(x + w, y + h, 0);
            gl.glEnd();

            gl.glColor4f(color[0], color[1], color[2], 1f);
            gl.glBegin(GL2.GL_LINE_LOOP);
            gl.glVertex3f(x + w, y, 0);
            gl.glVertex3f(x, y, 0);
            gl.glVertex3f(x, y + h, 0);
            gl.glVertex3f(x + w, y + h, 0);
            gl.glEnd();

            gl.glPopMatrix();
            gl.glMatrixMode(GL2.GL_PROJECTION);
            gl.glPopMatrix();
            gl.glMatrixMode(GL2.GL_MODELVIEW);
        } else {
            startPosition = null;
        }
    }

    public boolean isStop() {
        return stop;
    }

    public boolean isCtrl() {
        return ctrl;
    }

    public void setCtrl(boolean ctrl) {
        this.ctrl = ctrl;
    }
}

        this.startPosition = Arrays.copyOf(mousePosition, 2);
        this.startPosition3d = Arrays.copyOf(mousePosition3d, 2);
        this.rectangle[0] = startPosition[0];
        this.rectangle[1] = startPosition[1];
        this.rectangle3d[0] = startPosition3d[0];
        this.rectangle3d[1] = startPosition3d[1];
        stop = false;
        blocking = false;
    
<no_super_class>