2011-05-26 13:59:21 +00:00
/*
gGraph Graphing System Implementation
Author : Mark Watkins < jedimark64 @ users . sourceforge . net >
2011-06-17 09:19:58 +00:00
License : GPL
2011-05-26 13:59:21 +00:00
*/
2011-06-15 00:28:39 +00:00
# include "freetype-gl/font-manager.h"
# include "freetype-gl/texture-font.h"
2011-06-13 22:58:10 +00:00
2011-06-15 00:28:39 +00:00
# include "graph.h"
2011-06-14 04:41:38 +00:00
2011-06-14 09:51:05 +00:00
//#include <wx/glcanvas.h>
2011-06-14 04:41:38 +00:00
# include <wx/settings.h>
# include <wx/graphics.h>
2011-06-13 19:37:25 +00:00
# include <wx/image.h>
2011-06-15 00:28:39 +00:00
# include <wx/bitmap.h>
# include <wx/dcbuffer.h>
2011-06-16 21:21:52 +00:00
# include <wx/msgdlg.h>
2011-05-26 13:59:21 +00:00
# include <wx/log.h>
2011-06-10 11:21:20 +00:00
# include <math.h>
2011-06-12 03:47:10 +00:00
2011-05-30 11:59:20 +00:00
# include "sleeplib/profiles.h"
2011-06-13 19:37:25 +00:00
2011-06-17 15:59:04 +00:00
# include "graphs/freesans.h" // Remember to compress this..
2011-06-15 00:28:39 +00:00
//#include <wx/dcbuffer.h>
2011-05-26 13:59:21 +00:00
2011-06-11 10:20:44 +00:00
# if !wxUSE_GLCANVAS
# error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the wx library"
# endif
2011-06-16 08:18:48 +00:00
//#define EXTRA_ASSERTS
2011-06-15 00:28:39 +00:00
extern pBuffer * buffer ;
2011-06-11 10:20:44 +00:00
2011-05-26 13:59:21 +00:00
# if !wxCHECK_VERSION(2,9,0)
2011-05-29 03:27:42 +00:00
wxColor zwxYELLOW = wxColor ( 0xb0 , 0xb0 , 0x40 , 0xff ) ;
2011-05-26 13:59:21 +00:00
wxColor * wxYELLOW = & zwxYELLOW ;
# endif
2011-05-29 03:27:42 +00:00
wxColor zwxAQUA = wxColor ( 0x00 , 0xaf , 0xbf , 0xff ) ;
2011-05-26 13:59:21 +00:00
wxColor * wxAQUA = & zwxAQUA ;
2011-06-11 10:20:44 +00:00
2011-05-26 13:59:21 +00:00
wxColor zwxPURPLE = wxColor ( 0xff , 0x40 , 0xff , 0xff ) ;
wxColor * wxPURPLE = & zwxPURPLE ;
2011-06-11 10:20:44 +00:00
2011-06-15 15:43:33 +00:00
wxColor zwxGREEN2 = wxColor ( 0x80 , 0xff , 0x80 , 0x5f ) ;
2011-05-26 13:59:21 +00:00
wxColor * wxGREEN2 = & zwxGREEN2 ;
2011-06-11 10:20:44 +00:00
2011-05-28 03:27:07 +00:00
wxColor zwxLIGHT_YELLOW ( 228 , 228 , 168 , 255 ) ;
2011-05-26 13:59:21 +00:00
wxColor * wxLIGHT_YELLOW = & zwxLIGHT_YELLOW ;
wxColor zwxDARK_GREEN = wxColor ( 20 , 128 , 20 , 255 ) ;
wxColor * wxDARK_GREEN = & zwxDARK_GREEN ;
2011-06-11 10:20:44 +00:00
2011-05-31 04:50:06 +00:00
wxColor zwxDARK_GREY ( 0xA0 , 0xA0 , 0xA0 , 0xA0 ) ;
wxColor * wxDARK_GREY = & zwxDARK_GREY ;
2011-05-26 13:59:21 +00:00
2011-06-09 02:47:03 +00:00
2011-06-13 19:37:25 +00:00
FontManager * font_manager ;
2011-06-16 10:53:56 +00:00
TextureFont * bigfont = NULL , * zfont = NULL ;
2011-06-13 19:37:25 +00:00
VertexBuffer * vbuffer = NULL ;
TextMarkup * markup = NULL ;
2011-06-12 07:25:50 +00:00
2011-06-17 00:28:46 +00:00
static bool gfont_init = false ;
2011-06-09 02:47:03 +00:00
// Must be called from a thread inside the application.
void GraphInit ( )
{
2011-06-16 10:53:56 +00:00
# if defined(__WXMSW__)
2011-06-15 11:44:02 +00:00
static bool glewinit_called = false ;
2011-06-16 10:53:56 +00:00
if ( ! glewinit_called ) {
glewInit ( ) ; // Dont forget this nasty little sucker.. :)
glewinit_called = true ;
}
# endif
2011-06-09 02:47:03 +00:00
if ( ! gfont_init ) {
2011-06-16 08:18:48 +00:00
wxString glvendor = wxString ( ( char * ) glGetString ( GL_VENDOR ) , wxConvUTF8 ) ;
wxString glrenderer = wxString ( ( char * ) glGetString ( GL_RENDERER ) , wxConvUTF8 ) ;
wxString glversion = wxString ( ( char * ) glGetString ( GL_VERSION ) , wxConvUTF8 ) ;
wxLogDebug ( wxT ( " GLInfo: " ) + glvendor + wxT ( " " ) + glrenderer + wxT ( " " ) + glversion ) ;
2011-06-16 10:53:56 +00:00
// Despite the stupid warning, this does NOT always evaluate as true. Too lazy to put it in #ifdefs
2011-06-16 21:21:52 +00:00
/*if (!glGenBuffers) {
wxMessageBox ( wxT ( " Sorry, your computers graphics card drivers are too old to run this program. \n " ) + glvendor + wxT ( " may have an update. \n " ) + glrenderer + wxT ( " \n " ) + glversion , _ ( " Welcome to... " ) , wxOK , NULL ) ;
exit ( - 1 ) ;
} */
2011-06-16 08:18:48 +00:00
2011-06-13 19:37:25 +00:00
font_manager = new FontManager ( ) ;
2011-06-16 21:21:52 +00:00
//vbuffer=new VertexBuffer((char *)"v3i:t2f:c4f");
2011-06-15 11:44:02 +00:00
zfont = font_manager - > GetFromFilename ( pref . Get ( " {home}{sep}FreeSans.ttf " ) , 12 ) ;
2011-06-16 10:53:56 +00:00
bigfont = font_manager - > GetFromFilename ( pref . Get ( " {home}{sep}FreeSans.ttf " ) , 32 ) ;
2011-06-13 19:37:25 +00:00
markup = new TextMarkup ( ) ;
glBindTexture ( GL_TEXTURE_2D , font_manager - > m_atlas - > m_texid ) ;
2011-06-12 03:15:05 +00:00
wxString fontfile = pref . Get ( " {home}{sep}FreeSans.ttf " ) ;
if ( ! wxFileExists ( fontfile ) ) {
wxFFile f ;
f . Open ( fontfile , wxT ( " wb " ) ) ;
2011-06-17 09:59:10 +00:00
if ( ! f . Write ( FreeSans_ttf , FreeSans_length ) ) {
2011-06-12 03:15:05 +00:00
wxLogError ( wxT ( " Couldn't Write Font file.. Sorry.. need it to run " ) ) ;
return ;
}
f . Close ( ) ;
}
2011-06-09 02:47:03 +00:00
gfont_init = true ;
}
}
void GraphDone ( )
{
if ( gfont_init ) {
2011-06-13 19:37:25 +00:00
delete font_manager ;
2011-06-16 21:21:52 +00:00
// delete vbuffer;
2011-06-13 19:37:25 +00:00
delete markup ;
2011-06-09 02:47:03 +00:00
gfont_init = false ;
}
2011-06-12 07:25:50 +00:00
if ( shared_context ) {
delete shared_context ;
shared_context = NULL ;
}
2011-06-15 11:44:02 +00:00
if ( pbuffer ) {
delete pbuffer ;
pbuffer = NULL ;
}
2011-06-09 02:47:03 +00:00
}
2011-06-13 19:37:25 +00:00
void GetTextExtent ( wxString text , float & width , float & height , TextureFont * font = zfont )
2011-06-11 18:11:14 +00:00
{
2011-06-13 19:37:25 +00:00
TextureGlyph * glyph ;
height = width = 0 ;
2011-06-15 00:28:39 +00:00
for ( unsigned i = 0 ; i < text . Length ( ) ; i + + ) {
2011-06-13 19:37:25 +00:00
glyph = font - > GetGlyph ( ( wchar_t ) text [ i ] ) ;
if ( ! height ) height = glyph - > m_height ; // > height) height=glyph->m_height;
width + = glyph - > m_advance_x ;
}
2011-06-11 18:11:14 +00:00
}
2011-06-16 10:53:56 +00:00
void DrawText2 ( wxString text , float x , float y , TextureFont * font = zfont ) // The actual raw font drawing routine..
2011-06-13 19:37:25 +00:00
{
Pen pen ;
pen . x = x ;
pen . y = y ;
TextureGlyph * glyph ;
glyph = font - > GetGlyph ( ( wchar_t ) text [ 0 ] ) ;
if ( ! glyph ) return ;
2011-06-16 21:21:52 +00:00
//assert(vbuffer!=NULL);
//vbuffer->Clear();
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glEnable ( GL_TEXTURE_2D ) ;
glColor4f ( 0 , 0 , 0 , 1 ) ;
2011-06-13 19:37:25 +00:00
2011-06-16 21:21:52 +00:00
glyph - > Render ( markup , & pen ) ;
// glyph->AddToVertexBuffer(vbuffer, markup, &pen);
2011-06-15 00:28:39 +00:00
for ( unsigned j = 1 ; j < text . Length ( ) ; + + j ) {
2011-06-13 19:37:25 +00:00
glyph = font - > GetGlyph ( text [ j ] ) ;
pen . x + = glyph - > GetKerning ( text [ j - 1 ] ) ;
2011-06-16 21:21:52 +00:00
glyph - > Render ( markup , & pen ) ;
// glyph->AddToVertexBuffer(vbuffer, markup, &pen);
2011-06-13 19:37:25 +00:00
}
//glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
2011-06-16 21:21:52 +00:00
//vbuffer->Render(GL_TRIANGLES, (char *)"vtc" );
2011-06-15 15:43:33 +00:00
glDisable ( GL_TEXTURE_2D ) ;
2011-06-13 19:37:25 +00:00
glDisable ( GL_BLEND ) ;
2011-06-11 18:11:14 +00:00
2011-06-13 19:37:25 +00:00
}
void DrawText ( wxString text , float x , float y , float angle = 0 , const wxColor & color = * wxBLACK , TextureFont * font = zfont )
2011-06-11 18:11:14 +00:00
{
2011-06-12 05:43:49 +00:00
if ( ! font ) {
wxLogError ( wxT ( " Font Problem. Forgot to call GraphInit() ? " ) ) ;
abort ( ) ;
return ;
}
2011-06-11 18:11:14 +00:00
if ( angle = = 0 ) {
2011-06-14 04:41:38 +00:00
DrawText2 ( text , x , y , font ) ;
2011-06-11 18:11:14 +00:00
return ;
}
float w , h ;
2011-06-12 05:43:49 +00:00
GetTextExtent ( text , w , h , font ) ;
2011-06-13 19:37:25 +00:00
//glColor4ub(color.Red(),color.Green(),color.Blue(),color.Alpha());
2011-06-12 05:58:21 +00:00
2011-06-12 07:12:44 +00:00
glPushMatrix ( ) ;
2011-06-15 11:44:02 +00:00
glTranslatef ( floor ( x ) , floor ( y ) , 0 ) ;
2011-06-12 07:12:44 +00:00
glRotatef ( angle , 0.0f , 0.0f , 1.0f ) ;
2011-06-15 11:44:02 +00:00
DrawText2 ( text , floor ( - w / 2.0 ) , floor ( - h / 2.0 ) , font ) ;
glTranslatef ( floor ( - x ) , floor ( - y ) , 0 ) ;
2011-06-11 18:11:14 +00:00
glPopMatrix ( ) ;
}
2011-06-13 19:37:25 +00:00
void RoundedRectangle ( int x , int y , int w , int h , int radius , const wxColor & color )
{
2011-06-15 15:43:33 +00:00
//glDisable(GL_TEXTURE_2D);
2011-06-16 21:21:52 +00:00
2011-06-13 19:37:25 +00:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glColor4ub ( color . Red ( ) , color . Green ( ) , color . Blue ( ) , color . Alpha ( ) ) ;
glBegin ( GL_POLYGON ) ;
glVertex2i ( x + radius , y ) ;
glVertex2i ( x + w - radius , y ) ;
for ( float i = ( float ) M_PI * 1.5f ; i < M_PI * 2 ; i + = 0.1f )
glVertex2f ( x + w - radius + cos ( i ) * radius , y + radius + sin ( i ) * radius ) ;
glVertex2i ( x + w , y + radius ) ;
glVertex2i ( x + w , y + h - radius ) ;
for ( float i = 0 ; i < ( float ) M_PI * 0.5f ; i + = 0.1f )
glVertex2f ( x + w - radius + cos ( i ) * radius , y + h - radius + sin ( i ) * radius ) ;
glVertex2i ( x + w - radius , y + h ) ;
glVertex2i ( x + radius , y + h ) ;
for ( float i = ( float ) M_PI * 0.5f ; i < M_PI ; i + = 0.1f )
glVertex2f ( x + radius + cos ( i ) * radius , y + h - radius + sin ( i ) * radius ) ;
glVertex2i ( x , y + h - radius ) ;
glVertex2i ( x , y + radius ) ;
for ( float i = ( float ) M_PI ; i < M_PI * 1.5f ; i + = 0.1f )
glVertex2f ( x + radius + cos ( i ) * radius , y + radius + sin ( i ) * radius ) ;
glEnd ( ) ;
2011-06-15 15:43:33 +00:00
// glEnable(GL_TEXTURE_2D);
2011-06-13 19:37:25 +00:00
glDisable ( GL_BLEND ) ;
}
void LinedRoundedRectangle ( int x , int y , int w , int h , int radius , int lw , wxColor & color )
{
glDisable ( GL_TEXTURE_2D ) ;
glShadeModel ( GL_SMOOTH ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glColor4ub ( color . Red ( ) , color . Green ( ) , color . Blue ( ) , color . Alpha ( ) ) ;
glLineWidth ( ( GLfloat ) lw ) ;
glBegin ( GL_LINE_STRIP ) ;
for ( float i = ( float ) M_PI ; i < = 1.5f * M_PI ; i + = 0.1f )
glVertex2f ( radius * cos ( i ) + x + radius , radius * sin ( i ) + y + radius ) ;
for ( float i = 1.5f * ( float ) M_PI ; i < = 2 * M_PI ; i + = 0.1f )
glVertex2f ( radius * cos ( i ) + x + w - radius , radius * sin ( i ) + y + radius ) ;
for ( float i = 0 ; i < = 0.5f * M_PI ; i + = 0.1f )
glVertex2f ( radius * cos ( i ) + x + w - radius , radius * sin ( i ) + y + h - radius ) ;
for ( float i = 0.5f * ( float ) M_PI ; i < = M_PI ; i + = 0.1f )
glVertex2f ( radius * cos ( i ) + x + radius , radius * sin ( i ) + y + h - radius ) ;
glVertex2i ( x , y + radius ) ;
glEnd ( ) ;
glEnable ( GL_TEXTURE_2D ) ;
glDisable ( GL_BLEND ) ;
}
2011-06-11 18:11:14 +00:00
2011-05-26 13:59:21 +00:00
const wxColor * gradient_start_color = wxWHITE , * gradient_end_color = wxLIGHT_YELLOW ;
wxDirection gradient_direction = wxEAST ;
const wxColor * selection_color = wxBLUE ; //GREEN2;
gGraphData : : gGraphData ( int mp , gDataType t )
: vc ( 0 ) , type ( t ) , max_points ( mp )
{
m_ready = false ;
2011-06-02 16:31:36 +00:00
force_min_y = force_max_y = 0 ;
2011-05-26 13:59:21 +00:00
}
gGraphData : : ~ gGraphData ( )
{
}
void gGraphData : : Update ( Day * day )
{
Reload ( day ) ;
2011-06-03 07:06:18 +00:00
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator i = notify_layers . begin ( ) ; i ! = notify_layers . end ( ) ; i + + ) {
2011-06-03 07:06:18 +00:00
gGraphData * g = this ;
if ( ! day ) g = NULL ;
( * i ) - > DataChanged ( g ) ;
2011-05-26 13:59:21 +00:00
}
}
gPointData : : gPointData ( int mp )
: gGraphData ( mp , gDT_Point )
{
}
gPointData : : ~ gPointData ( )
{
2011-06-10 15:37:19 +00:00
for ( vector < wxPoint2DDouble * > : : iterator i = point . begin ( ) ; i ! = point . end ( ) ; i + + )
2011-05-26 13:59:21 +00:00
delete [ ] ( * i ) ;
}
void gPointData : : AddSegment ( int max_points )
{
maxsize . push_back ( max_points ) ;
np . push_back ( 0 ) ;
2011-06-10 15:37:19 +00:00
wxPoint2DDouble * p = new wxPoint2DDouble [ max_points ] ;
2011-05-26 13:59:21 +00:00
point . push_back ( p ) ;
}
gPoint3DData : : gPoint3DData ( int mp )
: gGraphData ( mp , gDT_Point3D )
{
}
gPoint3DData : : ~ gPoint3DData ( )
{
2011-06-02 04:42:37 +00:00
for ( vector < Point3D * > : : iterator i = point . begin ( ) ; i ! = point . end ( ) ; i + + )
2011-05-26 13:59:21 +00:00
delete [ ] ( * i ) ;
}
void gPoint3DData : : AddSegment ( int mp )
{
maxsize . push_back ( mp ) ;
np . push_back ( 0 ) ;
Point3D * p = new Point3D [ mp ] ;
point . push_back ( p ) ;
}
gLayer : : gLayer ( gPointData * d , wxString title )
: m_title ( title ) , data ( d )
{
if ( data ) {
data - > AddLayer ( this ) ;
}
m_visible = true ;
m_movable = false ;
2011-06-11 11:03:44 +00:00
color . push_back ( * wxRED ) ;
color . push_back ( * wxGREEN ) ;
2011-05-26 13:59:21 +00:00
}
gLayer : : ~ gLayer ( )
{
}
2011-06-13 19:37:25 +00:00
void gLayer : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-26 13:59:21 +00:00
{
}
2011-06-11 10:20:44 +00:00
IMPLEMENT_DYNAMIC_CLASS ( gGraphWindow , wxGLCanvas )
2011-05-26 13:59:21 +00:00
BEGIN_EVENT_TABLE ( gGraphWindow , wxWindow )
EVT_PAINT ( gGraphWindow : : OnPaint )
EVT_SIZE ( gGraphWindow : : OnSize )
EVT_MOTION ( gGraphWindow : : OnMouseMove )
EVT_LEFT_DOWN ( gGraphWindow : : OnMouseLeftDown )
2011-06-09 10:25:26 +00:00
EVT_LEFT_DCLICK ( gGraphWindow : : OnMouseLeftDClick )
2011-05-26 13:59:21 +00:00
EVT_LEFT_UP ( gGraphWindow : : OnMouseLeftRelease )
EVT_RIGHT_DOWN ( gGraphWindow : : OnMouseRightDown )
2011-06-15 15:43:33 +00:00
EVT_RIGHT_DCLICK ( gGraphWindow : : OnMouseRightDClick )
2011-05-26 13:59:21 +00:00
EVT_RIGHT_UP ( gGraphWindow : : OnMouseRightRelease )
//EVT_MOUSEWHEEL (gGraphWindow::OnMouseWheel )
//EVT_MIDDLE_DOWN (gGraphWindow::OnMouseRightDown)
//EVT_MIDDLE_UP (gGraphWindow::OnMouShowPopupMenu)
END_EVENT_TABLE ( )
2011-06-11 10:20:44 +00:00
//wxGLCanvas (wxWindow *parent, wxWindowID id=wxID_ANY, const int *attribList=NULL, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0, const wxString &name="GLCanvas", const wxPalette &palette=wxNullPalette)
static int wx_gl_attribs [ ] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER , WX_GL_DEPTH_SIZE , 24 , 0 } ;
gGraphWindow : : gGraphWindow ( )
2011-06-14 09:51:05 +00:00
: wxGLCanvas ( ( wxWindow * ) NULL , shared_context , wxID_ANY ) //,wxDefaultPosition,wxDefaultSize,wxT("GLContext"),(int *)wx_gl_attribs,wxNullPalette)
2011-06-11 10:20:44 +00:00
{
}
2011-06-12 07:12:44 +00:00
2011-05-31 04:28:11 +00:00
gGraphWindow : : gGraphWindow ( wxWindow * parent , wxWindowID id , const wxString & title , const wxPoint & pos , const wxSize & size , long flags )
2011-06-12 07:12:44 +00:00
: wxGLCanvas ( parent , shared_context , id , pos , size , flags , title , ( int * ) wx_gl_attribs , wxNullPalette )
2011-05-31 04:28:11 +00:00
{
m_scrX = m_scrY = 64 ;
m_title = title ;
m_mouseRDown = m_mouseLDown = false ;
2011-06-17 00:28:46 +00:00
//SetBackgroundColour( *wxWHITE );
2011-05-31 04:28:11 +00:00
m_bgColour = * wxWHITE ;
m_fgColour = * wxBLACK ;
2011-06-09 10:25:26 +00:00
SetMargins ( 5 , 15 , 0 , 0 ) ;
2011-06-16 21:21:52 +00:00
//m_block_move=false;
2011-05-31 04:28:11 +00:00
m_block_zoom = false ;
2011-06-08 13:54:27 +00:00
m_drag_foobar = false ;
2011-06-08 14:35:56 +00:00
m_foobar_pos = 0 ;
2011-06-08 16:20:03 +00:00
m_foobar_moved = 0 ;
2011-06-15 07:33:39 +00:00
lastlayer = NULL ;
ti = wxDateTime : : Now ( ) ;
2011-06-09 02:47:03 +00:00
gtitle = foobar = xaxis = yaxis = NULL ;
2011-06-12 07:12:44 +00:00
if ( ! shared_context ) {
2011-06-13 19:37:25 +00:00
# if defined(__DARWIN__) && !wxCHECK_VERSION(2,9,0)
2011-06-12 07:12:44 +00:00
// Screw you apple..
int * attribList = ( int * ) NULL ;
AGLPixelFormat aglpf = aglChoosePixelFormat ( NULL , 0 , attribList ) ;
shared_context = new wxGLContext ( aglpf , this , wxNullPalette , NULL ) ;
2011-06-15 02:50:17 +00:00
2011-06-12 07:12:44 +00:00
// Mmmmm.. Platform incosistency with wx..
2011-06-12 03:47:10 +00:00
# else
2011-06-13 19:37:25 +00:00
// Darwin joins the rest of the platforms as of wx2.9
2011-06-12 07:12:44 +00:00
shared_context = new wxGLContext ( this , NULL ) ;
2011-06-12 03:47:10 +00:00
# endif
2011-06-11 10:20:44 +00:00
2011-06-12 07:12:44 +00:00
}
2011-06-15 05:41:02 +00:00
# if defined(__WXMSW__)
shared_context - > SetCurrent ( * this ) ; // Windows needs this done now or it borks..
2011-06-15 02:50:17 +00:00
# endif
# if !defined(__WXMAC__) && defined (__UNIX__)
2011-06-15 05:41:02 +00:00
real_shared_context = glXGetCurrentContext ( ) ; // Unix likes this, but can't really have it..
2011-06-15 02:50:17 +00:00
# endif
2011-06-12 07:12:44 +00:00
GraphInit ( ) ; // Font
2011-06-13 19:37:25 +00:00
//texfont=::texfont;
if ( ! title . IsEmpty ( ) ) {
AddLayer ( new gGraphTitle ( title , wxVERTICAL ) ) ;
}
2011-06-17 00:28:46 +00:00
//SetBackgroundStyle(wxBG_STYLE_CUSTOM);
2011-06-09 02:47:03 +00:00
2011-05-31 04:28:11 +00:00
}
gGraphWindow : : ~ gGraphWindow ( )
{
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) delete ( * l ) ;
2011-05-31 04:28:11 +00:00
layers . clear ( ) ;
2011-06-11 10:20:44 +00:00
2011-05-31 04:28:11 +00:00
}
2011-05-26 13:59:21 +00:00
void gGraphWindow : : AddLayer ( gLayer * l ) {
if ( l ) {
2011-06-09 02:47:03 +00:00
if ( dynamic_cast < gXAxis * > ( l ) ) {
if ( xaxis ) {
wxLogError ( wxT ( " Can only have one gXAxis per graph " ) ) ;
return ;
}
if ( m_marginBottom < gXAxis : : Margin ) m_marginBottom + = gXAxis : : Margin ;
xaxis = l ;
}
if ( dynamic_cast < gFooBar * > ( l ) ) {
if ( foobar ) {
wxLogError ( wxT ( " Can only have one gFooBar per graph " ) ) ;
return ;
}
if ( m_marginBottom < gFooBar : : Margin ) m_marginBottom + = gFooBar : : Margin ;
foobar = l ;
}
if ( dynamic_cast < gYAxis * > ( l ) ) {
if ( yaxis ) {
wxLogError ( wxT ( " Can only have one gYAxis per graph " ) ) ;
return ;
}
if ( m_marginLeft < gYAxis : : Margin ) m_marginLeft + = gYAxis : : Margin ;
yaxis = l ;
}
if ( dynamic_cast < gGraphTitle * > ( l ) ) {
if ( gtitle ) {
wxLogError ( wxT ( " Can only have one gGraphTitle per graph " ) ) ;
return ;
}
if ( m_marginLeft < gGraphTitle : : Margin ) m_marginLeft + = gGraphTitle : : Margin ;
gtitle = l ;
}
2011-05-26 13:59:21 +00:00
l - > NotifyGraphWindow ( this ) ;
layers . push_back ( l ) ;
}
} ;
// Sets a new Min & Max X clipping, refreshing the graph and all it's layers.
void gGraphWindow : : SetXBounds ( double minx , double maxx )
{
//min_x=minx;
//max_x=maxx;
SetMinX ( minx ) ;
SetMaxX ( maxx ) ;
Refresh ( false ) ;
}
2011-05-29 05:58:00 +00:00
void gGraphWindow : : ResetXBounds ( )
{
//min_x=minx;
//max_x=maxx;
SetMinX ( RealMinX ( ) ) ;
SetMaxX ( RealMaxX ( ) ) ;
Refresh ( false ) ;
}
2011-05-26 13:59:21 +00:00
void gGraphWindow : : ZoomXPixels ( int x1 , int x2 )
2011-05-27 10:53:00 +00:00
{
double rx1 = 0 , rx2 = 0 ;
ZoomXPixels ( x1 , x2 , rx1 , rx2 ) ;
2011-06-02 04:42:37 +00:00
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
2011-05-27 10:53:00 +00:00
( * g ) - > SetXBounds ( rx1 , rx2 ) ;
}
2011-06-15 15:43:33 +00:00
//if (m_block_zoom) {
// Refresh(false); //Rect(m_mouseRBrect,false);
//} else {
2011-05-27 10:53:00 +00:00
SetXBounds ( rx1 , rx2 ) ;
2011-06-15 15:43:33 +00:00
//}
2011-05-27 10:53:00 +00:00
}
void gGraphWindow : : ZoomXPixels ( int x1 , int x2 , double & rx1 , double & rx2 )
2011-05-26 13:59:21 +00:00
{
x1 - = GetLeftMargin ( ) ;
x2 - = GetLeftMargin ( ) ;
if ( x1 < 0 ) x1 = 0 ;
if ( x2 < 0 ) x2 = 0 ;
if ( x1 > Width ( ) ) x1 = Width ( ) ;
if ( x2 > Width ( ) ) x2 = Width ( ) ;
2011-06-15 15:43:33 +00:00
double min ;
double max ;
if ( ! m_block_zoom ) {
min = min_x ;
max = max_x ;
} else {
min = rmin_x ;
max = rmax_x ;
}
2011-05-26 13:59:21 +00:00
double q = max - min ;
2011-05-27 10:53:00 +00:00
rx1 = min + ( double ( x1 ) / Width ( ) ) * q ;
rx2 = min + ( double ( x2 ) / Width ( ) ) * q ;
2011-05-26 13:59:21 +00:00
}
// Move x-axis by the amount of space represented by integer i Pixels (negative values moves backwards)
2011-05-27 10:53:00 +00:00
void gGraphWindow : : MoveX ( int i , double & min , double & max )
2011-05-26 13:59:21 +00:00
{
//if (i==0) return;
2011-05-27 10:53:00 +00:00
min = min_x ;
max = max_x ;
double q = max - min ;
2011-05-26 13:59:21 +00:00
double rx1 = ( double ( i ) / Width ( ) ) * q ;
2011-05-27 10:53:00 +00:00
min - = rx1 ;
max - = rx1 ;
2011-05-26 13:59:21 +00:00
// Keep bounds when hitting hard edges
2011-05-27 10:53:00 +00:00
if ( min < rmin_x ) { //(t=rRealMinX())) {
min = rmin_x ;
max = min + q ;
2011-05-26 13:59:21 +00:00
}
2011-05-27 10:53:00 +00:00
if ( max > rmax_x ) {
max = rmax_x ;
min = max - q ;
2011-05-26 13:59:21 +00:00
}
2011-05-27 10:53:00 +00:00
}
2011-05-26 13:59:21 +00:00
2011-05-27 10:53:00 +00:00
void gGraphWindow : : MoveX ( int i )
{
double min , max ;
MoveX ( i , min , max ) ;
2011-06-08 15:30:57 +00:00
/* for (list<gGraphWindow *>::iterator g=link_zoom.begin();g!=link_zoom.end();g++) {
2011-05-27 10:53:00 +00:00
( * g ) - > SetXBounds ( min , max ) ;
2011-06-08 15:30:57 +00:00
} */
2011-06-15 15:43:33 +00:00
//if (!m_block_zoom) {
2011-06-15 07:33:39 +00:00
SetXBounds ( min , max ) ;
2011-06-15 15:43:33 +00:00
//}
2011-05-26 13:59:21 +00:00
}
void gGraphWindow : : ZoomX ( double mult , int origin_px )
{
if ( origin_px = = 0 ) origin_px = ( Width ( ) / 2 ) ; else origin_px - = GetLeftMargin ( ) ;
if ( origin_px < 0 ) origin_px = 0 ;
if ( origin_px > Width ( ) ) origin_px = Width ( ) ;
double min = min_x ;
double max = max_x ;
double hardspan = rmax_x - rmin_x ;
double span = max - min ;
double origin = double ( origin_px ) / Width ( ) * span ;
double q = span * mult ;
if ( q > hardspan ) q = hardspan ;
2011-06-16 15:44:24 +00:00
if ( q < hardspan / 400 ) q = hardspan / 400 ;
2011-05-26 13:59:21 +00:00
min = min + ( origin - ( q / 2.0 ) ) ;
max = min + q ;
if ( min < rmin_x ) {
min = rmin_x ;
max = min + q ;
}
if ( max > rmax_x ) {
max = rmax_x ;
min = max - q ;
}
SetXBounds ( min , max ) ;
}
2011-06-09 08:49:40 +00:00
gGraphWindow * LastGraphLDown = NULL ;
2011-06-15 15:43:33 +00:00
gGraphWindow * LastGraphRDown = NULL ;
2011-05-26 13:59:21 +00:00
void gGraphWindow : : OnMouseMove ( wxMouseEvent & event )
{
// static bool first=true;
static wxRect last ;
2011-06-15 15:43:33 +00:00
if ( m_mouseLDown & & LastGraphLDown & & ( LastGraphLDown ! = this ) ) {
2011-06-09 08:49:40 +00:00
LastGraphLDown - > OnMouseMove ( event ) ;
return ;
}
2011-06-15 15:43:33 +00:00
if ( m_mouseRDown & & LastGraphRDown & & ( LastGraphRDown ! = this ) ) {
LastGraphRDown - > OnMouseMove ( event ) ;
return ;
}
2011-06-09 08:49:40 +00:00
2011-06-16 10:53:56 +00:00
int y = event . GetY ( ) ;
int x = event . GetX ( ) ;
2011-06-09 02:47:03 +00:00
if ( foobar & & m_drag_foobar ) {
2011-06-08 13:54:27 +00:00
if ( x < GetLeftMargin ( ) ) return ;
int x1 = x - GetLeftMargin ( ) ;
int width = m_scrX - GetRightMargin ( ) - GetLeftMargin ( ) ;
2011-06-10 15:37:19 +00:00
//int height=m_scrY-GetBottomMargin()-GetTopMargin();
2011-06-08 13:54:27 +00:00
if ( x > m_scrX - GetRightMargin ( ) ) return ;
double mx = double ( x1 ) / double ( width ) ;
double rminx = RealMinX ( ) ;
double rmaxx = RealMaxX ( ) ;
double rx = rmaxx - rminx ;
double qx = rx * mx ;
qx + = rminx ;
// qx is centerpoint of new zoom area.
2011-06-08 16:20:03 +00:00
double minx = MinX ( ) ;
double dx = MaxX ( ) - minx ; // zoom rect width;
2011-06-08 14:35:56 +00:00
// Could smarten this up by remembering where the mouse was clicked on the foobar
double gx = dx * m_foobar_pos ;
2011-06-08 13:54:27 +00:00
qx - = gx ;
if ( qx < rminx ) qx = rminx ;
double ex = qx + dx ;
if ( ( qx + dx ) > rmaxx ) {
ex = rmaxx ;
qx = ex - dx ;
}
2011-06-15 15:43:33 +00:00
if ( m_mouseRDown )
m_foobar_moved + = fabs ( ( qx - minx ) ) + fabs ( ( m_mouseRClick . x - x ) ) + fabs ( ( m_mouseRClick . y - y ) ) ;
if ( m_mouseLDown )
m_foobar_moved + = fabs ( ( qx - minx ) ) + fabs ( ( m_mouseLClick . x - x ) ) + fabs ( ( m_mouseLClick . y - y ) ) ;
//else
2011-06-08 13:54:27 +00:00
SetXBounds ( qx , ex ) ;
2011-06-09 13:49:13 +00:00
if ( pref [ " LinkGraphMovement " ] ) {
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
2011-06-15 07:33:39 +00:00
assert ( ( * g ) ! = this ) ;
2011-06-09 13:49:13 +00:00
( * g ) - > SetXBounds ( qx , ex ) ;
}
}
2011-06-08 13:54:27 +00:00
} else
2011-05-26 13:59:21 +00:00
if ( event . m_rightDown ) {
2011-06-16 10:53:56 +00:00
MoveX ( x - m_mouseRClick . x ) ;
m_mouseRClick . x = x ;
2011-06-09 13:49:13 +00:00
double min = MinX ( ) ;
double max = MaxX ( ) ;
if ( pref [ " LinkGraphMovement " ] ) {
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
( * g ) - > SetXBounds ( min , max ) ;
}
}
2011-05-26 13:59:21 +00:00
} else
if ( event . m_leftDown ) {
int x1 = m_mouseLClick . x ;
2011-06-16 10:53:56 +00:00
int x2 = x ;
2011-05-26 13:59:21 +00:00
int t1 = MIN ( x1 , x2 ) ;
int t2 = MAX ( x1 , x2 ) ;
if ( t1 < = m_marginLeft ) t1 = m_marginLeft + 1 ;
if ( t2 > ( m_scrX - m_marginRight ) ) t2 = m_scrX - m_marginRight ;
2011-06-11 18:11:14 +00:00
wxRect r ( t1 , m_marginBottom , t2 - t1 , m_scrY - m_marginBottom - m_marginTop ) ;
2011-05-26 13:59:21 +00:00
m_mouseRBlast = m_mouseRBrect ;
m_mouseRBrect = r ;
2011-06-15 07:33:39 +00:00
// TODO: Only the rect needs clearing, however OpenGL & wx have reversed coordinate systems.
Refresh ( false ) ; //r.Union(m_mouseRBlast),true);
2011-05-26 13:59:21 +00:00
}
event . Skip ( ) ;
}
2011-06-15 15:43:33 +00:00
void gGraphWindow : : OnMouseRightDClick ( wxMouseEvent & event )
{
OnMouseRightDown ( event ) ;
}
2011-05-26 13:59:21 +00:00
void gGraphWindow : : OnMouseRightDown ( wxMouseEvent & event )
{
2011-06-08 13:54:27 +00:00
if ( event . GetY ( ) < GetTopMargin ( ) ) // before top margin
return ;
//else if (event.GetY()>m_scrY-GetBottomMargin()) { // after top margin
// return;
//}
2011-05-26 13:59:21 +00:00
2011-06-08 13:54:27 +00:00
// inside the margin area..
2011-06-15 15:43:33 +00:00
int y = event . GetY ( ) ;
int x = event . GetX ( ) ;
int width = m_scrX - GetRightMargin ( ) - GetLeftMargin ( ) ;
int height = m_scrY - GetBottomMargin ( ) - GetTopMargin ( ) ;
wxRect hot1 ( GetLeftMargin ( ) , GetTopMargin ( ) , width , height ) ; // Graph data area.
m_mouseRClick . x = x ;
m_mouseRClick . y = y ;
2011-06-08 13:54:27 +00:00
m_mouseRClick_start = m_mouseRClick ;
m_mouseRDown = true ;
2011-05-26 13:59:21 +00:00
2011-06-15 15:43:33 +00:00
// m_mouseRDown=true;
if ( foobar & & m_block_zoom & & ( ( ( y > GetTopMargin ( ) ) ) & & ( y < m_scrY ) ) ) {
double rx = RealMaxX ( ) - RealMinX ( ) ;
double qx = double ( width ) / rx ;
double minx = MinX ( ) - RealMinX ( ) ;
double maxx = MaxX ( ) - RealMinX ( ) ; ;
int x1 = ( qx * minx ) ;
int x2 = ( qx * maxx ) ; // length in pixels
int xw = x2 - x1 ;
x1 + = GetLeftMargin ( ) ;
x2 + = GetLeftMargin ( ) ;
if ( ( x > x1 ) & & ( x < x2 ) ) {
double xj = x - x1 ;
m_foobar_pos = ( 1.0 / double ( xw ) ) * xj ; // where along the foobar the user clicked.
m_foobar_moved = 0 ;
m_drag_foobar = true ;
event . Skip ( ) ;
LastGraphRDown = this ;
return ;
// wxLogMessage("Foobar Area Pushed");
} else {
m_drag_foobar = false ;
m_mouseRDown = false ;
x1 = ( rx / width ) * ( x - GetLeftMargin ( ) ) + rmin_x ;
double z = ( max_x - min_x ) ; // width of selected area
x1 - = z / 2.0 ;
if ( x1 < rmin_x ) x1 = rmin_x ;
x2 = x1 + z ;
if ( x2 > rmax_x ) {
x2 = rmax_x ;
x1 = x2 - z ;
}
// SetXBounds(x1,x2);
LastGraphRDown = this ;
}
}
2011-05-26 13:59:21 +00:00
event . Skip ( ) ;
}
2011-06-08 13:54:27 +00:00
2011-05-26 13:59:21 +00:00
void gGraphWindow : : OnMouseRightRelease ( wxMouseEvent & event )
{
2011-06-15 15:43:33 +00:00
if ( LastGraphRDown & & ( LastGraphRDown ! = this ) ) { // Same graph that initiated the click??
LastGraphRDown - > OnMouseLeftRelease ( event ) ; // Nope.. Give it the event.
return ;
}
LastGraphRDown = NULL ;
if ( ! m_mouseRDown ) return ;
2011-06-08 13:54:27 +00:00
// Do this properly with real hotspots later..
2011-06-15 15:43:33 +00:00
int y = event . GetY ( ) ;
int x = event . GetX ( ) ;
int width = m_scrX - GetRightMargin ( ) - GetLeftMargin ( ) ;
int height = m_scrY - GetBottomMargin ( ) - GetTopMargin ( ) ;
wxRect hot1 ( GetLeftMargin ( ) , GetTopMargin ( ) , width , height ) ; // Graph data area.
if ( m_block_zoom ) { // && hot1.Contains(x,y)) {
2011-06-16 10:53:56 +00:00
//bool zoom_in=false;
2011-06-15 15:43:33 +00:00
bool did_draw = false ;
2011-06-08 13:54:27 +00:00
2011-06-15 15:43:33 +00:00
// Finished Dragging the FooBar?
if ( foobar & & m_drag_foobar ) {
if ( m_foobar_moved < 5 ) {
double zoom_fact = 2 ;
if ( event . ControlDown ( ) ) zoom_fact = 5 ;
//if (!m_block_zoom) {
ZoomX ( zoom_fact , 0 ) ;
did_draw = true ;
//}
m_foobar_moved = 0 ;
}
}
m_drag_foobar = false ;
if ( did_draw ) {
double min = MinX ( ) ;
double max = MaxX ( ) ;
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
( * g ) - > SetXBounds ( min , max ) ;
}
}
event . Skip ( ) ;
return ;
}
2011-06-08 13:54:27 +00:00
2011-05-29 05:58:00 +00:00
double zoom_fact = 2 ;
2011-06-16 10:53:56 +00:00
if ( y < GetTopMargin ( ) ) {
2011-06-08 13:54:27 +00:00
return ;
2011-06-16 10:53:56 +00:00
} else if ( y > m_scrY - GetBottomMargin ( ) ) {
2011-06-09 02:47:03 +00:00
if ( ! foobar ) return ;
}
2011-06-08 13:54:27 +00:00
if ( event . ControlDown ( ) ) zoom_fact = 5.0 ;
2011-06-16 10:53:56 +00:00
if ( abs ( x - m_mouseRClick_start . x ) < 3 & & abs ( y - m_mouseRClick_start . y ) < 3 ) {
2011-06-15 10:34:25 +00:00
// for (list<gGraphWindow *>::iterator g=link_zoom.begin();g!=link_zoom.end();g++) {
//(*g)->ZoomX(zoom_fact,0);
//}
2011-06-15 15:43:33 +00:00
//if (!m_block_zoom) {
2011-06-08 13:54:27 +00:00
ZoomX ( zoom_fact , 0 ) ; //event.GetX()); // adds origin to zoom out.. Doesn't look that cool.
2011-06-15 10:34:25 +00:00
double min = MinX ( ) ;
double max = MaxX ( ) ;
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
( * g ) - > SetXBounds ( min , max ) ;
}
2011-06-15 15:43:33 +00:00
//}
2011-06-15 10:34:25 +00:00
} /* else {
2011-06-08 15:30:57 +00:00
double min = MinX ( ) ;
double max = MaxX ( ) ;
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
( * g ) - > SetXBounds ( min , max ) ;
}
2011-06-15 10:34:25 +00:00
} */
2011-06-08 13:54:27 +00:00
2011-05-26 13:59:21 +00:00
m_mouseRDown = false ;
event . Skip ( ) ;
}
2011-06-09 10:25:26 +00:00
void gGraphWindow : : OnMouseLeftDClick ( wxMouseEvent & event )
{
//wxLogMessage(wxT("WTF?? STUPID MOUSEz"));
OnMouseLeftDown ( event ) ;
}
2011-05-26 13:59:21 +00:00
void gGraphWindow : : OnMouseLeftDown ( wxMouseEvent & event )
{
2011-06-08 11:46:24 +00:00
int y = event . GetY ( ) ;
2011-06-08 13:54:27 +00:00
int x = event . GetX ( ) ;
int width = m_scrX - GetRightMargin ( ) - GetLeftMargin ( ) ;
int height = m_scrY - GetBottomMargin ( ) - GetTopMargin ( ) ;
wxRect hot1 ( GetLeftMargin ( ) , GetTopMargin ( ) , width , height ) ; // Graph data area.
2011-06-08 16:28:03 +00:00
m_mouseLClick . x = x ;
m_mouseLClick . y = y ;
2011-06-08 13:54:27 +00:00
2011-06-15 15:43:33 +00:00
if ( foobar & & ( ( y > ( m_scrY - GetBottomMargin ( ) ) ) & & ( y < ( m_scrY - GetBottomMargin ( ) ) + 20 ) ) ) {
2011-06-08 13:54:27 +00:00
double rx = RealMaxX ( ) - RealMinX ( ) ;
double qx = double ( width ) / rx ;
double minx = MinX ( ) - RealMinX ( ) ;
double maxx = MaxX ( ) - RealMinX ( ) ; ;
int x1 = ( qx * minx ) ;
int x2 = ( qx * maxx ) ; // length in pixels
2011-06-08 14:35:56 +00:00
int xw = x2 - x1 ;
2011-06-08 13:54:27 +00:00
x1 + = GetLeftMargin ( ) ;
x2 + = GetLeftMargin ( ) ;
if ( ( x > x1 ) & & ( x < x2 ) ) {
2011-06-09 10:25:26 +00:00
double xj = x - x1 ;
m_foobar_pos = ( 1.0 / double ( xw ) ) * xj ; // where along the foobar the user clicked.
2011-06-08 16:20:03 +00:00
m_foobar_moved = 0 ;
2011-06-08 13:54:27 +00:00
m_drag_foobar = true ;
// wxLogMessage("Foobar Area Pushed");
2011-06-09 10:25:26 +00:00
} else m_drag_foobar = false ;
2011-06-15 15:43:33 +00:00
m_mouseLDown = true ;
LastGraphLDown = this ;
2011-06-09 10:25:26 +00:00
} else if ( hot1 . Contains ( x , y ) ) {
m_mouseLDown = true ;
2011-06-15 15:43:33 +00:00
LastGraphLDown = this ;
2011-06-08 11:46:24 +00:00
}
2011-06-08 13:54:27 +00:00
event . Skip ( ) ;
2011-05-26 13:59:21 +00:00
}
void gGraphWindow : : OnMouseLeftRelease ( wxMouseEvent & event )
{
2011-06-09 06:36:03 +00:00
if ( LastGraphLDown & & ( LastGraphLDown ! = this ) ) { // Same graph that initiated the click??
2011-06-09 08:49:40 +00:00
LastGraphLDown - > OnMouseLeftRelease ( event ) ; // Nope.. Give it the event.
2011-06-09 06:36:03 +00:00
return ;
}
2011-06-09 02:47:03 +00:00
int y = event . GetY ( ) ;
2011-06-08 13:54:27 +00:00
int x = event . GetX ( ) ;
int width = m_scrX - GetRightMargin ( ) - GetLeftMargin ( ) ;
int height = m_scrY - GetBottomMargin ( ) - GetTopMargin ( ) ;
2011-06-08 15:30:57 +00:00
wxRect hot1 ( GetLeftMargin ( ) , GetTopMargin ( ) , width , height ) ; // Graph data area.
2011-06-08 13:54:27 +00:00
2011-06-15 15:43:33 +00:00
bool was_dragging_foo = false ;
2011-06-09 06:36:03 +00:00
bool did_draw = false ;
2011-06-09 02:47:03 +00:00
2011-06-09 10:25:26 +00:00
// Finished Dragging the FooBar?
if ( foobar & & m_drag_foobar ) {
2011-06-15 15:43:33 +00:00
m_drag_foobar = false ;
was_dragging_foo = true ;
2011-06-09 10:25:26 +00:00
if ( m_foobar_moved < 5 ) {
double zoom_fact = 0.5 ;
if ( event . ControlDown ( ) ) zoom_fact = 0.25 ;
2011-06-15 15:43:33 +00:00
//if (!m_block_zoom) {
ZoomX ( zoom_fact , 0 ) ;
did_draw = true ;
//}
2011-06-09 10:25:26 +00:00
m_foobar_moved = 0 ;
2011-06-15 15:56:19 +00:00
} else m_mouseLDown = false ;
2011-06-15 15:43:33 +00:00
2011-06-09 10:25:26 +00:00
}
2011-06-09 02:47:03 +00:00
2011-06-15 15:43:33 +00:00
if ( ! did_draw & & m_mouseLDown ) {
2011-06-08 13:54:27 +00:00
wxPoint release ( event . GetX ( ) , m_scrY - m_marginBottom ) ;
wxPoint press ( m_mouseLClick . x , m_marginTop ) ;
int x1 = m_mouseRBrect . x ;
int x2 = x1 + m_mouseRBrect . width ;
2011-06-09 13:49:13 +00:00
int t1 = MIN ( x1 , x2 ) ;
int t2 = MAX ( x1 , x2 ) ;
2011-06-08 13:54:27 +00:00
2011-06-09 13:49:13 +00:00
if ( ( t2 - t1 ) > 4 ) {
// Range Selected
ZoomXPixels ( t1 , t2 ) ;
did_draw = true ;
}
2011-06-09 03:43:51 +00:00
2011-06-09 06:36:03 +00:00
}
2011-06-09 10:25:26 +00:00
if ( ! did_draw & & hot1 . Contains ( x , y ) & & ! m_drag_foobar & & m_mouseLDown ) {
2011-06-15 15:43:33 +00:00
if ( m_block_zoom ) {
x - = GetLeftMargin ( ) ;
double rx = rmax_x - rmin_x ;
double mx = max_x - min_x ;
if ( mx < rx ) {
double qx = ( rx / width ) * double ( x ) ;
qx + = rmin_x ;
qx - = mx / 2.0 ;
if ( qx < rmin_x ) {
qx = rmin_x ;
}
if ( qx + mx > rmax_x ) {
qx = rmax_x - mx ;
}
SetXBounds ( qx , qx + mx ) ;
did_draw = true ;
}
} else {
int xp = x ;
xp = 0 ;
double zoom_fact = 0.5 ;
if ( event . ControlDown ( ) ) zoom_fact = 0.25 ;
2011-06-09 06:36:03 +00:00
ZoomX ( zoom_fact , xp ) ; //event.GetX()); // adds origin to zoom in.. Doesn't look that cool.
2011-06-15 10:34:25 +00:00
did_draw = true ;
2011-06-09 06:36:03 +00:00
}
2011-06-15 15:43:33 +00:00
//}
2011-06-09 06:36:03 +00:00
}
2011-05-29 05:58:00 +00:00
2011-06-09 10:25:26 +00:00
m_drag_foobar = false ;
wxRect r = m_mouseRBrect ;
2011-06-09 06:36:03 +00:00
m_mouseRBrect = wxRect ( 0 , 0 , 0 , 0 ) ;
2011-06-09 08:49:40 +00:00
m_mouseLDown = false ;
m_drag_foobar = false ;
2011-06-15 10:34:25 +00:00
if ( ! did_draw ) {
2011-06-09 10:25:26 +00:00
if ( r ! = m_mouseRBrect )
2011-06-15 07:33:39 +00:00
Refresh ( false ) ;
} else {
2011-06-09 13:49:13 +00:00
double min = MinX ( ) ;
double max = MaxX ( ) ;
for ( list < gGraphWindow * > : : iterator g = link_zoom . begin ( ) ; g ! = link_zoom . end ( ) ; g + + ) {
( * g ) - > SetXBounds ( min , max ) ;
}
2011-06-15 07:33:39 +00:00
}
2011-06-09 13:49:13 +00:00
//}
2011-06-09 08:49:40 +00:00
LastGraphLDown = NULL ;
2011-05-26 13:59:21 +00:00
event . Skip ( ) ;
}
2011-06-13 19:37:25 +00:00
/*void gGraphWindow::Update()
2011-05-26 13:59:21 +00:00
{
Refresh ( ) ;
2011-06-13 19:37:25 +00:00
} */
2011-06-11 10:20:44 +00:00
void gGraphWindow : : SetMargins ( float top , float right , float bottom , float left )
2011-05-26 13:59:21 +00:00
{
m_marginTop = top ;
m_marginBottom = bottom ;
m_marginLeft = left ;
m_marginRight = right ;
}
2011-06-13 20:25:18 +00:00
2011-06-15 00:28:39 +00:00
wxGLContext * shared_context = NULL ;
2011-06-14 19:46:07 +00:00
2011-06-15 00:28:39 +00:00
pBuffer * pbuffer = NULL ;
2011-06-14 19:46:07 +00:00
2011-06-07 09:17:22 +00:00
wxBitmap * gGraphWindow : : RenderBitmap ( int width , int height )
{
2011-06-17 15:59:04 +00:00
wxBitmap * bmp ;
2011-06-17 09:14:36 +00:00
2011-06-15 00:28:39 +00:00
if ( ! pbuffer ) {
try {
2011-06-17 15:59:04 +00:00
wxSize res = wxGetDisplaySize ( ) ;
pbuffer = new FBO ( res . GetWidth ( ) , res . GetHeight ( ) ) ;
/*
2011-06-13 19:59:46 +00:00
# if defined(__WXMSW__)
2011-06-15 00:28:39 +00:00
pbuffer = new pBufferWGL ( width , height ) ;
2011-06-13 22:58:10 +00:00
# elif defined(__WXMAC__) || defined(__WXDARWIN__)
2011-06-17 15:59:04 +00:00
throw GLException ( wxT ( " Macintrash " ) ) ;
//pbuffer=new pBufferAGL(width,height);
2011-06-13 19:59:46 +00:00
# elif defined(__UNIX__)
2011-06-15 00:28:39 +00:00
pbuffer = new pBufferGLX ( width , height ) ;
2011-06-13 19:50:51 +00:00
# endif
2011-06-17 15:59:04 +00:00
*/
2011-06-15 00:28:39 +00:00
} catch ( GLException e ) {
// Should log already if failed..
2011-06-17 15:59:04 +00:00
wxLogDebug ( wxT ( " pBuffers not implemented or functional on this platform.. Trying FBO " ) ) ;
pbuffer = NULL ;
}
}
if ( ! pbuffer ) {
try {
pbuffer = new FBO ( width , height ) ;
} catch ( GLException e ) {
wxLogError ( wxT ( " No offscreen rendering capabilities detected on this machine. " ) ) ;
2011-06-15 02:50:17 +00:00
pbuffer = NULL ;
2011-06-15 00:28:39 +00:00
return NULL ;
}
2011-06-13 19:37:25 +00:00
}
2011-06-15 00:28:39 +00:00
if ( pbuffer ) {
pbuffer - > UseBuffer ( true ) ;
2011-06-17 15:59:04 +00:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
// Can't use font's in multiple contexts
Render ( width , height ) ;
2011-06-17 09:14:36 +00:00
2011-06-17 15:59:04 +00:00
bmp = pbuffer - > Snapshot ( width , height ) ;
glFlush ( ) ;
pbuffer - > UseBuffer ( false ) ;
} else bmp = NULL ;
2011-06-17 09:14:36 +00:00
2011-06-11 10:20:44 +00:00
2011-06-13 19:37:25 +00:00
return bmp ;
2011-06-11 10:20:44 +00:00
}
2011-06-13 19:37:25 +00:00
void gGraphWindow : : Render ( float scrX , float scrY )
2011-05-26 13:59:21 +00:00
{
2011-06-13 19:37:25 +00:00
glViewport ( 0 , 0 , scrX , scrY ) ;
2011-06-11 10:20:44 +00:00
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
2011-06-13 19:37:25 +00:00
glOrtho ( 0 , scrX , 0 , scrY , - 1 , 1 ) ;
2011-06-11 10:20:44 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glDisable ( GL_DEPTH_TEST ) ;
2011-06-13 19:37:25 +00:00
//glDisable(GL_LIGHTING);
2011-06-11 10:20:44 +00:00
glBegin ( GL_QUADS ) ;
glColor3f ( 1.0 , 1.0 , 1.0 ) ; // Gradient start
2011-06-13 19:37:25 +00:00
glVertex2f ( 0 , scrY ) ;
2011-06-11 10:20:44 +00:00
glVertex2f ( 0 , 0 ) ;
glColor3f ( 0.8 , 0.8 , 1.0 ) ; // Gradient End
2011-06-13 19:37:25 +00:00
glVertex2f ( scrX , 0 ) ;
glVertex2f ( scrX , scrY ) ;
2011-06-11 10:20:44 +00:00
glEnd ( ) ;
2011-06-13 19:37:25 +00:00
glEnable ( GL_TEXTURE_2D ) ;
2011-06-11 10:20:44 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-06-13 19:37:25 +00:00
( * l ) - > Plot ( * this , scrX , scrY ) ;
2011-06-11 10:20:44 +00:00
}
2011-06-15 00:28:39 +00:00
glEnable ( GL_DEPTH_TEST ) ;
2011-06-13 19:37:25 +00:00
}
2011-06-11 10:20:44 +00:00
2011-06-13 19:37:25 +00:00
void gGraphWindow : : OnPaint ( wxPaintEvent & event )
{
// Shouldn't need this anymore as opengl double buffers anyway.
2011-06-15 00:28:39 +00:00
2011-06-13 19:37:25 +00:00
//#if defined(__WXMSW__)
// wxAutoBufferedPaintDC dc(this);
2011-06-11 05:02:00 +00:00
//#else
2011-06-13 19:37:25 +00:00
wxPaintDC dc ( this ) ;
//#endif
2011-06-11 10:20:44 +00:00
2011-06-13 19:37:25 +00:00
//#if wxCHECK_VERSION(2,9,0)
//SetCurrent(*shared_context);
//#else
2011-06-11 10:20:44 +00:00
2011-06-13 19:37:25 +00:00
# if defined(__DARWIN__) && !wxCHECK_VERSION(2,9,0)
shared_context - > SetCurrent ( ) ;
# else
2011-06-15 02:50:17 +00:00
shared_context - > SetCurrent ( * this ) ;
2011-06-13 19:37:25 +00:00
# endif
2011-06-10 15:37:19 +00:00
2011-06-11 05:02:00 +00:00
//#endif
2011-06-10 15:37:19 +00:00
2011-06-13 22:58:10 +00:00
# if !defined(__WXMAC__) && defined (__UNIX__)
2011-06-13 19:37:25 +00:00
real_shared_context = glXGetCurrentContext ( ) ;
2011-06-13 20:25:18 +00:00
# endif
2011-05-26 13:59:21 +00:00
2011-06-13 19:37:25 +00:00
GetClientSize ( & m_scrX , & m_scrY ) ;
2011-05-26 13:59:21 +00:00
2011-06-17 00:48:20 +00:00
Render ( m_scrX , m_scrY ) ;
2011-05-26 13:59:21 +00:00
2011-06-13 19:37:25 +00:00
if ( m_mouseLDown ) {
if ( m_mouseRBrect . width > 0 )
2011-06-15 00:28:39 +00:00
glDisable ( GL_DEPTH_TEST ) ;
2011-06-13 19:37:25 +00:00
RoundedRectangle ( m_mouseRBrect . x , m_mouseRBrect . y , m_mouseRBrect . width - 1 , m_mouseRBrect . height , 5 , * wxDARK_GREY ) ;
2011-06-15 00:28:39 +00:00
glEnable ( GL_DEPTH_TEST ) ;
2011-06-09 15:50:17 +00:00
}
2011-05-26 13:59:21 +00:00
2011-06-15 00:28:39 +00:00
SwapBuffers ( ) ; // Dump to screen.
2011-05-26 13:59:21 +00:00
2011-06-17 15:59:04 +00:00
event . Skip ( ) ;
2011-05-26 13:59:21 +00:00
}
void gGraphWindow : : OnSize ( wxSizeEvent & event )
{
GetClientSize ( & m_scrX , & m_scrY ) ;
2011-06-15 10:34:25 +00:00
Refresh ( false ) ;
2011-05-26 13:59:21 +00:00
}
double gGraphWindow : : MinX ( )
{
//static bool f=true; //need a bool for each one, and reset when a layer reports data change.
//if (!f) return min_x;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > MinX ( ) ;
2011-05-30 22:53:48 +00:00
if ( ! ( ( val = = ( * l ) - > MaxX ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
tmp = ( * l ) - > MinX ( ) ;
if ( ! ( ( tmp = = ( * l ) - > MaxX ( ) ) & & ( tmp = = 0 ) ) ) {
if ( tmp < val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return min_x = val ;
}
double gGraphWindow : : MaxX ( )
{
//static bool f=true;
//if (!f) return max_x;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > MaxX ( ) ;
2011-05-30 22:53:48 +00:00
if ( ! ( ( val = = ( * l ) - > MinX ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
tmp = ( * l ) - > MaxX ( ) ;
if ( ! ( ( tmp = = ( * l ) - > MinX ( ) ) & & ( tmp = = 0 ) ) ) {
if ( tmp > val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return max_x = val ;
}
double gGraphWindow : : MinY ( )
{
//static bool f=true;
//if (!f) return min_y;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > MinY ( ) ;
2011-05-29 07:00:13 +00:00
if ( ! ( ( val = = ( * l ) - > MaxY ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-29 07:00:13 +00:00
tmp = ( * l ) - > MinY ( ) ;
if ( ! ( ( tmp = = ( * l ) - > MaxY ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this layer if both are 0
if ( tmp < val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return min_y = val ;
}
double gGraphWindow : : MaxY ( )
{
//static bool f=true;
//if (!f) return max_y;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > MaxY ( ) ;
2011-05-29 07:00:13 +00:00
if ( ! ( ( val = = ( * l ) - > MinY ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-29 07:00:13 +00:00
tmp = ( * l ) - > MaxY ( ) ;
if ( ! ( ( tmp = = ( * l ) - > MinY ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this layer if both are 0
if ( tmp > val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return max_y = val ;
}
double gGraphWindow : : RealMinX ( )
{
//static bool f=true;
//if (!f) return rmin_x;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > RealMinX ( ) ;
2011-05-30 22:53:48 +00:00
if ( ! ( ( val = = ( * l ) - > RealMaxX ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
tmp = ( * l ) - > RealMinX ( ) ;
if ( ! ( ( tmp = = ( * l ) - > RealMaxX ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this layer if both are 0
if ( tmp < val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return rmin_x = val ;
}
double gGraphWindow : : RealMaxX ( )
{
//static bool f=true;
//if (!f) return rmax_x;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > RealMaxX ( ) ;
2011-05-30 22:53:48 +00:00
if ( ! ( ( val = = ( * l ) - > RealMinX ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
tmp = ( * l ) - > RealMaxX ( ) ;
if ( ! ( ( tmp = = ( * l ) - > RealMinX ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this layer if both are 0
if ( tmp > val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return rmax_x = val ;
}
double gGraphWindow : : RealMinY ( )
{
//static bool f=true;
//if (!f) return rmin_y;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > RealMinY ( ) ;
2011-05-29 07:00:13 +00:00
if ( ! ( ( val = = ( * l ) - > RealMaxY ( ) ) & & ( val = = 0 ) ) )
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-29 07:00:13 +00:00
tmp = ( * l ) - > RealMinY ( ) ;
if ( ! ( ( tmp = = ( * l ) - > RealMaxY ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this if both are 0
if ( tmp < val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return rmin_y = val ;
}
double gGraphWindow : : RealMaxY ( )
{
//static bool f=true;
//if (!f) return rmax_y;
//f=false;
bool first = true ;
2011-06-06 05:17:23 +00:00
double val = 0 , tmp ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
if ( first ) {
val = ( * l ) - > RealMaxY ( ) ;
2011-05-29 07:00:13 +00:00
if ( ! ( ( val = = ( * l ) - > RealMinY ( ) ) & & ( val = = 0 ) ) ) // Does this create a loop??
first = false ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-29 07:00:13 +00:00
tmp = ( * l ) - > RealMaxY ( ) ;
if ( ! ( ( tmp = = ( * l ) - > RealMinY ( ) ) & & ( tmp = = 0 ) ) ) { // Ignore this if both are 0
if ( tmp > val ) val = tmp ;
}
2011-05-26 13:59:21 +00:00
}
}
return rmax_y = val ;
}
void gGraphWindow : : SetMinX ( double v )
{
min_x = v ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
( * l ) - > SetMinX ( v ) ;
}
}
void gGraphWindow : : SetMaxX ( double v )
{
max_x = v ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
( * l ) - > SetMaxX ( v ) ;
}
}
void gGraphWindow : : SetMinY ( double v )
{
min_y = v ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
( * l ) - > SetMinY ( v ) ;
}
}
void gGraphWindow : : SetMaxY ( double v )
{
max_y = v ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; l + + ) {
2011-05-26 13:59:21 +00:00
( * l ) - > SetMaxY ( v ) ;
}
}
void gGraphWindow : : DataChanged ( gLayer * layer )
{
2011-06-15 07:33:39 +00:00
wxDateTime n = wxDateTime : : Now ( ) ;
wxTimeSpan t = n - ti ;
ti = n ;
2011-05-26 13:59:21 +00:00
2011-06-03 07:06:18 +00:00
if ( layer ) {
MinX ( ) ; MinY ( ) ; MaxX ( ) ; MaxY ( ) ;
RealMinX ( ) ; RealMinY ( ) ; RealMaxX ( ) ; RealMaxY ( ) ;
} else {
max_x = min_x = 0 ;
}
2011-06-15 10:34:25 +00:00
2011-06-16 10:53:56 +00:00
//long l=t.GetMilliseconds().GetLo();
2011-06-16 08:18:48 +00:00
//wxLogMessage(wxString::Format(wxT("%li"),l));
2011-06-15 07:33:39 +00:00
if ( ( t = = wxTimeSpan : : Milliseconds ( 0 ) ) & & ( layer ! = lastlayer ) ) {
lastlayer = layer ;
return ;
}
lastlayer = layer ;
// This is possibly evil.. It needs to push one refresh event for all layers
// Assmption currently is Refresh que does skip
2011-05-26 13:59:21 +00:00
Refresh ( false ) ;
}
2011-05-31 04:50:06 +00:00
gXAxis : : gXAxis ( const wxColor * col )
: gLayer ( NULL )
2011-05-26 13:59:21 +00:00
{
if ( col ) {
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-05-26 13:59:21 +00:00
}
}
2011-05-30 22:53:48 +00:00
gXAxis : : ~ gXAxis ( )
2011-05-26 13:59:21 +00:00
{
}
2011-06-13 19:37:25 +00:00
void gXAxis : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-30 13:35:14 +00:00
{
float px , py ;
2011-06-15 00:28:39 +00:00
//int start_px=w.GetLeftMargin();
//int start_py=w.GetTopMargin();
float width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
// float height=scry-(w.GetTopMargin()+w.GetBottomMargin());
2011-05-30 13:35:14 +00:00
2011-06-15 15:43:33 +00:00
double minx ;
double maxx ;
if ( w . BlockZoom ( ) ) {
minx = w . rmin_x ;
maxx = w . rmax_x ;
} else {
minx = w . min_x ;
maxx = w . max_x ;
}
double xx = maxx - minx ;
2011-05-30 13:35:14 +00:00
2011-05-31 03:09:03 +00:00
if ( xx = = 0 ) return ;
2011-06-13 19:37:25 +00:00
2011-06-15 15:43:33 +00:00
double xmult = width / xx ;
2011-05-31 02:18:41 +00:00
wxString fd ;
if ( xx < 1.5 ) {
fd = wxT ( " 00:00:00:0000 " ) ;
} else {
fd = wxT ( " XX XXX " ) ;
}
2011-06-13 19:37:25 +00:00
float x , y ;
GetTextExtent ( fd , x , y ) ;
2011-05-30 13:35:14 +00:00
double max_ticks = ( x + 25.0 ) / width ; // y+50 for rotated text
double jj = 1 / max_ticks ;
double minor_tick = max_ticks * xx ;
2011-06-15 15:43:33 +00:00
double st2 = minx ; //double(int(frac*1440.0))/1440.0;
2011-05-30 13:35:14 +00:00
double st , q ;
bool show_seconds = false ;
bool show_milliseconds = false ;
bool show_time = true ;
double min_tick ;
if ( xx < 1.5 ) {
int rounding [ 16 ] = { 12 , 24 , 48 , 72 , 96 , 144 , 288 , 720 , 1440 , 2880 , 5760 , 8640 , 17280 , 86400 , 172800 , 345600 } ; // time rounding
int ri ;
for ( ri = 0 ; ri < 16 ; ri + + ) {
st = round ( st2 * rounding [ ri ] ) / rounding [ ri ] ;
min_tick = round ( minor_tick * rounding [ ri ] ) / rounding [ ri ] ;
q = xx / min_tick ; // number of ticks that fits in range
if ( q < = jj ) break ; // compared to number of ticks that fit on screen.
}
if ( ri > 8 ) show_seconds = true ;
if ( ri > = 14 ) show_milliseconds = true ;
if ( min_tick < = 0.25 / 86400.0 )
min_tick = 0.25 / 86400 ;
} else { // Day ticks..
show_time = false ;
st = st2 ;
2011-05-31 04:28:11 +00:00
min_tick = 1.0 ;
2011-05-30 13:35:14 +00:00
double mtiks = ( x + 20.0 ) / width ;
double mt = mtiks * xx ;
min_tick = mt ;
2011-05-31 04:28:11 +00:00
//if (min_tick<1.0) min_tick=1.0;
//if (min_tick>10) min_tick=10;
2011-05-30 13:35:14 +00:00
}
double st3 = st ;
2011-06-15 15:43:33 +00:00
while ( st3 > minx ) {
2011-05-30 13:35:14 +00:00
st3 - = min_tick / 10.0 ;
}
st3 + = min_tick / 10.0 ;
2011-06-11 18:11:14 +00:00
py = w . GetBottomMargin ( ) ;
2011-05-30 13:35:14 +00:00
2011-06-16 08:18:48 +00:00
const int maxverts = 2048 ;
int vertcnt = 0 ;
2011-06-16 10:10:02 +00:00
static GLshort vertarray [ maxverts + 4 ] ;
2011-06-16 08:18:48 +00:00
2011-06-15 15:43:33 +00:00
for ( double i = st3 ; i < = maxx ; i + = min_tick / 10.0 ) {
if ( i < minx ) continue ;
2011-06-16 08:18:48 +00:00
px = ( i - minx ) * xmult + w . GetLeftMargin ( ) ;
vertarray [ vertcnt + + ] = px ;
vertarray [ vertcnt + + ] = py ;
vertarray [ vertcnt + + ] = px ;
vertarray [ vertcnt + + ] = py - 4 ;
2011-05-30 13:35:14 +00:00
}
2011-06-15 15:43:33 +00:00
while ( st < minx ) {
2011-05-31 11:48:57 +00:00
st + = min_tick ; //10.0; // mucking with this changes the scrollyness of the ticker.
2011-05-30 13:35:14 +00:00
}
int hour , minute , second , millisecond ;
wxDateTime d ;
2011-05-31 02:18:41 +00:00
2011-06-15 15:43:33 +00:00
for ( double i = st ; i < = maxx ; i + = min_tick ) { //600.0/86400.0) {
2011-05-31 11:48:57 +00:00
d . Set ( i + 2400000.5 + .00000001 + 1 ) ; // JDN vs MJD vs Rounding errors
2011-05-30 13:35:14 +00:00
if ( show_time ) {
minute = d . GetMinute ( ) ;
hour = d . GetHour ( ) ;
second = d . GetSecond ( ) ;
millisecond = d . GetMillisecond ( ) ;
if ( show_milliseconds ) {
fd = wxString : : Format ( wxT ( " %02i:%02i:%02i:%04i " ) , hour , minute , second , millisecond ) ;
} else if ( show_seconds ) {
fd = wxString : : Format ( wxT ( " %02i:%02i:%02i " ) , hour , minute , second ) ;
} else {
fd = wxString : : Format ( wxT ( " %02i:%02i " ) , hour , minute ) ;
}
} else {
2011-05-31 02:18:41 +00:00
fd = d . Format ( wxT ( " %d %b " ) ) ;
2011-05-30 13:35:14 +00:00
}
2011-06-15 15:43:33 +00:00
px = ( i - minx ) * xmult + w . GetLeftMargin ( ) ;
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = px ;
vertarray [ vertcnt + + ] = py ;
vertarray [ vertcnt + + ] = px ;
vertarray [ vertcnt + + ] = py - 6 ;
2011-06-11 10:20:44 +00:00
2011-06-13 19:37:25 +00:00
GetTextExtent ( fd , x , y ) ;
2011-05-31 02:18:41 +00:00
if ( ! show_time ) {
2011-06-16 08:18:48 +00:00
DrawText ( fd , px - ( y / 2 ) - 2 , py - ( x / 2 ) - 14 , 90.0 , * wxBLACK ) ;
2011-05-30 13:35:14 +00:00
} else {
2011-06-11 18:11:14 +00:00
DrawText ( fd , px - ( x / 2 ) , py - 14 - y ) ;
2011-05-30 13:35:14 +00:00
}
}
2011-06-16 08:18:48 +00:00
// Draw the little ticks.
assert ( vertcnt < maxverts ) ;
glLineWidth ( 1 ) ;
glColor3f ( 0 , 0 , 0 ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2011-06-16 10:10:02 +00:00
glVertexPointer ( 2 , GL_SHORT , 0 , vertarray ) ;
2011-06-16 08:18:48 +00:00
glDrawArrays ( GL_LINES , 0 , vertcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ; // deactivate vertex arrays after drawing
2011-05-31 11:48:57 +00:00
2011-05-30 13:35:14 +00:00
}
2011-05-28 09:36:42 +00:00
2011-05-31 04:50:06 +00:00
gYAxis : : gYAxis ( const wxColor * col )
: gLayer ( NULL )
2011-05-26 13:59:21 +00:00
{
2011-05-30 22:53:48 +00:00
if ( col ) {
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-05-30 22:53:48 +00:00
}
m_show_major_lines = true ;
m_show_minor_lines = true ;
}
gYAxis : : ~ gYAxis ( )
{
}
2011-06-13 19:37:25 +00:00
void gYAxis : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-30 22:53:48 +00:00
{
2011-06-16 08:18:48 +00:00
static wxColor wxDARK_GREY ( 0xb8 , 0xb8 , 0xb8 , 0xa0 ) ;
2011-06-13 19:37:25 +00:00
float x , y ;
2011-06-10 15:37:19 +00:00
int labelW = 0 ;
2011-05-26 13:59:21 +00:00
2011-06-03 07:06:18 +00:00
double miny = w . min_y ;
double maxy = w . max_y ;
2011-06-16 08:18:48 +00:00
if ( maxy = = miny ) return ;
2011-06-03 08:12:00 +00:00
if ( ( w . max_x - w . min_x ) = = 0 ) return ;
2011-06-03 07:06:18 +00:00
2011-05-26 13:59:21 +00:00
int start_px = w . GetLeftMargin ( ) ;
2011-06-11 18:11:14 +00:00
int start_py = w . GetBottomMargin ( ) ;
2011-06-16 08:18:48 +00:00
int width = scrx - ( w . GetRightMargin ( ) + start_px ) ;
int height = scry - ( w . GetTopMargin ( ) + start_py ) ;
2011-06-11 10:20:44 +00:00
const wxColor & linecol1 = * wxLIGHT_GREY ;
const wxColor & linecol2 = wxDARK_GREY ;
2011-05-30 22:53:48 +00:00
wxString fd = wxT ( " 0 " ) ;
2011-06-13 19:37:25 +00:00
GetTextExtent ( fd , x , y ) ;
2011-06-16 08:18:48 +00:00
double max_yticks = round ( height / ( y + 15.0 ) ) ; // plus spacing between lines
double yt = 1 / max_yticks ;
double mxy = MAX ( maxy , fabs ( miny ) ) ;
double mny = MIN ( maxy , fabs ( miny ) ) ;
if ( miny < 0 ) mny = - mny ;
if ( maxy < 0 ) mxy = - mxy ;
double rxy = mxy - mny ;
double ymult = height / rxy ;
double min_ytick = rxy * yt ;
//if (miny>=0) {
//} else {
//}
/*double max_yticks=1/max_yticksdiv;
2011-05-30 22:53:48 +00:00
double yy = w . max_y - w . min_y ;
double ymult = height / yy ;
double major_ytick = max_yticksdiv * yy ;
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
double min_ytick , q ;
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
if ( w . min_y > = 0 ) {
int yrounding [ 9 ] = { 1 , 2 , 5 , 10 , 20 , 30 , 40 , 50 , 100 } ; // time rounding
int ry ;
for ( ry = 0 ; ry < 9 ; ry + + ) {
// st=round(st2*rounding[ry])/rounding[ry];
min_ytick = round ( major_ytick * yrounding [ ry ] ) / yrounding [ ry ] ;
q = yy / min_ytick ; // number of ticks that fits in range
if ( q < = max_yticks ) break ; // compared to number of ticks that fit on screen.
}
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
min_ytick = 60 ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
if ( min_ytick < = 0.25 )
2011-06-16 08:18:48 +00:00
min_ytick = 0.25 ; */
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
int ty , h ;
2011-06-16 08:18:48 +00:00
const int maxverts = 2048 ;
int vertcnt = 0 ;
2011-06-16 10:10:02 +00:00
static GLshort vertarray [ maxverts + 4 ] ;
2011-06-13 19:37:25 +00:00
2011-06-11 11:03:44 +00:00
glColor4ub ( linecol1 . Red ( ) , linecol1 . Green ( ) , linecol1 . Blue ( ) , linecol1 . Alpha ( ) ) ;
2011-06-16 10:10:02 +00:00
glLineWidth ( 1 ) ;
2011-06-16 08:18:48 +00:00
2011-06-17 15:59:04 +00:00
for ( double i = miny + ( min_ytick / 2.0 ) ; i < maxy ; i + = min_ytick ) {
ty = ( i - miny ) * ymult ;
2011-06-16 08:18:48 +00:00
h = ( start_py + height ) - ty ;
vertarray [ vertcnt + + ] = start_px - 4 ;
vertarray [ vertcnt + + ] = h ;
vertarray [ vertcnt + + ] = start_px ;
vertarray [ vertcnt + + ] = h ;
if ( m_show_minor_lines & & ( i > miny ) ) {
2011-06-11 10:20:44 +00:00
glBegin ( GL_LINES ) ;
glVertex2f ( start_px + 1 , h ) ;
glVertex2f ( start_px + width , h ) ;
glEnd ( ) ;
}
2011-05-30 22:53:48 +00:00
}
2011-05-26 13:59:21 +00:00
2011-06-17 15:59:04 +00:00
for ( double i = miny ; i < = maxy ; i + = min_ytick ) {
ty = ( i - miny ) * ymult ;
fd = Format ( i ) ; // Override this as a function.
GetTextExtent ( fd , x , y ) ;
if ( x > labelW ) labelW = x ;
2011-06-11 18:11:14 +00:00
h = start_py + ty ;
2011-06-17 15:59:04 +00:00
DrawText ( fd , start_px - 8 - x , h - ( y / 2 ) ) ;
2011-06-11 10:20:44 +00:00
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = start_px - 4 ;
vertarray [ vertcnt + + ] = h ;
vertarray [ vertcnt + + ] = start_px ;
vertarray [ vertcnt + + ] = h ;
2011-06-11 10:20:44 +00:00
2011-06-16 08:18:48 +00:00
if ( m_show_major_lines & & ( i > miny ) ) {
glColor4ub ( linecol2 . Red ( ) , linecol2 . Green ( ) , linecol2 . Blue ( ) , linecol2 . Alpha ( ) ) ;
2011-06-11 10:20:44 +00:00
glBegin ( GL_LINES ) ;
glVertex2f ( start_px + 1 , h ) ;
glVertex2f ( start_px + width , h ) ;
glEnd ( ) ;
}
2011-05-30 22:53:48 +00:00
}
2011-06-16 08:18:48 +00:00
assert ( vertcnt < maxverts ) ;
// Draw the little ticks.
glLineWidth ( 1 ) ;
glColor3f ( 0 , 0 , 0 ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2011-06-16 10:10:02 +00:00
glVertexPointer ( 2 , GL_SHORT , 0 , vertarray ) ;
2011-06-16 08:18:48 +00:00
glDrawArrays ( GL_LINES , 0 , vertcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ; // deactivate vertex arrays after drawing
2011-05-30 22:53:48 +00:00
}
2011-05-26 13:59:21 +00:00
2011-06-13 19:37:25 +00:00
gGraphTitle : : gGraphTitle ( const wxString & _title , wxOrientation o , const wxColor * color )
: gLayer ( NULL ) , m_title ( _title ) , m_orientation ( o ) , m_color ( ( wxColor * ) color ) //m_font((wxFont*)font),
2011-06-09 02:47:03 +00:00
{
m_textheight = m_textwidth = 0 ;
}
gGraphTitle : : ~ gGraphTitle ( )
{
}
2011-06-13 19:37:25 +00:00
void gGraphTitle : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-06-09 02:47:03 +00:00
{
if ( ! m_visible ) return ;
2011-06-11 18:11:14 +00:00
2011-06-09 10:25:26 +00:00
wxAlignment m_alignment = wxALIGN_LEFT ;
2011-06-09 02:47:03 +00:00
2011-06-11 18:11:14 +00:00
float width , height ;
2011-06-09 02:47:03 +00:00
if ( m_orientation = = wxHORIZONTAL ) {
2011-06-12 05:43:49 +00:00
GetTextExtent ( m_title , width , height ) ;
DrawText ( m_title , 4 , scrx - height , 0 ) ;
2011-06-09 02:47:03 +00:00
} else {
2011-06-13 19:37:25 +00:00
GetTextExtent ( m_title , width , height ) ;
2011-06-11 18:11:14 +00:00
int xp = ( height / 2 ) + 5 ;
if ( m_alignment = = wxALIGN_RIGHT ) xp = scrx - 4 - height ;
2011-06-13 19:37:25 +00:00
DrawText ( m_title , xp , w . GetBottomMargin ( ) + ( ( scry - w . GetBottomMargin ( ) ) / 2.0 ) + ( height / 2 ) , 90.0 , * wxBLACK ) ;
2011-06-09 02:47:03 +00:00
}
}
2011-06-15 15:43:33 +00:00
gFooBar : : gFooBar ( const wxColor * col1 , const wxColor * col2 , bool funkbar )
: gLayer ( NULL ) , m_funkbar ( funkbar )
2011-05-31 04:50:06 +00:00
{
2011-06-09 02:47:03 +00:00
if ( col1 & & col2 ) {
2011-05-31 04:50:06 +00:00
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col2 ) ;
color . push_back ( * col1 ) ;
2011-05-31 04:50:06 +00:00
}
}
gFooBar : : ~ gFooBar ( )
{
}
2011-06-13 19:37:25 +00:00
void gFooBar : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-31 04:50:06 +00:00
{
if ( ! m_visible ) return ;
double xx = w . max_x - w . min_x ;
2011-06-11 18:11:14 +00:00
2011-06-03 07:06:18 +00:00
if ( xx = = 0 )
return ;
2011-05-31 04:50:06 +00:00
int start_px = w . GetLeftMargin ( ) ;
2011-06-11 10:20:44 +00:00
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
2011-06-15 15:43:33 +00:00
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) ;
2011-05-31 04:50:06 +00:00
2011-06-11 11:03:44 +00:00
wxColor & col1 = color [ 0 ] ;
wxColor & col2 = color [ 1 ] ;
2011-06-11 18:11:14 +00:00
float h = w . GetBottomMargin ( ) - 10 ;
2011-06-11 11:03:44 +00:00
glColor4ub ( col1 . Red ( ) , col1 . Green ( ) , col1 . Blue ( ) , col1 . Alpha ( ) ) ;
2011-06-11 10:20:44 +00:00
glLineWidth ( 1 ) ;
glBegin ( GL_LINES ) ;
2011-06-11 18:11:14 +00:00
glVertex2f ( start_px , h ) ;
glVertex2f ( start_px + width , h ) ;
2011-06-11 10:20:44 +00:00
glEnd ( ) ;
2011-05-31 04:50:06 +00:00
double rmx = w . rmax_x - w . rmin_x ;
double px = ( ( 1 / rmx ) * ( w . min_x - w . rmin_x ) ) * width ;
double py = ( ( 1 / rmx ) * ( w . max_x - w . rmin_x ) ) * width ;
2011-06-11 10:20:44 +00:00
2011-06-11 11:03:44 +00:00
glColor4ub ( col2 . Red ( ) , col2 . Green ( ) , col2 . Blue ( ) , col2 . Alpha ( ) ) ;
2011-06-11 10:20:44 +00:00
glLineWidth ( 4 ) ;
glBegin ( GL_LINES ) ;
2011-06-11 18:11:14 +00:00
glVertex2f ( start_px + px , h ) ;
glVertex2f ( start_px + py , h ) ;
2011-06-11 10:20:44 +00:00
glEnd ( ) ;
2011-06-15 15:43:33 +00:00
if ( ( m_funkbar ) ) { // && ((w.min_x>w.rmin_x) || (w.max_x<w.rmax_x))) {
glColor4f ( .8 , .8 , .8 , .6 ) ;
glEnable ( GL_BLEND ) ;
glBegin ( GL_QUADS ) ;
glVertex2f ( start_px + px , w . GetBottomMargin ( ) ) ;
glVertex2f ( start_px + px , w . GetBottomMargin ( ) + height ) ;
glVertex2f ( start_px + py , w . GetBottomMargin ( ) + height ) ;
glVertex2f ( start_px + py , w . GetBottomMargin ( ) ) ;
glEnd ( ) ;
glDisable ( GL_BLEND ) ;
}
2011-05-31 04:50:06 +00:00
}
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
gCandleStick : : gCandleStick ( gPointData * d , wxOrientation o )
: gLayer ( d )
{
m_direction = o ;
}
gCandleStick : : ~ gCandleStick ( )
{
}
2011-06-13 19:37:25 +00:00
void gCandleStick : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-30 22:53:48 +00:00
{
if ( ! m_visible ) return ;
if ( ! data ) return ;
if ( ! data - > IsReady ( ) ) return ;
int start_px = w . GetLeftMargin ( ) ;
2011-06-13 19:37:25 +00:00
int start_py = w . GetBottomMargin ( ) ;
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) - 1 ;
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) - 1 ;
2011-05-30 22:53:48 +00:00
float sum = 0 ;
for ( int i = 0 ; i < data - > np [ 0 ] ; i + + )
2011-06-10 15:37:19 +00:00
sum + = data - > point [ 0 ] [ i ] . m_y ;
2011-05-30 22:53:48 +00:00
float pxr ;
float px ;
if ( m_direction = = wxVERTICAL ) {
pxr = height / sum ;
px = start_py ;
} else {
pxr = width / sum ;
px = start_px ;
}
2011-06-13 19:37:25 +00:00
float x , y ;
2011-05-30 22:53:48 +00:00
2011-06-13 19:37:25 +00:00
float t1 , t2 ;
2011-06-07 11:26:10 +00:00
int barwidth ;
if ( m_direction = = wxVERTICAL ) {
barwidth = width ;
} else {
barwidth = height ;
}
2011-05-30 22:53:48 +00:00
2011-06-16 10:10:02 +00:00
const wxColor & col2 = * wxLIGHT_GREY ;
wxColor c ( 0 , 0 , 0 , 255 ) ;
2011-05-30 22:53:48 +00:00
wxString str ;
2011-06-16 10:10:02 +00:00
wxRect rect ;
wxDirection dir ;
2011-05-30 22:53:48 +00:00
for ( int i = 0 ; i < data - > np [ 0 ] ; i + + ) {
t1 = floor ( px ) ;
2011-06-10 15:37:19 +00:00
t2 = data - > point [ 0 ] [ i ] . m_y * pxr ;
2011-05-30 22:53:48 +00:00
px + = t2 ;
2011-06-16 10:53:56 +00:00
t2 = ceil ( t2 ) ;
2011-05-26 13:59:21 +00:00
if ( m_direction = = wxVERTICAL ) {
2011-05-30 22:53:48 +00:00
rect = wxRect ( start_px , t1 , barwidth , t2 ) ;
dir = wxEAST ;
2011-05-26 13:59:21 +00:00
} else {
2011-05-30 22:53:48 +00:00
rect = wxRect ( t1 , start_py , t2 , barwidth ) ;
dir = wxSOUTH ;
2011-05-26 13:59:21 +00:00
}
2011-06-13 19:37:25 +00:00
const wxColor & col1 = color [ i % color . size ( ) ] ;
glBegin ( GL_QUADS ) ;
glColor4ub ( col1 . Red ( ) , col1 . Green ( ) , col1 . Blue ( ) , col1 . Alpha ( ) ) ;
2011-06-16 21:21:52 +00:00
glVertex2f ( rect . x + 1 , rect . y + height ) ;
2011-06-13 19:37:25 +00:00
glVertex2f ( rect . x + rect . width , rect . y + height ) ;
glColor4ub ( col2 . Red ( ) , col2 . Green ( ) , col2 . Blue ( ) , col2 . Alpha ( ) ) ;
2011-06-16 21:21:52 +00:00
glVertex2f ( rect . x + rect . width , rect . y + 1 ) ;
glVertex2f ( rect . x + 1 , rect . y + 1 ) ;
2011-06-13 19:37:25 +00:00
glEnd ( ) ;
2011-06-16 21:21:52 +00:00
glColor4ub ( 0 , 0 , 0 , 255 ) ;
glBegin ( GL_LINE_LOOP ) ;
glVertex2f ( rect . x + 1 , rect . y + height ) ;
glVertex2f ( rect . x + rect . width , rect . y + height ) ;
glVertex2f ( rect . x + rect . width , rect . y + 1 ) ;
glVertex2f ( rect . x + 1 , rect . y + 1 ) ;
glEnd ( ) ;
//LinedRoundedRectangle(rect.x,rect.y,rect.width,rect.height,0,1,c);
2011-06-13 19:37:25 +00:00
2011-05-30 22:53:48 +00:00
str = wxT ( " " ) ;
2011-06-04 02:38:18 +00:00
if ( ( int ) m_names . size ( ) > i ) {
2011-05-30 22:53:48 +00:00
str = m_names [ i ] + wxT ( " " ) ;
}
2011-06-10 15:37:19 +00:00
str + = wxString : : Format ( wxT ( " %0.1f " ) , data - > point [ 0 ] [ i ] . m_x ) ;
2011-06-13 19:37:25 +00:00
GetTextExtent ( str , x , y ) ;
2011-06-16 10:53:56 +00:00
//x+=5;
if ( t2 > x + 5 ) {
2011-06-10 15:37:19 +00:00
int j = t1 + ( ( t2 / 2 ) - ( x / 2 ) ) ;
2011-05-26 13:59:21 +00:00
if ( m_direction = = wxVERTICAL ) {
2011-06-13 19:37:25 +00:00
DrawText ( str , start_px + barwidth + 2 + y , j , 270.0 , * wxBLACK ) ;
2011-05-26 13:59:21 +00:00
} else {
2011-06-14 05:56:56 +00:00
DrawText ( str , j , start_py + ( barwidth / 2 ) - ( y / 2 ) + 1 ) ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
}
2011-06-16 10:10:02 +00:00
} // for (int i
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
gBarChart : : gBarChart ( gPointData * d , const wxColor * col , wxOrientation o )
2011-05-26 13:59:21 +00:00
: gLayer ( d ) , m_direction ( o )
{
2011-05-30 22:53:48 +00:00
if ( col ) {
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-05-30 22:53:48 +00:00
}
2011-05-31 04:50:06 +00:00
Xaxis = new gXAxis ( wxBLACK ) ;
2011-05-26 13:59:21 +00:00
}
gBarChart : : ~ gBarChart ( )
{
2011-05-30 22:53:48 +00:00
delete Xaxis ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
2011-06-13 19:37:25 +00:00
void gBarChart : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-26 13:59:21 +00:00
{
if ( ! m_visible ) return ;
if ( ! data ) return ;
2011-05-30 22:53:48 +00:00
if ( ! data - > IsReady ( ) ) return ;
2011-05-26 13:59:21 +00:00
int start_px = w . GetLeftMargin ( ) ;
2011-06-11 18:11:14 +00:00
int start_py = w . GetBottomMargin ( ) ;
2011-05-26 13:59:21 +00:00
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) ;
2011-05-30 22:53:48 +00:00
double xx = w . max_x - w . min_x ;
double days = int ( xx ) ;
//days=data->np[0];
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
days = 0 ;
for ( int i = 0 ; i < data - > np [ 0 ] ; i + + ) {
2011-06-10 15:37:19 +00:00
if ( ( data - > point [ 0 ] [ i ] . m_x > = w . min_x ) & & ( data - > point [ 0 ] [ i ] . m_x < w . max_x ) ) days + = 1 ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
if ( days = = 0 ) return ;
2011-05-26 13:59:21 +00:00
float barwidth , pxr ;
2011-06-04 02:38:18 +00:00
float px ; //,py;
2011-05-26 13:59:21 +00:00
if ( m_direction = = wxVERTICAL ) {
2011-05-30 22:53:48 +00:00
barwidth = ( height - days ) / float ( days ) ;
pxr = width / w . max_y ;
2011-05-26 13:59:21 +00:00
px = start_py ;
} else {
2011-05-30 22:53:48 +00:00
barwidth = ( width - days ) / float ( days ) ;
pxr = height / w . max_y ;
2011-05-26 13:59:21 +00:00
px = start_px ;
}
px + = 1 ;
int t1 , t2 ;
int u1 , u2 ;
2011-06-11 18:11:14 +00:00
float textX , textY ;
2011-06-13 19:37:25 +00:00
2011-05-26 13:59:21 +00:00
wxString str ;
2011-05-30 22:53:48 +00:00
bool draw_xticks_instead = false ;
2011-05-26 13:59:21 +00:00
2011-05-30 22:53:48 +00:00
for ( int i = 0 ; i < data - > np [ 0 ] ; i + + ) {
2011-06-10 15:37:19 +00:00
if ( data - > point [ 0 ] [ i ] . m_x < w . min_x ) continue ;
if ( data - > point [ 0 ] [ i ] . m_x > = w . max_x ) break ;
2011-05-30 22:53:48 +00:00
t1 = px ;
px + = barwidth + 1 ;
2011-05-26 13:59:21 +00:00
t2 = px - t1 - 1 ;
wxRect rect ;
wxDirection dir ;
2011-06-10 15:37:19 +00:00
u2 = data - > point [ 0 ] [ i ] . m_y * pxr ;
2011-06-11 18:11:14 +00:00
u1 = start_py ;
2011-05-30 22:53:48 +00:00
if ( m_direction = = wxVERTICAL ) {
rect = wxRect ( start_px , t1 , u2 , t2 ) ;
} else {
2011-05-26 13:59:21 +00:00
rect = wxRect ( t1 , u1 , t2 , u2 ) ;
}
2011-05-30 22:53:48 +00:00
dir = wxEAST ;
2011-06-11 11:22:33 +00:00
//RoundedRectangle(rect.x,rect.y,rect.width,rect.height,1,color[0]); //,*wxLIGHT_GREY,dir);
2011-06-11 18:11:14 +00:00
// TODO: Put this in a function..
2011-06-11 11:22:33 +00:00
wxColor & col1 = color [ 0 ] ;
wxColor & col2 = * ( ( wxColor * ) wxLIGHT_GREY ) ;
glBegin ( GL_QUADS ) ;
//red color
glColor4ub ( col1 . Red ( ) , col1 . Green ( ) , col1 . Blue ( ) , col1 . Alpha ( ) ) ;
glVertex2f ( rect . x , rect . y + rect . height ) ;
glVertex2f ( rect . x , rect . y ) ;
//blue color
glColor4ub ( col2 . Red ( ) , col2 . Green ( ) , col2 . Blue ( ) , col2 . Alpha ( ) ) ;
glVertex2f ( rect . x + rect . width , rect . y ) ;
glVertex2f ( rect . x + rect . width , rect . y + rect . height ) ;
glEnd ( ) ;
2011-06-11 10:20:44 +00:00
wxColor c ( 0 , 0 , 0 , 255 ) ;
LinedRoundedRectangle ( rect . x , rect . y , rect . width , rect . height , 0 , 1 , c ) ;
2011-05-26 13:59:21 +00:00
2011-06-10 15:37:19 +00:00
str = FormatX ( data - > point [ 0 ] [ i ] . m_x ) ;
2011-06-11 18:11:14 +00:00
GetTextExtent ( str , textX , textY ) ;
2011-06-15 11:44:02 +00:00
if ( t2 > textY + 6 ) {
2011-05-26 13:59:21 +00:00
int j = t1 + ( ( t2 / 2 ) - ( textY / 2 ) ) ;
if ( m_direction = = wxVERTICAL ) {
2011-06-11 18:11:14 +00:00
DrawText ( str , start_px - textX - 8 , j ) ;
2011-05-26 13:59:21 +00:00
} else {
2011-06-15 11:44:02 +00:00
DrawText ( str , j , start_py - 18 - ( textX / 2 ) , 90 , * wxBLACK ) ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
} else draw_xticks_instead = true ;
2011-05-26 13:59:21 +00:00
}
2011-05-30 22:53:48 +00:00
if ( draw_xticks_instead )
2011-06-13 19:37:25 +00:00
Xaxis - > Plot ( w , scrx , scry ) ;
2011-05-26 13:59:21 +00:00
2011-06-11 18:11:14 +00:00
glColor3f ( 0.1F , 0.1F , 0.1F ) ;
2011-06-16 10:10:02 +00:00
glLineWidth ( 1 ) ;
2011-06-11 18:11:14 +00:00
glBegin ( GL_LINES ) ;
glVertex2f ( start_px , start_py ) ;
glVertex2f ( start_px , start_py + height ) ;
glVertex2f ( start_px , start_py ) ;
glVertex2f ( start_px + width , start_py ) ;
glEnd ( ) ;
2011-05-26 13:59:21 +00:00
}
2011-06-01 13:08:44 +00:00
gLineChart : : gLineChart ( gPointData * d , const wxColor * col , int dlsize , bool _accelerate , bool _hide_axes , bool _square_plot )
: gLayer ( d ) , m_accelerate ( _accelerate ) , m_drawlist_size ( dlsize ) , m_hide_axes ( _hide_axes ) , m_square_plot ( _square_plot )
2011-05-26 13:59:21 +00:00
{
2011-06-12 10:10:47 +00:00
m_drawlist = new wxRealPoint [ dlsize ] ;
2011-05-26 13:59:21 +00:00
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-06-06 16:05:02 +00:00
m_report_empty = false ;
2011-05-26 13:59:21 +00:00
}
gLineChart : : ~ gLineChart ( )
{
delete [ ] m_drawlist ;
}
// Time Domain Line Chart
2011-06-13 19:37:25 +00:00
void gLineChart : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-26 13:59:21 +00:00
{
if ( ! m_visible ) return ;
if ( ! data ) return ;
if ( ! data - > IsReady ( ) ) return ;
2011-06-11 18:11:14 +00:00
int start_px = w . GetLeftMargin ( ) , start_py = w . GetBottomMargin ( ) ;
2011-05-26 13:59:21 +00:00
2011-06-10 11:21:20 +00:00
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) ;
2011-05-26 13:59:21 +00:00
2011-06-10 11:21:20 +00:00
double minx = w . min_x , miny = w . min_y , maxx = w . max_x , maxy = w . max_y ;
double xx = maxx - minx , yy = maxy - miny ;
2011-06-12 10:10:47 +00:00
float xmult = width / xx , ymult = height / yy ; // time to pixel conversion multiplier
2011-05-26 13:59:21 +00:00
2011-06-10 11:21:20 +00:00
// Return on screwy min/max conditions
if ( ( xx < 0 ) | | ( yy < 0 ) ) return ;
if ( ( yy = = 0 ) & & ( miny = = 0 ) ) return ;
2011-05-31 02:18:41 +00:00
2011-06-10 11:21:20 +00:00
int num_points = 0 ;
for ( int z = 0 ; z < data - > VC ( ) ; z + + ) num_points + = data - > np [ z ] ; // how many points all up?
2011-05-26 13:59:21 +00:00
2011-06-10 11:21:20 +00:00
// Draw bounding box if something else will be drawn.
if ( ! ( ! m_report_empty & & ! num_points ) ) {
2011-06-11 10:20:44 +00:00
glColor3f ( 0.1F , 0.1F , 0.1F ) ;
glLineWidth ( 1 ) ;
glBegin ( GL_LINE_LOOP ) ;
glVertex2f ( start_px , start_py ) ;
glVertex2f ( start_px , start_py + height ) ;
glVertex2f ( start_px + width , start_py + height ) ;
glVertex2f ( start_px + width , start_py ) ;
glEnd ( ) ;
2011-06-10 11:21:20 +00:00
}
2011-06-06 16:05:02 +00:00
2011-06-10 11:21:20 +00:00
width - - ;
if ( ! num_points ) { // No Data?
if ( m_report_empty ) {
2011-06-06 16:05:02 +00:00
wxString msg = _ ( " No Waveform Available " ) ;
2011-06-16 08:18:48 +00:00
float x , y ;
2011-06-16 15:44:24 +00:00
//TextMarkup...
2011-06-16 10:53:56 +00:00
GetTextExtent ( msg , x , y , bigfont ) ;
DrawText ( msg , start_px + ( width / 2.0 ) - ( x / 2.0 ) , start_py + ( height / 2.0 ) - ( y / 2.0 ) , 0 , * wxDARK_GREY , bigfont ) ;
2011-06-06 16:05:02 +00:00
}
2011-06-10 11:21:20 +00:00
return ;
2011-06-06 15:35:54 +00:00
}
2011-06-06 16:05:02 +00:00
2011-06-10 11:21:20 +00:00
bool accel = m_accelerate ;
2011-06-16 15:44:24 +00:00
double sfit , sr ;
int dp , sam ;
2011-06-10 11:21:20 +00:00
2011-06-12 10:10:47 +00:00
wxColor & col = color [ 0 ] ;
// Selected the plot line color
2011-06-16 08:18:48 +00:00
2011-06-16 10:53:56 +00:00
const int maxverts = 65536 * 2 ; // Resolution dependant..
2011-06-16 08:18:48 +00:00
int vertcnt = 0 ;
2011-06-16 10:10:02 +00:00
static GLshort vertarray [ maxverts + 8 ] ;
2011-06-16 08:18:48 +00:00
2011-06-12 10:10:47 +00:00
float lastpx , lastpy ;
float px , py ;
2011-06-16 15:44:24 +00:00
int idx , idxend , np ;
bool done , first ;
double x0 , x1 , xL ;
2011-06-16 16:03:34 +00:00
int visible_points = 0 ;
2011-06-16 15:44:24 +00:00
for ( int n = 0 ; n < data - > VC ( ) ; n + + ) { // for each segment
int siz = data - > np [ n ] ;
if ( siz < = 1 ) continue ; // Don't bother drawing 1 point or less.
2011-06-10 11:21:20 +00:00
2011-06-10 15:37:19 +00:00
wxPoint2DDouble * point = data - > point [ n ] ;
2011-06-10 11:21:20 +00:00
2011-06-16 15:44:24 +00:00
x0 = point [ 0 ] . m_x ;
xL = point [ siz - 1 ] . m_x ;
2011-06-16 08:18:48 +00:00
2011-06-16 15:44:24 +00:00
if ( maxx < x0 ) continue ;
if ( xL < minx ) continue ;
2011-06-16 08:18:48 +00:00
2011-06-16 15:44:24 +00:00
if ( x0 > xL ) {
if ( siz = = 2 ) { // this happens on CPAP
wxPoint2DDouble t = point [ 0 ] ;
point [ 0 ] = point [ siz - 1 ] ;
point [ siz - 1 ] = t ;
x0 = point [ 0 ] . m_x ;
2011-05-26 13:59:21 +00:00
} else {
2011-06-16 15:44:24 +00:00
wxLogDebug ( wxT ( " Reversed order sample fed to gLineChart - ignored. " ) ) ;
continue ;
//assert(x1<x2);
2011-05-26 13:59:21 +00:00
}
2011-06-16 15:44:24 +00:00
}
done = false ;
first = true ;
dp = 0 ;
2011-05-26 13:59:21 +00:00
2011-06-16 15:44:24 +00:00
x1 = point [ 1 ] . m_x ;
// if (accel) {
sr = x1 - x0 ; // Time distance between samples
double qx = xL - x0 ; // Full time range of this segment
double gx = xx / qx ; // ratio of how much of the whole data set this represents
double segwidth = width * gx ;
double XR = xx / sr ;
double Z1 = MAX ( x0 , minx ) ;
double Z2 = MIN ( xL , maxx ) ;
double ZD = Z2 - Z1 ;
double ZR = ZD / sr ;
double ZQ = ZR / XR ;
double ZW = ZR / ( width * ZQ ) ;
const int num_averages = 15 ; // Number of samples taken from samples per pixel for better min/max values
2011-06-16 16:03:34 +00:00
visible_points + = ZR * ZQ ;
2011-06-16 15:44:24 +00:00
if ( accel & & n > 0 ) {
sam = 1 ;
}
if ( ZW < num_averages ) {
sam = 1 ;
accel = false ;
} else {
sam = ZW / num_averages ;
if ( sam < 1 ) {
sam = 1 ;
accel = false ;
}
}
2011-05-26 13:59:21 +00:00
2011-06-10 11:21:20 +00:00
// Prepare the min max y values if we still are accelerating this plot
2011-05-26 13:59:21 +00:00
if ( accel ) {
for ( int i = 0 ; i < width ; i + + ) {
m_drawlist [ i ] . x = height ;
m_drawlist [ i ] . y = 0 ;
}
}
int minz = width , maxz = 0 ;
2011-06-12 10:10:47 +00:00
// Technically shouldn't never ever get fed reverse data.
2011-06-16 08:18:48 +00:00
2011-06-16 15:44:24 +00:00
// these calculations over estimate
// The Z? values are much more accurate
idx = 0 ;
idxend = 0 ;
np = 0 ;
2011-06-16 10:53:56 +00:00
if ( m_accelerate ) {
if ( minx > x1 ) {
2011-06-16 15:44:24 +00:00
double j = minx - x0 ; // == starting min of first sample in this segment
2011-06-16 10:53:56 +00:00
idx = floor ( j / sr ) ;
2011-06-16 15:44:24 +00:00
// Loose the precision
idx - = idx % sam ;
2011-06-16 10:53:56 +00:00
} // else just start from the beginning
idxend = floor ( xx / sr ) ;
idxend / = sam ; // devide by number of samples skips
2011-06-16 15:44:24 +00:00
2011-06-16 10:53:56 +00:00
np = ( idxend - idx ) + sam ;
np / = sam ;
} else {
2011-06-16 15:44:24 +00:00
2011-06-16 10:53:56 +00:00
np = siz ;
}
2011-06-16 08:18:48 +00:00
2011-06-16 10:53:56 +00:00
bool watch_verts_carefully = false ;
2011-06-16 08:18:48 +00:00
// better to do it here than in the main loop.
2011-06-16 10:53:56 +00:00
np < < = 2 ;
if ( ! accel & & m_square_plot )
np < < = 1 ; // double it again
if ( np > = maxverts ) {
watch_verts_carefully = true ;
//assert(np<maxverts);
2011-06-16 08:18:48 +00:00
}
2011-05-28 09:16:46 +00:00
2011-06-12 10:10:47 +00:00
bool firstpx = true ;
2011-06-16 08:18:48 +00:00
for ( int i = idx ; i < siz ; i + = sam ) {
2011-06-10 11:21:20 +00:00
2011-06-10 15:37:19 +00:00
if ( point [ i ] . m_x < minx ) continue ; // Skip stuff before the start of our data window
2011-06-10 11:21:20 +00:00
2011-05-28 09:16:46 +00:00
if ( first ) {
first = false ;
2011-06-10 11:21:20 +00:00
if ( i > = sam ) i - = sam ; // Start with the previous sample (which will be in clipping area)
2011-05-28 09:16:46 +00:00
}
2011-05-26 13:59:21 +00:00
2011-06-10 15:37:19 +00:00
if ( point [ i ] . m_x > maxx ) done = true ; // Let this iteration finish.. (This point will be in far clipping)
2011-06-10 11:21:20 +00:00
2011-06-11 18:11:14 +00:00
px = 1 + ( ( point [ i ] . m_x - minx ) * xmult ) ; // Scale the time scale X to pixel scale X
2011-05-26 13:59:21 +00:00
2011-06-12 10:10:47 +00:00
if ( ! accel ) {
2011-06-16 15:44:24 +00:00
py = 1 + ( ( point [ i ] . m_y - miny ) * ymult ) ; // Same for Y scale
2011-06-12 10:10:47 +00:00
if ( firstpx ) {
firstpx = false ;
} else {
if ( m_square_plot ) {
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = lastpx ;
vertarray [ vertcnt + + ] = lastpy ;
vertarray [ vertcnt + + ] = start_px + px ;
vertarray [ vertcnt + + ] = lastpy ;
vertarray [ vertcnt + + ] = start_px + px ;
vertarray [ vertcnt + + ] = lastpy ;
2011-06-12 10:10:47 +00:00
} else {
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = lastpx ;
vertarray [ vertcnt + + ] = lastpy ;
2011-06-12 10:10:47 +00:00
}
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = start_px + px ;
vertarray [ vertcnt + + ] = start_py + py ;
# if defined(EXTRA_ASSERTS)
assert ( vertcnt < maxverts ) ;
# endif
2011-06-12 10:10:47 +00:00
}
lastpx = start_px + px ;
lastpy = start_py + py ;
} else {
2011-06-10 11:21:20 +00:00
// Just clip ugly in accel mode.. Too darn complicated otherwise
2011-06-16 15:44:24 +00:00
/* if (px<0) {
2011-06-10 11:21:20 +00:00
px = 0 ;
}
if ( px > width ) {
px = width ;
2011-06-16 15:44:24 +00:00
} */
2011-06-10 11:21:20 +00:00
// In accel mode, each pixel has a min/max Y value.
// m_drawlist's index is the pixel index for the X pixel axis.
2011-06-16 15:44:24 +00:00
float zz = ( maxy - miny ) / 2.0 ; // centreline
float jy = fabs ( point [ i ] . m_y ) ;
int y1 = 1 + ( jy - miny ) * ymult ;
int y2 = 1 + ( - jy - miny ) * ymult ;
//py=1+((point[i].m_y - miny) * ymult); // Same for Y scale
2011-05-26 13:59:21 +00:00
int z = round ( px ) ;
2011-06-10 11:21:20 +00:00
if ( z < minz ) minz = z ; // minz=First pixel
if ( z > maxz ) maxz = z ; // maxz=Last pixel
// Update the Y pixel bounds.
2011-06-16 15:44:24 +00:00
if ( y2 < m_drawlist [ z ] . x ) m_drawlist [ z ] . x = y2 ;
if ( y1 > m_drawlist [ z ] . y ) m_drawlist [ z ] . y = y1 ;
2011-06-10 11:21:20 +00:00
2011-05-26 13:59:21 +00:00
}
2011-06-12 10:10:47 +00:00
2011-05-26 13:59:21 +00:00
if ( done ) break ;
}
if ( accel ) {
dp = 0 ;
2011-06-12 10:10:47 +00:00
// Plot compressed accelerated vertex list
2011-06-09 10:25:26 +00:00
for ( int i = minz ; i < maxz ; i + + ) {
2011-06-16 08:18:48 +00:00
vertarray [ vertcnt + + ] = start_px + i + 1 ;
vertarray [ vertcnt + + ] = start_py + m_drawlist [ i ] . x ;
vertarray [ vertcnt + + ] = start_px + i + 1 ;
vertarray [ vertcnt + + ] = start_py + m_drawlist [ i ] . y ;
# if defined(EXTRA_ASSERTS)
assert ( vertcnt < maxverts ) ;
# endif
2011-06-11 10:20:44 +00:00
}
2011-05-26 13:59:21 +00:00
}
2011-06-16 15:44:24 +00:00
}
2011-06-16 08:18:48 +00:00
2011-06-16 16:03:34 +00:00
wxString b ;
int j = vertcnt / 2 ;
if ( accel ) j / = 2 ;
b < < visible_points < < wxT ( " " ) < < ( sam ) < < wxT ( " " ) < < num_points < < wxT ( " " ) < < j ;
float x , y ;
GetTextExtent ( b , x , y ) ;
DrawText ( b , scrx - w . GetRightMargin ( ) - x - 15 , scry - w . GetTopMargin ( ) - 10 ) ;
2011-06-16 15:44:24 +00:00
glColor4ub ( col . Red ( ) , col . Green ( ) , col . Blue ( ) , 255 ) ;
// Crop to inside the margins.
2011-06-16 15:47:42 +00:00
glScissor ( w . GetLeftMargin ( ) , w . GetBottomMargin ( ) , width , height ) ;
glEnable ( GL_SCISSOR_TEST ) ;
2011-06-16 15:44:24 +00:00
glLineWidth ( 1 ) ;
bool antialias = pref [ " UseAntiAliasing " ] ;
if ( antialias ) {
glEnable ( GL_BLEND ) ;
2011-06-16 21:21:52 +00:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ; //_MINUS_SRC_ALPHA);
2011-06-16 15:44:24 +00:00
glEnable ( GL_LINE_SMOOTH ) ;
glHint ( GL_LINE_SMOOTH_HINT , GL_NICEST ) ;
2011-06-16 21:21:52 +00:00
2011-06-16 15:44:24 +00:00
}
2011-06-16 16:03:34 +00:00
2011-06-16 15:44:24 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , vertarray ) ;
glDrawArrays ( GL_LINES , 0 , vertcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
if ( antialias ) {
glDisable ( GL_LINE_SMOOTH ) ;
glDisable ( GL_BLEND ) ;
2011-05-26 13:59:21 +00:00
}
2011-06-16 15:47:42 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2011-05-26 13:59:21 +00:00
}
2011-05-27 11:35:45 +00:00
gLineOverlayBar : : gLineOverlayBar ( gPointData * d , const wxColor * col , wxString _label , LO_Type _lot )
: gLayer ( d ) , label ( _label ) , lo_type ( _lot )
2011-05-26 13:59:21 +00:00
{
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-05-26 13:59:21 +00:00
}
gLineOverlayBar : : ~ gLineOverlayBar ( )
{
}
2011-06-14 09:51:05 +00:00
//nov = number of vertex
//r = radius
void Dot ( int nov , float r )
{
if ( nov < 4 ) nov = 4 ;
if ( nov > 360 ) nov = 360 ;
float angle = ( 360 / nov ) * ( 3.142159 / 180 ) ;
float x [ 360 ] = { 0 } ;
float y [ 360 ] = { 0 } ;
for ( int i = 0 ; i < nov ; i + + ) {
x [ i ] = cosf ( r * cosf ( i * angle ) ) ;
y [ i ] = sinf ( r * sinf ( i * angle ) ) ;
glBegin ( GL_POLYGON ) ;
for ( int i = 0 ; i < nov ; i + + ) {
glVertex2f ( x [ i ] , y [ i ] ) ;
}
glEnd ( ) ;
}
//render to texture and map to GL_POINT_SPRITE
}
2011-06-13 19:37:25 +00:00
void gLineOverlayBar : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-26 13:59:21 +00:00
{
if ( ! m_visible ) return ;
if ( ! data ) return ;
if ( ! data - > IsReady ( ) ) return ;
2011-06-15 00:28:39 +00:00
//int start_px=w.GetLeftMargin();
2011-06-11 18:11:14 +00:00
int start_py = w . GetBottomMargin ( ) ;
2011-05-26 13:59:21 +00:00
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) ;
double xx = w . max_x - w . min_x ;
if ( xx < = 0 ) return ;
2011-06-11 10:20:44 +00:00
2011-06-12 10:55:42 +00:00
float x1 , x2 ;
float x , y ; //,descent,leading;
2011-05-26 13:59:21 +00:00
2011-06-12 10:55:42 +00:00
// Crop to inside the margins.
glScissor ( w . GetLeftMargin ( ) , w . GetBottomMargin ( ) , width , height ) ;
glEnable ( GL_SCISSOR_TEST ) ;
2011-05-26 13:59:21 +00:00
2011-06-16 10:10:02 +00:00
const int maxverts = 65536 ;
int vertcnt = 0 ;
static GLshort vertarray [ maxverts + 8 ] ;
int pointcnt = 0 ;
static GLshort pointarray [ maxverts + 8 ] ;
int quadcnt = 0 ;
static GLshort quadarray [ maxverts + 8 ] ;
float bottom = start_py + 25 , top = start_py + height - 25 ;
2011-06-11 11:03:44 +00:00
wxColor & col = color [ 0 ] ;
2011-05-26 13:59:21 +00:00
for ( int n = 0 ; n < data - > VC ( ) ; n + + ) {
2011-06-15 00:28:39 +00:00
// bool done=false;
2011-06-16 10:10:02 +00:00
for ( int i = 0 ; i < data - > np [ n ] ; i + + ) {
wxPoint2DDouble & rp = data - > point [ n ] [ i ] ;
if ( rp . m_y < w . min_x ) continue ;
if ( rp . m_x > w . max_x ) break ;
x1 = w . x2p ( rp . m_x ) ;
if ( rp . m_x ! = rp . m_y ) {
2011-06-12 10:55:42 +00:00
x2 = w . x2p ( rp . m_y ) ;
2011-06-16 10:10:02 +00:00
//double w1=x2-x1;
quadarray [ quadcnt + + ] = x1 ;
quadarray [ quadcnt + + ] = start_py ;
quadarray [ quadcnt + + ] = x1 ;
quadarray [ quadcnt + + ] = start_py + height ;
quadarray [ quadcnt + + ] = x2 ;
quadarray [ quadcnt + + ] = start_py + height ;
quadarray [ quadcnt + + ] = x2 ;
quadarray [ quadcnt + + ] = start_py ;
} else {
if ( lo_type = = LOT_Dot ) {
pointarray [ pointcnt + + ] = x1 ;
pointarray [ pointcnt + + ] = top - 15 ;
} else if ( lo_type = = LOT_Bar ) {
pointarray [ pointcnt + + ] = x1 ;
pointarray [ pointcnt + + ] = top ;
vertarray [ vertcnt + + ] = x1 ;
vertarray [ vertcnt + + ] = top ;
vertarray [ vertcnt + + ] = x1 ;
vertarray [ vertcnt + + ] = bottom ;
2011-05-27 11:35:45 +00:00
if ( xx < ( 1800.0 / 86400 ) ) {
2011-06-11 18:11:14 +00:00
GetTextExtent ( label , x , y ) ;
DrawText ( label , x1 - ( x / 2 ) , start_py + height - 30 + y ) ;
2011-06-16 10:10:02 +00:00
}
2011-05-26 13:59:21 +00:00
}
}
}
}
2011-06-16 10:10:02 +00:00
assert ( vertcnt < maxverts ) ;
assert ( quadcnt < maxverts ) ;
assert ( pointcnt < maxverts ) ;
glColor4ub ( col . Red ( ) , col . Green ( ) , col . Blue ( ) , col . Alpha ( ) ) ;
if ( quadcnt > 0 ) {
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , quadarray ) ;
glDrawArrays ( GL_QUADS , 0 , quadcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
}
if ( vertcnt > 0 ) {
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , vertarray ) ;
glDrawArrays ( GL_LINES , 0 , vertcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
}
if ( pointcnt > 0 ) {
glPointSize ( 4 ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , pointarray ) ;
glDrawArrays ( GL_POINTS , 0 , pointcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
}
2011-06-12 10:55:42 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2011-05-26 13:59:21 +00:00
}
gFlagsLine : : gFlagsLine ( gPointData * d , const wxColor * col , wxString _label , int _line_num , int _total_lines )
: gLayer ( d ) , label ( _label ) , line_num ( _line_num ) , total_lines ( _total_lines )
{
color . clear ( ) ;
2011-06-11 11:03:44 +00:00
color . push_back ( * col ) ;
2011-05-26 13:59:21 +00:00
}
gFlagsLine : : ~ gFlagsLine ( )
{
}
2011-06-13 19:37:25 +00:00
void gFlagsLine : : Plot ( gGraphWindow & w , float scrx , float scry )
2011-05-26 13:59:21 +00:00
{
if ( ! m_visible ) return ;
if ( ! data ) return ;
if ( ! data - > IsReady ( ) ) return ;
2011-05-31 04:28:11 +00:00
2011-06-15 15:43:33 +00:00
double minx ;
double maxx ;
if ( w . BlockZoom ( ) ) {
minx = w . rmin_x ;
maxx = w . rmax_x ;
} else {
minx = w . min_x ;
maxx = w . max_x ;
}
double xx = maxx - minx ;
2011-05-31 04:28:11 +00:00
if ( xx < = 0 ) return ;
2011-05-26 13:59:21 +00:00
int start_px = w . GetLeftMargin ( ) ;
2011-06-11 18:11:14 +00:00
int start_py = w . GetBottomMargin ( ) ;
2011-05-26 13:59:21 +00:00
int width = scrx - ( w . GetLeftMargin ( ) + w . GetRightMargin ( ) ) ;
int height = scry - ( w . GetTopMargin ( ) + w . GetBottomMargin ( ) ) ;
2011-06-15 15:43:33 +00:00
double xmult = width / xx ;
2011-06-11 18:11:14 +00:00
static wxColor col1 = wxColor ( 0xd0 , 0xff , 0xd0 , 0xff ) ;
static wxColor col2 = wxColor ( 0xff , 0xff , 0xff , 0xff ) ;
2011-05-26 13:59:21 +00:00
2011-06-11 18:11:14 +00:00
float line_h = float ( height - 2 ) / float ( total_lines ) ;
line_h = line_h ;
float line_top = ( start_py + height - line_h ) - line_num * line_h ;
2011-06-09 03:43:51 +00:00
2011-06-11 18:11:14 +00:00
if ( ( line_num = = total_lines - 1 ) ) { // last lines responsibility to draw the title.
2011-06-11 11:03:44 +00:00
glColor3f ( 0.1F , 0.1F , 0.1F ) ;
glLineWidth ( 1 ) ;
glBegin ( GL_LINE_LOOP ) ;
glVertex2f ( start_px - 1 , start_py ) ;
2011-06-11 18:11:14 +00:00
glVertex2f ( start_px - 1 , start_py + height ) ;
glVertex2f ( start_px + width , start_py + height ) ;
2011-06-11 11:03:44 +00:00
glVertex2f ( start_px + width , start_py ) ;
glEnd ( ) ;
2011-06-12 10:55:42 +00:00
}
2011-05-26 13:59:21 +00:00
2011-06-12 10:55:42 +00:00
// Alternating box color
2011-06-11 10:20:44 +00:00
wxColor * barcol = & col2 ;
2011-06-15 07:33:39 +00:00
if ( line_num & 1 )
2011-06-11 10:20:44 +00:00
barcol = & col1 ;
2011-06-12 10:55:42 +00:00
2011-06-15 07:33:39 +00:00
// Filled rectangle
glColor4ub ( barcol - > Red ( ) , barcol - > Green ( ) , barcol - > Blue ( ) , barcol - > Alpha ( ) ) ;
glBegin ( GL_QUADS ) ;
glVertex2f ( start_px , line_top ) ;
glVertex2f ( start_px , line_top + line_h ) ;
glVertex2f ( start_px + width , line_top + line_h ) ;
glVertex2f ( start_px + width , line_top ) ;
glEnd ( ) ;
2011-06-12 10:55:42 +00:00
2011-06-16 10:10:02 +00:00
const int maxverts = 65536 ;
int vertcnt = 0 ;
static GLshort vertarray [ maxverts + 8 ] ;
int quadcnt = 0 ;
static GLshort quadarray [ maxverts + 8 ] ;
2011-06-12 10:55:42 +00:00
// Draw text label
2011-06-11 18:11:14 +00:00
float x , y ;
2011-06-15 10:34:25 +00:00
GetTextExtent ( label , x , y ) ;
DrawText ( label , start_px - x - 6 , line_top + ( line_h / 2 ) - ( y / 2 ) ) ;
2011-05-26 13:59:21 +00:00
2011-06-16 10:53:56 +00:00
float x1 , x2 ;
2011-06-11 10:20:44 +00:00
2011-06-11 11:03:44 +00:00
wxColor & col = color [ 0 ] ;
2011-06-16 10:10:02 +00:00
float top = floor ( line_top ) + 2 ;
float bottom = top + floor ( line_h ) - 3 ;
2011-06-11 10:20:44 +00:00
2011-05-26 13:59:21 +00:00
for ( int n = 0 ; n < data - > VC ( ) ; n + + ) {
2011-06-15 07:33:39 +00:00
if ( ! data - > np [ n ] ) continue ;
2011-06-15 15:43:33 +00:00
2011-06-16 10:10:02 +00:00
for ( int i = 0 ; i < data - > np [ n ] ; i + + ) {
2011-06-10 15:37:19 +00:00
wxPoint2DDouble & rp = data - > point [ n ] [ i ] ;
2011-06-16 10:10:02 +00:00
if ( rp . m_y < minx ) continue ;
if ( rp . m_x > maxx ) break ;
x1 = ( rp . m_x - minx ) * xmult + w . GetLeftMargin ( ) ;
2011-06-10 15:37:19 +00:00
if ( rp . m_x = = rp . m_y ) {
2011-06-16 10:10:02 +00:00
vertarray [ vertcnt + + ] = x1 ;
vertarray [ vertcnt + + ] = top ;
vertarray [ vertcnt + + ] = x1 ;
vertarray [ vertcnt + + ] = bottom ;
} else {
2011-06-15 15:43:33 +00:00
x2 = ( rp . m_y - minx ) * xmult + w . GetLeftMargin ( ) ;
2011-06-16 10:10:02 +00:00
//w1=x2-x1;
quadarray [ quadcnt + + ] = x1 ;
quadarray [ quadcnt + + ] = top ;
quadarray [ quadcnt + + ] = x1 ;
quadarray [ quadcnt + + ] = bottom ;
quadarray [ quadcnt + + ] = x2 ;
quadarray [ quadcnt + + ] = bottom ;
quadarray [ quadcnt + + ] = x2 ;
quadarray [ quadcnt + + ] = top ;
2011-06-12 10:55:42 +00:00
}
2011-05-26 13:59:21 +00:00
}
2011-06-16 10:10:02 +00:00
}
glLineWidth ( 1 ) ;
2011-06-15 07:33:39 +00:00
2011-06-16 10:10:02 +00:00
glColor4ub ( col . Red ( ) , col . Green ( ) , col . Blue ( ) , col . Alpha ( ) ) ;
glScissor ( w . GetLeftMargin ( ) , w . GetBottomMargin ( ) , width , height ) ;
glEnable ( GL_SCISSOR_TEST ) ;
2011-06-17 00:28:46 +00:00
glLineWidth ( 1 ) ;
bool antialias = pref [ " UseAntiAliasing " ] ;
if ( antialias ) {
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ; //_MINUS_SRC_ALPHA);
glEnable ( GL_LINE_SMOOTH ) ;
glHint ( GL_LINE_SMOOTH_HINT , GL_NICEST ) ;
}
2011-06-16 10:10:02 +00:00
if ( quadcnt > 0 ) {
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , quadarray ) ;
glDrawArrays ( GL_QUADS , 0 , quadcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
}
if ( vertcnt > 0 ) {
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 2 , GL_SHORT , 0 , vertarray ) ;
glDrawArrays ( GL_LINES , 0 , vertcnt > > 1 ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
2011-05-26 13:59:21 +00:00
}
2011-06-17 00:28:46 +00:00
if ( antialias ) {
glDisable ( GL_LINE_SMOOTH ) ;
glDisable ( GL_BLEND ) ;
}
2011-06-12 10:55:42 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2011-05-26 13:59:21 +00:00
}
2011-06-06 10:06:57 +00:00
WaveData : : WaveData ( MachineCode _code , int _size )
: gPointData ( _size ) , code ( _code )
2011-05-26 13:59:21 +00:00
{
}
2011-06-06 10:06:57 +00:00
WaveData : : ~ WaveData ( )
2011-05-26 13:59:21 +00:00
{
}
2011-06-06 10:06:57 +00:00
void WaveData : : Reload ( Day * day )
2011-05-26 13:59:21 +00:00
{
vc = 0 ;
if ( ! day ) {
m_ready = false ;
return ;
}
2011-05-29 03:27:42 +00:00
min_x = day - > first ( ) . GetMJD ( ) ;
max_x = day - > last ( ) . GetMJD ( ) ;
2011-05-26 13:59:21 +00:00
max_y = 0 ;
bool first = true ;
2011-06-02 04:42:37 +00:00
for ( vector < Session * > : : iterator s = day - > begin ( ) ; s ! = day - > end ( ) ; s + + ) {
2011-05-26 13:59:21 +00:00
if ( ( * s ) - > waveforms . find ( code ) = = ( * s ) - > waveforms . end ( ) ) continue ;
2011-06-02 04:42:37 +00:00
for ( vector < Waveform * > : : iterator l = ( * s ) - > waveforms [ code ] . begin ( ) ; l ! = ( * s ) - > waveforms [ code ] . end ( ) ; l + + ) {
2011-05-28 03:41:44 +00:00
int ps = point . size ( ) ;
if ( vc > = ps ) {
2011-05-26 13:59:21 +00:00
AddSegment ( max_points ) ; // TODO: Add size limit capabilities.
}
int t = 0 ;
Waveform * w = ( * l ) ;
double st = w - > start ( ) . GetMJD ( ) ;
double rate = ( w - > duration ( ) / w - > samples ( ) ) / 86400.0 ;
for ( int i = 0 ; i < w - > samples ( ) ; i + + ) {
2011-06-10 15:37:19 +00:00
wxPoint2DDouble r ( st , ( * w ) [ i ] ) ;
2011-05-26 13:59:21 +00:00
st + = rate ;
point [ vc ] [ t + + ] = r ;
assert ( t < max_points ) ;
if ( first ) {
2011-06-10 15:37:19 +00:00
min_y = r . m_y ;
2011-05-26 13:59:21 +00:00
first = false ;
} else {
2011-06-10 15:37:19 +00:00
if ( r . m_y < min_y ) min_y = r . m_y ;
2011-05-26 13:59:21 +00:00
}
2011-06-10 15:37:19 +00:00
if ( r . m_y > max_y ) max_y = r . m_y ;
2011-05-26 13:59:21 +00:00
}
np [ vc ] = t ;
vc + + ;
}
}
min_y = floor ( min_y ) ;
max_y = ceil ( max_y ) ;
2011-05-29 03:27:42 +00:00
//double t1=MAX(fabs(min_y),fabs(max_y));
2011-06-06 10:06:57 +00:00
// Get clever here..
2011-06-01 13:08:44 +00:00
if ( max_y > 128 ) {
} else if ( max_y > 90 ) {
max_y = 120 ;
min_y = - 120 ;
} else if ( max_y > 60 ) {
min_y = - 90 ;
max_y = 90 ;
} else {
min_y = - 60 ;
max_y = 60 ;
}
2011-05-26 13:59:21 +00:00
2011-06-02 16:31:36 +00:00
if ( force_min_y ! = force_max_y ) {
min_y = force_min_y ;
max_y = force_max_y ;
}
2011-05-26 13:59:21 +00:00
real_min_x = min_x ;
real_min_y = min_y ;
real_max_x = max_x ;
real_max_y = max_y ;
m_ready = true ;
//graph->Refresh(false);
}
2011-06-06 04:31:11 +00:00
2011-06-06 10:06:57 +00:00
EventData : : EventData ( MachineCode _code , int _field , int _size , bool _skipzero )
: gPointData ( _size ) , code ( _code ) , field ( _field ) , skipzero ( _skipzero )
2011-06-06 03:37:31 +00:00
{
}
2011-06-06 10:06:57 +00:00
EventData : : ~ EventData ( )
2011-06-06 03:37:31 +00:00
{
}
2011-06-06 10:06:57 +00:00
void EventData : : Reload ( Day * day )
2011-06-06 03:37:31 +00:00
{
vc = 0 ;
if ( ! day ) {
m_ready = false ;
return ;
}
min_x = day - > first ( ) . GetMJD ( ) ;
max_x = day - > last ( ) . GetMJD ( ) ;
assert ( min_x < max_x ) ;
min_y = max_y = 0 ;
int tt = 0 ;
bool first = true ;
2011-06-06 04:31:11 +00:00
EventDataType lastp = 0 ;
2011-06-06 03:37:31 +00:00
for ( vector < Session * > : : iterator s = day - > begin ( ) ; s ! = day - > end ( ) ; s + + ) {
if ( ( * s ) - > events . find ( code ) = = ( * s ) - > events . end ( ) ) continue ;
if ( vc > = ( int ) point . size ( ) ) {
AddSegment ( max_points ) ;
}
int t = 0 ;
2011-06-06 04:31:11 +00:00
EventDataType p ;
2011-06-06 03:37:31 +00:00
for ( vector < Event * > : : iterator ev = ( * s ) - > events [ code ] . begin ( ) ; ev ! = ( * s ) - > events [ code ] . end ( ) ; ev + + ) {
p = ( * ( * ev ) ) [ field ] ;
2011-06-06 10:06:57 +00:00
if ( ( ( p ! = 0 ) & & skipzero ) | | ! skipzero ) {
2011-06-10 15:37:19 +00:00
wxPoint2DDouble r ( ( * ev ) - > time ( ) . GetMJD ( ) , p ) ;
2011-06-06 03:37:31 +00:00
point [ vc ] [ t + + ] = r ;
assert ( t < max_points ) ;
if ( first ) {
2011-06-10 15:37:19 +00:00
max_y = min_y = r . m_y ;
2011-06-06 04:31:11 +00:00
//lastp=p;
2011-06-06 03:37:31 +00:00
first = false ;
} else {
2011-06-10 15:37:19 +00:00
if ( r . m_y < min_y ) min_y = r . m_y ;
if ( r . m_y > max_y ) max_y = r . m_y ;
2011-06-06 03:37:31 +00:00
}
} else {
2011-06-07 03:26:15 +00:00
if ( ( p ! = lastp ) & & ( t > 0 ) ) { // There really should not be consecutive zeros.. just in case..
2011-06-06 03:37:31 +00:00
np [ vc ] = t ;
tt + = t ;
t = 0 ;
vc + + ;
if ( vc > = ( int ) point . size ( ) ) {
AddSegment ( max_points ) ;
}
}
}
lastp = p ;
}
np [ vc ] = t ;
2011-06-07 04:40:48 +00:00
if ( t > 0 ) {
tt + = t ;
vc + + ;
}
2011-06-06 03:37:31 +00:00
}
if ( tt > 0 ) {
min_y = floor ( min_y ) ;
max_y = ceil ( max_y + 1 ) ;
if ( min_y > 1 ) min_y - = 1 ;
}
if ( force_min_y ! = force_max_y ) {
min_y = force_min_y ;
max_y = force_max_y ;
}
real_min_x = min_x ;
real_min_y = min_y ;
real_max_x = max_x ;
real_max_y = max_y ;
m_ready = true ;
}
2011-05-26 13:59:21 +00:00
2011-05-29 07:53:37 +00:00
TAPData : : TAPData ( MachineCode _code )
: gPointData ( 256 ) , code ( _code )
2011-05-26 13:59:21 +00:00
{
AddSegment ( max_points ) ;
}
TAPData : : ~ TAPData ( )
{
}
void TAPData : : Reload ( Day * day )
{
if ( ! day ) {
m_ready = false ;
return ;
}
for ( int i = 0 ; i < max_slots ; i + + ) pTime [ i ] = wxTimeSpan : : Seconds ( 0 ) ;
int cnt = 0 ;
bool first ;
wxDateTime last ;
2011-06-06 05:17:23 +00:00
int lastval = 0 , val ;
2011-05-26 13:59:21 +00:00
int field = 0 ;
2011-06-17 15:59:04 +00:00
2011-06-02 04:42:37 +00:00
for ( vector < Session * > : : iterator s = day - > begin ( ) ; s ! = day - > end ( ) ; s + + ) {
2011-05-26 13:59:21 +00:00
if ( ( * s ) - > events . find ( code ) = = ( * s ) - > events . end ( ) ) continue ;
first = true ;
2011-06-02 04:42:37 +00:00
for ( vector < Event * > : : iterator e = ( * s ) - > events [ code ] . begin ( ) ; e ! = ( * s ) - > events [ code ] . end ( ) ; e + + ) {
2011-05-26 13:59:21 +00:00
Event & ev = ( * ( * e ) ) ;
val = ev [ field ] * 10.0 ;
if ( field > ev . fields ( ) ) throw BoundsError ( ) ;
if ( first ) {
2011-06-06 05:17:23 +00:00
first = false ; // only bother setting lastval (below) this time.
2011-05-26 13:59:21 +00:00
} else {
wxTimeSpan d = ev . time ( ) - last ;
if ( lastval > max_slots ) throw BoundsError ( ) ;
pTime [ lastval ] + = d ;
}
cnt + + ;
last = ev . time ( ) ;
lastval = val ;
}
}
wxTimeSpan TotalTime ( 0 ) ;
for ( int i = 0 ; i < max_slots ; i + + ) {
TotalTime + = pTime [ i ] ;
}
int jj = 0 ;
int seconds = TotalTime . GetSeconds ( ) . GetLo ( ) ;
for ( int i = 0 ; i < max_slots ; i + + ) {
if ( pTime [ i ] > wxTimeSpan : : Seconds ( 0 ) ) {
2011-06-10 15:37:19 +00:00
point [ 0 ] [ jj ] . m_x = i / 10.0 ;
point [ 0 ] [ jj ] . m_y = ( 100.0 / seconds ) * pTime [ i ] . GetSeconds ( ) . GetLo ( ) ;
2011-05-26 13:59:21 +00:00
jj + + ;
}
}
np [ 0 ] = jj ;
//graph->Refresh();
m_ready = true ;
}
AHIData : : AHIData ( )
: gPointData ( 256 )
{
AddSegment ( max_points ) ;
}
AHIData : : ~ AHIData ( )
{
}
void AHIData : : Reload ( Day * day )
{
if ( ! day ) {
m_ready = false ;
return ;
}
2011-06-10 15:37:19 +00:00
point [ 0 ] [ 0 ] . m_y = day - > count ( CPAP_Hypopnea ) / day - > hours ( ) ;
point [ 0 ] [ 0 ] . m_x = point [ 0 ] [ 0 ] . m_y ;
point [ 0 ] [ 1 ] . m_y = day - > count ( CPAP_Obstructive ) / day - > hours ( ) ;
point [ 0 ] [ 1 ] . m_x = point [ 0 ] [ 1 ] . m_y ;
point [ 0 ] [ 2 ] . m_y = day - > count ( CPAP_ClearAirway ) / day - > hours ( ) ;
point [ 0 ] [ 2 ] . m_x = point [ 0 ] [ 2 ] . m_y ;
point [ 0 ] [ 3 ] . m_y = day - > count ( CPAP_RERA ) / day - > hours ( ) ;
point [ 0 ] [ 3 ] . m_x = point [ 0 ] [ 3 ] . m_y ;
point [ 0 ] [ 4 ] . m_y = day - > count ( CPAP_FlowLimit ) / day - > hours ( ) ;
point [ 0 ] [ 4 ] . m_x = point [ 0 ] [ 4 ] . m_y ;
point [ 0 ] [ 5 ] . m_y = ( 100.0 / day - > hours ( ) ) * ( day - > sum ( CPAP_CSR ) / 3600.0 ) ;
point [ 0 ] [ 5 ] . m_x = point [ 0 ] [ 5 ] . m_y ;
2011-05-26 13:59:21 +00:00
np [ 0 ] = 6 ;
m_ready = true ;
//REFRESH??
}
FlagData : : FlagData ( MachineCode _code , double _value , int _field , int _offset )
2011-05-28 03:41:44 +00:00
: gPointData ( 1024 ) , code ( _code ) , value ( _value ) , field ( _field ) , offset ( _offset )
2011-05-26 13:59:21 +00:00
{
AddSegment ( max_points ) ;
}
FlagData : : ~ FlagData ( )
{
}
void FlagData : : Reload ( Day * day )
{
if ( ! day ) {
m_ready = false ;
return ;
}
int c = 0 ;
vc = 0 ;
double v1 , v2 ;
bool first ;
min_x = day - > first ( ) . GetMJD ( ) ;
max_x = day - > last ( ) . GetMJD ( ) ;
2011-06-02 04:42:37 +00:00
for ( vector < Session * > : : iterator s = day - > begin ( ) ; s ! = day - > end ( ) ; s + + ) {
2011-05-26 13:59:21 +00:00
if ( ( * s ) - > events . find ( code ) = = ( * s ) - > events . end ( ) ) continue ;
first = true ;
2011-06-02 04:42:37 +00:00
for ( vector < Event * > : : iterator e = ( * s ) - > events [ code ] . begin ( ) ; e ! = ( * s ) - > events [ code ] . end ( ) ; e + + ) {
2011-05-26 13:59:21 +00:00
Event & ev = ( * ( * e ) ) ;
v2 = v1 = ev . time ( ) . GetMJD ( ) ;
if ( offset > = 0 )
v1 - = ev [ offset ] / 86400.0 ;
2011-06-10 15:37:19 +00:00
point [ vc ] [ c ] . m_x = v1 ;
point [ vc ] [ c ] . m_y = v2 ;
2011-05-26 13:59:21 +00:00
//point[vc][c].z=value;
c + + ;
assert ( c < max_points ) ;
/*if (first) {
min_y = v1 ;
first = false ;
} else {
2011-06-03 08:12:00 +00:00
if ( v1 < min_x ) min_x = v1 ;
2011-05-26 13:59:21 +00:00
}
if ( v2 > max_x ) max_x = v2 ; */
}
}
2011-05-29 03:27:42 +00:00
min_y = - value ;
2011-05-26 13:59:21 +00:00
max_y = value ;
np [ vc ] = c ;
vc + + ;
real_min_x = min_x ;
real_min_y = min_y ;
real_max_x = max_x ;
real_max_y = max_y ;
m_ready = true ;
}
2011-05-31 02:18:41 +00:00
////////////////////////////////////////////////////////////////////////////////////////////
// HistoryData Implementation
////////////////////////////////////////////////////////////////////////////////////////////
2011-05-30 11:59:20 +00:00
HistoryData : : HistoryData ( Profile * _profile )
: gPointData ( 1024 ) , profile ( _profile )
2011-05-26 13:59:21 +00:00
{
AddSegment ( max_points ) ;
2011-05-30 11:59:20 +00:00
if ( profile - > LastDay ( ) . IsValid ( ) ) {
2011-05-31 02:18:41 +00:00
real_min_x = profile - > FirstDay ( ) . GetMJD ( ) ;
2011-06-02 16:31:36 +00:00
real_max_x = profile - > LastDay ( ) . GetMJD ( ) + 1 ;
2011-05-30 11:59:20 +00:00
}
2011-06-03 08:12:00 +00:00
real_min_y = real_max_y = 0 ;
2011-05-26 13:59:21 +00:00
}
HistoryData : : ~ HistoryData ( )
{
}
2011-05-30 11:59:20 +00:00
void HistoryData : : ResetDateRange ( )
{
if ( profile - > LastDay ( ) . IsValid ( ) ) {
2011-05-31 02:18:41 +00:00
real_min_x = profile - > FirstDay ( ) . GetMJD ( ) ;
2011-06-02 16:31:36 +00:00
real_max_x = profile - > LastDay ( ) . GetMJD ( ) + 1 ;
2011-05-30 11:59:20 +00:00
}
2011-06-03 08:12:00 +00:00
// Reload(NULL);
2011-05-30 11:59:20 +00:00
}
2011-05-26 13:59:21 +00:00
double HistoryData : : Calc ( Day * day )
{
2011-06-01 15:35:20 +00:00
return ( day - > summary_sum ( CPAP_Obstructive ) + day - > summary_sum ( CPAP_Hypopnea ) + day - > summary_sum ( CPAP_ClearAirway ) ) / day - > hours ( ) ;
2011-05-26 13:59:21 +00:00
}
void HistoryData : : Reload ( Day * day )
{
2011-05-30 11:59:20 +00:00
wxDateTime date ;
2011-05-26 13:59:21 +00:00
vc = 0 ;
2011-05-30 11:59:20 +00:00
int i = 0 ;
2011-05-26 13:59:21 +00:00
bool first = true ;
2011-05-30 11:59:20 +00:00
bool done = false ;
2011-06-01 13:08:44 +00:00
double y , lasty = 0 ;
2011-06-03 08:12:00 +00:00
min_y = max_y = 0 ;
min_x = max_x = 0 ;
2011-05-30 11:59:20 +00:00
for ( int x = real_min_x ; x < = real_max_x ; x + + ) {
date . Set ( x + 2400000.5 ) ;
date . ResetTime ( ) ;
if ( profile - > daylist . find ( date ) = = profile - > daylist . end ( ) ) continue ;
y = 0 ;
int z = 0 ;
vector < Day * > & daylist = profile - > daylist [ date ] ;
2011-06-02 04:42:37 +00:00
for ( vector < Day * > : : iterator dd = daylist . begin ( ) ; dd ! = daylist . end ( ) ; dd + + ) { // average any multiple data sets
2011-05-30 11:59:20 +00:00
Day * d = ( * dd ) ;
2011-06-06 05:17:23 +00:00
if ( d - > machine_type ( ) = = MT_CPAP ) {
y = Calc ( d ) ;
z + + ;
}
2011-05-30 11:59:20 +00:00
}
2011-06-03 08:12:00 +00:00
if ( ! z ) continue ;
2011-05-30 11:59:20 +00:00
if ( z > 1 ) y / = z ;
2011-05-26 13:59:21 +00:00
if ( first ) {
2011-05-31 02:18:41 +00:00
// max_x=min_x=x;
2011-06-01 13:08:44 +00:00
lasty = max_y = min_y = y ;
2011-05-26 13:59:21 +00:00
first = false ;
}
2011-06-10 15:37:19 +00:00
point [ vc ] [ i ] . m_x = x ;
point [ vc ] [ i ] . m_y = y ;
2011-05-26 13:59:21 +00:00
if ( y > max_y ) max_y = y ;
if ( y < min_y ) min_y = y ;
2011-05-31 02:18:41 +00:00
//if (x<min_x) min_x=x;
//if (x>max_x) max_x=x;
2011-05-26 13:59:21 +00:00
i + + ;
2011-05-30 11:59:20 +00:00
if ( i > max_points ) {
wxLogError ( wxT ( " max_points is not enough in HistoryData " ) ) ;
done = true ;
}
if ( done ) break ;
2011-06-01 13:08:44 +00:00
lasty = y ;
2011-05-30 11:59:20 +00:00
}
2011-05-26 13:59:21 +00:00
np [ vc ] = i ;
vc + + ;
2011-05-31 02:18:41 +00:00
min_x = real_min_x ;
max_x = real_max_x ;
2011-06-03 07:06:18 +00:00
2011-05-31 02:18:41 +00:00
// max_x+=1;
//real_min_x=min_x;
//real_max_x=max_x;
2011-06-02 16:31:36 +00:00
if ( force_min_y ! = force_max_y ) {
min_y = force_min_y ;
max_y = force_max_y ;
2011-06-03 07:06:18 +00:00
} else {
if ( ! ( ( min_y = = max_y ) & & ( min_y = = 0 ) ) ) {
2011-06-04 03:23:29 +00:00
if ( min_y > 1 ) min_y - = 1 ;
2011-06-03 07:06:18 +00:00
max_y + + ;
}
2011-06-02 16:31:36 +00:00
}
2011-05-26 13:59:21 +00:00
real_min_y = min_y ;
real_max_y = max_y ;
m_ready = true ;
}
double HistoryData : : GetAverage ( )
{
2011-06-04 03:18:11 +00:00
double x , val = 0 ;
int cnt = 0 ;
2011-05-26 13:59:21 +00:00
for ( int i = 0 ; i < np [ 0 ] ; i + + ) {
2011-06-10 15:37:19 +00:00
x = point [ 0 ] [ i ] . m_x ;
2011-06-04 03:18:11 +00:00
if ( ( x < min_x ) | | ( x > max_x ) ) continue ;
2011-06-10 15:37:19 +00:00
val + = point [ 0 ] [ i ] . m_y ;
2011-06-04 03:18:11 +00:00
cnt + + ;
2011-05-26 13:59:21 +00:00
}
2011-06-04 03:18:11 +00:00
if ( ! cnt ) return 0 ;
val / = cnt ;
2011-05-26 13:59:21 +00:00
return val ;
}
2011-05-30 11:59:20 +00:00
void HistoryData : : SetDateRange ( wxDateTime start , wxDateTime end )
{
2011-05-31 04:28:11 +00:00
double x1 = start . GetMJD ( ) - 0.5 ;
2011-05-31 02:18:41 +00:00
double x2 = end . GetMJD ( ) ;
2011-05-30 11:59:20 +00:00
if ( x1 < real_min_x ) x1 = real_min_x ;
2011-05-31 02:18:41 +00:00
if ( x2 > ( real_max_x ) ) x2 = ( real_max_x ) ;
2011-05-30 11:59:20 +00:00
min_x = x1 ;
max_x = x2 ;
2011-06-02 04:42:37 +00:00
for ( list < gLayer * > : : iterator i = notify_layers . begin ( ) ; i ! = notify_layers . end ( ) ; i + + ) {
2011-05-30 11:59:20 +00:00
( * i ) - > DataChanged ( this ) ;
} // Do nothing else.. Callers responsibility to Refresh window.
}
2011-05-26 13:59:21 +00:00
2011-05-30 11:59:20 +00:00
HistoryCodeData : : HistoryCodeData ( Profile * _profile , MachineCode _code )
: HistoryData ( _profile ) , code ( _code )
2011-05-26 13:59:21 +00:00
{
}
HistoryCodeData : : ~ HistoryCodeData ( )
{
}
double HistoryCodeData : : Calc ( Day * day )
{
return day - > summary_avg ( code ) ;
}
2011-05-30 11:59:20 +00:00
UsageHistoryData : : UsageHistoryData ( Profile * _profile , T_UHD _uhd )
: HistoryData ( _profile ) , uhd ( _uhd )
2011-05-27 14:07:35 +00:00
{
}
UsageHistoryData : : ~ UsageHistoryData ( )
{
}
double UsageHistoryData : : Calc ( Day * day )
{
double d ;
if ( uhd = = UHD_Bedtime ) {
d = day - > first ( ) . GetHour ( ) ;
if ( d < 12 ) d + = 24 ;
d + = ( day - > first ( ) . GetMinute ( ) / 60.0 ) ;
d + = ( day - > first ( ) . GetSecond ( ) / 3600.0 ) ;
return d ;
}
else if ( uhd = = UHD_Waketime ) {
d = day - > last ( ) . GetHour ( ) ;
d + = ( day - > last ( ) . GetMinute ( ) / 60.0 ) ;
d + = ( day - > last ( ) . GetSecond ( ) / 3600.0 ) ;
return d ;
}
else if ( uhd = = UHD_Hours ) return day - > hours ( ) ;
else
return 0 ;
}