/******************************************************************************* * Copyright (c) 2017 Rogue Wave Software Inc. and others. * 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: * Rogue Wave Software Inc. - initial implementation *******************************************************************************/ package org.eclipse.php.profile.ui.views; import java.io.File; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Arrays; import java.util.Locale; import org.eclipse.birt.chart.model.Chart; import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; import org.eclipse.osgi.util.NLS; import org.eclipse.php.profile.core.data.ProfilerFileData; import org.eclipse.php.profile.core.data.ProfilerGlobalData; import org.eclipse.php.profile.core.engine.IProfileSessionListener; import org.eclipse.php.profile.core.engine.ProfileSessionsManager; import org.eclipse.php.profile.core.engine.ProfilerDB; import org.eclipse.php.profile.ui.PHPProfileUIMessages; import org.eclipse.php.profile.ui.utils.ChartUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; /** * Profiler information view. */ public class ProfilerInformationView extends AbstractProfilerView implements IProfileSessionListener { private DecimalFormat fDecimalFormat = new DecimalFormat("#0.0##", //$NON-NLS-1$ new DecimalFormatSymbols(new Locale("en"))); //$NON-NLS-1$ private ScrolledForm fForm; private Label fUriLabel; private Label fQueryLabel; private Label fPathLabel; private Label fTotalTimeLabel; private Label fFileCountLabel; private Label fDateLabel; private ProfilerDB fProfilerDB; private ChartViewer fChartViewer; /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt. * widgets.Composite) */ public void createPartControl(Composite parent) { createForm(parent); ProfileSessionsManager.addProfileSessionListener(this); setInput(ProfileSessionsManager.getCurrent()); // TODO - help context // parent.setData(WorkbenchHelpSystem.HELP_KEY, // IStudioHelpContextIds.PROFILER_INFORMATION_VIEW); // parent.addHelpListener(new HelpListener() { // public void helpRequested(HelpEvent arg0) { // org.eclipse.swt.program.Program.launch( // IStudioHelpContextIds.PROFILER_INFORMATION_VIEW); // } // }); } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ public void dispose() { ProfileSessionsManager.removeProfileSessionListener(this); super.dispose(); } private void createForm(Composite parent) { FormToolkit toolkit = new FormToolkit(parent.getDisplay()); fForm = toolkit.createScrolledForm(parent); FillLayout layout = new FillLayout(); layout.type = SWT.HORIZONTAL; layout.marginWidth = 5; layout.marginHeight = 5; layout.spacing = 10; fForm.getBody().setLayout(layout); createGeneralSection(toolkit); createChartSection(toolkit); } private void createGeneralSection(FormToolkit toolkit) { Section section = toolkit.createSection(fForm.getBody(), SWT.DEFAULT); section.setText(PHPProfileUIMessages.getString("ProfilerInformationView_0")); //$NON-NLS-1$ Composite sectionClient = new Composite(section, SWT.NONE); toolkit.paintBordersFor(sectionClient); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 10; sectionClient.setLayout(layout); GridData data = new GridData(); data.grabExcessHorizontalSpace = true; data.horizontalAlignment = SWT.FILL; fUriLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fUriLabel.setLayoutData(data); fQueryLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fQueryLabel.setLayoutData(data); fPathLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fPathLabel.setLayoutData(data); fTotalTimeLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fTotalTimeLabel.setLayoutData(data); fFileCountLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fFileCountLabel.setLayoutData(data); fDateLabel = toolkit.createLabel(sectionClient, ""); //$NON-NLS-1$ fDateLabel.setLayoutData(data); section.setClient(sectionClient); toolkit.adapt(sectionClient); } private void createChartSection(FormToolkit toolkit) { Section section = toolkit.createSection(fForm.getBody(), SWT.DEFAULT); section.setText(PHPProfileUIMessages.getString("ProfilerInformationView_1")); //$NON-NLS-1$ Composite sectionClient = new Composite(section, SWT.NONE); toolkit.paintBordersFor(sectionClient); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; sectionClient.setLayout(layout); fChartViewer = new ChartViewer(sectionClient, SWT.NONE); toolkit.adapt(fChartViewer, false, false); GridData data = new GridData(); data.widthHint = 300; data.heightHint = 400; data.grabExcessHorizontalSpace = true; fChartViewer.setLayoutData(data); section.setClient(sectionClient); toolkit.adapt(sectionClient); } private void redrawPieChart(ProfilerDB db) { if (db != null) { ProfilerGlobalData globalData = db.getGlobalData(); String[] fileNames = globalData.getFileNames(); int fileCount = fileNames.length; FileTime[] allValues = new FileTime[fileCount]; // create FileTime values for (int i = 0; i < fileCount; i++) { ProfilerFileData fileData = db.getFileData(fileNames[i]); if (fileData != null) { allValues[i] = new FileTime(fileData.getTotalOwnTimeInMilli(), fileData.getName()); } } Arrays.sort(allValues); int slicesLimit = 5; int actualNumber = Math.min(slicesLimit, fileCount); FileTime[] selectedFiles = new FileTime[actualNumber]; // creating the new array of values int index = 0; for (int i = fileCount - 1; i >= 0; i--) { if (index >= slicesLimit - 1 && fileCount != slicesLimit) { // sum // the // other // values // all // together // - // the // "Other" if (selectedFiles[slicesLimit - 1] == null) { selectedFiles[slicesLimit - 1] = new FileTime(allValues[i].getTime(), NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_8"), //$NON-NLS-1$ Integer.toString(fileCount - slicesLimit + 1))); } else { selectedFiles[slicesLimit - 1] .setTime(selectedFiles[slicesLimit - 1].getTime() + allValues[i].getTime()); } } else { selectedFiles[index] = new FileTime(allValues[i].getTime(), allValues[i].getName()); index++; } } double globalTime = 0; final double values[] = new double[selectedFiles.length]; for (int i = 0; i < selectedFiles.length; ++i) { values[i] = selectedFiles[i].getTime() * 1000; globalTime += selectedFiles[i].getTime(); } final String labels[] = new String[selectedFiles.length]; String tooltips[] = new String[selectedFiles.length]; DecimalFormat percentFormat = new DecimalFormat("#0.#", //$NON-NLS-1$ new DecimalFormatSymbols(new Locale("en"))); //$NON-NLS-1$ double percentageSum = 0; for (int i = 0; i < selectedFiles.length; i++) { FileTime file = selectedFiles[i]; if (file != null) { File currentFile = new File(file.getName()); String percentageString = ""; //$NON-NLS-1$ if (i == selectedFiles.length - 1) { percentageString = NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_11"), //$NON-NLS-1$ percentFormat.format(100 - percentageSum)); } else { double currentPercent = (file.getTime() / globalTime) * 100; percentageSum += currentPercent; percentageString = NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_11"), //$NON-NLS-1$ percentFormat.format(currentPercent)); } labels[i] = NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_12"), //$NON-NLS-1$ new String[] { currentFile.getName(), file.isMicroSecOrLess() ? ("<= " + fDecimalFormat //$NON-NLS-1$ .format(file.getTime())) : fDecimalFormat.format(file.getTime()), percentageString }); String fullPath = currentFile.getAbsolutePath(); // to check whether it's the last file with the Other if (currentFile.getName() .startsWith(PHPProfileUIMessages.getString("ProfilerInformationView_8").substring(0, //$NON-NLS-1$ PHPProfileUIMessages.getString("ProfilerInformationView_8") //$NON-NLS-1$ .indexOf("("))) //$NON-NLS-1$ && i == selectedFiles.length - 1) { fullPath = currentFile.getName(); } tooltips[i] = NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_12"), //$NON-NLS-1$ new String[] { fullPath, fDecimalFormat.format(file.getTime()), percentageString }); } } if (labels.length > 0) { final Display display = getSite().getShell().getDisplay(); display.asyncExec(new Runnable() { public void run() { BusyIndicator.showWhile(getSite().getShell().getDisplay(), new Runnable() { public void run() { Chart chart = ChartUtil.createPieChart(labels, values); chart.getBlock() .setBackground(ColorDefinitionImpl.create(fForm.getBackground().getRed(), fForm.getBackground().getGreen(), fForm.getBackground().getBlue())); fChartViewer.updateChartModel(chart); } }); } }); } } else { fChartViewer.updateChartModel(null); } } private void setGeneralInfoLabelText(ProfilerDB db) { if (db != null) { ProfilerGlobalData globalData = db.getGlobalData(); fUriLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_2"), //$NON-NLS-1$ globalData.getOriginalURL().replaceAll("&", "&&"))); //$NON-NLS-1$ //$NON-NLS-2$ fUriLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_2"), //$NON-NLS-1$ globalData.getOriginalURL())); fQueryLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_3"), //$NON-NLS-1$ calculateQueryMessage(globalData.getQuery().replaceAll("&", "&&")))); //$NON-NLS-1$ //$NON-NLS-2$ fQueryLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_3"), //$NON-NLS-1$ calculateQueryMessage(globalData.getQuery()))); fPathLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_4"), //$NON-NLS-1$ globalData.getPath())); fPathLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_4"), //$NON-NLS-1$ globalData.getPath())); String totalTime = fDecimalFormat.format(globalData.getGlobalTimeInMilli()); fTotalTimeLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_5"), //$NON-NLS-1$ totalTime)); fTotalTimeLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_5"), //$NON-NLS-1$ totalTime)); fFileCountLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_6"), //$NON-NLS-1$ Integer.toString(globalData.getFileCount()))); fFileCountLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_6"), //$NON-NLS-1$ Integer.toString(globalData.getFileCount()))); fDateLabel.setText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_7"), //$NON-NLS-1$ db.getProfileDate().toString())); fDateLabel.setToolTipText(NLS.bind(PHPProfileUIMessages.getString("ProfilerInformationView_7"), //$NON-NLS-1$ db.getProfileDate().toString())); } else { fUriLabel.setText(""); //$NON-NLS-1$ fUriLabel.setToolTipText(""); //$NON-NLS-1$ fQueryLabel.setText(""); //$NON-NLS-1$ fQueryLabel.setToolTipText(""); //$NON-NLS-1$ fPathLabel.setText(""); //$NON-NLS-1$ fPathLabel.setToolTipText(""); //$NON-NLS-1$ fTotalTimeLabel.setText(""); //$NON-NLS-1$ fTotalTimeLabel.setToolTipText(""); //$NON-NLS-1$ fFileCountLabel.setText(""); //$NON-NLS-1$ fFileCountLabel.setToolTipText(""); //$NON-NLS-1$ fDateLabel.setText(""); //$NON-NLS-1$ fDateLabel.setToolTipText(""); //$NON-NLS-1$ } fForm.redraw(); } public static String calculateQueryMessage(String query) { String newString = query; if (query.indexOf("start_debug") != -1) { //$NON-NLS-1$ newString = query.substring(0, query.indexOf("start_debug")); //$NON-NLS-1$ } if (newString.equals("")) { //$NON-NLS-1$ return PHPProfileUIMessages.getString("ProfilerInformationView_10"); //$NON-NLS-1$ } if (newString.endsWith("&")) { //$NON-NLS-1$ newString = newString.substring(0, newString.length() - 1); } return newString; } /* * (non-Javadoc) * * @see org.eclipse.php.profile.ui.views.AbstractProfilerView#getInput() */ public ProfilerDB getInput() { return fProfilerDB; } /* * (non-Javadoc) * * @see org.eclipse.php.profile.ui.views.AbstractProfilerView#setInput(org. * eclipse. php.profile.core.profiler.ProfilerDB) */ public void setInput(ProfilerDB profilerDB) { if (fProfilerDB != profilerDB) { setGeneralInfoLabelText(profilerDB); redrawPieChart(profilerDB); fProfilerDB = profilerDB; } } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ public void setFocus() { } private static class FileTime implements Comparable<Object> { private static final double microSecOrLess = 0.001; private double time; private String name; public FileTime(double time, String name) { this.time = time > 0 ? time : microSecOrLess; this.name = name; } public double getTime() { return time; } public String getName() { return name; } public boolean isMicroSecOrLess() { return time == microSecOrLess; } public void setTime(double time) { this.time = time; } public int compareTo(Object o) { double newTime = ((FileTime) o).getTime(); if (time - newTime <= 0) { if (time - newTime == 0) { return 0; } return -1; } return 1; } } /* * (non-Javadoc) * * @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener# * currentSessionChanged(org.eclipse.php.profile.core.profiler.ProfilerDB) */ public void currentSessionChanged(final ProfilerDB current) { getSite().getShell().getDisplay().asyncExec(new Runnable() { /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public void run() { setInput(current); } }); } /* * (non-Javadoc) * * @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener# * profileSessionAdded(org.eclipse.php.profile.core.profiler.ProfilerDB) */ public void profileSessionAdded(ProfilerDB db) { } /* * (non-Javadoc) * * @seeorg.eclipse.php.profile.core.profiler.IProfileSessionListener# * profileSessionRemoved(org.eclipse.php.profile.core.profiler.ProfilerDB) */ public void profileSessionRemoved(ProfilerDB db) { } }