001package org.vishia.gral.swt;
002
003
004
005import java.util.List;
006
007import org.eclipse.swt.SWT;
008import org.eclipse.swt.events.FocusEvent;
009import org.eclipse.swt.events.FocusListener;
010import org.eclipse.swt.events.PaintEvent;
011import org.eclipse.swt.events.PaintListener;
012import org.eclipse.swt.graphics.Color;
013import org.eclipse.swt.graphics.GC;
014import org.eclipse.swt.graphics.Image;
015import org.eclipse.swt.graphics.Point;
016import org.eclipse.swt.widgets.Canvas;
017import org.eclipse.swt.widgets.Composite;
018import org.vishia.gral.base.GralCurveView;
019import org.vishia.gral.base.GralMng;
020import org.vishia.gral.base.GralPos;
021import org.vishia.gral.base.GralWidget;
022import org.vishia.gral.ifc.GralColor;
023import org.vishia.gral.ifc.GralRectangle;
024import org.vishia.util.Assert;
025import org.vishia.util.Debugutil;
026
027
028
029
030public class SwtCurveView extends GralCurveView.GraphicImplAccess
031{
032  
033  /**Version, history and license.
034   * <ul>
035   * <li>2016-07-03 Hartmut chg: Now derived from {@link GralCurveView.GraphicImplAccess} adequate to the  new concept: 
036   *   An implementing widget is derived from its derived class of {@link GralWidget.ImplAccess}. Therefore only that base class implements the GralWidgetImpl_ifc.
037   * <li>2014-02-03 Hartmut new: {@link CommonCurve#bFreeze}: freeze as common property of more as one GralCurveView. Constructor argument.
038   * <li>2013-05-19 Hartmut new: Usage of the common {@link SwtGralMouseListener} and 
039   *   implementation of the special functionality in the superclass {@link GralCurveView.GralCurveViewMouseAction}. 
040   * <li>2012-08-11 Hartmut now grid with  timestamps
041   * <li>2012-03-25 Hartmut improved zoom
042   * <li>2012-03-17 Hartmut some improvements in paint routine.
043   * <li>2012-02-26 Hartmut A lot of details, see {@link GralCurveView}
044   * <li>2012-02-21 Hartmut Now the CurveView works in the new environment. Some adjustments necessary yet.
045   * <li>2011-06-00 Hartmut New concept of GralWidget etc and new Configuration concept
046   *   with {@link org.vishia.gral.cfg.GralCfgBuilder}. The old GuiDialogZbnfControlled.class
047   *   was not use nevermore. But the CurveView was not adapted for that.
048   * <li>2010-03-00 Hartmut The curve view was development as basic feature.
049   * </ul>
050   * <br><br>
051   * <b>Copyright/Copyleft</b>:
052   * For this source the LGPL Lesser General Public License,
053   * published by the Free Software Foundation is valid.
054   * It means:
055   * <ol>
056   * <li> You can use this source without any restriction for any desired purpose.
057   * <li> You can redistribute copies of this source to everybody.
058   * <li> Every user of this source, also the user of redistribute copies
059   *    with or without payment, must accept this license for further using.
060   * <li> But the LPGL is not appropriate for a whole software product,
061   *    if this source is only a part of them. It means, the user
062   *    must publish this part of source,
063   *    but doesn't need to publish the whole source of the own product.
064   * <li> You can study and modify (improve) this source
065   *    for own using or for redistribution, but you have to license the
066   *    modified sources likewise under this LGPL Lesser General Public License.
067   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
068   * </ol>
069   * If you intent to use this source without publishing its usage, you can get
070   * a second license subscribing a special contract with the author. 
071   * 
072   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
073   * 
074   */
075  @SuppressWarnings("hiding")
076  public final static int version = 20120317;
077
078  private final CurveView curveSwt;
079  
080  private final Image cursorStore1, cursorStore2;
081  
082  
083
084  protected Color gridColor, gridColorStrong;
085  
086  protected final Color colorCursor, colorBack;
087  
088
089  
090  public SwtCurveView(GralCurveView widgg, SwtMng mng) //String sName, GralPos pos, SwtMng mng, int nrofXvalues, GralCurveView.CommonCurve common)
091  {
092    super(widgg);
093    //super(sName, mng.mng, nrofXvalues, common);
094    mouseListenerCurve = new SwtGralMouseListener.MouseListenerGralAction();
095  
096    GralRectangle bounds = mng.calcWidgetPosAndSize(widgg.pos(), 800, 600);
097    Composite panelSwt = (Composite)widgg.pos().panel.getWidgetImplementation();
098    curveSwt = this.new CurveView(panelSwt, bounds.dx, bounds.dy, widgg.maxNrofXValues);
099    curveSwt.setData(this);
100    curveSwt.setSize(bounds.dx, bounds.dy);
101    curveSwt.setBounds(bounds.x, bounds.y, bounds.dx, bounds.dy);
102    //mng.setBounds_(curveSwt); //, dyGrid, dxGrid);
103    curveSwt.setGridVertical(10, 5);   //10 data-points per grid line, 50 data-points per strong line.
104    curveSwt.setGridHorizontal(50.0F, 5);  //10%-divisions, with 5 sub-divisions
105    cursorStore1 = new Image(panelSwt.getDisplay(), 1, 2000);
106    cursorStore2 = new Image(panelSwt.getDisplay(), 1, 2000);
107    
108    gridColor = new Color(curveSwt.getDisplay(), 192, 255, 255);
109    gridColorStrong = new Color(curveSwt.getDisplay(), 128, 255, 255);
110    colorCursor = new Color(curveSwt.getDisplay(), 64, 64, 64);
111    colorBack = new Color(curveSwt.getDisplay(), 0xff, 0xff, 0xff);
112    widgg.initMenuContext();
113  }
114  
115  
116  @Override public void repaintGthread(){
117    int chg = dyda().getChanged();  //impl.getChanged();
118    int acknChg = 0;
119    if((chg & chgVisible)!=0){
120      acknChg |= chgVisible;
121      curveSwt.setVisible(true);
122      setFocusGThread();
123    }
124    if((chg & chgInvisible)!=0){
125      acknChg |= chgInvisible;
126      curveSwt.setVisible(false);
127    }
128    dyda().acknChanged(acknChg);
129    curveSwt.redraw();
130  }
131
132
133    
134  
135  /**Draws one track using the {@link ixDataShown} indices to the data.
136   * @param g graphic context from SWT
137   * @param size of the panel in pixel
138   * @param track data
139   * @param iTrack Index of track, only used for debugging or test outputs.
140   * @param ixixDataLast The end index in {@link ixDataShown} for this presentation.
141   */
142  private void drawTrack(GC g, Point size, GralCurveView.Track track, int iTrack, int ixixDataLast){
143    int ixixiData = 0;
144    //float pixelFromRight = 0;
145    int xp2 = size.x -1;
146    int xp1 = xp2;
147    int ixData2 = super.ixDataShown[ixixiData];
148    int nrofPixel4Data = super.nrofPixel4data[ixixiData];
149    int ixData = ixData2;
150    int ixD = (ixData >> widgg.shIxiData) & widgg.mIxiData; //real index in data
151    //
152    float yFactor = size.y / -10.0F / track.scale.yScale;  //y-scaling
153    float y0Pix = (1.0F - track.scale.y0Line/100.0F) * size.y; //y0-line
154    float yF = track.values[ixD];
155    int time2 = widgg.timeValues[ixD];
156    int time1;
157    int yp9 = (int)( (yF - track.scale.yOffset) * yFactor + y0Pix);
158    int yp2 = yp9;  //right value
159    int yp1; //left value
160    int ixData1;
161    Color lineColor = track.lineColor !=null ? (Color)widgg.gralMng().impl.getColorImpl(track.lineColor) : ((SwtProperties)widgg.gralMng().propertiesGui).colorBackground;
162    if(iTrack == 0){
163      //System.out.println("SwtCurveView-drawTrack-start(y0Pix=" + y0Pix + ", yFactor=" + yFactor + ", y=" + yF + ")");
164    }
165    //
166    while( ixixiData < ixixDataLast){ //for all gotten ixData
167      ixixiData += nrofPixel4Data +1;
168      ixData1 = super.ixDataShown[ixixiData];
169      //ixData1 = ixDataShown[(int)pixelFromRight];
170      
171      xp1 -= nrofPixel4Data +1;
172      if(ixData != ixData1) {
173        int yp1min = Integer.MAX_VALUE, yp1max = Integer.MIN_VALUE;
174        int nrofYp = 0;
175        yp1 = 0;
176        do{ //all values per 1 pixel
177          ixData -= widgg.adIxData;
178          ixD = (ixData >> widgg.shIxiData) & widgg.mIxiData;
179          int yp11;
180          //if(ixData == ixDataDraw){
181          if(ixixiData >= ixixDataLast){
182              yp11 = track.ypixLast;
183          } else {
184            yF = track.values[ixD];
185            time1 = widgg.timeValues[ixD];
186            int dTime = time2 - time1;
187            //pixelFromRight += dTime * pixel7time;
188            yp11 = (int)( (yF - track.scale.yOffset) * yFactor + y0Pix);
189          }
190          yp1 += yp11;  //build middle value or init first.
191          if(ixData != ixData1){  //more as one value on the same xp
192            if(yp1min > yp11){ yp1min = yp11; }
193            if(yp1max < yp11){ yp1max = yp11; }
194          }
195          nrofYp +=1;
196        } while(ixData != ixData1); // iData != ixDrawValues); //all values per 1 pixel
197        g.setForeground(lineColor);
198        g.setLineWidth(track.lineWidth);
199        if(nrofYp > 1){ //more as one value on the same xp
200          g.drawLine(xp1, yp1min, xp1, yp1max);  //draw vertical line to show range.
201          yp1 = yp1 / nrofYp;
202        }
203        g.drawLine(xp2, yp2, xp1, yp1);
204        if(iTrack == 0){
205          //System.out.println("SwtCurveView-drawTrack(" + xp2 + "+" + (xp1 - xp2) + ", " + yp2 + "+" + (yp1 - yp2) + ")");
206        }
207        xp2 = xp1; //next xp from right to left.
208        yp2 = yp1;
209        nrofPixel4Data = super.nrofPixel4data[ixixiData];
210        ixData2 = ixData1;
211      } else {
212      }
213    } //while(iData != ixDrawValues);
214    track.ypixLast = yp9;
215    
216  }
217  
218  
219  
220  /**Shifts the left draw area to left because only a right part of the curve should be drawn.
221   * It is to save calculation time
222   */
223  private int drawShiftAreaToLeft(GC g, Point size, int xView, int dxView, int yView, int dyView, int xViewPart, int timeDiff){
224    final int xp0;
225    testHelp.ctRedrawBecauseNewData +=1;
226    //
227    //calculate the number of x-pixel to shift in graphic to left and the width of the range to paint new:
228    //
229    //Shift the graphic if the reason of redraw is only increment samples
230    //and the number the values are shifted at least by that number, which is mapped to 1 pixel.
231    if(xViewPart >0 && xViewPart < size.x){
232      super.timeCaryOverNewValue = (int)(timeDiff - xViewPart * widgg.timeorg.timePerPixel);
233      super.xViewLastF -= xViewPart;
234      if(xView != 0){
235        //TODO what is if only a part of control is shown
236        stop();
237      }
238      xp0 = xView + dxView - xViewPart;
239      if(super.xpCursor1 >= 0){ //xViewPart){  //only if the cursor is in the shifted area:
240        //restore graphic under cursor
241        g.drawImage(cursorStore1, size.x - super.xpCursor1, 0);
242        //System.out.println("cursor1 " + xpCursor1);
243      }
244      if(super.xpCursor2 >= 0){ //xViewPart){  //only if the cursor is in the shifted area:
245        //restore graphic under cursor
246        g.drawImage(cursorStore2, size.x - super.xpCursor2, 0);
247        //System.out.println("cursor2 " + xpCursor2);
248      }
249      g.copyArea(xView + xViewPart, yView, dxView - xViewPart , dyView -5, xView, yView, false);
250      //
251      widgg.timeorg.pixelWrittenAfterStrongDiv += xViewPart;
252      
253      //System.out.println("SwtCurveView - draw - shift graphic;" + xViewPart);
254      //System.arraycopy(ixDataShown, 0, ixDataShown, xViewPart, size.x - xViewPart);
255      testHelp.ctRedrawPart +=1;
256    } else if(xViewPart >=size.x){ 
257      //too many new values. Show all
258      xViewPart = size.x;
259      xp0 = 0;
260      testHelp.ctRedrawAllShift +=1;
261      super.xViewLastF = 0.0F;
262    } else { //xViewPart <=0
263      //don't paint.
264      //System.out.println("SwtCurveView - draw - don't shift graphic;" + xViewPart);
265      xViewPart = 0;
266      xp0 = size.x;
267    }
268    return xp0;
269  }
270  
271  
272  
273  /**Draws the curves.
274   * @param g
275   * @param size
276   * @param xView
277   * @param dxView
278   * @param yView
279   * @param dyView
280   * @param ixDataRight
281   * @param xViewPart
282   * @param timeDiff
283   * @param xp0
284   */
285  private void drawRightOrAll(GC g, Point size, int xView, int dxView, int yView, int dyView
286      , int ixDataRight, int xViewPart, int timeDiff, int xp0, boolean bPaintAll){
287    g.setBackground(colorBack);
288    //fill, clear the area either from 0 to end or from size.x - xView to end,
289    g.fillRectangle(xp0, yView, xViewPart, dyView);  //fill the current background area
290    { //draw horizontal grid
291      float yG = dyView / super.gridDistanceX;
292      int yS = super.gridStrongPeriodX;
293      /*TODO
294      while(yGridF < dyView){
295        int yGrid = (int)yGridF;
296        if(--yS1 <=0){
297          yS1 = yS; g.setForeground(gridColorStrong);
298        } else { g.setForeground(gridColor);
299        }
300        g.drawLine(xViewLast, yGrid, dxView, yGrid);
301        yGridF += yG;
302      }
303      */
304    } 
305    //  
306    //prepare indices of data. Fills {@link #ixDataShown}
307    int ixixDataLast = super.prepareIndicesDataForDrawing(ixDataRight, xViewPart, timeDiff, bPaintAll);
308    // 
309    //write time divisions:
310    g.setForeground(gridColor);
311    g.setLineWidth(1);
312    g.setLineStyle(SWT.LINE_DOT);
313    for(int ii=1; ii <=9; ++ii){  //draw the horizontal grid
314      int y = (int)(size.y /10.0f * ii);
315      g.drawLine(size.x - xViewPart, y, size.x, y);
316      
317    }
318    //
319    int ixPixelTimeDiv =-1;
320    int xPixelTimeDiv1;                     //draw the vertical fine grid, the time divisions
321    while((xPixelTimeDiv1 = widgg.timeorg.xPixelTimeDivFine[++ixPixelTimeDiv]) >=0) {
322      g.drawLine(size.x - xPixelTimeDiv1, 0, size.x - xPixelTimeDiv1, size.y);
323      //System.out.println("draw " + xPixelTimeDiv);
324    }
325    g.setForeground(gridColorStrong);
326    g.setLineWidth(1);
327    ixPixelTimeDiv =-1;                     //draw the vertical grid, strong lines.
328    while((xPixelTimeDiv1 = widgg.timeorg.xPixelTimeDiv[++ixPixelTimeDiv]) >=0) {
329      g.drawLine(size.x - xPixelTimeDiv1, 0, size.x - xPixelTimeDiv1, size.y);
330      if(xPixelTimeDiv1 > 30){
331        g.setForeground((Color)widgg.gralMng().impl.getColorImpl(GralColor.getColor("bk")));
332        g.drawText(widgg.timeorg.sTimeAbsDiv[ixPixelTimeDiv], size.x - 6 - xPixelTimeDiv1, size.y - 25);
333        g.setForeground(gridColorStrong);
334        widgg.timeorg.pixelWrittenAfterStrongDiv = Integer.MIN_VALUE;
335      }
336      //System.out.println("draw " + xPixelTimeDiv);
337    }
338    //write all tracks.
339    g.setLineStyle(SWT.LINE_SOLID);
340    int iTrack = 0;
341    List<GralCurveView.Track> listTracks1 = widgg.listTracks; //Atomic access, iterate in local referenced list.
342    for(GralCurveView.Track track: listTracks1){
343      //draw line per track
344      if(track.showSelected !=0) {
345        drawTrack(g, size, track, iTrack, ixixDataLast);
346      }
347      iTrack +=1;
348    } //for listlines
349    super.ixDataDraw = ixDataRight;
350    //
351    if(widgg.timeorg.pixelWrittenAfterStrongDiv > 30){
352      g.drawText(widgg.timeorg.sTimeAbsDiv[0], size.x - 6 - widgg.timeorg.pixelWrittenAfterStrongDiv, size.y - 25);
353      widgg.timeorg.pixelWrittenAfterStrongDiv = Integer.MIN_VALUE;
354    }
355    //set the cursors
356    if(super.xpCursor1New >=0){
357      super.xpCursor1 = super.xpCursor1New;
358      super.xpCursor1New = -1;
359    }
360    if(super.xpCursor2New >=0){
361      super.xpCursor2 = super.xpCursor2New;
362      super.xpCursor2New = -1;
363    }
364    if(super.xpCursor1 >=0){
365      int xpCursor = size.x - super.xpCursor1;
366      g.copyArea(cursorStore1, xpCursor, 0);
367      g.setForeground(colorCursor);
368      g.setLineWidth(1);
369      g.drawLine(xpCursor, 0, xpCursor, size.y);
370    }
371    if(super.xpCursor2 >=0){
372      int xpCursor = size.x - super.xpCursor2;
373      g.copyArea(cursorStore2, xpCursor, 0);
374      //if(xViewPart >= size.x){
375        g.setForeground(colorCursor);
376        g.setLineWidth(1);
377        g.drawLine(xpCursor, 0, xpCursor, size.y);
378      //}
379    }
380
381  }
382  
383  
384  
385  /**This routine overrides 
386   * @see org.eclipse.swt.widgets.Canvas#drawBackground(org.eclipse.swt.graphics.GC, int, int, int, int)
387   * It is called in this class in {@link #paintListener} in the {@link PaintListener#paintControl(PaintEvent)} method.
388   * It draws the whole content.
389   * <br><br>
390   * Because of saving calculation time there will be drawn only a small peace on right side of the area
391   * with the new data normally. The rest inclusive grid lines, curves, text is moved to left. But if the whole
392   * window should be refreshed, the whole widget is drawn newly.
393   * 
394   */
395  protected void drawBackground(GC g, Point size, int xView, int yView, int dxView, int dyView) {
396    //NOTE: forces stack overflow because calling of this routine recursively: super.paint(g);
397    try{
398      boolean redrawBecauseNewData1, redrawAll;
399      synchronized(this){
400        redrawBecauseNewData1 = super.redrawBecauseNewData;
401        redrawAll = super.bRedrawAll;
402        if(!redrawBecauseNewData1){
403          Debugutil.stop();
404        }
405        super.bRedrawAll = false;  //it is done
406        super.redrawBecauseNewData = false;  //it is done.
407      }
408      //
409      //detect how many new data are given. Because the data are written in another thread,
410      //the number of data, the write index are accessed only one time from this
411      //Note that ixDataShowRight is set by ixDataWr if the curve is running.
412      int ixDataRight = super.ixDataShowRight; 
413      super.pixelOrg.xPixelCurve = size.x;
414      super.pixelOrg.yPixelCurve = size.y;
415      @SuppressWarnings("hiding")
416      GralCurveView.TimeOrganisation timeorg = widgg.timeorg;
417      timeorg.timePerPixel = (float)timeorg.timeSpread / (size.x +1); //nr of time units per pixel. 
418      timeorg.pixel7time = (float)(size.x +1) / timeorg.timeSpread; //nr of pixel per time unit.
419      int xViewPart = -1;   //nr of new pixel if only a part is drawn
420      final int xp0;  //left point to draw.
421      final int timeDiff; //time for new values.
422      testHelp.xView =xView; testHelp.yView =yView; testHelp.dxView =dxView; testHelp.dyView =dyView;
423      //
424      final boolean bPaintAll;
425      if(!widgg.common.bFreeze && !super.bPaintAllCmd && !redrawAll ) { //redrawBecauseNewData1) {
426        //paint only a part of the curve to save calculation time.
427        //The curve will be shifted to left.
428        //
429        bPaintAll = false;
430        if(ixDataRight != super.ixDataDraw){
431          widgg.testStopWr = true;
432          stop();
433        }  
434        int timeLast = widgg.timeValues[(super.ixDataDraw >> widgg.shIxiData) & widgg.mIxiData];
435        int timeNow = widgg.timeValues[(ixDataRight >> widgg.shIxiData) & widgg.mIxiData];
436        timeDiff = timeNow - timeLast + super.timeCaryOverNewValue;  //0 if nothing was written.
437        xViewPart = (int)(timeorg.pixel7time * timeDiff + 0.0f);
438        if(xViewPart > size.x){
439          xViewPart = size.x;   //for example if no data were received in the past, then timeDiff is hi.
440        }
441        xp0 = drawShiftAreaToLeft(g, size, xView, dxView, yView, dyView, xViewPart, timeDiff);
442      } else { //paintall
443        bPaintAll = true;
444        timeorg.calc();
445        //System.out.println("SwtCurveView - paintall;" + bFreeze + bPaintAllCmd + redrawBecauseNewData1);
446        xViewPart = size.x;
447        super.timeCaryOverNewValue = 0;
448        timeDiff = (int)(timeorg.timePerPixel * xViewPart);
449        xp0 = 0;
450        super.bPaintAllCmd = false; //accepted, done
451        testHelp.ctRedrawAll +=1;
452        //xViewLast = 0;
453        super.xViewLastF = 0.0F;
454        super.nrofDataShift.set(0);
455      }
456      widgg.newSamples = 0;  //next call of setSample will cause only draw of less area.
457      
458      //draw grid and 0-lines:
459      if(xViewPart >0) { //only if anything is to draw
460        //only if a new point should be drawn.
461        try{Thread.sleep(2);} catch(InterruptedException exc){}
462        drawRightOrAll(g, size, xView, dxView, yView, dyView, ixDataRight, xViewPart, timeDiff, xp0, bPaintAll);
463        
464      } else { //xViewPart == 0
465        //This is is normal case if a new value in data has a too less new timestamp.
466        //It can't be shown. Await the next values. Any value will be have a more newer timestamp
467        //with a great-enough time difference to show it.
468        super.nrofValuesLessViewPart +=1;
469        //System.out.println("SwtCurveView - xViewPart=0");
470      }
471      if(widgg.nrofValues >0){  //don't work if no data are stored.
472        int ixDataShow2 = ((widgg.ixDataWr - super.ixDataDraw)  >> widgg.shIxiData) & widgg.mIxiData;  //index of data which are shown right
473        int ixDataShow1 = ((widgg.ixDataWr - super.ixDataShown[size.x])  >> widgg.shIxiData) & widgg.mIxiData; //index of data which are shown left
474        float ixDataRel2 = (float)ixDataShow2 / widgg.maxNrofXValues;  //value 0..1 which range of buffer is shown 
475        float ixDataRel1 = (float)ixDataShow1 / widgg.maxNrofXValues;
476        int iPixRange2 = size.x - (int)(size.x * ixDataRel2);  //Position shown range right in pixel
477        int iPixRange1 = size.x - (int)(size.x * ixDataRel1);  //left
478        //int ixDWr = (ixDataWr >> shIxiData) & mIxiData;
479        //System.out.println("SwtCurveView.spread; " + ixDataRel1 + ".." + ixDataRel2);
480        g.setLineWidth(5);
481        g.setForeground((Color)widgg.gralMng().impl.getColorImpl(GralColor.getColor("ye")));
482        g.drawLine(0, size.y -3, iPixRange1, size.y -3);  //left not shown range.
483        g.drawLine(iPixRange2, size.y -3, size.x, size.y -3);  //right non shown range.
484        g.setForeground((Color)widgg.gralMng().impl.getColorImpl(GralColor.getColor("dgr")));
485        //g.setAlpha(128);
486        g.drawLine(iPixRange1, size.y -3, iPixRange2, size.y -3);  //shown range
487      }
488    } catch(Exception exc){
489      CharSequence sError = Assert.exceptionInfo("SwtCurveView.draw - exception", exc, 0, 20, true);
490      System.err.append(sError);
491    }
492    //g.drawString(""+xShift+ ":"+ xViewLast + ":" + nrofDataShift.get(), 200, dyView-28);
493    //g.drawString("xx", 200, dyView-16);
494    super.focusChanged = false; //paint only last area by next paint event without focus event.
495    widgg.testStopWr = false;
496  } 
497
498  
499  
500  private class CurveView extends Canvas
501  {
502    
503    //private final CurveView widgSwt;
504
505    //final Canvas canvas;
506    
507    //private final Color[] lineColors;
508    
509    
510    public CurveView(Composite parent, int xPixel, int yPixel, int nrofXvalues){
511      super(parent, org.eclipse.swt.SWT.NO_SCROLL|org.eclipse.swt.SWT.NO_BACKGROUND);
512      setData("Control", this);
513      setSize(xPixel, yPixel);  //the size may be changed later by drag the window.
514      //this.xPixel = xPixel;
515      //this.yPixel = yPixel;
516      //lineColors = new Color[nrofTracks];
517      Color defaultColor = new Color(getDisplay(), 255,0,0);
518      addPaintListener(paintListener);
519      addFocusListener(focusListener);
520      addMouseListener(mouseListenerCurve);
521      //addMouseListener(mouseLeftButtonListener);
522      //addMouseMoveListener(mouseMoveListener);
523      //widgSwt = this;
524    }
525    
526    
527
528    
529    public void setGridVertical(int dataPointsBetweenGridLines, int periodStrongLine){
530      SwtCurveView.this.gridDistanceY = dataPointsBetweenGridLines;
531      SwtCurveView.this.gridStrongPeriodY = periodStrongLine;
532      widgg.gridDistanceStrongY = dataPointsBetweenGridLines * periodStrongLine;
533    }
534    
535    
536    /**Set distance for horizontal grid lines.
537     * @param percentY percent of y-view for grid lines. For example 50.0: divide y-axis in 50 steps. 
538     * @param periodStrongLine period for strong lines For example 5, any 5. line is stroke.
539     */
540    public void setGridHorizontal(float percentY, int periodStrongLine){
541      SwtCurveView.this.gridDistanceX = percentY;
542      SwtCurveView.this.gridStrongPeriodX = periodStrongLine;
543    }
544    
545    
546    
547    public void redrawData(){
548      SwtCurveView.this.redrawBecauseNewData = true;
549      redraw();
550    }
551    
552    
553    
554    
555    
556    
557    
558    PaintListener paintListener = new PaintListener()
559    {
560
561      @Override public void paintControl(PaintEvent e) {
562        GC gc = e.gc;
563        drawBackground(e.gc, e.x, e.y, e.width, e.height);
564      }
565      
566    };
567
568    
569    
570    FocusListener focusListener = new FocusListener()
571    { @Override public void focusGained(FocusEvent e) {
572      SwtCurveView.this.focusChanged = true;
573      }
574
575      @Override public void focusLost(FocusEvent e) {
576        SwtCurveView.this.focusChanged = true;
577      }
578    }; 
579
580    
581    /**This routine overrides 
582     * @see org.eclipse.swt.widgets.Canvas#drawBackground(org.eclipse.swt.graphics.GC, int, int, int, int)
583     * It is called in this class in {@link #paintListener} in the {@link PaintListener#paintControl(PaintEvent)} method.
584     * It draws the whole content.
585     * <br><br>
586     * Because of saving calculation time there will be drawn only a small peace on right side of the area
587     * with the new data normally. The rest inclusive grid lines, curves, text is moved to left. But if the whole
588     * window should be refreshed, the whole widget is drawn newly.
589     * 
590     */
591    @Override public void drawBackground(GC g, int xView, int yView, int dxView, int dyView) {
592      //NOTE: forces stack overflow because calling of this routine recursively: super.paint(g);
593      SwtCurveView.this.drawBackground(g, getSize(), xView, yView, dxView, dyView);
594    }    
595  }
596
597  
598  /**This class is only used to store values to inspect. The Inspector is a tool which works with
599   * reflection and with it internal variable can be visited in runtime. See {@link org.vishia.inspectorTarget.Inspector}.
600   */
601  @SuppressWarnings("unused")
602  private static class TestHelp{
603    /**Counts any redraw action for complete redraw, to see how often.  */
604    int ctRedrawAll;
605    /**Counts any redraw action for complete redraw because nrof shift>100, to see how often.  */
606    int ctRedrawAllShift;
607    
608    /**Counts any redraw action for partial redraw, to see how often.  */
609    int ctRedrawPart;
610    
611    /**Ct if redraw only because new data. */
612    int ctRedrawBecauseNewData;
613    
614    /**Coordinates while redraw. {@link CurveView#drawBackground(GC, int, int, int, int)}. */
615    int xView, yView, dxView, dyView;
616  } 
617  TestHelp testHelp = new TestHelp();
618
619  
620  final SwtGralMouseListener.MouseListenerGralAction mouseListenerCurve;
621  
622
623  void stop(){}
624
625
626  @Override
627  public boolean setFocusGThread()
628  {
629    // TODO Auto-generated method stub
630    return false;
631  }
632
633
634  @Override
635  public void setVisibleGThread(boolean bVisible)
636  {
637    // TODO Auto-generated method stub
638    
639  }
640
641
642  @Override
643  public void removeWidgetImplementation()
644  {
645    // TODO Auto-generated method stub
646    
647  }
648
649
650  @Override public Object getWidgetImplementation(){ return curveSwt; }
651
652
653  @Override
654  public void setBoundsPixel(int x, int y, int dx, int dy)
655  {
656    // TODO Auto-generated method stub
657    
658  }
659
660
661  @Override
662  public GralRectangle getPixelPositionSize()
663  {
664    // TODO Auto-generated method stub
665    return null;
666  }
667
668
669  @Override
670  public boolean remove()
671  {
672    // TODO Auto-generated method stub
673    return false;
674  }  
675  
676}