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}