Skip to content

Commit

Permalink
Merge pull request #2822 from SCADA-LTS/fix/#2726_Legend_occupies_too…
Browse files Browse the repository at this point in the history
…_much_space_in_reports_screen2

#2726 Legend occupies too much space in reports screen
  • Loading branch information
Limraj authored Feb 29, 2024
2 parents 556c4ef + 376f095 commit 9ca6d33
Show file tree
Hide file tree
Showing 18 changed files with 806 additions and 41 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ test {
includeTestsMatching "com.serotonin.mango.rt.maint.work.CreateWorkItemToStringTest"
includeTestsMatching "com.serotonin.util.SerializationHelperTest"
includeTestsMatching "org.scada_lts.web.mvc.api.json.WorkItemInfoListTest"
includeTestsMatching "com.serotonin.mango.vo.report.ImageChartUtilsTestsSuite"
includeTestsMatching "org.scada_lts.serorepl.utils.StringUtilsTestsSuite"
includeTestsMatching "org.scada_lts.monitor.ConcurrentMonitoredValuesTest"

}
}
52 changes: 52 additions & 0 deletions src/com/serotonin/mango/vo/report/ImageChartUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
Expand All @@ -48,10 +52,15 @@
import com.serotonin.mango.util.mindprod.StripEntities;
import com.serotonin.util.StringUtils;

import static org.scada_lts.serorepl.utils.StringUtils.truncate;

/**
* @author Matthew Lohbihler
*/
public class ImageChartUtils {

private static final Log LOG = LogFactory.getLog(ImageChartUtils.class);

private static final int NUMERIC_DATA_INDEX = 0;
private static final int DISCRETE_DATA_INDEX = 1;

Expand Down Expand Up @@ -210,4 +219,47 @@ public static void addSecond(TimeSeries timeSeries, long time, Number value) {
catch (SeriesException e) { /* duplicate Second. Ignore. */
}
}

public static int calculateHeightChart(List<ReportChartCreator.PointStatistics> pointStatistics, int imageHeightPixels,
int pointLabelHeightInLegendPixels, int lineLengthInLegendLimit, int dataPointExtendedNameLengthLimit) {
int linesNumber = calculateLinesNumber(toListNames(pointStatistics), lineLengthInLegendLimit, dataPointExtendedNameLengthLimit);
return imageHeightPixels - pointLabelHeightInLegendPixels + ((linesNumber + 1) * pointLabelHeightInLegendPixels);
}

public static int calculateLinesNumber(List<String> pointStatisticsNames, int lineLengthInLegendLimit, int dataPointExtendedNameLengthLimit) {
if(pointStatisticsNames.isEmpty() || (pointStatisticsNames.size() == 1 && pointStatisticsNames.get(0) == null)) {
return 1;
}
StringBuilder subLegend = new StringBuilder();
int linesNumber = 1;
String split = " ** ";
for (int i = 0; i < pointStatisticsNames.size(); i++) {
String name = pointStatisticsNames.get(i);
if (name == null || name.isEmpty())
continue;
name = truncate(split + truncate(name, "", dataPointExtendedNameLengthLimit), "", lineLengthInLegendLimit);
if (subLegend.length() + name.length() > lineLengthInLegendLimit) {
LOG.debug(subLegend);
subLegend.delete(0, subLegend.length());
linesNumber++;
}
subLegend.append(name);
if(i == pointStatisticsNames.size() - 1) {
LOG.debug(subLegend);
subLegend.delete(0, subLegend.length());
}
}
return linesNumber;
}

public static String calculatePointNameForReport(String extendedName) {
if(extendedName.length() > ReportChartCreator.getDataPointExtendedNameLengthLimit()) {
return truncate(extendedName, "...", ReportChartCreator.getDataPointExtendedNameLengthLimit());
}
return extendedName;
}

private static List<String> toListNames(List<ReportChartCreator.PointStatistics> pointStatistics) {
return pointStatistics.stream().map(ReportChartCreator.PointStatistics::getName).collect(Collectors.toList());
}
}
47 changes: 31 additions & 16 deletions src/com/serotonin/mango/vo/report/ReportChartCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ public class ReportChartCreator {
/**
* This image width is specifically chosen such that the report will print on a single page width in landscape.
*/
private static final int IMAGE_WIDTH = 930;
private static final int IMAGE_HEIGHT = 400;
private static final int IMAGE_WIDTH_PIXELS = 930;
private static final int IMAGE_HEIGHT_PIXELS = 400;
private static final int POINT_LABEL_HEIGHT_IN_LEGEND_PIXELS = 20;
private static final int LINE_LENGTH_IN_LEGEND_LIMIT = 161;
private static final int DATA_POINT_EXTENDED_NAME_LENGTH_LIMIT = 64;
public static final String IMAGE_CONTENT_ID = "reportChart.png";

public static final int POINT_IMAGE_WIDTH = 440;
public static final int POINT_IMAGE_HEIGHT = 250; // 340
public static final int POINT_IMAGE_WIDTH_PIXELS = 440;
public static final int POINT_IMAGE_HEIGHT_PIXELS = 250; // 340

String inlinePrefix;
private String html;
Expand All @@ -79,7 +82,7 @@ public ReportChartCreator(ResourceBundle bundle) {
this.bundle = bundle;
}

/**
/**
* Uses the given parameters to create the data for the fields of this class. Once the content has been created the
* getters for the fields can be used to retrieve.
*
Expand All @@ -97,7 +100,7 @@ public void createContent(ReportInstance reportInstance, ReportDao reportDao, St

// Use a stream handler to get the report data from the database.
StreamHandler handler = new StreamHandler(reportInstance.getReportStartTime(),
reportInstance.getReportEndTime(), IMAGE_WIDTH, createExportFile, bundle);
reportInstance.getReportEndTime(), IMAGE_WIDTH_PIXELS, createExportFile, bundle);
// Process the report content with the handler.
reportDao.reportInstanceData(reportInstance.getId(), handler);

Expand Down Expand Up @@ -131,7 +134,7 @@ else if (pointStat.getDiscreteTimeSeries() != null)
if (ptsc.hasData()) {
if (inlinePrefix != null)
model.put("chartName", inlinePrefix + pointStat.getChartName());
pointStat.setImageData(ImageChartUtils.getChartData(ptsc, POINT_IMAGE_WIDTH, POINT_IMAGE_HEIGHT));
pointStat.setImageData(ImageChartUtils.getChartData(ptsc, POINT_IMAGE_WIDTH_PIXELS, POINT_IMAGE_HEIGHT_PIXELS));
}
}

Expand All @@ -144,8 +147,9 @@ else if (pointStat.getDiscreteTimeSeries() != null)
// The path comes from the servlet path definition in web.xml.
model.put("chartName", IMAGE_SERVLET + chartName);
}

imageData = ImageChartUtils.getChartData(ptsc, true, IMAGE_WIDTH, IMAGE_HEIGHT);
int consolidatedChartHeight = ImageChartUtils.calculateHeightChart(pointStatistics, IMAGE_HEIGHT_PIXELS,
POINT_LABEL_HEIGHT_IN_LEGEND_PIXELS, LINE_LENGTH_IN_LEGEND_LIMIT, DATA_POINT_EXTENDED_NAME_LENGTH_LIMIT);
imageData = ImageChartUtils.getChartData(ptsc, true, IMAGE_WIDTH_PIXELS, consolidatedChartHeight);
}

List<EventInstance> events = null;
Expand Down Expand Up @@ -255,7 +259,15 @@ public List<PointStatistics> getPointStatistics() {
return pointStatistics;
}

public class PointStatistics {
public static int getDataPointExtendedNameLengthLimit(){
return DATA_POINT_EXTENDED_NAME_LENGTH_LIMIT;
}

public static int getLineLengthInLegendLimit() {
return LINE_LENGTH_IN_LEGEND_LIMIT;
}

public static class PointStatistics {
private final int reportPointId;
private String name;
private int dataType;
Expand All @@ -268,8 +280,11 @@ public class PointStatistics {
private DiscreteTimeSeries discreteTimeSeries;
private byte[] imageData;

public PointStatistics(int reportPointId) {
private String inlinePrefix;

public PointStatistics(int reportPointId, String inlinePrefix) {
this.reportPointId = reportPointId;
this.inlinePrefix = inlinePrefix;
}

public String getName() {
Expand Down Expand Up @@ -475,8 +490,8 @@ public PointTimeSeriesCollection getPointTimeSeriesCollection() {
public void startPoint(ReportPointInfo pointInfo) {
donePoint();

point = new PointStatistics(pointInfo.getReportPointId());
point.setName(pointInfo.getExtendedName());
point = new PointStatistics(pointInfo.getReportPointId(), inlinePrefix);
point.setName(pointInfo.getExtendedNameForReport());
point.setDataType(pointInfo.getDataType());
point.setDataTypeDescription(DataTypes.getDataTypeMessage(pointInfo.getDataType()).getLocalizedMessage(
bundle));
Expand All @@ -501,7 +516,7 @@ public void startPoint(ReportPointInfo pointInfo) {
quantizer = new NumericDataQuantizer(start, end, imageWidth, this);

discreteTimeSeries = null;
numericTimeSeries = new TimeSeries(pointInfo.getExtendedName(), null, null, Second.class);
numericTimeSeries = new TimeSeries(pointInfo.getExtendedNameForReport(), null, null, Second.class);
numericTimeSeries.setRangeDescription(point.getTextRenderer().getMetaText());
point.setNumericTimeSeries(numericTimeSeries);
point.setNumericTimeSeriesColor(colour);
Expand All @@ -512,7 +527,7 @@ else if (pointInfo.getDataType() == DataTypes.MULTISTATE) {
point.setStats(new StartsAndRuntimeList(pointInfo.getStartValue(), start, end));
quantizer = new MultistateDataQuantizer(start, end, imageWidth, this);

discreteTimeSeries = new DiscreteTimeSeries(pointInfo.getExtendedName(), pointInfo.getTextRenderer(),
discreteTimeSeries = new DiscreteTimeSeries(pointInfo.getExtendedNameForReport(), pointInfo.getTextRenderer(),
colour);
point.setDiscreteTimeSeries(discreteTimeSeries);
if (pointInfo.isConsolidatedChart())
Expand All @@ -523,7 +538,7 @@ else if (pointInfo.getDataType() == DataTypes.BINARY) {
point.setStats(new StartsAndRuntimeList(pointInfo.getStartValue(), start, end));
quantizer = new BinaryDataQuantizer(start, end, imageWidth, this);

discreteTimeSeries = new DiscreteTimeSeries(pointInfo.getExtendedName(), pointInfo.getTextRenderer(),
discreteTimeSeries = new DiscreteTimeSeries(pointInfo.getExtendedNameForReport(), pointInfo.getTextRenderer(),
colour);
point.setDiscreteTimeSeries(discreteTimeSeries);
if (pointInfo.isConsolidatedChart())
Expand Down
4 changes: 3 additions & 1 deletion src/com/serotonin/mango/vo/report/ReportPointInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public class ReportPointInfo {
public String getExtendedName() {
return deviceName + " - " + pointName;
}

public String getExtendedNameForReport() {
return ImageChartUtils.calculatePointNameForReport(getExtendedName());
}
public int getReportPointId() {
return reportPointId;
}
Expand Down
31 changes: 28 additions & 3 deletions src/org/scada_lts/dao/report/ReportInstancePointDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.commons.logging.LogFactory;
import org.scada_lts.dao.DAO;
import org.scada_lts.dao.SerializationData;
import org.scada_lts.serorepl.utils.StringUtils;
import org.springframework.jdbc.core.ArgumentPreparedStatementSetter;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
Expand Down Expand Up @@ -111,6 +112,10 @@ public PointInfo(DataPointVO point, String colour, boolean consolidatedChart) {
this.consolidatedChart = consolidatedChart;
}

public int getId() {
return point.getId();
}

public DataPointVO getPoint() {
return point;
}
Expand All @@ -119,6 +124,20 @@ public String getColour() {
return colour;
}

public String getName() {
return StringUtils.truncate(point.getName(), "", 100);
}

public String getDeviceName() {
return StringUtils.truncate(point.getDeviceName(), "", 40);
}

public TextRenderer getTextRenderer() {
return point.getTextRenderer();
}



public boolean isConsolidatedChart() {
return consolidatedChart;
}
Expand All @@ -133,8 +152,14 @@ public List<ReportPointInfo> getPointInfos(int instanceId) {
return DAO.getInstance().getJdbcTemp().query(REPORT_INSTANCE_POINT_SELECT_WHERE, new Object[]{instanceId}, new ReportPointInfoRowMapper());
}

@Deprecated(since = "2.7.7")
@Transactional(readOnly = false,propagation= Propagation.REQUIRES_NEW,isolation= Isolation.READ_COMMITTED,rollbackFor=SQLException.class)
public int insert(final ReportInstance reportInstance, final DataPointVO point, final String name, final int dataType, final MangoValue startValue, final PointInfo pointInfo) {
return insert(reportInstance, dataType, startValue, pointInfo);
}

@Transactional(readOnly = false,propagation= Propagation.REQUIRES_NEW,isolation= Isolation.READ_COMMITTED,rollbackFor=SQLException.class)
public int insert(final ReportInstance reportInstance, final int dataType, final MangoValue startValue, final PointInfo pointInfo) {

if (LOG.isTraceEnabled()) {
LOG.trace("insert()");
Expand All @@ -147,11 +172,11 @@ public PreparedStatement createPreparedStatement(Connection connection) throws S
PreparedStatement preparedStatement = connection.prepareStatement(REPORT_INSTANCE_POINT_INSERT, Statement.RETURN_GENERATED_KEYS);
new ArgumentPreparedStatementSetter(new Object[] {
reportInstance.getId(),
point.getDeviceName(),
name,
pointInfo.getDeviceName(),
pointInfo.getName(),
dataType,
DataTypes.valueToString(startValue),
new SerializationData().writeObject(point.getTextRenderer()),
new SerializationData().writeObject(pointInfo.getTextRenderer()),
pointInfo.getColour(),
DAO.boolToChar(pointInfo.isConsolidatedChart())
}).setValues(preparedStatement);
Expand Down
15 changes: 6 additions & 9 deletions src/org/scada_lts/mango/service/ReportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,13 @@
import com.serotonin.mango.vo.User;
import com.serotonin.mango.vo.UserComment;
import com.serotonin.mango.vo.report.*;
import com.serotonin.util.StringUtils;
import com.serotonin.web.i18n.I18NUtils;
import com.serotonin.web.taglib.Functions;
import org.scada_lts.dao.DAO;
import org.scada_lts.dao.report.*;
import org.scada_lts.mango.adapter.MangoReport;
import org.scada_lts.permissions.service.GetReportInstancesWithAccess;
import org.scada_lts.permissions.service.GetReportsWithAccess;
import org.scada_lts.serorepl.utils.StringUtils;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -222,7 +221,7 @@ else if (instance.isToNow()) {
MangoValue startValue = null;
if (!instance.isFromInception()) {
// Get the value just before the start of the report
PointValueTime pvt = pointValueService.getPointValueBefore(point.getId(), instance.getReportStartTime());
PointValueTime pvt = pointValueService.getPointValueBefore(pointInfo.getId(), instance.getReportStartTime());
if (pvt != null)
startValue = pvt.getValue();

Expand All @@ -233,10 +232,8 @@ else if (instance.isToNow()) {

// Insert the reportInstancePoints record
//TODO SeroUtils
String name = Functions.truncate(point.getName(), 100);

int reportPointId = reportInstancePointDAO.insert(instance, point, name, dataType, startValue, pointInfo);
count += reportInstanceDataDAO.insert(appendParameters(timestampParams, point.getId(), dataType), reportPointId, StringUtils.replaceMacro(timestampSql, "field", "ts"));
int reportPointId = reportInstancePointDAO.insert(instance, dataType, startValue, pointInfo);
count += reportInstanceDataDAO.insert(appendParameters(timestampParams, pointInfo.getId(), dataType), reportPointId, StringUtils.replaceMacro(timestampSql, "field", "ts"));

String annotationCase = " case pva.sourceType" //
+ " when 1 then concat('" + userLabel + ": ',ifnull(u.username,'" + deletedLabel + "')) " //
Expand Down Expand Up @@ -269,7 +266,7 @@ else if (instance.isToNow()) {
}

eventSQL += StringUtils.replaceMacro(timestampSql, "field", "e.activeTs");
DAO.getInstance().getJdbcTemp().update(eventSQL, appendParameters(timestampParams, instance.getUserId(), point.getId()));
DAO.getInstance().getJdbcTemp().update(eventSQL, appendParameters(timestampParams, instance.getUserId(), pointInfo.getId()));
}

// Insert the reportInstanceUserComments records for the point.
Expand All @@ -285,7 +282,7 @@ else if (instance.isToNow()) {

// Only include comments made in the duration of the report.
commentSQL += StringUtils.replaceMacro(timestampSql, "field", "uc.ts");
DAO.getInstance().getJdbcTemp().update(commentSQL, appendParameters(timestampParams, point.getId()));
DAO.getInstance().getJdbcTemp().update(commentSQL, appendParameters(timestampParams, pointInfo.getId()));
}
}

Expand Down
Loading

0 comments on commit 9ca6d33

Please sign in to comment.