2222import androidx .constraintLayout .desktop .ui .timeline .graph .Oscillator ;
2323import androidx .constraintLayout .desktop .ui .ui .MeModel ;
2424import androidx .constraintLayout .desktop .ui .utils .Debug ;
25+ import java .awt .BasicStroke ;
2526import java .awt .Color ;
2627import java .awt .Graphics ;
28+ import java .awt .Graphics2D ;
29+ import java .awt .RenderingHints ;
30+ import java .awt .Stroke ;
2731import java .util .Arrays ;
2832import java .util .Comparator ;
2933import java .util .HashMap ;
@@ -36,6 +40,7 @@ public class GraphRender {
3640 private Cycle mCycle = null ;
3741 private Attribute [] mAttribute = null ;
3842 private String [] mStartEndString = new String [2 ];
43+ private static boolean mShowNewGraph = false ;
3944
4045 static String [] ourWaveTypes = {"sin" , "square" , "triangle" , "sawtooth" , "reverseSawtooth" , "cos" , "bounce" };
4146 static HashMap <String , Integer > ourWaveTypeMap = new HashMap <>();
@@ -67,6 +72,10 @@ public boolean setUp(MeModel model, TimeLineRowData row) {
6772 return false ;
6873 }
6974
75+ public void setShowNewGraph (boolean isNewGraph ) {
76+ mShowNewGraph = isNewGraph ;
77+ }
78+
7079 public String getValue (MTag kf , String keyProp ) {
7180 MTag [] tag = kf .getChildTags ();
7281 if (tag != null && tag .length > 0 ) {
@@ -120,7 +129,7 @@ public int compare(MTag t1, MTag t2) {
120129 }
121130
122131 mCycle = new Cycle ();
123- mCycle .setCycle (pos , period , amp , offset , curveType );
132+ mCycle .setCycle (pos , period , amp , offset , curveType , row );
124133 mCycle .fixRange (row .mKeyProp );
125134 return true ;
126135 }
@@ -185,13 +194,27 @@ public void draw(Graphics g, TimelineStructure mTimelineStructure, int x, int y,
185194 g .drawRect (x , y , w , h - 1 );
186195 g .setColor (MEUI .Graph .ourG_line );
187196
197+ // with the new graph design, the ticks are drawn before the actual graph.
198+ if (mShowNewGraph ) {
199+ g .setColor (MEUI .myGridColor );
200+ TimeLineRow .drawTicks (g , mTimelineStructure , h , y );
201+ }
202+
188203 if (mCycle != null ) {
189- mCycle .plot (g , gx , y , gw , h );
204+ if (mShowNewGraph ) {
205+ mCycle .plotAreaGraph (g , gx , y , gw , h );
206+ } else {
207+ mCycle .plot (g , gx , y , gw , h );
208+ }
190209 }
191210 if (mAttribute != null ) {
192211 for (int i = 0 ; i < mAttribute .length ; i ++) {
193212 Attribute attribute = mAttribute [i ];
194- attribute .plot (g , gx , y , gw , h );
213+ if (mShowNewGraph ) {
214+ attribute .plotAreaGraph (g , gx , y , gw , h );
215+ } else {
216+ attribute .plot (g , gx , y , gw , h );
217+ }
195218 }
196219 }
197220
@@ -251,9 +274,11 @@ static class Attribute {
251274 int [] yPoints = new int [2000 ];
252275 double mMin ;
253276 double mMax ;
277+ int colorIndex = 0 ;
254278
255279 public Attribute (TimeLineRowData row , String attr , double startValue , double endValue ) {
256280 mType = attr ;
281+ colorIndex = row .mKeyPropIndex ;
257282 setup (row , attr , startValue , endValue );
258283 }
259284
@@ -334,6 +359,29 @@ public void plot(Graphics g, int x, int y, int w, int h) {
334359 g .drawPolyline (xPoints , yPoints , count );
335360 }
336361 }
362+
363+ // plot the attribute with an Area Graph
364+ public void plotAreaGraph (Graphics g , int x , int y , int w , int h ) {
365+
366+ if (spline != null ) {
367+ double steps = 1.0 / w ;
368+ // add the starting point for drawing a polygon instead of a ployline
369+ xPoints [0 ] = x ;
370+ yPoints [0 ] = y + h ;
371+ int count = 1 ;
372+ for (double i = steps ; i <= 1 ; i += steps ) {
373+ double yp = spline .getPos (i , 0 );
374+ xPoints [count ] = (int )(x + i * w );
375+ yPoints [count ] = (int )(y + h - (yp - mMin ) * h / (mMax - mMin ));
376+ count ++;
377+ }
378+ // add the ending point for drawing a polygon instead of a ployline
379+ xPoints [count ] = x + w ;
380+ yPoints [count ] = yPoints [0 ];
381+ g .setColor (MEUI .graphColors [colorIndex % MEUI .graphColors .length ]);
382+ g .fillPolygon (xPoints , yPoints , count + 1 );
383+ }
384+ }
337385 }
338386
339387 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -346,11 +394,18 @@ static class Cycle {
346394 float [] yMax = new float [xpos .length ];
347395 float [] yMin = new float [xpos .length ];
348396 float mMaxY , mMinY ;
349- int [] xPoints = new int [xpos .length ];
350- int [] yPoints = new int [xpos .length ];
397+ // add two more points (in start and end) for drawing a polygon
398+ int numPoints = mShowNewGraph ? xpos .length + 2 : xpos .length ;
399+ int [] xPoints = new int [numPoints ];
400+ int [] yPoints = new int [numPoints ];
401+ int colorIndex = 0 ; // index for picking a color for the graph.
402+ String attr = "" ;
403+ // Store the waveOffest Y position.
404+ double [] offsetY = new double [xpos .length ];
405+ int [] offsetYPoints = new int [xpos .length ];
351406
352407 void setCycle (double [] pos , double [] period , double [] amplitude , double [] offset ,
353- int curveType ) {
408+ int curveType , TimeLineRowData row ) {
354409 if (pos .length == 1 ) {
355410 pos = new double []{0.0 , pos [0 ], 1.0 };
356411 period = new double []{period [0 ], period [0 ], period [0 ]};
@@ -384,13 +439,16 @@ void setCycle(double[] pos, double[] period, double[] amplitude, double[] offset
384439 mOscillator = osc ;
385440 mMaxY = -Float .MAX_VALUE ;
386441 mMinY = Float .MAX_VALUE ;
442+ colorIndex = row .mKeyPropIndex ;
443+ attr = row .mKeyProp ;
387444
388445 for (int i = 0 ; i < xpos .length ; i ++) {
389446 xpos [i ] = (float )(i / (xpos .length - 1.0f ));
390447 double amp = mMonotoneSpline .getPos (xpos [i ], 0 );
391448 double off = mMonotoneSpline .getPos (xpos [i ], 1 );
392449 try {
393450 ypos [i ] = mOscillator .getValue (xpos [i ]) * amp + off ;
451+ offsetY [i ] = off ;
394452 }
395453 catch (Exception e ) {
396454 ypos [i ] = Math .random (); // visual hint that it is broken
@@ -427,6 +485,52 @@ void plot(Graphics g, int x, int y, int w, int h) {
427485 g .drawPolyline (xPoints , yPoints , xPoints .length );
428486 }
429487
488+ void plotAreaGraph (Graphics g , int x , int y , int w , int h ) {
489+
490+ ((Graphics2D ) g )
491+ .setRenderingHint (RenderingHints .KEY_ANTIALIASING , RenderingHints .VALUE_ANTIALIAS_ON );
492+
493+ // add the starting point to draw the polygon
494+ xPoints [0 ] = x ;
495+ yPoints [0 ] = y + (int )(h - h * (0 - mMinY ) / (mMaxY - mMinY ));
496+ int count = 1 ;
497+ for (int i = 0 ; i < xpos .length ; i ++) {
498+ int xp = (int )(w * xpos [i ] + x );
499+ int yp = y + (int )(h - h * (ypos [i ] - mMinY ) / (mMaxY - mMinY ));
500+ xPoints [count ] = xp ;
501+ yPoints [count ] = yp ;
502+ count ++;
503+
504+ // points for drawing the waveOffset polyline
505+ int offsetYP = y + (int )(h - h * (offsetY [i ] - mMinY ) / (mMaxY - mMinY ));
506+ offsetYPoints [i ] = offsetYP ;
507+ }
508+ // add the ending point to draw the polygon
509+ xPoints [count ] = x + w ;
510+ yPoints [count ] = yPoints [0 ];
511+
512+ // Draw a baseline where the y position is 0
513+ g .setColor (MEUI .myGridColor );
514+ g .drawPolyline (Arrays .copyOfRange (xPoints , 1 , xPoints .length - 1 ), Arrays .copyOfRange (yPoints , 1 , yPoints .length - 1 ), count - 1 );
515+
516+ // Draw a line where the y position is 1 when the attribute is scaleX or scaleY
517+ if (attr .equals ("scaleX" ) || attr .equals ("scaleY" )) {
518+ int yTop = y + (int )(h - h * (1 - mMinY ) / (mMaxY - mMinY ));
519+ g .drawLine (x , yTop , x + w , yTop );
520+ }
521+
522+ // Draw the animation graph
523+ g .setColor (MEUI .graphColors [colorIndex % MEUI .graphColors .length ]);
524+ g .fillPolygon (xPoints , yPoints , count + 1 );
525+
526+ // Draw the waveOffset dashed line
527+ Stroke dashed = new BasicStroke (1f , BasicStroke .CAP_BUTT , BasicStroke .JOIN_BEVEL , 0f ,
528+ new float []{9 }, 0f );
529+ ((Graphics2D ) g ).setStroke (dashed );
530+ g .setColor (MEUI .ourDashedLineColor );
531+ g .drawPolyline (Arrays .copyOfRange (xPoints , 1 , xPoints .length - 1 ), offsetYPoints , count - 1 );
532+ }
533+
430534 float getComputedValue (float v ) {
431535 if (mMonotoneSpline == null ) {
432536 return 0 ;
0 commit comments