/* ===================================================================== * Ocelotl Visualization Tool * ===================================================================== * * Ocelotl is a Framesoc plug in that enables to visualize a trace * overview by using aggregation techniques * * (C) Copyright 2013 INRIA * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Damien Dosimont <damien.dosimont@imag.fr> * Generoso Pagano <generoso.pagano@inria.fr> */ package fr.inria.soctrace.tools.ocelotl.ui.views; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.LightweightSystem; import org.eclipse.draw2d.MouseEvent; import org.eclipse.draw2d.MouseListener; import org.eclipse.draw2d.OrderedLayout; import org.eclipse.draw2d.PolylineConnection; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.ToolbarLayout; import org.eclipse.draw2d.XYLayout; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.wb.swt.SWTResourceManager; import fr.inria.lpaggreg.quality.DLPQuality; /** * _2DCacheMicroDescription View : part representation, according to LP * algorithm result * * @author "Damien Dosimont <damien.dosimont@imag.fr>" */ public class QualityView { class ParamMouseListener implements MouseListener { State state = State.RELEASED; @Override public void mouseDoubleClicked(final MouseEvent arg0) { // TODO Auto-generated method stub } @Override public void mousePressed(final MouseEvent arg0) { state = State.PRESSED; if (qualities != null) if (arg0.x > XBorder && arg0.x < root.getSize().width() - Border) { final float param = 1 - (float) (arg0.x - XBorder) / (root.getSize().width() - XBorder - Border); ocelotlView.getParam().setText(String.valueOf(param)); createDiagram(); //ocelotlView.setConfiguration(); } } @Override public void mouseReleased(final MouseEvent arg0) { state = State.RELEASED; if (qualities != null) ocelotlView.cancelSelection(); ocelotlView.getBtnRun().notifyListeners(SWT.Selection, new Event()); } } static public enum State { PRESSED, RELEASED; } private Figure root; private Canvas canvas; private final static int XBorder = 50; private final static int YBorder = 25; private final static int Border = 15; private final static int AxisWidth = 1; private final static int YGradDefaultNumber = 10; private double yGradNumber = 10.0; private double qualityWidth = 10.0; private final static long YGradWidthMin = 20; private double yGradWidth = 50; private final static int TextWidth = 50; private final static int TextHeight = 16; private final static int TextOffset = 2; private final static long MiniDivide = 5; private final static double XGradNumber = 10; private List<DLPQuality> qualities; private List<Double> parameterList; private double currentParameter; private final OcelotlView ocelotlView; private double maxValue; private double minValue; private final static float ParamLineWidth = 1.8F; private final static float QualityLineWidth = 2.0F; public QualityView(final OcelotlView lpaggregView) { super(); ocelotlView = lpaggregView; } public Figure getRoot() { return root; } public void createDiagram() { root.removeAll(); if (ocelotlView.getCore().getLpaggregManager() != null) { qualities = ocelotlView.getCore().getLpaggregManager().getQualities(); parameterList = new ArrayList<Double>(ocelotlView.getCore().getLpaggregManager().getParameters()); currentParameter = ocelotlView.getCore().getOcelotlParameters().getParameter(); if (qualities != null && (root.getSize().width() > (XBorder + Border) * 1.5)) { maxValue = Math.max(qualities.get(qualities.size() - 1).getGain(), qualities.get(qualities.size() - 1).getLoss()); minValue = Math.min(0, Math.min(qualities.get(0).getGain(), qualities.get(0).getLoss())); if (maxValue == 0.0 && minValue == 0.0) { drawError(); } else { drawYGrads(); drawXGrads(); drawXYLines(); drawQualities(); drawParam(); } } canvas.update(); root.validate(); } } private void drawError() { final RectangleFigure rectangleText = new RectangleFigure(); root.add(rectangleText, new Rectangle(new Point(XBorder, (int) ((root.getSize().height() - YBorder - Border) / 3)), new Point(new Point(root.getSize().width() - XBorder, (int) ((root.getSize().height() - YBorder - Border) / 2))))); rectangleText.setBackgroundColor(ColorConstants.white); rectangleText.setForegroundColor(ColorConstants.white); final Label label = new Label("Error: unable to get several aggregations"); label.setLabelAlignment(SWT.CENTER); label.setForegroundColor(ColorConstants.darkGray); rectangleText.setFont(SWTResourceManager.getFont("Cantarell", TextHeight / 2, SWT.NORMAL)); rectangleText.setLineWidth(1); rectangleText.add(label); final ToolbarLayout layout = new ToolbarLayout(); layout.setMinorAlignment(OrderedLayout.ALIGN_CENTER); rectangleText.setLayoutManager(layout); rectangleText.setBackgroundColor(root.getBackgroundColor()); rectangleText.setForegroundColor(root.getBackgroundColor()); } public void drawParam() { if (currentParameter == -1) return; final int width = root.getSize().width - XBorder - Border; final int yOff = root.getSize().height() - YBorder; final PolylineConnection line = new PolylineConnection(); line.setEndpoints(new Point((int) (XBorder + width * (1 - currentParameter)), yOff), new Point((int) (XBorder + width * (1 - currentParameter)), Border)); line.setForegroundColor(ColorConstants.blue); line.setLineWidthFloat(ParamLineWidth); root.add(line); } public void drawQualities() { int i; final int width = root.getSize().width - XBorder - Border; final int yOff = root.getSize().height() - YBorder; final int height = root.getSize().height() - YBorder - Border; qualities.add(new DLPQuality(qualities.get(qualities.size() - 1))); parameterList.add(1.0); for (i = 1; i < qualities.size(); i++) { final double cParam = 1 - parameterList.get(i); final double nParam = 1 - parameterList.get(i - 1); double cgain = qualities.get(qualities.size() - 1).getGain() - qualities.get(i).getGain(); double ngain = qualities.get(qualities.size() - 1).getGain() - qualities.get(i - 1).getGain(); double closs = qualities.get(qualities.size() - 1).getLoss() - qualities.get(i).getLoss(); double nloss = qualities.get(qualities.size() - 1).getLoss() - qualities.get(i - 1).getLoss(); if (!ocelotlView.getOcelotlParameters().isGrowingQualities()) { cgain = qualities.get(i).getGain(); ngain = qualities.get(i - 1).getGain(); closs = qualities.get(i).getLoss(); nloss = qualities.get(i - 1).getLoss(); } final PolylineConnection lineGain1 = new PolylineConnection(); lineGain1.setEndpoints(new Point((int) (XBorder + width * cParam), (int) (yOff - height * cgain / (maxValue - minValue))), new Point((int) (XBorder + width * cParam), (int) (yOff - height * ngain / (maxValue - minValue)))); final PolylineConnection lineLoss1 = new PolylineConnection(); lineLoss1.setEndpoints(new Point((int) (XBorder + width * cParam), (int) (yOff - height * closs / (maxValue - minValue))), new Point((int) (XBorder + width * cParam), (int) (yOff - height * nloss / (maxValue - minValue)))); final PolylineConnection lineGain2 = new PolylineConnection(); lineGain2.setEndpoints(new Point((int) (XBorder + width * cParam), (int) (yOff - height * ngain / (maxValue - minValue))), new Point((int) (XBorder + width * nParam), (int) (yOff - height * ngain / (maxValue - minValue)))); final PolylineConnection lineLoss2 = new PolylineConnection(); lineLoss2.setEndpoints(new Point((int) (XBorder + width * cParam), (int) (yOff - height * nloss / (maxValue - minValue))), new Point((int) (XBorder + width * nParam), (int) (yOff - height * nloss / (maxValue - minValue)))); lineGain1.setForegroundColor(ColorConstants.green); lineLoss1.setForegroundColor(ColorConstants.red); lineGain1.setLineWidthFloat(QualityLineWidth); lineLoss1.setLineWidthFloat(QualityLineWidth); root.add(lineGain1); root.add(lineLoss1); lineGain2.setForegroundColor(ColorConstants.green); lineLoss2.setForegroundColor(ColorConstants.red); lineGain2.setLineWidthFloat(QualityLineWidth); lineLoss2.setLineWidthFloat(QualityLineWidth); root.add(lineGain2); root.add(lineLoss2); } qualities.remove(qualities.size() - 1); } public void drawXGrads() { double width = (root.getSize().width - XBorder - Border) / XGradNumber; double xGradNumber = XGradNumber; while (width < TextWidth && width > 1) { xGradNumber /= 2; width = (root.getSize().width - XBorder - Border) / xGradNumber; } final PolylineConnection lineEnd = new PolylineConnection(); lineEnd.setEndpoints(new Point((int) (xGradNumber * width + XBorder), root.getSize().height() - YBorder), new Point(new Point((int) (xGradNumber * width + XBorder), Border))); lineEnd.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); lineEnd.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); lineEnd.setLineWidth(1); root.add(lineEnd); for (int i = 0; i < xGradNumber + 1; i++) { final PolylineConnection line = new PolylineConnection(); line.setEndpoints(new Point((int) (i * width + XBorder), root.getSize().height() - YBorder), new Point(new Point((int) (i * width + XBorder), Border))); line.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); line.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); line.setLineWidth(1); root.add(line); final float value = (float) ((10 - (i * XGradNumber / xGradNumber)) * 0.1); final Label label = new Label("" + value); label.setLabelAlignment(SWT.CENTER); label.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); label.setFont(SWTResourceManager.getFont("Cantarell", TextHeight / 2, SWT.NORMAL)); root.add(label, new Rectangle(new Point((int) (i * width + XBorder - width / 2), root.getSize().height() - YBorder + TextOffset), new Point(new Point((int) ((i + 1) * width + XBorder - width / 2), root.getSize().height() - YBorder - AxisWidth + TextHeight + TextOffset)))); final ToolbarLayout layout = new ToolbarLayout(); layout.setMinorAlignment(OrderedLayout.ALIGN_CENTER); label.setLayoutManager(layout); if (i * (XGradNumber / xGradNumber) != (int) XGradNumber && width / MiniDivide > YGradWidthMin / 2) for (int j = 1; j < 5; j++) { if (((i * width + XBorder) + (int) (j * width / MiniDivide)) < xGradNumber * width + XBorder) { final PolylineConnection lineDash = new PolylineConnection(); lineDash.setEndpoints(new Point((int) (i * width + XBorder) + (int) (j * width / MiniDivide), root.getSize().height() - YBorder), new Point(new Point((int) (i * width + XBorder) + (int) (j * width / MiniDivide), Border))); lineDash.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); lineDash.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); lineDash.setLineWidth(1); lineDash.setLineStyle(SWT.LINE_DASH); root.add(lineDash); } } } } public void drawXYLines() { final RectangleFigure rectangleX = new RectangleFigure(); final RectangleFigure rectangleY = new RectangleFigure(); root.add(rectangleX, new Rectangle(new Point(XBorder, root.getSize().height() - YBorder + AxisWidth), new Point(root.getSize().width() - Border, root.getSize().height() - YBorder))); rectangleX.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); rectangleX.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); root.add(rectangleY, new Rectangle(new Point(XBorder - AxisWidth, Border), new Point(XBorder, root.getSize().height() - YBorder))); rectangleY.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); rectangleY.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); rectangleX.setLineWidth(1); rectangleY.setLineWidth(1); } public void drawYGrads() { YGrads(); NumberFormat formatter = null; formatter = NumberFormat.getInstance(Locale.US); formatter = new DecimalFormat("0.0E0"); final double width = root.getSize().width - XBorder - Border; final double height = root.getSize().height - YBorder; final PolylineConnection lineEnd = new PolylineConnection(); lineEnd.setEndpoints(new Point(XBorder, (int) (height - yGradNumber * yGradWidth)), new Point((int) (width + XBorder), (int) (height - yGradNumber * yGradWidth))); lineEnd.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); lineEnd.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); lineEnd.setLineWidth(1); root.add(lineEnd); for (int i = 0; i < (int) yGradNumber + 1; i++) { final PolylineConnection line = new PolylineConnection(); line.setEndpoints(new Point(XBorder, (int) (height - i * yGradWidth)), new Point((int) (width + XBorder), (int) (height - i * yGradWidth))); line.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); line.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); line.setLineWidth(1); root.add(line); final double value = i == yGradNumber ? maxValue - minValue : (double) ((long) (i * qualityWidth * 10) / 10.0); String text = formatter.format(value); if (value < 1000) text = String.valueOf(value); final Label label = new Label(text); label.setFont(SWTResourceManager.getFont("Cantarell", TextHeight / 2, SWT.NORMAL)); label.setLabelAlignment(SWT.CENTER); label.setForegroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_FOREGROUND)); label.setBackgroundColor(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); root.add(label, new Rectangle(new Point(XBorder - TextWidth - TextOffset, (int) (height - i * yGradWidth) + TextHeight / 3), new Point(new Point(XBorder - TextOffset, (int) (height - i * yGradWidth - TextHeight / 1.5))))); final ToolbarLayout layout = new ToolbarLayout(); layout.setMinorAlignment(OrderedLayout.ALIGN_CENTER); label.setLayoutManager(layout); } } public Canvas initDiagram(final Composite parent) { root = new Figure(); root.setFont(parent.getFont()); final XYLayout layout = new XYLayout(); root.setLayoutManager(layout); canvas = new Canvas(parent, SWT.DOUBLE_BUFFERED); canvas.setBackground(ColorConstants.gray); canvas.setSize(parent.getSize()); final LightweightSystem lws = new LightweightSystem(canvas); lws.setContents(root); lws.setControl(canvas); root.setFont(SWTResourceManager.getFont("Cantarell", 8, SWT.NORMAL)); root.setSize(parent.getSize().x, parent.getSize().y); canvas.addControlListener(new ControlListener() { @Override public void controlMoved(final ControlEvent arg0) { // TODO Auto-generated method stub canvas.redraw(); root.repaint(); resizeDiagram(); } @Override public void controlResized(final ControlEvent arg0) { canvas.redraw(); root.repaint(); resizeDiagram(); } }); root.addMouseListener(new ParamMouseListener()); return canvas; } public void resizeDiagram() { createDiagram(); root.repaint(); } public void YGrads() { final double maxValue = Math.max(qualities.get(qualities.size() - 1).getGain(), qualities.get(qualities.size() - 1).getLoss()); final double minValue = Math.min(0, Math.min(qualities.get(0).getGain(), qualities.get(0).getLoss())); long temp = (long) (maxValue - minValue); int i; for (i = 1; temp > 10; i++) temp /= 10; final long factor = temp < 6 ? YGradDefaultNumber : temp; for (int j = 1; j < i; j++) temp *= 10; qualityWidth = (double) temp / (double) factor; yGradNumber = (maxValue - minValue) / qualityWidth; yGradWidth = (root.getSize().height - YBorder - Border) / yGradNumber; while (yGradWidth < YGradWidthMin && yGradNumber > 6) { yGradNumber /= 2; yGradWidth *= 2; qualityWidth *= 2; } } public void deleteDiagram() { root.removeAll(); qualities = null; root.repaint(); } }