#include <sstream>
#include <string>
#include "graph.h"
#include "wx/wx.h"
using std::vector;
neLine::neLine(std::vector<neCoord> in_vec,wxString name)
{
coords = in_vec;
line_name = name;
}
void neLine::ClearItems(void)
{
for (unsigned int i = 0; i < coords.size(); i++)
coords.pop_back();
}
BEGIN_EVENT_TABLE(neGraph, wxScrolledWindow)
EVT_PAINT (neGraph::OnPaint)
EVT_INIT_DIALOG (neGraph::InitGraph)
EVT_BUTTON (BUTTON_START, neGraph::OnStartClicked)
EVT_COMBOBOX (COMBO_BOX_TIMESPAN, neGraph::OnTimeSelection)
END_EVENT_TABLE()
neGraph::neGraph(MyFrame *parent)
: wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
{
start = wxDateTime::Now();
scale = 0;
grid = false;
g_size.x = 170;
g_size.y = 220;
req_g_size = wxSize(170,220);
m_owner = parent;
offset = wxSize(STD_OFFSET,STD_OFFSET);
DrawControls();
}
neGraph::neGraph( MyFrame *parent, wxSize gridsize)
: wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
{
start = wxDateTime::Now();
scale = 0;
grid = false;
m_owner = parent;
offset = wxSize(STD_OFFSET,STD_OFFSET);
req_g_size = gridsize;
SetGridSize(gridsize);
DrawControls();
}
neGraph::~neGraph()
{
delete t_inputd;
delete t_inputt;
delete b_go;
delete c_timespan;
}
void neGraph::SetGridSize(wxSize gridsize)
{
req_g_size = gridsize;
/* First find a number of pixels that can be cut in equal parts */
while (gridsize.y % 10) gridsize.y--;
if (scale == 0) /* 2 weeks */
while (gridsize.x % 14) gridsize.x--;
else /* one day or 1 hour*/
while (gridsize.x % 12) gridsize.x--;
g_size.x = gridsize.x;
g_size.y = gridsize.y;
}
void neGraph::ClearGraph()
{
for (unsigned int i = 0; i < grid_data.size(); i++)
grid_data.clear();
}
void neGraph::SetStartDate(const wxChar* indate)
{
start.ParseDate(indate);
}
void neGraph::SetOffSet(wxSize off)
{
offset.x = off.x + STD_OFFSET;
offset.y = off.y + STD_OFFSET;
}
/* - Set X-axes scale. 0=2 weeks, 1=1 day, 2=1 hour*/
void neGraph::SetScale(int sc)
{
scale = sc;
SetGridSize(req_g_size);
}
void neGraph::DrawAxes(wxDC& dc)
{
if (grid)
{
wxPen pen(wxColour(180,180,180), 1);
dc.SetPen(pen);
for (int i = 0; i < g_size.x; i += 10)
dc.DrawLine(offset.x+i, offset.y, offset.x+i, offset.y+g_size.y);
for (int j = 0; j < g_size.y; j += 10)
dc.DrawLine(offset.x, offset.y+j, offset.x+g_size.x, offset.y+j);
}
wxPen pen2(*wxBLACK, 2);
dc.SetPen(pen2);
dc.DrawLine(offset.x, offset.y, offset.x, offset.y+g_size.y+5);
dc.DrawLine(offset.x-5, offset.y+g_size.y, offset.x+g_size.x, offset.y+g_size.y);
dc.DrawLine(offset.x-5, offset.y, offset.x+5, offset.y);
dc.DrawLine(offset.x+g_size.x, offset.y+g_size.y-5, offset.x+g_size.x, offset.y+g_size.y+5);
dc.SetPen(wxNullPen);
}
void neGraph::FillAxes(wxDC& dc)
{
double step=0;
wxDateTime datetime = start;
// X-axes can have only 3 scales (2 weeks, 1 day or 1 hour)
switch (scale)
{
case 0: // 2 weeks
step = g_size.x / 14;
for (int i = 0; i <= 14; i++)
{
std::string temp = IntToString(datetime.GetDay(),1) + "-" + IntToString(datetime.GetMonth()+1,1);
dc.DrawLine(offset.x+(i*step), offset.y+g_size.y, offset.x+(i*step), offset.y+g_size.y+5);
if ((g_size.x > 500) || (g_size.x > 250 && g_size.x <=500 && !(i%2)) ||(g_size.x <= 250 && !(i%4)))
dc.DrawText(temp , offset.x+(step*i)-20, offset.y+g_size.y+10);
datetime.Add(wxTimeSpan::Day());
}
break;
case 1: // 1 day
step = g_size.x / 12;
for (int i = 0; i <= 12; i++)
{
std::string temp = IntToString(datetime.GetHour(),1) + ":" + IntToString(datetime.GetMinute(),1);
dc.DrawLine(offset.x+(i*step), offset.y+g_size.y, offset.x+(i*step), offset.y+g_size.y+5);
if ((g_size.x > 500) || (g_size.x > 250 && g_size.x <=500 && !(i%2)) ||(g_size.x <= 250 && !(i%4)))
dc.DrawText(temp, offset.x+(step*i)-20, offset.y+g_size.y+10);
datetime.Add(wxTimeSpan::Hours(2));
}
break;
case 2: // 1 hour
step = g_size.x / 12;
for (int i = 0; i <= 12; i++)
{
std::string temp = IntToString(datetime.GetHour(),1) + ":" + IntToString(datetime.GetMinute(),1);
dc.DrawLine(offset.x+(i*step), offset.y+g_size.y, offset.x+(i*step), offset.y+g_size.y+5);
if ((g_size.x > 500) || (g_size.x > 250 && g_size.x <=500 && !(i%2)) ||(g_size.x <= 250 && !(i%4)))
dc.DrawText(temp, offset.x+(step*i)-20, offset.y+g_size.y+10);
datetime.Add(wxTimeSpan::Minutes(5));
}
break;
}
step = g_size.y / 10;
for (int i = 0; i <= 10; i ++)
{
dc.DrawLine(offset.x-5, offset.y+g_size.y-(i*step),offset.x,offset.y+g_size.y-(i*step));
dc.DrawText(IntToString(i*10), offset.x-50, offset.y+g_size.y-(i*step)-10);
}
}
void neGraph::DrawData(wxDC& dc)
{
wxColour colour_arr[10] = {*wxBLUE,*wxRED,*wxCYAN,*wxGREEN,*wxWHITE,*wxLIGHT_GREY,*wxBLUE,*wxRED,*wxCYAN,*wxGREEN};
// calc how many minutes
double minute_step=0.0;
switch(scale)
{
case 0:
minute_step = (double)g_size.x / (14.0*24.0*60.0);
break;
case 1:
minute_step = (double)g_size.x / (24.0*60.0);
break;
case 2:
minute_step = (double)g_size.x / 60.0;
break;
}
// max of 10 line per graph
for (unsigned int line = 0; line < grid_data.size() && line < 10; line++)
{
wxPen pen(colour_arr[line], 1);
dc.SetBrush(colour_arr[line]);
dc.SetPen(pen);
dc.DrawRoundedRectangle(offset.x+g_size.x, offset.y+(25*line), 30, 20,5.0);
dc.FloodFill(offset.x+g_size.x+10, offset.y+(25*line)+10, *wxWHITE, wxFLOOD_SURFACE);
dc.DrawText(grid_data[line].line_name,offset.x+g_size.x+40, offset.y+(25*line));
for (unsigned int point = 0; point < grid_data[line].coords.size() -1; point++)
{
dc.DrawLine(
offset.x+(grid_data[line].coords[point].minutes*minute_step),
offset.y+g_size.y-((g_size.y/100)*grid_data[line].coords[point].y),
offset.x+(grid_data[line].coords[point + 1].minutes*minute_step),
offset.y+g_size.y-((g_size.y/100)*grid_data[line].coords[point + 1].y)
);
}
}
}
void neGraph::DrawControls()
{
t_inputd = new wxTextCtrl(this, -1, "dd-mm-yyyy", wxPoint(20,0));
t_inputt = new wxTextCtrl(this, -1, "hh:mm:ss", wxPoint(t_inputd->GetPosition().x+t_inputd->GetSize().x + 10,0));
c_timespan = new wxComboBox(this, COMBO_BOX_TIMESPAN,C_HOUR, wxPoint(t_inputt->GetPosition().x+t_inputt->GetSize().x + 10, 0));
c_timespan->AppendString(C_HOUR);
c_timespan->AppendString(C_DAY);
c_timespan->AppendString(C_WEEKS);
b_go = new wxButton(this, BUTTON_START , "Start",wxPoint(c_timespan->GetPosition().x+c_timespan->GetSize().x + 10, 0));
}
void neGraph::OnPaint(wxPaintEvent &WXUNUSED(event) )
{
wxPaintDC dc(this);
PrepareDC(dc);
dc.Clear();
DrawAxes(dc);
FillAxes(dc);
DrawData(dc);
}
void neGraph::InitGraph(wxInitDialogEvent &WXUNUSED(event))
{
}
void neGraph::OnStartClicked(wxCommandEvent &WXUNUSED(event))
{
wxDateTime in_time;
wxString dt = t_inputd->GetValue() + " " + t_inputt->GetValue();
if (!in_time.ParseDateTime(dt))
{
neBox("Error in input!");
t_inputt->SetValue("hh:mm:ss");
t_inputd->SetValue("dd-mm-yyyy");
return;
}
start = in_time;
ClearGraph();
/*****************************/
/* TODO: Reload data here !! */
/*****************************/
this->Refresh();
}
void neGraph::OnTimeSelection(wxCommandEvent &WXUNUSED(event))
{
if (c_timespan->GetValue() == C_DAY)
SetScale(1);
else if (c_timespan->GetValue() == C_WEEKS)
SetScale(0);
else SetScale(2);
ClearGraph();
/*****************************/
/* TODO: Reload data here !! */
/*****************************/
this->Refresh();
}
/* some common functions */
void neBox(const wxString input)
{
wxMessageDialog* temp = new wxMessageDialog(NULL,input);
temp->ShowModal();
delete temp;
return;
}
std::string IntToString(int Input, int add_a_zero)
{
std::stringstream temp;
std::string str;
temp << Input;
temp >> str;
if (add_a_zero && Input < 10) str = "0" + str;
return str;
}