487 lines
16 KiB
C++
487 lines
16 KiB
C++
/******************************************************************
|
||
|
||
JEDI-VCL Demo
|
||
|
||
Copyright (C) 2004 Project JEDI
|
||
|
||
Original author: Olivier Sannier (obones att altern dott org)
|
||
|
||
You may retrieve the latest version of this file at the JEDI-JVCL
|
||
home page, located at http://jvcl.sourceforge.net
|
||
|
||
The contents of this file are used with permission, subject to
|
||
the Mozilla Public License Version 1.1 (the "License"); you may
|
||
not use this file except in compliance with the License. You may
|
||
obtain a copy of the License at
|
||
http://www.mozilla.org/MPL/MPL-1_1Final.html
|
||
|
||
Software distributed under the License is distributed on an
|
||
"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||
implied. See the License for the specific language governing
|
||
rights and limitations under the License.
|
||
|
||
******************************************************************/
|
||
//---------------------------------------------------------------------------
|
||
|
||
#include <vcl.h>
|
||
#pragma hdrstop
|
||
|
||
#include "MainForm.h"
|
||
#include <Math.hpp>
|
||
#include <Math.h>
|
||
//#include <JvJVCLAboutForm.hpp>
|
||
//---------------------------------------------------------------------------
|
||
#pragma package(smart_init)
|
||
#pragma link "JvChart"
|
||
#pragma link "JvComponent"
|
||
#pragma link "JvExControls"
|
||
#pragma link "Math"
|
||
//#pragma link "JvJVCLAboutForm"
|
||
#pragma resource "*.dfm"
|
||
TfrmMain *frmMain;
|
||
|
||
#if __BORLANDC__ < 0x560
|
||
static const Extended NaN = 0.0 / 0.0;
|
||
#endif
|
||
|
||
//---------------------------------------------------------------------------
|
||
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
|
||
: TForm(Owner), FStatHgt(10), FStatHg0(10)
|
||
{
|
||
}
|
||
|
||
//---------------------------------------------------------------------------
|
||
void TfrmMain::_Generate()
|
||
{
|
||
randomize();
|
||
FHgt = abs(random(80)+(random(((FGenerationIndex / Foo) % Foo1) * 250) * 5 + 9500));
|
||
FHg0 = abs(random(280)+random(((FGenerationIndex / Foo) % Foo2) * 650)*5 + 1003);
|
||
FGenerationIndex++;
|
||
}
|
||
|
||
/* Bogus random spiky-looking function to simulate a QA value,
|
||
which hovers within +/- 10% of perfect (100%), but
|
||
with relatively infrequent spiky errors */
|
||
int TfrmMain::_QAProblemScatter()
|
||
{
|
||
double n,m;
|
||
|
||
randomize();
|
||
n = Log10(random(10000)+1); // Random is my favourite function. How about you? -WP
|
||
n = n * Log10(random(10000)+1);
|
||
m = Log10(random(10000)+1);
|
||
m = m * Log10(random(10000)+1);
|
||
n = abs(100 + n - m);
|
||
if (n<0)
|
||
n = 0;
|
||
if (n>150)
|
||
n = 150;
|
||
|
||
return floor(n+0.5);
|
||
}
|
||
|
||
void TfrmMain::_StoreValue(int I)
|
||
{
|
||
FStatHgt.AddValue(FHgt);
|
||
FStatHg0.AddValue(FHg0);
|
||
|
||
|
||
// PAY ATTENTION HERE, this is where we set the Chart.Data.Value[ index,pen] = <values>
|
||
// stuff which is the MOST IMPORTANT THING, unless you like blank charts:
|
||
|
||
// Set Data.Value[Pen, Series] = dataValue ...
|
||
Chart->Data->Value[0][I] = FStatHgt.Average() / 1000;
|
||
|
||
// Test blanks on big chart, show missing data:
|
||
Chart->Data->Value[1][I] = FStatHg0.Average()/1000;
|
||
|
||
FHg2p = ( FStatHgt.Average() - FStatHg0.Average())/1000;
|
||
if (FHg2p < 0.0)
|
||
FHg2p = 0.0;
|
||
Chart->Data->Value[2][I] = FHg2p;
|
||
|
||
Fds = Fdt + (FGenerationIndex / 576);
|
||
|
||
// There are TWO ways to get an X Axis label plotted:
|
||
if (DateTimeAxisMode->Checked)
|
||
Chart->Data->Timestamp[I] = Fds; // X legends generated by timestamps
|
||
else
|
||
// X Legends generated by user are used by default.
|
||
// This would be redundant, and would be a waste of memory
|
||
// if (Chart.Options.XAxisDateTimeMode was also set.
|
||
Chart->Options->XLegends->Add(FormatDateTime("hh:nn:ss", Fds) );
|
||
|
||
if (MenuSecondaryAxisMode->Checked)
|
||
{
|
||
if (I == 1)
|
||
Chart->Data->Value[3][I] = 100;
|
||
else if ((I % 4) == 3)
|
||
{
|
||
//Chart->Data->Value[3][I] = 1+ ((I % 12) * 10) // stairstep
|
||
//random:
|
||
Chart->Data->Value[3][I] = _QAProblemScatter();
|
||
}
|
||
else
|
||
Chart->Data->Value[3][I] = NaN; // leave some blanks.
|
||
}
|
||
}
|
||
|
||
void TfrmMain::NewValues()
|
||
{
|
||
int nValueCount;
|
||
|
||
ListBox1->Clear();
|
||
Chart->Data->Clear();
|
||
|
||
|
||
randomize();
|
||
|
||
Chart->Options->XAxisDateTimeMode = DateTimeAxisMode->Checked; // Use datetime timestamp labels, just Fer Instance->
|
||
|
||
if ( !Chart->Options->XAxisDateTimeMode)
|
||
Chart->Options->XAxisLegendSkipBy = 5;
|
||
|
||
|
||
|
||
if (LargeDataset576samples1->Checked )
|
||
{
|
||
// A larger bogus data set for demonstration purposes->
|
||
nValueCount = 576; // 2->5 minute sample period, 576 samples == 1 day->
|
||
Foo = 5; // Used in generating our bogus data below, not really important->
|
||
Chart->Options->XAxisValuesPerDivision = 24; // 24 samples * 150 seconds == 1 hour time divisions ( Chart->Options->XAxisValuesPerDivision = 4;
|
||
}
|
||
else
|
||
{
|
||
// A smaller bogus data set for demonstration purposes->
|
||
nValueCount = 24; // 2->5 minute sample period, 24 samples =1 hour->
|
||
Foo = 1; // Used in generating our bogus data below, not really important->
|
||
Chart->Options->XAxisValuesPerDivision = 4; // five divisions, 4 values per division
|
||
}
|
||
|
||
//Chart->ResetGraphModule; // Clears YMax->
|
||
Fdt = floor(Now()- 1.0); // yesterday, midnight->
|
||
Foo1 = random(5)+2; // more randomness
|
||
Foo2 = random(3)+5; // more randomness
|
||
FGenerationIndex = 1;
|
||
for (int i = 0; i < nValueCount; i++)
|
||
{
|
||
if (i > 0)
|
||
{ // generate random data that appears to show a sawtooth-frequency-pattern plus a lot of random noise:
|
||
_Generate();
|
||
}
|
||
else
|
||
{
|
||
FHgt = 7000; // First sample always known value, helps me troubleshoot->
|
||
FHg0 = 1000;
|
||
}
|
||
|
||
_StoreValue(i);
|
||
|
||
|
||
// Override stored value in special cases:
|
||
|
||
// How to make a gap in the data!
|
||
if ((nValueCount>100 ) && ShowgapinLineChart1->Checked)
|
||
{
|
||
if ((i > 100) && (i < 130))
|
||
{
|
||
Chart->Data->Value[0][i] = NaN; // Use special Math->NaN const
|
||
Chart->Data->Value[1][i] = NaN; // Use special Math->NaN const
|
||
Chart->Data->Value[2][i] = NaN; // Use special Math->NaN const
|
||
}
|
||
}
|
||
|
||
// Just so that the last two values are visibly different, to make sure
|
||
// the chart handles the final vaulues correctly, we set all the final
|
||
// values to known amounts also:
|
||
if ((i==nValueCount-2))
|
||
{
|
||
Chart->Data->Value[0][i] = 6.0; // Use special Math->NaN const
|
||
Chart->Data->Value[1][i] = 4.0; // Use special Math->NaN const
|
||
Chart->Data->Value[2][i] = 2.0; // Use special Math->NaN const
|
||
}
|
||
else if ((i==nValueCount-1))
|
||
{
|
||
Chart->Data->Value[0][i] = 3.0; // Use special Math->NaN const
|
||
Chart->Data->Value[1][i] = 2.0; // Use special Math->NaN const
|
||
Chart->Data->Value[2][i] = 1.0; // Use special Math->NaN const
|
||
|
||
}
|
||
|
||
ListBox1->Items->Append( Chart->Data->DebugStr(i) );
|
||
}
|
||
|
||
|
||
|
||
// with Chart->Options do
|
||
{
|
||
Chart->Options->Title = "Chart Title";
|
||
Chart->Options->XAxisHeader = "Date/Time";
|
||
Chart->Options->YAxisHeader = "Readings (ng/m3)";
|
||
|
||
// Try out the pen styles:
|
||
if (Chart->Options->ChartKind == ckChartStackedBar)
|
||
Chart->Options->PenStyle[0] = psClear; // THIS IS HOW YOU TEMPORARILY HIDE ONE PEN!
|
||
else
|
||
Chart->Options->PenStyle[0] = psSolid;
|
||
Chart->Options->PenStyle[1] = psDash;
|
||
Chart->Options->PenStyle[2] = psDot;
|
||
|
||
if (MenuSecondaryAxisMode->Checked) {
|
||
Chart->Options->PenCount = 4; // Add a pen for right side demo->
|
||
Chart->Options->SecondaryYAxis->YMax = 140; // Example shows Q/A percentage-> Experimental results
|
||
// results are compared to expected results, and the
|
||
// response percentage, is plotted from 0% to 140%
|
||
// of expected value->
|
||
Chart->Options->SecondaryYAxis->YMin = 0;
|
||
Chart->Options->SecondaryYAxis->YLegendDecimalPlaces = 2;
|
||
Chart->Options->PenSecondaryAxisFlag[3] = True; // Move pen index 3 (Fourth pen) to secondary axis->
|
||
Chart->Options->PenMarkerKind[3] = pmkDiamond;
|
||
Chart->Options->PenValueLabels[3] = true; // Label with text->
|
||
Chart->Options->PenStyle[3] = psClear; // Markers only, no lines->
|
||
Chart->Options->PenColor[3] = clGray;
|
||
Chart->Options->MarkerSize = 5; // Make "em bigger->
|
||
}
|
||
else
|
||
{
|
||
Chart->Options->PenCount = 3;
|
||
Chart->Options->MarkerSize = 3; // Make "em little
|
||
}
|
||
|
||
|
||
Chart->Options->PenLegends->Clear();
|
||
Chart->Options->PenLegends->Add("HgT");
|
||
Chart->Options->PenLegends->Add("Hg0");
|
||
Chart->Options->PenLegends->Add("Hg2+");
|
||
if (MenuSecondaryAxisMode->Checked)
|
||
Chart->Options->PenLegends->Add("Quality%");
|
||
|
||
Chart->Options->PenUnit->Clear();
|
||
Chart->Options->PenUnit->Add("ug/m3");
|
||
Chart->Options->PenUnit->Add("ug/m3");
|
||
Chart->Options->PenUnit->Add("ug/m3");
|
||
if (MenuSecondaryAxisMode->Checked)
|
||
Chart->Options->PenUnit->Add("%"); // Optional Pen in percentage scale->
|
||
|
||
//ShowLegend = TRUE;
|
||
Chart->Options->Legend = clChartLegendBelow;
|
||
|
||
//ChartKind = ckChartLine;
|
||
}
|
||
// Chart->AutoFormatGraph(); // WPostma. Removed.
|
||
Chart->PlotGraph();
|
||
|
||
//Chart->ResizeChartCanvas;
|
||
}
|
||
|
||
|
||
void __fastcall TfrmMain::FormResize(TObject *Sender)
|
||
{
|
||
if (Chart != NULL)
|
||
Chart->ResizeChartCanvas();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonBarChartClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartBar;
|
||
NewValues();
|
||
//Chart->PlotGraph();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonLineClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartLine;
|
||
for (int i = 0; Chart->Options->PenCount; i++)
|
||
Chart->Options->PenMarkerKind[i] = pmkNone;
|
||
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonLineMarkerClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartLine;
|
||
Chart->Options->PenMarkerKind[0] = pmkDiamond; // demonstrate both Diamond and Circle Marks.
|
||
Chart->Options->PenMarkerKind[1] = pmkDiamond;
|
||
Chart->Options->PenMarkerKind[2] = pmkCircle;
|
||
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonStackedBarClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartStackedBar;
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonStackedBarAveClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartStackedBarAverage;
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonBarAveClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartBarAverage;
|
||
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonPieClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartPieChart;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonMarkersClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartMarkers;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ButtonDeltaAverageClick(TObject *Sender)
|
||
{
|
||
Chart->Options->ChartKind = ckChartDeltaAverage;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::FormCreate(TObject *Sender)
|
||
{
|
||
if (Chart != NULL)
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ShowgapinLineChart1Click(TObject *Sender)
|
||
{
|
||
ShowgapinLineChart1->Checked = !ShowgapinLineChart1->Checked;
|
||
ButtonLine->Down = true;
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::Print1Click(TObject *Sender)
|
||
{
|
||
if (PrintDialog1->Execute())
|
||
Chart->PrintGraph();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::Generatenewrandomvalues1Click(TObject *Sender)
|
||
{
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::CopyToClipboard1Click(TObject *Sender)
|
||
{
|
||
Chart->GraphToClipboard();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::SetHeaderFont1Click(TObject *Sender)
|
||
{
|
||
// Get the current font for the Header text...
|
||
FontDialog1->Font->Assign(Chart->Options->AxisFont);
|
||
|
||
if (FontDialog1->Execute())
|
||
// Set the font for the Header text...}
|
||
Chart->Options->AxisFont = FontDialog1->Font;
|
||
Chart->PlotGraph();
|
||
Chart->Invalidate();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::About1Click(TObject *Sender)
|
||
{
|
||
Application->MessageBox(
|
||
"JvChart comes from AABSoft Graph written by M<>rten Henrichson, JVCL 3.0 "
|
||
"version by Warren Postma. ","About JvChart", MB_OK);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::AboutJVCL301Click(TObject *Sender)
|
||
{
|
||
// TJvJVCLAboutForm->Execute(false);
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::Scrolling1Click(TObject *Sender)
|
||
{
|
||
Scrolling1->Checked = !Scrolling1->Checked;
|
||
Timer1->Enabled = Scrolling1->Checked;
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::Timer1Timer(TObject *Sender)
|
||
{
|
||
Chart->Data->Scroll();
|
||
_Generate();
|
||
_StoreValue( Chart->Data->ValueCount-1 );
|
||
Chart->PlotGraph();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ShowDataInListbox1Click(TObject *Sender)
|
||
{
|
||
ShowDataInListbox1->Checked = ! ShowDataInListbox1->Checked;
|
||
ListBox1->Visible = ShowDataInListbox1->Checked;
|
||
|
||
if (!ShowDataInListbox1->Checked)
|
||
Chart->CursorPosition = -1; // Invisible.
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::LargeDataset576samples1Click(TObject *Sender)
|
||
{
|
||
LargeDataset576samples1->Checked = ! LargeDataset576samples1->Checked;
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::DateTimeAxisModeClick(TObject *Sender)
|
||
{
|
||
DateTimeAxisMode->Checked = !DateTimeAxisMode->Checked;
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::PrintOptions1Click(TObject *Sender)
|
||
{
|
||
PrinterSetupDialog1->Execute();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::MenuSecondaryAxisModeClick(TObject *Sender)
|
||
{
|
||
MenuSecondaryAxisMode->Checked = ! MenuSecondaryAxisMode->Checked;
|
||
|
||
if (MenuSecondaryAxisMode->Checked)
|
||
{
|
||
ButtonLine->Down = true;
|
||
ButtonLineClick(Sender);
|
||
}
|
||
else
|
||
NewValues();
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ListBox1DblClick(TObject *Sender)
|
||
{
|
||
Chart->CursorPosition = ListBox1->ItemIndex; // Highlight one sample.
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|
||
void __fastcall TfrmMain::ListBox1Click(TObject *Sender)
|
||
{
|
||
Chart->CursorPosition = ListBox1->ItemIndex; // Highlight one sample.
|
||
}
|
||
//---------------------------------------------------------------------------
|
||
|