Package org.jscsi.whiskas.views

Source Code of org.jscsi.whiskas.views.Pattern

/**
* Copyright (c) 2012, University of Konstanz, Distributed Systems Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the University of Konstanz nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jscsi.whiskas.views;


import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.SWT;
import org.eclipse.ui.part.ViewPart;
import org.jscsi.whiskas.Activator;

/**
* This clas provides a view of block access patterns on a jSCSI device. It is
* part of the Whiskas Plugin and is therefore instantiated by the
* Whiskas Control Center.
* @author Halld�r Janetzko
*/
public class Pattern extends ViewPart implements ControlListener, PaintListener,
VisualListener, DisposeListener, SelectionListener, MouseMoveListener {
    /**Reference of supervising Control center.*/
    private Control ctr;
    /** Map of color for rendering.*/
    private ColorMap cm;
    /**reference object of the top-composite.*/
    private Composite topshell;
    /**canvas to paint Pattern on.*/
    private Canvas c;
    /**image buffer for double buffering.*/
    private Image buffer;
    /**Composites for settings an detail view.*/
    private Composite preference, details;
    /**List of access (read/write) for pattern visualisation.*/
    private List visualizing;
    /**List of devices for pattern visualisation.*/
    private List device;
    /**Label for GUI.*/
    private Label lbDevice, lbDetails;
    /**Button for resetting Touch History.*/
    private Button btResetHistory;
    /**internal memory of number of rows.*/
    private int lines;
    /**internal memory of number of colums.*/
    private int colums;
    /**Counter for devision of Canvas.*/
    private int counter;
    /**Boolean to remember if it is the first time of painting,
     * if it is the canvas has to be devided.*/
    private boolean first = true;
    /**Arrays to hold values for each rectangle.*/
    private int[] xPos, yPos, widths, heights;
    /**Arrays for blocktype and hits.*/
    private byte[] types, values;
    /**Array to save if block has never been touched.*/
    private boolean[] neverTouched;
    /**internal values for difference of overall block width(height)
     *  and screen width(height).*/
    private int xDiff, yDiff;
    /**Strings to detect changes of settings.*/
    private String lastVis, lastDev = "";
    /**Spinners for minimum and maximum block to display.*/
    private Spinner min, max;
    /**Thickness of border in pixel.*/
    private int border = 5;
    /**Variables to store last max and min value of spinner
     * to notice changes.*/
    private int lastMinNo = 0, lastMaxNo = 0;
    /**
     * The Constructor of Pattern initializes values for drawing and
     * it registers itself at the Activator.
     */
    public Pattern() {
        lines = 1;
        colums = 1;
        Activator.getDefault().list_of_visualizer.add(this);
    }
    /**
     * Method which is always executed by the Activator class
     * and builds the GUI.
     * @param parent the parent of the Pattern view.
     */
    public final void createPartControl(final Composite parent) {
        topshell = parent;
        topshell.addControlListener(this);
        cm = new ColorMap(topshell.getDisplay());
        RowLayout rl = new RowLayout();
        rl.type = SWT.VERTICAL;
        rl.wrap = false;
        rl.justify = true;
        topshell.setLayout(rl);
        preference = new Composite(topshell, SWT.BORDER);
        preference.setLayoutData(new RowData(
                topshell.getClientArea().width, 50));
        RowLayout rl2 = new RowLayout();
        rl2.spacing = 10;
        preference.setLayout(rl2);
        lbDevice = new Label(preference, SWT.READ_ONLY);
        lbDevice.setText("Device: ");
        RowData rowd = new RowData();
        rowd.height = 45;
        rowd.width = 130;
        device = new List(preference, SWT.SINGLE | SWT.V_SCROLL);
        device.setLayoutData(rowd);
        visualizing = new List(preference, SWT.SINGLE);
        visualizing.setItems(new String[] {"Read", "Write"});
        visualizing.setSelection(0);
        lastVis = "Read";
        Label lbmin = new Label(preference,SWT.NONE);
        lbmin.setText("Min Blockno.");
        min = new Spinner(preference,SWT.NONE);
        min.setMinimum(0);
        min.setMaximum(1000000);
        Label lbmax = new Label(preference,SWT.NONE);
        lbmax.setText("Max Blockno.");
        max = new Spinner(preference,SWT.NONE);
        max.setMinimum(0);
        max.setMaximum(1000000);
        btResetHistory = new Button(preference, SWT.PUSH);
        btResetHistory.setText("Reset Touch History");
        btResetHistory.addSelectionListener(this);
        details = new Composite(preference, SWT.BORDER);
        details.setLayout(new FillLayout());
        lbDetails = new Label(details, SWT.NONE);
        lbDetails.setText("Details: N/A");
        preference.pack();
        c = new Canvas(topshell, SWT.DOUBLE_BUFFERED | SWT.BORDER);
        c.setLayoutData(new RowData(topshell.getClientArea().width,
                topshell.getClientArea().height - 150));
        c.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLACK));
        c.addPaintListener(this);
        c.addMouseMoveListener(this);
        xPos = new int[lines * colums];
        yPos = new int[lines * colums];
        widths = new int[lines * colums];
        heights = new int[lines * colums];
        types = new byte[lines * colums];
        values = new byte[lines * colums];
        neverTouched = new boolean[lines * colums];
        for (int i = 0; i < lines * colums; i++) {
            types[i] = 5;
            values[i] = -128;
            neverTouched[i] = true;
        }
        topshell.addDisposeListener(this);
    }
    /**
     * Method to calculate position and measures of each block
     * representing rectangle.
     */
    public final void calcGrid() {
        counter = 0;
        int widthFactor = (c.getBounds().width - border) / colums;
        int heightFactor = (c.getBounds().height - border) / lines;
        int width = ((c.getBounds().width - border) / colums) * colums;
        int height = ((c.getBounds().height - border) / lines) * lines;
        xDiff = (c.getBounds().width - border) - width;
        yDiff = (c.getBounds().height - border) - height;
        int remainingYDiff = this.yDiff;
        for (int x = 0; x < lines; x++) {
            if (x % 2 == 0) {
                if (remainingYDiff == 0) {
                    divide(0, widthFactor, colums,
                            x * heightFactor + this.yDiff, heightFactor);
                } else {
                    divide(0, widthFactor, colums,
                            x * heightFactor + this.yDiff - remainingYDiff,
                            heightFactor + 1);
                    remainingYDiff = remainingYDiff - 1;
                }
            }
            if (x % 2 == 1) {
                if (remainingYDiff == 0) {
                    divide((c.getBounds().width - border), widthFactor,
                            colums, x * heightFactor + this.yDiff,
                            heightFactor);
                } else {
                    divide((c.getBounds().width - border), widthFactor,
                            colums, x * heightFactor + this.yDiff
                            - remainingYDiff,
                            heightFactor + 1);
                    remainingYDiff = remainingYDiff - 1;
                }
            }
        }
    }
    /**
     * Method to devide one line into <i>number</i> rectangles.
     * @param xBegin xPos of the begin of the line
     * @param widthFactor factor calculated by width devided by
     *  number of rectangles in one line
     * @param number of rectangles to place in one line
     * @param y yPos of the line
     * @param height of the line to devide
     */
    private void divide(final int xBegin, final int widthFactor,
            final int number, final int y, final int height) {
        int remainingXDiff = this.xDiff;
        if (xBegin != 0) {
            remainingXDiff = 0;
        }
        for (int x = 1; x <= number; x++) {
            if (xBegin > 0) {
                if (x < number - this.xDiff + 1) {
                    xPos[counter] = xBegin - x * widthFactor;
                    yPos[counter] = y;
                    widths[counter] = widthFactor;
                    heights[counter] = height;
                } else {
                    remainingXDiff = remainingXDiff + 1;
                    xPos[counter] = xBegin - x * widthFactor - remainingXDiff;
                    yPos[counter] = y;
                    widths[counter] = widthFactor + 1;
                    heights[counter] = height;
                }
            }
            if (xBegin == 0) {
                if (remainingXDiff == 0) {
                    xPos[counter] = xBegin + (x - 1) * widthFactor
                        + this.xDiff;
                    yPos[counter] = y;
                    widths[counter] = widthFactor;
                    heights[counter] = height;
                } else {
                    xPos[counter] = xBegin + (x - 1) * widthFactor
                        + this.xDiff - remainingXDiff;
                    yPos[counter] = y;
                    widths[counter] = widthFactor + 1;
                    heights[counter] = height;
                    remainingXDiff = remainingXDiff - 1;
                }
            }
            if (counter < xPos.length - 1) {
                counter++;
            }
            if (counter >= xPos.length) {
                System.out.println(counter + "  " + xPos.length);
            }
        }
    }
    /**
     * Method which is not used by Pattern.
     * @param e ControlEvent
     */
    public void controlMoved(final ControlEvent e) { }
    /**
     * Method which orders recalculation of Grid if Frame is resized.
     * @param e ControlEvent
     */
    public final void controlResized(final ControlEvent e) {
        preference.setLayoutData(new RowData(
                topshell.getClientArea().width - 10, 60));
        c.setLayoutData(new RowData(
                topshell.getClientArea().width - 10,
                topshell.getClientArea().height - 80));
        first = true;
        c.redraw();
    }
    /**
     * This method is called whenever repaint is called,
     * then the Pattern will be painted.
     * @param e PaintEvent called by Eclipse
     */
    public final void paintControl(final PaintEvent e) {
        if (first)  {
            calcGrid();
            first = false;
        }
        repaintBuffer();
        e.gc.drawImage(buffer, 0, 0);
    }
    /**
     * Repaints buffer with new Pattern, the buffer will be painted
     * by paintControl.
     */
    public final void repaintBuffer() {
        if (buffer != null) {
            buffer.dispose();
        }
        buffer = new Image(topshell.getDisplay(),
                c.getBounds().width, c.getBounds().height);
        GC bufferGC = new GC(buffer);
        paint(bufferGC);
        bufferGC.dispose();
    }
    /**
     * Here is the painting implemented. Each rectangle will be painted
     * one after the other.
     * @param g is the GraphicContext
     */
    public final void paint(final GC g) {
        for (int i = 0; i < colums * lines; i++) {
            if (neverTouched[i]) {
                try {
                    g.setBackground(cm.getColors(types[i])[0]);
                } catch (Exception e) {
                    System.out.println(types.length);
                }
                g.fillRectangle(xPos[i], yPos[i], widths[i], heights[i]);
                g.setBackground(cm.getColors(types[i])[99]);
                g.fillRectangle((int) (xPos[i] + 0.5 * widths[i] -
                                0.3 * widths[i] / 2.0),
                        (int) (yPos[i] + 0.5 * heights[i] -
                                0.3 * heights[i] / 2.0),
                        (int) (0.3 * widths[i]) + 1,
                        (int) (0.3 * heights[i]) + 1);
            }
            if (!neverTouched[i] && values != null && values[i] > -128) {
                int cIndex;
                if (values != null) {
                    cIndex = (int) ((float) ((values[i]) + 128) / (256) * 99.0);
                } else {
                    cIndex = (int) ((float) (-128 + 128) / (256) * 99.0);
                }
                g.setBackground(cm.getColors(types[i])[cIndex]);
                g.fillRectangle(xPos[i], yPos[i], widths[i], heights[i]);
                g.setBackground(cm.getColors(types[i])[99]);
                int[] points = new int[6];
                points[0] = xPos[i];
                points[2] = xPos[i] + widths[i];
                points[4] = xPos[i] + widths[i];
                points[1] = yPos[i];
                points[3] = yPos[i];
                points[5] = yPos[i] + heights[i];
                g.fillPolygon(points);
            }
            if (!neverTouched[i] && values != null && values[i] == -128) {
                g.setBackground(cm.getColors(types[i])[99]);
                g.fillRectangle(xPos[i], yPos[i], widths[i], heights[i]);
                g.setBackground(cm.getColors(types[i])[0]);
                g.fillRectangle((int) (xPos[i] + 0.5 * widths[i] -
                                0.3 * widths[i] / 2.0),
                        (int) (yPos[i] + 0.5 * heights[i] -
                                0.3 * heights[i] / 2.0),
                        (int) (0.3 * widths[i]) + 1,
                        (int) (0.3 * heights[i]) + 1);
            }
        }
    }
    /**
     * The Control object has every values to draw, here they are
     * pulled from the matching hashtable.
     */
    public final void getNewValues() {
        this.ctr = Activator.getDefault().ctr;
        if (ctr.getDaten() == null) {
            return;
        }
        String newVisualizing = visualizing.getItem(
                visualizing.getSelectionIndex());
        String newDevice = "";
        if (device.getItemCount() > 0 && device.getSelectionIndex() != -1) {
            newDevice = device.getItem(device.getSelectionIndex());
            byte[] newValues = new byte[0];
            if (newVisualizing.equals("Read")) {
                newValues = ctr.getDaten().getValuesPatR().get(newDevice);
            }
            if (newVisualizing.equals("Write")) {
                newValues = ctr.getDaten().getValuesPatW().get(newDevice);
            }
            if (!newVisualizing.equals(lastVis) || !lastDev.equals(newDevice)) {
                lastVis = newVisualizing;
                lastDev = newDevice;
                resetNeverTouched();
            }
            if (newValues == null) {
                return;
            }
            int maxNo = max.getSelection(), minNo = min.getSelection();
            if (maxNo > newValues.length) {
                maxNo = newValues.length;
            }
            if (maxNo >= minNo && maxNo > 0) {
                byte[] processedNewValues = new byte[(int) Math.pow(
                        (int) Math.sqrt(maxNo - minNo) + 1, 2)];
                for (int i = 0; i < processedNewValues.length; i++) {
                    processedNewValues[i] = newValues[i + minNo];
                }
                newValues = processedNewValues;
            }
            if (maxNo != lastMaxNo || minNo != lastMinNo) {
                resetNeverTouched();
            }
            lastMaxNo = maxNo;
            lastMinNo = minNo;
            int newLines = (int) Math.sqrt(newValues.length) + 1;
            int newColums = (int) Math.sqrt(newValues.length) + 1;
            if (newLines != lines || newColums != colums) {
                xPos = new int[newLines * newColums];
                yPos = new int[newLines * newColums];
                widths = new int[newLines * newColums];
                heights = new int[newLines * newColums];
                boolean[] newNeverTouched = new boolean[newLines * newColums];
                types = new byte[newLines * newColums];
                for (int i = 0; i < newLines * newColums; i++) {
                    if (i < lines * colums) {
                        newNeverTouched[i] = neverTouched[i];
                    } else {
                        newNeverTouched[i] = true;
                    }
                    if (ctr.getDaten().getTypes() != null
                            && ctr.getDaten().getTypes().length > i) {
                        types[i] = ctr.getDaten().getTypes()[i];
                    }
                    if (ctr.getDaten().getTypes() == null) {
                        types[i] = 5;
                    }
                    if (ctr.getDaten().getTypes() != null
                            && ctr.getDaten().getTypes().length < i) {
                        types[i] = 9;
                    }
                }
                lines = newLines;
                colums = newColums;
                neverTouched = newNeverTouched;
                calcGrid();
            }
            values = new byte[lines * colums];
            for (int i = 0; i < newValues.length; i++) {
                values[i] = newValues[i];
                if (values != null && values[i] >= -127) {
                    neverTouched[i] = false;
                }
            }
            for (int i = newValues.length; i < lines * colums; i++) {
                values[i] = -128;
            }
            repaintBuffer();
            c.redraw();
        }
        String[] keys = ctr.getDaten().
                  getValuesPatR().keySet().toArray(new String[0]);
        boolean equal = keys.length == device.getItemCount();
        for (int i = 0; i < device.getItemCount(); i++) {
            equal = equal && device.getItem(i).equals(keys[i]);
        }
        if (!equal || device.getItemCount() == 0) {
            device.setItems(keys);
            if (!newDevice.equals("")) {
                for (int i = 0; i < device.getItemCount(); i++) {
                    if (device.getItem(i).equals(newDevice)) {
                        device.setSelection(i);
                    }
                }
            }
        }
    }
    /**
     * Implementation of Interface VisualListener.
     * @return Composite: parent shell of pattern view
     */
    public final Composite getComposite() {
        return topshell;
    }
    /**
     * When the pattern view is closed the Activator object
     * has to be informed and the pattern object will be
     * removed from Activator's list of visualizer.
     * @param e - DisposeEvent from Eclipse
     */
    public final void widgetDisposed(final DisposeEvent e) {
        c.dispose();
        buffer.dispose();
        visualizing.dispose();
        lbDevice.dispose();
        btResetHistory.dispose();
        lbDetails.dispose();
        details.dispose();
        preference.dispose();
        Activator.getDefault().list_of_visualizer.remove(this);
    }
    /**
     * Implementation of SelectionListener (method not used).
     * @param e - SelectionEvent
     */
    public void widgetDefaultSelected(final SelectionEvent e) { }
    /**
     * Implementation of SelectionListener (used for button
     * "Reset Touch History").
     * @param e - SelectionEvent
     */
    public final void widgetSelected(final SelectionEvent e) {
        if (e.widget.toString().contains("Reset Touch History")) {
            resetNeverTouched();
        }
    }
    /**
     * This method is called when touch history is to
     * be resetted (by user or be realignment of blocks).
     */
    public final void resetNeverTouched() {
        for (int i = 0; i < colums * lines; i++) {
            neverTouched[i] = true;
        }
    }
    /**
     * Implements MouseMoveListener (used for determination
     * of block on which mouse points).
     * @param e - MouseEvent
     */
    public final void mouseMove(final MouseEvent e) {
        int x = e.x;
        int y = e.y;
        boolean gefunden = false;
        for (int i = 0; i < colums * lines && !gefunden; i++) {
            if ((x >= xPos[i]) && (x <= xPos[i] + widths[i])
                    && (y >= yPos[i]) && (y <= yPos[i] + heights[i])) {
                gefunden = true;
                String[] s = {"Free Block", "Root Block",
                        "Positional BTree Block", "Keyed Trie Block",
                        "Keyed BTree Block", "Node Block", "Name Block",
                        "Value Block", "Histogram", "Unknown Block"};
                if (ctr.getDaten().getTypes() != null) {
                    lbDetails.setText("Details:\nTouches: " + values[i]
                                        + "\tPos: " + (i + min.getSelection())
                                        + "\n" + s[types[i]]);
                } else {
                    lbDetails.setText("Details:\nTouches: " + values[i]
                                               + "\tPos: " + (i + min.getSelection()));
                }
                details.pack();
            }
        }
        if (!gefunden) {
            lbDetails.setText("Details: N/A");
            details.pack();
        }
    }
    /**
     * Implements setFocus from Workbench (not used).
     */
    public void setFocus() { }
}
TOP

Related Classes of org.jscsi.whiskas.views.Pattern

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.