1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.trend.impl;
14 import java.awt.Color;
15 import java.awt.Graphics2D;
16 import java.text.Format;
17 import java.text.NumberFormat;
19 import org.simantics.g2d.utils.GridSpacing;
20 import org.simantics.g2d.utils.GridUtil;
21 import org.simantics.trend.configuration.TimeWindow;
22 import org.simantics.trend.configuration.TrendSpec;
23 import org.simantics.utils.format.TimeFormat;
25 public class HorizRuler extends TrendGraphicalNode {
27 private static final long serialVersionUID = 7155812928124259094L;
29 GridSpacing spacing = GridSpacing.SOME_SPACING;
30 public double from = 0;
31 public double end = 100;
32 public boolean autoscroll = true; // Determines if auto-scroll is on/off
33 boolean manualscale = false; // Locked in trend spec
34 TimeFormat timeFormat = new TimeFormat(0, 0);
35 private Format f = timeFormat;
36 double iFrom = Double.MAX_VALUE;
37 double iEnd = -Double.MAX_VALUE;
38 public double basetime = 0;
39 public TimeWindowListener listener;
40 public static final Color AUTOSCROLL_ON = new Color(0, 225, 34);
41 public static final Color AUTOSCROLL_OFF = new Color(255, 115, 115);
44 public boolean setWidth(double width) {
45 if (getWidth()==width) return false;
46 this.setSize(width, 20);
50 public boolean setFromEnd(double from, double end) {
51 if (this.from!=from || this.end!=end) {
54 getTrend().shapedirty = true;
60 public boolean setFromScale(double from, double scaleX) {
61 double end = getWidth() * scaleX + from;
62 return setFromEnd(from, end);
66 public void fireListener() {
67 if (listener != null) {
68 double wid = getWidth();
69 if ( wid == 0.0 ) wid = 0.1;
70 double sx = (end-from) / wid;
71 listener.onNewWindow(from, end, sx);
76 * Set grid spacing and text formatter;
78 public void layout() {
79 TrendNode trend = getTrend();
80 if (trend.timeFormat == org.simantics.trend.configuration.TimeFormat.Time) {
81 // Figure out how many decimals are needed
82 timeFormat.setMaxValue(end);
83 timeFormat.setDecimals(1);
85 double labelWidth = 0;
86 double maxLabelWidth = 0;
87 for (int i=0; i<2; i++) {
88 labelWidth = GridUtil.calcLabelWidth(from - basetime, end - basetime, timeFormat, spacing);
89 maxLabelWidth = Math.max(labelWidth, maxLabelWidth);
90 spacing = GridSpacing.makeGridSpacing(end-from, getWidth(), labelWidth+10);
91 timeFormat.setDecimals((int) -spacing.segmentExp);
94 if (maxLabelWidth>labelWidth) {
95 spacing = GridSpacing.makeGridSpacing(end-from, getWidth(), maxLabelWidth+10);
96 timeFormat.setDecimals((int) -spacing.segmentExp);
102 f = NumberFormat.getInstance();
103 double labelWidth = GridUtil.calcLabelWidth(from - basetime, end, f, spacing);
104 this.spacing = GridSpacing.makeGridSpacing(end-from, getWidth(), labelWidth+10);
109 protected void doRender(Graphics2D g2d) {
110 TrendNode trend = getTrend();
112 // Draw little "Frozen"
113 if ( !trend.printing )
115 // g2d.setColor( Color.LIGHT_GRAY );
116 g2d.setColor( autoscroll ? AUTOSCROLL_ON : AUTOSCROLL_OFF );
117 g2d.setFont( GridUtil.RULER_FONT );
118 String txt = !autoscroll ? (manualscale ? "*" : "Auto-scroll off") : (manualscale ? "" : "Auto-scroll on");
120 // g2d.drawString(txt, 0.f, (float)getHeight() + 12.f );
122 g2d.drawString(txt, (float) getWidth()+20, 20.f );
125 g2d.setPaint(Color.GRAY);
126 g2d.setStroke( GridUtil.RULER_LINE_STROKE );
127 GridUtil.paintHorizontalRuler(
136 * This method sets iFrom and iEnd values.
137 * Read reads values from ItemNodes.
138 * So it is good idea to call {@link ItemNode#readMinMaxFromEnd()} first.
140 public void setKnownFromEnd() {
141 TrendNode trendNode = (TrendNode) getParent();
143 iFrom = Double.MAX_VALUE;
144 iEnd = -Double.MAX_VALUE;
145 for (ItemNode item : trendNode.allItems) {
146 if ( !Double.isNaN(item.from) ) iFrom = Math.min(iFrom, item.from);
147 if ( !Double.isNaN(item.end ) ) iEnd = Math.max(iEnd , item.end );
149 // Scale to 0..10 if there is no data
150 if (iFrom == Double.MAX_VALUE && iEnd == -Double.MAX_VALUE) {
157 * If zoomed, do nothing.
158 * If not zoomed, set from and end according to TrendSpec's time window settings.
160 public boolean autoscale() {
161 if (!autoscroll) return false;
164 TrendNode trendNode = (TrendNode) getParent();
165 TrendSpec spec = trendNode.spec;
170 TimeWindow timeWindow = spec.viewProfile.timeWindow;
171 double len = timeWindow.timeWindowLength != null ? timeWindow.timeWindowLength : iEnd-iFrom;
173 if (timeWindow.timeWindowStart != null) {
175 if (timeWindow.timeWindowIncrement != null && timeWindow.timeWindowLength==null) {
176 nFrom = timeWindow.timeWindowStart + basetime;
180 len = Math.max(0, iEnd-nFrom);
181 double f = (100-timeWindow.timeWindowIncrement) / 100;
183 double x = Math.log( len ) / Math.log( b );
189 nFrom = timeWindow.timeWindowStart + basetime;
194 if (timeWindow.timeWindowIncrement == null) {
202 if (timeWindow.timeWindowLength != null) {
203 double f = timeWindow.timeWindowIncrement / 100;
204 double fraction = len * f;
206 nEnd = Math.floor( (iEnd +fraction)/ fraction ) * fraction;
209 double diff = iFrom-nFrom;
214 if (Double.isInfinite(nEnd)) {
222 double f = (100-timeWindow.timeWindowIncrement) / 100;
224 double x = Math.log( len ) / Math.log( b );
233 if (nFrom>nEnd) nFrom = nEnd;
236 return setFromEnd(nFrom, nEnd);
239 public void translate(double dx) {
247 * Convert x position in rulers coordinate space to time value.
248 * This function does not apply basetime. To apply basetime deduct it from
254 public double toTime( double x ) {
255 double sx = (end-from) / getWidth();
259 public double toX( double time ) {
260 double sx = (end-from) / getWidth();
261 return (time-from) / sx;
264 public void zoomIn(double x, double width) {
267 double sx = (end-from) / getWidth();
268 double newFrom = from + x*sx;
269 double newEnd = from + (x+width)*sx;
276 public void zoomOut() {
283 public double unitsPerPixel() {
284 return (end-from) / getWidth();
288 * @return the current starting sample time calculated from all visible chart
291 public double getItemFromTime() {
296 * @return the current ending sample time calculated from all visible chart
299 public double getItemEndTime() {
303 public interface TimeWindowListener {
304 void onNewWindow(double from, double end, double sx);