From 58f1933dcd430ac80d718df3d45eb86254b05836 Mon Sep 17 00:00:00 2001
From: Mark Watkins <jedimark@users.sourceforge.net>
Date: Thu, 25 Aug 2011 20:38:42 +1000
Subject: [PATCH] Horizontal grid overlay

---
 Graphs/gGraphView.cpp |  18 +++--
 Graphs/gGraphView.h   |   2 +-
 Graphs/gYAxis.cpp     | 163 ++++++++++++++++++++++++++++++++++++++++--
 Graphs/gYAxis.h       |  20 ++++--
 daily.cpp             |   9 +++
 5 files changed, 196 insertions(+), 16 deletions(-)

diff --git a/Graphs/gGraphView.cpp b/Graphs/gGraphView.cpp
index 0b1c6d3d..90eb46b5 100644
--- a/Graphs/gGraphView.cpp
+++ b/Graphs/gGraphView.cpp
@@ -806,11 +806,18 @@ void gGraphView::paintGL()
             glColor4f(0,0,0,1);
             //if (i<numgraphs-1) {
                 glBegin(GL_QUADS);
+                glColor4f(.5,.5,.5,1.0);
+                glVertex2f(0,py+h);
+                glVertex2f(w,py+h);
+                glColor4f(.7,.7,.7,1.0);
+                glVertex2f(w,py+h+graphSpacer/2.0);
+                glVertex2f(0,py+h+graphSpacer/2.0);
+                glColor4f(1,1,1,1.0);
+                glVertex2f(0,py+h+graphSpacer/2.0);
+                glVertex2f(w,py+h+graphSpacer/2.0);
                 glColor4f(.3,.3,.3,1.0);
-                glVertex2i(0,py+h);
-                glVertex2i(w,py+h);
-                glVertex2i(w,py+h+graphSpacer);
-                glVertex2i(0,py+h+graphSpacer);
+                glVertex2f(w,py+h+graphSpacer);
+                glVertex2f(0,py+h+graphSpacer);
                 glEnd();
             //}
         }
@@ -968,6 +975,7 @@ void gGraphView::mousePressEvent(QMouseEvent * event)
                 } else { // send event to graph..
                     m_global_point_clicked=QPoint(x,y);
                     m_point_clicked=QPoint (x-titleWidth,y-py);
+
                     m_selected_graph=m_graphs[i];
 
                     QMouseEvent e(event->type(),m_point_clicked,event->button(),event->buttons(),event->modifiers());
@@ -1033,7 +1041,7 @@ void gGraphView::mouseDoubleClickEvent(QMouseEvent * event)
 
         h=m_graphs[i]->height()*m_scaleY;
         if (py>height())
-            break; // we are done.. can't draw anymore
+            break;
 
         if ((py + h + graphSpacer) >= 0) {
             if ((y >= py) && (y <= py + h)) {
diff --git a/Graphs/gGraphView.h b/Graphs/gGraphView.h
index ae535357..730d2010 100644
--- a/Graphs/gGraphView.h
+++ b/Graphs/gGraphView.h
@@ -192,7 +192,7 @@ public:
     void setScrollBar(MyScrollBar *sb);
     MyScrollBar * scrollBar() { return m_scrollbar; }
     static const int titleWidth=30;
-    static const int graphSpacer=4;
+    static const int graphSpacer=5;
 
     float findTop(gGraph * graph);
 
diff --git a/Graphs/gYAxis.cpp b/Graphs/gYAxis.cpp
index 76a0b8cc..683675ed 100644
--- a/Graphs/gYAxis.cpp
+++ b/Graphs/gYAxis.cpp
@@ -12,16 +12,167 @@ gYSpacer::gYSpacer(int spacer) :Layer(EmptyChannel)
 {
 };
 
+gXGrid::gXGrid(QColor col)
+    :Layer(EmptyChannel)
+{
+    m_major_color=QColor(190,190,190,64);
+    m_minor_color=QColor(220,220,220,64);
+    m_show_major_lines=true;
+    m_show_minor_lines=true;
+}
+gXGrid::~gXGrid()
+{
+}
+void gXGrid::paint(gGraph & w,int left,int top, int width, int height)
+{
+    float x,y;
+
+    double miny=w.min_y;
+    double maxy=w.max_y;
+
+    if (miny<0) {
+        miny=-MAX(fabs(miny),fabs(maxy));
+    }
+    double dy=maxy-miny;
+    if (dy<=0) {
+        //miny=miny;
+        maxy++;
+        dy=1;
+    }
+
+
+    int m;
+    if (maxy>500) {
+        m=ceil(maxy/100.0);
+        maxy=m*100;
+        m=floor(miny/100.0);
+        miny=m*100;
+    } else if (maxy>150) {
+        m=ceil(maxy/50.0);
+        maxy=m*50;
+        m=floor(miny/50.0);
+        miny=m*50;
+    } else if (maxy>80) {
+        m=ceil(maxy/20.0);
+        maxy=m*20;
+        m=floor(miny/20.0);
+        miny=m*20;
+    } else if (maxy>30) {
+        m=ceil(maxy/10.0);
+        maxy=m*10;
+        m=floor(miny/10.0);
+        miny=m*10;
+    } else if (maxy>5) {
+        m=ceil(maxy/5.0);
+        maxy=m*5;
+        m=floor(miny/5.0);
+        miny=m*5;
+    }
+    if (height<0) return;
+
+    QString fd="0";
+    GetTextExtent(fd,x,y);
+
+    double max_yticks=round(height / (y+15.0)); // plus spacing between lines
+    double yt=1/max_yticks;
+
+    double mxy=MAX(fabs(maxy),fabs(miny));
+    double mny=miny;
+    if (miny<0) {
+        mny=-mxy;
+    }
+    double rxy=mxy-mny;
+    double ymult=height/rxy;
+
+    double min_ytick=rxy*yt;
+
+    float ty,h;
+
+    qint32 vertcnt=0;
+    GLshort * vertarray=(GLshort *)vertex_array[0];
+    qint32 minorvertcnt=0;
+    GLshort * minorvertarray=(GLshort *)vertex_array[1];
+    qint32 majorvertcnt=0;
+    GLshort * majorvertarray=(GLshort *)vertex_array[2];
+
+    if ((vertarray==NULL) || (minorvertarray==NULL) || (majorvertarray==NULL)) {
+        qWarning() << "gXGrid::Paint()  VertArray==NULL";
+        return;
+    }
+
+    if (min_ytick<=0) {
+        qDebug() << "min_ytick error in gXGrid::paint()";
+        return;
+    }
+    if (min_ytick>=1000000) {
+        min_ytick=100;
+    }
+
+    double q=((maxy-(miny+(min_ytick/2.0)))/min_ytick)*4;
+    if (q>=maxverts) {
+        qDebug() << "Would exeed maxverts. Should be another two bounds exceeded messages after this. (I can do a minor optimisation by disabling the other checks if this turns out to be consistent)" << q << maxverts;
+    }
+
+    for (double i=miny; i<=maxy+min_ytick-0.00001; i+=min_ytick) {
+        ty=(i - miny) * ymult;
+        h=top+height-ty;
+        if (m_show_major_lines && (i > miny)) {
+            majorvertarray[majorvertcnt++]=left;
+            majorvertarray[majorvertcnt++]=h;
+            majorvertarray[majorvertcnt++]=left+width;
+            majorvertarray[majorvertcnt++]=h;
+        }
+        double z=(min_ytick/4)*ymult;
+        double g=h;
+        for (int i=0;i<3;i++) {
+            g+=z;
+            if (g>top+height) break;
+            if (vertcnt>=maxverts) {
+                qWarning() << "vertarray bounds exceeded in gYAxis for " << w.title() << "graph" << "MinY =" <<miny << "MaxY =" << maxy << "min_ytick=" <<min_ytick;
+                break;
+            }
+            if (m_show_minor_lines) {// && (i > miny)) {
+                minorvertarray[minorvertcnt++]=left;
+                minorvertarray[minorvertcnt++]=g;
+                minorvertarray[minorvertcnt++]=left+width;
+                minorvertarray[minorvertcnt++]=g;
+            }
+        }
+        if (vertcnt>=maxverts) {
+            qWarning() << "vertarray bounds exceeded in gYAxis for " << w.title() << "graph" << "MinY =" <<miny << "MaxY =" << maxy << "min_ytick=" <<min_ytick;
+            break;
+        }
+
+
+    }
+    if (vertcnt>=maxverts) {
+        qWarning() << "gXGrid tickers and display should be corrupted, because something dumb is happening in " << w.title() << "graph";
+        return;
+    }
+
+    // Draw the lines & ticks
+    // Turn on blending??
+    glLineWidth(1);
+    glEnableClientState(GL_VERTEX_ARRAY);
+    w.qglColor(m_minor_color);
+    glVertexPointer(2, GL_SHORT, 0, minorvertarray);
+    glDrawArrays(GL_LINES, 0, minorvertcnt>>1);
+    w.qglColor(m_major_color);
+    glVertexPointer(2, GL_SHORT, 0, majorvertarray);
+    glDrawArrays(GL_LINES, 0, majorvertcnt>>1);
+    glDisableClientState(GL_VERTEX_ARRAY); // deactivate vertex arrays after drawing
+}
+
+
+
 gYAxis::gYAxis(QColor col)
 :Layer(EmptyChannel)
 {
     m_line_color=col;
     m_text_color=col;
-    m_major_color=QColor(190,190,190,64);
-    m_minor_color=QColor(220,220,220,64);
+    //m_major_color=QColor(190,190,190,64);
+    //m_minor_color=QColor(220,220,220,64);
 
-    m_show_major_lines=true;
-    m_show_minor_lines=true;
     m_yaxis_scale=1;
 }
 gYAxis::~gYAxis()
@@ -196,12 +347,12 @@ void gYAxis::paint(gGraph & w,int left,int top, int width, int height)
     glEnableClientState(GL_VERTEX_ARRAY);
     glVertexPointer(2, GL_SHORT, 0, vertarray);
     glDrawArrays(GL_LINES, 0, vertcnt>>1);
-    w.qglColor(m_minor_color);
+    /*w.qglColor(m_minor_color);
     glVertexPointer(2, GL_SHORT, 0, minorvertarray);
     glDrawArrays(GL_LINES, 0, minorvertcnt>>1);
     w.qglColor(m_major_color);
     glVertexPointer(2, GL_SHORT, 0, majorvertarray);
-    glDrawArrays(GL_LINES, 0, majorvertcnt>>1);
+    glDrawArrays(GL_LINES, 0, majorvertcnt>>1); */
     glDisableClientState(GL_VERTEX_ARRAY); // deactivate vertex arrays after drawing
 }
 
diff --git a/Graphs/gYAxis.h b/Graphs/gYAxis.h
index d3fdf4b2..1854c991 100644
--- a/Graphs/gYAxis.h
+++ b/Graphs/gYAxis.h
@@ -17,9 +17,23 @@ class gYSpacer:public Layer
 
 };
 
-/*class gYGrid:public Layer
+class gXGrid:public Layer
 {
-};*/
+public:
+    gXGrid(QColor col=QColor("black"));
+    virtual ~gXGrid();
+    virtual void paint(gGraph & w,int left,int top, int width, int height);
+
+    void setShowMinorLines(bool b) { m_show_minor_lines=b; }
+    void setShowMajorLines(bool b) { m_show_major_lines=b; }
+    bool showMinorLines() { return m_show_minor_lines; }
+    bool showMajorLines() { return m_show_major_lines; }
+protected:
+    bool m_show_major_lines;
+    bool m_show_minor_lines;
+    QColor m_major_color;
+    QColor m_minor_color;
+};
 
 class gYAxis:public Layer
 {
@@ -49,8 +63,6 @@ class gYAxis:public Layer
 
         QColor m_line_color;
         QColor m_text_color;
-        QColor m_major_color;
-        QColor m_minor_color;
 
 };
 
diff --git a/daily.cpp b/daily.cpp
index 9deaca8a..1ac9fe3f 100644
--- a/daily.cpp
+++ b/daily.cpp
@@ -93,6 +93,7 @@ Daily::Daily(QWidget *parent,QGLWidget * shared, MainWindow *mw)
     SF->AddLayer(new gFooBar(),LayerBottom,0,10);
     SF->AddLayer(new gXAxis(),LayerBottom,0,gXAxis::Margin);
 
+    PRD->AddLayer(new gXGrid());
     PRD->AddLayer(AddCPAP(new gLineChart(CPAP_Pressure,QColor("dark green"),true)));
     PRD->AddLayer(AddCPAP(new gLineChart(CPAP_EPAP,Qt::blue,true)));
     PRD->AddLayer(AddCPAP(new gLineChart(CPAP_IPAP,Qt::red,true)));
@@ -102,6 +103,7 @@ Daily::Daily(QWidget *parent,QGLWidget * shared, MainWindow *mw)
     gLineChart *l;
     l=new gLineChart(CPAP_FlowRate,Qt::black,false,false);
     AddCPAP(l);
+    FRW->AddLayer(new gXGrid());
     FRW->AddLayer(l);
     FRW->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     FRW->AddLayer(new gXAxis(),LayerBottom,0,20);
@@ -120,30 +122,37 @@ Daily::Daily(QWidget *parent,QGLWidget * shared, MainWindow *mw)
     FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Obstructive,QColor("#40c0ff"),"OA")));
     FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_ClearAirway,QColor("purple"),"CA")));
 
+    LEAK->AddLayer(new gXGrid());
     LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_Leak,Qt::darkYellow,true)));
     LEAK->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     LEAK->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    SNORE->AddLayer(new gXGrid());
     SNORE->AddLayer(AddCPAP(new gLineChart(CPAP_Snore,Qt::darkGray,true)));
     SNORE->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     SNORE->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    MP->AddLayer(new gXGrid());
     MP->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure,Qt::blue,false)));
     MP->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     MP->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    RR->AddLayer(new gXGrid());
     RR->AddLayer(AddCPAP(new gLineChart(CPAP_RespiratoryRate,Qt::darkMagenta,true)));
     RR->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     RR->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    MV->AddLayer(new gXGrid());
     MV->AddLayer(AddCPAP(new gLineChart(CPAP_MinuteVentilation,Qt::darkCyan,true)));
     MV->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     MV->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    TV->AddLayer(new gXGrid());
     TV->AddLayer(AddCPAP(new gLineChart(CPAP_TidalVolume,Qt::magenta,true)));
     TV->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     TV->AddLayer(new gXAxis(),LayerBottom,0,20);
 
+    FLG->AddLayer(new gXGrid());
     FLG->AddLayer(AddCPAP(new gLineChart(CPAP_FlowLimitGraph,Qt::darkBlue,true)));
     FLG->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
     FLG->AddLayer(new gXAxis(),LayerBottom,0,20);