[chronojump] Encoder signal graph while capture now is managed by a Cairo scroll



commit 2055d5b9fb1afbe4695d825bc51b22b4258506e7
Author: Xavier de Blas <xaviblas gmail com>
Date:   Tue Mar 15 10:57:08 2022 +0100

    Encoder signal graph while capture now is managed by a Cairo scroll

 glade/app1.glade         |  55 +++++++++++----
 src/Makefile.am          |   1 +
 src/encoderCapture.cs    |  11 +++
 src/gui/app1/encoder.cs  |  38 ++++++++++-
 src/gui/cairo/encoder.cs | 169 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gui/cairo/xy.cs      |   9 +++
 6 files changed, 268 insertions(+), 15 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index 5c5357b8a..508d00bae 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -26252,6 +26252,9 @@ Concentric</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
@@ -32660,18 +32663,6 @@ Concentric</property>
                                                             <property name="can_focus">False</property>
                                                             <property name="spacing">6</property>
                                                             <child>
-                                                            <widget class="GtkLabel" 
id="label_video_encoder_tests_will_be_filmed">
-                                                            <property name="can_focus">False</property>
-                                                            <property name="label" translatable="yes">Tests 
will be filmed</property>
-                                                            </widget>
-                                                            <packing>
-                                                            <property name="expand">False</property>
-                                                            <property name="fill">False</property>
-                                                            <property name="pack_type">end</property>
-                                                            <property name="position">0</property>
-                                                            </packing>
-                                                            </child>
-                                                            <child>
                                                             <widget class="GtkHBox" 
id="hbox_video_encoder_capturing">
                                                             <property name="can_focus">False</property>
                                                             <property name="spacing">4</property>
@@ -32708,6 +32699,18 @@ Concentric</property>
                                                             </packing>
                                                             </child>
                                                             <child>
+                                                            <widget class="GtkLabel" 
id="label_video_encoder_tests_will_be_filmed">
+                                                            <property name="can_focus">False</property>
+                                                            <property name="label" translatable="yes">Tests 
will be filmed</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="pack_type">end</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkHBox" 
id="hbox_video_encoder_no_capturing">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -33777,6 +33780,10 @@ Concentric</property>
                                                             <property name="show_tabs">False</property>
                                                             <property name="show_border">False</property>
                                                             <child>
+                                                            <widget class="GtkVBox" id="vbox260">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <child>
                                                             <widget class="GtkDrawingArea" 
id="encoder_capture_signal_drawingarea">
                                                             <property name="height_request">100</property>
                                                             <property name="visible">True</property>
@@ -33785,6 +33792,27 @@ Concentric</property>
                                                             <signal name="expose_event" 
handler="on_encoder_capture_signal_drawingarea_expose_event" swapped="no"/>
                                                             <signal name="configure_event" 
handler="on_encoder_capture_signal_drawingarea_configure_event" swapped="no"/>
                                                             </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkDrawingArea" 
id="encoder_capture_signal_drawingarea_cairo">
+                                                            <property name="height_request">100</property>
+                                                            <property name="visible">True</property>
+                                                            <property name="sensitive">False</property>
+                                                            <property name="can_focus">False</property>
+                                                            <signal name="expose_event" 
handler="on_encoder_capture_signal_drawingarea_cairo_expose_event" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
                                                             </child>
                                                             <child>
                                                             <widget class="GtkLabel" 
id="label_encoder_capture">
@@ -42362,6 +42390,9 @@ then click this button.</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index 345129917..f09a4adc4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,6 +36,7 @@ SOURCES = \
        gui/app1/runEncoderAnalyze.cs\
        gui/app1/shortcuts.cs\
        gui/cairo/bars.cs\
+       gui/cairo/encoder.cs\
        gui/cairo/generic.cs\
        gui/cairo/jumpsDjOptimalFall.cs\
        gui/cairo/jumpsRunsEvolution.cs\
diff --git a/src/encoderCapture.cs b/src/encoderCapture.cs
index ade10d134..d7fa6ece7 100644
--- a/src/encoderCapture.cs
+++ b/src/encoderCapture.cs
@@ -37,6 +37,8 @@ public abstract class EncoderCapture
        //this is unused if showOnlyBars (configChronojump.EncoderCaptureShowOnlyBars)
        public List<Gdk.Point> EncoderCapturePoints;
        public List<Gdk.Point> EncoderCapturePointsInertialDisc;
+       public List<PointF> EncoderCapturePointsCairo;
+       public List<PointF> EncoderCapturePointsInertialDiscCairo;
        public int EncoderCapturePointsCaptured;
        public int EncoderCapturePointsPainted;
 
@@ -166,6 +168,8 @@ public abstract class EncoderCapture
                {
                        EncoderCapturePoints = new List<Gdk.Point>();
                        EncoderCapturePointsInertialDisc = new List<Gdk.Point>();
+                       EncoderCapturePointsCairo = new List<PointF>();
+                       EncoderCapturePointsInertialDiscCairo = new List<PointF>();
                        EncoderCapturePointsCaptured = 0;
                        EncoderCapturePointsPainted = 0;        //-1 means delete screen
                }
@@ -676,6 +680,8 @@ public abstract class EncoderCapture
                {
                        EncoderCapturePoints = new List<Gdk.Point>();
                        EncoderCapturePointsInertialDisc = new List<Gdk.Point>();
+                       EncoderCapturePointsCairo = new List<PointF>();
+                       EncoderCapturePointsInertialDiscCairo = new List<PointF>();
                        EncoderCapturePointsCaptured = 0;
                        EncoderCapturePointsPainted = -1;       //-1 means delete screen
                }
@@ -758,6 +764,8 @@ public abstract class EncoderCapture
                                Convert.ToInt32(widthG * i / xWidth),
                                Convert.ToInt32( (heightG/2) - ( sum * heightG / realHeightG) )
                                ));
+
+               EncoderCapturePointsCairo.Add(new PointF(i, sum));
        }
                                
        //on inertial also uses to EncoderCapturePointsInertialDisc
@@ -970,6 +978,9 @@ public class EncoderCaptureInertial : EncoderCapture
                                Convert.ToInt32(widthG * i / xWidth),
                                Convert.ToInt32( (heightG/2) - ( sumInertialDisc * heightG / realHeightG) )
                                ));
+
+               EncoderCapturePointsCairo.Add(new PointF(i, sum));
+               EncoderCapturePointsInertialDiscCairo.Add(new PointF(i, sumInertialDisc));
        }
        
        protected override void encoderCapturePointsAdaptativeDisplay()
diff --git a/src/gui/app1/encoder.cs b/src/gui/app1/encoder.cs
index 2ecdb2b8d..02fea23a3 100644
--- a/src/gui/app1/encoder.cs
+++ b/src/gui/app1/encoder.cs
@@ -342,6 +342,7 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.TreeView treeview_encoder_analyze_curves;
 
        [Widget] Gtk.DrawingArea encoder_capture_signal_drawingarea;
+       [Widget] Gtk.DrawingArea encoder_capture_signal_drawingarea_cairo;
        [Widget] Gtk.DrawingArea encoder_capture_curves_bars_drawingarea;
        Gdk.Pixmap encoder_capture_signal_pixmap = null;
        Gdk.Pixmap encoder_capture_curves_bars_pixmap = null;
@@ -449,6 +450,10 @@ public partial class ChronoJumpWindow
         *
         */
 
+       CairoGraphEncoderSignal cairoGraphEncoderSignal;
+       static List<PointF> cairoGraphEncoderSignalPoints_l;
+       static List<PointF> cairoGraphEncoderSignalInertialPoints_l;
+
        enum encoderSensEnum { 
                NOSESSION, NOPERSON, YESPERSON, PROCESSINGCAPTURE, PROCESSINGR, DONENOSIGNAL, DONEYESSIGNAL }
        encoderSensEnum encoderSensEnumStored; //tracks how was sensitive before PROCESSINGCAPTURE or 
PROCESSINGR
@@ -1021,6 +1026,10 @@ public partial class ChronoJumpWindow
 
                sensitiveGuiEventDoing(preferences.encoderCaptureInfinite);
 
+               cairoGraphEncoderSignal = null;
+               cairoGraphEncoderSignalPoints_l = new List<PointF>();
+               cairoGraphEncoderSignalInertialPoints_l = new List<PointF>();
+
                LogB.Debug("Calling encoderThreadStart for capture");
 
                //record this encoderConfiguration to SQL for next Chronojump open
@@ -5890,6 +5899,7 @@ public partial class ChronoJumpWindow
                for(int j=0, i = eCapture.EncoderCapturePointsPainted +1 ; i <= last ; i ++, j++)
                {
                        paintPoints[j] = eCapture.EncoderCapturePoints[i];
+                       cairoGraphEncoderSignalPoints_l.Add(eCapture.EncoderCapturePointsCairo[i]);
 
                        if(refreshAreaOnly) {
                                if(eCapture.EncoderCapturePoints[i].Y > maxY)
@@ -5897,7 +5907,6 @@ public partial class ChronoJumpWindow
                                if(eCapture.EncoderCapturePoints[i].Y < minY)
                                        minY = eCapture.EncoderCapturePoints[i].Y;
                        }
-
                }
 
                if(mode == UpdateEncoderPaintModes.INERTIAL) {
@@ -5916,6 +5925,9 @@ public partial class ChronoJumpWindow
                                                        minY = eCapture.EncoderCapturePointsInertialDisc[i].Y;
                                        }
                                }
+                               //only assign the points if they are different than paintPoints
+//                             if(eCapture.EncoderCapturePointsInertialDiscCairo[i] != 
eCapture.EncoderCapturePointsCairo[i]) //do not avoid this step on cairo
+                                       
cairoGraphEncoderSignalInertialPoints_l.Add(eCapture.EncoderCapturePointsInertialDiscCairo[i]);
                        }
                        encoder_capture_signal_pixmap.DrawPoints(pen_gray_encoder_signal, 
paintPointsInertial);
                }
@@ -6147,6 +6159,21 @@ public partial class ChronoJumpWindow
                encoder_capture_signal_allocationXOld = allocation.Width;
        }
 
+       public void on_encoder_capture_signal_drawingarea_cairo_expose_event (object o, ExposeEventArgs args)
+       {
+               updateEncoderCaptureSignalCairo (current_mode == Constants.Modes.POWERINERTIAL, true);
+       }
+       private void updateEncoderCaptureSignalCairo (bool inertial, bool forceRedraw)
+       {
+               if(cairoGraphEncoderSignal == null)
+                       cairoGraphEncoderSignal = new CairoGraphEncoderSignal (
+                               encoder_capture_signal_drawingarea_cairo, "title");
+
+               cairoGraphEncoderSignal.DoSendingList (preferences.fontType.ToString(), inertial,
+                               cairoGraphEncoderSignalPoints_l, cairoGraphEncoderSignalInertialPoints_l,
+                               forceRedraw, CairoXY.PlotTypes.LINES);
+       }
+
        private double sendMaxPowerSpeedForceIntersession(Constants.EncoderVariablesCapture evc)
        {
                if(evc == Constants.EncoderVariablesCapture.MeanPower)
@@ -6536,6 +6563,8 @@ public partial class ChronoJumpWindow
                if(eraseSignal && encoder_capture_signal_pixmap != null)
                        UtilGtk.ErasePaint(encoder_capture_signal_drawingarea, encoder_capture_signal_pixmap);
 
+               //TODO maybe delete cairo signal here
+
                layout_encoder_capture_signal = new Pango.Layout 
(encoder_capture_signal_drawingarea.PangoContext);
                layout_encoder_capture_signal.FontDescription = Pango.FontDescription.FromString 
(preferences.GetFontTypeWithSize(10));
 
@@ -6850,10 +6879,13 @@ public partial class ChronoJumpWindow
                        //capturingSendCurveToR(); //unused, done while capturing
                        readingCurveFromR();
 
-                       if(encoderConfigurationCurrent.has_inertia)
+                       if(encoderConfigurationCurrent.has_inertia) {
                                updateEncoderCaptureGraphPaint(UpdateEncoderPaintModes.INERTIAL);
-                       else
+                               updateEncoderCaptureSignalCairo (true, false); //inertial, forceRedraw
+                       } else {
                                updateEncoderCaptureGraphPaint(UpdateEncoderPaintModes.GRAVITATORY);
+                               updateEncoderCaptureSignalCairo (false, false);
+                       }
 
                        if(needToRefreshTreeviewCapture) 
                        {
diff --git a/src/gui/cairo/encoder.cs b/src/gui/cairo/encoder.cs
new file mode 100644
index 000000000..93fb586ba
--- /dev/null
+++ b/src/gui/cairo/encoder.cs
@@ -0,0 +1,169 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2022   Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using System.Collections.Generic; //List
+using Gtk;
+using Cairo;
+
+
+public class CairoGraphEncoderSignal : CairoXY
+{
+       //TODO: check if this two are doing anything
+       private int points_list_painted;
+       private int points_list_inertial_painted;
+       //private bool doing;
+
+       //regular constructor
+       public CairoGraphEncoderSignal (DrawingArea area, string title)
+       {
+               this.area = area;
+               this.title = title;
+               this.colorBackground = colorFromGdk(Config.ColorBackground); //but note if we are using 
system colors, this will not match
+               
+               //doing = false;
+               points_list_painted = 0;
+               points_list_inertial_painted = 0;
+       }
+
+       //TODO: remove most of the null comparisons, see if we can do at start and delete graph or whatever, 
but not continue all the time making comparisons
+       public override void DoSendingList (string font, bool isInertial,
+                       List<PointF> points_list, List<PointF> points_list_inertial,
+                       bool forceRedraw, PlotTypes plotType)
+       {
+//             if(doing)
+//                     return;
+
+               //doing = true;
+               bool initGraphDone = false;
+               bool maxValuesChanged = false;
+
+               if(points_list != null)
+               {
+                       maxValuesChanged = findPointMaximums(false, points_list);
+                       if(isInertial && points_list_inertial != null)
+                       {
+                               bool maxValuesChangedInertial = findPointMaximums(false, 
points_list_inertial);
+                               if(! maxValuesChanged && maxValuesChangedInertial)
+                                       maxValuesChanged = true;
+                       }
+
+                       //show a vertical window of 100 mm (on inertial -+100 mm)
+                       //LogB.Information(string.Format("minY: {0}, maxY: {1}", minY, maxY));
+                       if(maxY < 100)
+                               maxY = 100; //to be able to graph at start when all the points are 0
+                       if(isInertial && minY > -100)
+                               minY = -100;
+               }
+
+               if( maxValuesChanged || forceRedraw ||
+                               (points_list != null && points_list.Count != points_list_painted) ||
+                               (points_list_inertial != null && points_list_inertial.Count != 
points_list_inertial_painted)
+                               )
+               {
+                       initGraph( font, 1, (maxValuesChanged || forceRedraw) );
+                       initGraphDone = true;
+                       points_list_painted = 0;
+                       points_list_inertial_painted = 0;
+               }
+
+               //do not draw axis at the moment (and it is not in 0Y right now)
+               //if(maxValuesChanged || forceRedraw)
+               //      paintAxis();
+
+               if( points_list == null || points_list.Count == 0 ||
+                               (isInertial && (points_list_inertial == null || points_list_inertial.Count == 
0)) )
+                       return;
+
+               g.LineWidth = 1;
+               pointsRadius = 1;
+
+               //display this milliseconds on screen, when is higher, scroll
+               int msWidth = 10000;
+               if(absoluteMaxX < msWidth)
+                       absoluteMaxX = msWidth;
+
+               int startAt = 0;
+               if(points_list.Count - msWidth > 0)
+               {
+                       startAt = points_list.Count - msWidth;
+                       minX = points_list[startAt].X;
+               }
+
+               if(maxValuesChanged || forceRedraw || points_list.Count != points_list_painted)
+               {
+                       //on inertial draw person on 3 px, disk on 1
+                       if(isInertial)
+                               g.LineWidth = 2;
+
+                       plotRealPoints(plotType, points_list, startAt);
+                       points_list_painted = points_list.Count;
+               }
+
+               if( isInertial &&
+                               (maxValuesChanged || forceRedraw || points_list_inertial.Count != 
points_list_inertial_painted) )
+               {
+                       g.LineWidth = 1;
+                       plotRealPoints(plotType, points_list_inertial, startAt);
+                       points_list_inertial_painted = points_list_inertial.Count;
+               }
+
+               if(initGraphDone)
+                       endGraphDisposing(g, surface, area.GdkWindow);
+
+               //doing = false;
+       }
+
+       //based on XY findPointMaximums
+       private bool findPointMaximums (List<PointF> points_list)
+       {
+               bool changedY = false;
+               for(int i = 0; i < points_list.Count; i ++)
+               {
+                       PointF p = points_list[i];
+
+                       if(p.X < minX)
+                               minX = p.X;
+                       if(p.X > maxX)
+                               maxX = p.X;
+                       if(p.Y < minY)
+                       {
+                               minY = p.Y;
+                               changedY = true;
+                       }
+                       if(p.Y > maxY)
+                       {
+                               maxY = p.Y;
+                               changedY = true;
+                       }
+               }
+
+               //if there is only one point, or by any reason mins == maxs, have mins and maxs separated
+               separateMinXMaxXIfNeeded();
+               separateMinYMaxYIfNeeded();
+
+               return changedY;
+       }
+
+       protected override void writeTitle()
+       {
+       }
+}
+
diff --git a/src/gui/cairo/xy.cs b/src/gui/cairo/xy.cs
index 441d4c00f..eb44bb301 100644
--- a/src/gui/cairo/xy.cs
+++ b/src/gui/cairo/xy.cs
@@ -110,6 +110,15 @@ public abstract class CairoXY : CairoGeneric
        public virtual void Do(string font)
        {
        }
+
+       //encoderSignal (with inertial stuff & ! triggers at the moment)
+       public virtual void DoSendingList(string font, bool isInertial,
+                       List<PointF> points_list, List<PointF> points_list_inertial,
+                       bool forceRedraw, PlotTypes plotType)
+       {
+       }
+
+       //raceAnalyzer XY graphs (triggers)
        public virtual void DoSendingList(string font, List<PointF> points_list, TriggerList triggerList, 
bool forceRedraw, PlotTypes plotType)
        {
        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]