summaryrefslogtreecommitdiff
path: root/iup/srcpplot
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/srcpplot
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/srcpplot')
-rwxr-xr-xiup/srcpplot/Makefile6
-rwxr-xr-xiup/srcpplot/config.mak25
-rwxr-xr-xiup/srcpplot/iupPPlot.cpp2470
-rwxr-xr-xiup/srcpplot/iupPPlot.h645
-rwxr-xr-xiup/srcpplot/iupPPlotInteraction.cpp832
-rwxr-xr-xiup/srcpplot/iupPPlotInteraction.h328
-rwxr-xr-xiup/srcpplot/iup_pplot.cpp2959
-rwxr-xr-xiup/srcpplot/iup_pplot.def11
-rw-r--r--iup/srcpplot/iup_pplot.dep12
-rwxr-xr-xiup/srcpplot/iuppplot.hpp137
-rwxr-xr-xiup/srcpplot/make_uname3
-rwxr-xr-xiup/srcpplot/make_uname.bat4
12 files changed, 7432 insertions, 0 deletions
diff --git a/iup/srcpplot/Makefile b/iup/srcpplot/Makefile
new file mode 100755
index 0000000..e10ef19
--- /dev/null
+++ b/iup/srcpplot/Makefile
@@ -0,0 +1,6 @@
+
+.PHONY: do_all iup_pplot
+do_all: iup_pplot
+
+iup_pplot:
+ @$(MAKE) --no-print-directory -f ../tecmake_compact.mak
diff --git a/iup/srcpplot/config.mak b/iup/srcpplot/config.mak
new file mode 100755
index 0000000..7c3975b
--- /dev/null
+++ b/iup/srcpplot/config.mak
@@ -0,0 +1,25 @@
+PROJNAME = iup
+LIBNAME = iup_pplot
+OPT = YES
+
+USE_CD = Yes
+
+ifdef DBG
+ DEFINES += IUP_ASSERT
+endif
+
+INCLUDES = ../include ../src
+LDIR = ../lib/$(TEC_UNAME)
+LIBS = iup iupcd
+
+DEFINES = _IUP_PPLOT_ CD_NO_OLD_INTERFACE
+
+SRC = iupPPlot.cpp iupPPlotInteraction.cpp iup_pplot.cpp
+
+ifneq ($(findstring owc, $(TEC_UNAME)), )
+ CPPFLAGS = -xr -xst
+endif
+
+ifeq "$(TEC_UNAME)" "vc6"
+ INCLUDES += C:\LNG\STLport\include
+endif
diff --git a/iup/srcpplot/iupPPlot.cpp b/iup/srcpplot/iupPPlot.cpp
new file mode 100755
index 0000000..c0d07c9
--- /dev/null
+++ b/iup/srcpplot/iupPPlot.cpp
@@ -0,0 +1,2470 @@
+/***************************************************************************
+ * *
+ * Copyright notice: *
+ * *
+ * This is free Pier ware. You may do whatever you want with this code, *
+ * except that you should not remove this copyright notice. *
+ * *
+ ***************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4100)
+#pragma warning(disable: 4512)
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+
+#include "iupPPlot.h"
+
+const float kFloatSmall = 1e-20f;
+const float kLogMin = 1e-10f;// min argument for log10 function
+const float kExpMax = 1e10f;// max argument for pow10 function
+const float kLogMinClipValue = 1e-10f;// pragmatism to avoid problems with small values in log plot
+const float kEps = 1e-4f;
+const float kRelMajorTickSize = 0.02f;
+const float kRelMinorTickSize = 0.01f;
+const int kMinMinorTickScreenSize = 1;// minor ticks should not become smaller than this
+const float kMaxMajorTickSizeInFontHeight = 0.5f;// not larger than half the font height
+const float kLittleIncrease = 1.0001f;
+const float kLittleDecrease = 0.9999f;
+const float kTickValueVeryBig = 1.0e4;// switch to scientific format
+const float kTickValueVerySmall = (float)1.0e-3;
+const float kMajorTickXInitialFac = 2.0f;
+const float kMajorTickYInitialFac = 3.0f;
+const PMargins kDefaultMargins = PMargins (40,20,5,42);
+
+const float PPlot::kRangeVerySmall = (float)1.0e-3; // also in ZoomInteraction
+
+template <class T> const T & PMax (const T &a, const T &b) {
+ return b> a ? b: a;
+}
+
+inline float SafeLog (float inFloat, float inBase, float inFac) {
+ if (inFloat<kLogMin) {
+ inFloat = kLogMin;
+ }
+ return inFac*log10 (inFloat)/log10(inBase);
+}
+
+inline float SafeExp (float inFloat, float inBase, float inFac) {
+ if (inFloat>kExpMax) {
+ inFloat = kExpMax;
+ }
+ return pow(inBase, inFloat/inFac);
+}
+
+long PlotDataBase::GetSize () const {
+ if (GetRealPlotData ()) {
+ return GetRealPlotData ()->size ();
+ }
+ if (GetCalculatedData ()) {
+ return GetCalculatedData ()->GetSize ();
+ }
+ return 0;
+}
+
+float PlotDataBase::GetValue (long inIndex) const {
+ if (GetRealPlotData ()) {
+ return (*GetRealPlotData ())[inIndex];
+ }
+ if (GetCalculatedData ()) {
+ return GetCalculatedData ()->GetValue (inIndex);
+ }
+ return 0;
+}
+
+bool PlotDataBase::CalculateRange (float &outXMin, float &outXMax) {
+ const RealData *theData = GetRealPlotData ();
+ if (theData && theData->size () >0) {
+ vector<float>::const_iterator imin = min_element (theData->begin (), theData->end ());
+ vector<float>::const_iterator imax = max_element (theData->begin (), theData->end ());
+ outXMin = *imin;
+ outXMax = *imax;
+ return true;
+ }
+ else {
+ const CalculatedDataBase *theCalculated = GetCalculatedData ();
+ if (theCalculated) {
+ outXMin = theCalculated->GetValue (0);
+ outXMax = theCalculated->GetValue (theCalculated->GetSize () - 1);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+DummyPlotData::DummyPlotData (long inSize) {
+ for (int theI=0;theI<inSize;theI++) {
+ mRealPlotData.push_back (theI);// simple ascending data
+ }
+}
+
+void StringPlotData::AddItem (const char *inString) {
+ mStringPlotData.push_back (inString);
+ mRealPlotData.push_back (mStringPlotData.size ()-1);
+}
+
+void StringPlotData::InsertItem (int inIndex, const char *inString) {
+ mStringPlotData.insert(mStringPlotData.begin()+inIndex, inString);
+ mRealPlotData.insert(mRealPlotData.begin()+inIndex, (float)inIndex);
+}
+
+
+void LegendData::SetDefaultColor (int inPlotIndex) {
+ mColor = GetDefaultColor (inPlotIndex);
+}
+
+void LegendData::SetDefaultValues (int inPlotIndex) {
+ SetDefaultColor (inPlotIndex);
+ char theBuf[32];
+ sprintf (theBuf, "plot %d", inPlotIndex);
+ mName = theBuf;
+}
+
+
+bool PlotDataSelection::IsSelected (long inIndex) const {
+ if (size ()<=inIndex) {
+ return false;
+ }
+ return (*this)[inIndex]>0;
+}
+
+long PlotDataSelection::GetSelectedCount () const {
+ long theCount = 0;
+ for (int theI=0;theI<size (); theI++) {
+ if (IsSelected (theI)) {
+ theCount++;
+ }
+ }
+ return theCount;
+}
+
+int PPlot::Round (float inFloat) {
+#ifdef _IUP_PPLOT_
+ return ((int)(inFloat < 0? (inFloat-0.5f): (inFloat+0.5f)));
+#else
+ return (int)floor (inFloat+0.5f);
+#endif
+}
+
+PColor LegendData::GetDefaultColor (int inPlotIndex) {
+
+ PColor theC;
+ switch (inPlotIndex%7) {
+ case 0:
+ theC.mR = 255;
+ theC.mG = 0;
+ theC.mB = 0;
+ break;
+ case 1:
+ theC.mR = 0;
+ theC.mG = 0;
+ theC.mB = 255;
+ break;
+ case 2:
+ theC.mR = 0;
+ theC.mG = 255;
+ theC.mB = 0;
+ break;
+ case 3:
+ theC.mR = 0;
+ theC.mG = 255;
+ theC.mB = 255;
+ break;
+ case 4:
+ theC.mR = 255;
+ theC.mG = 0;
+ theC.mB = 255;
+ break;
+ case 5:
+ theC.mR = 255;
+ theC.mG = 255;
+ theC.mB = 0;
+ break;
+ default:
+ // black
+ break;
+ }
+ return theC;
+}
+
+
+
+float TickInfo::RoundSpan (float inSpan) {
+ // round it to something producing readable tick labels
+ // write it in the form inSpan = a*SafeExp10 (b)
+
+ if (inSpan<=0) {
+ // error
+ return (float)-1.234567;
+ }
+
+ int thePow = 0;
+ float theSpan = inSpan;
+ if (inSpan>1) {
+ while (theSpan>10) {
+ theSpan/=10;
+ if (theSpan == inSpan) { // not a number
+ return (float)-1.234567;
+ }
+ thePow++;
+ }
+ }
+ else {
+ while (theSpan<1) {
+ theSpan*=10;
+ thePow--;
+ }
+ }
+ int theRoundedFirstDigit = PPlot::Round (theSpan);
+ int thePreferredFirstDigit = 1;
+ switch (theRoundedFirstDigit) {
+ case 1:
+ thePreferredFirstDigit = 1;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ thePreferredFirstDigit = 2;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ thePreferredFirstDigit = 5;
+ break;
+ case 10:
+ thePreferredFirstDigit = 1;
+ thePow++;
+ break;
+ default:
+ // error
+ return (float)-1.234567;
+ break;
+ }
+ float theRes = thePreferredFirstDigit*pow (10., thePow); /* M.T. changed to force a double cast */
+ return theRes;
+}
+
+void TickInfo::MakeFormatString (float inValue, string &outFormatString) {
+ if (inValue<0) {
+ inValue = - inValue;
+ }
+ if (inValue > kTickValueVeryBig || inValue < kTickValueVerySmall) {
+ outFormatString = "%.1e";
+ }
+ else {
+
+ int thePrecision = 0;
+ if (inValue<1) {
+ float theSpan = inValue;
+ while (theSpan<1) {
+ thePrecision++;
+ theSpan *=10;
+ }
+ }
+
+ char theBuf[128] = "%.0f";
+ theBuf[2] = '0'+thePrecision;
+
+ outFormatString = theBuf;
+ }
+}
+
+
+PlotDataBase::~PlotDataBase (){
+};
+
+
+PlotDataContainer::PlotDataContainer (){
+}
+PlotDataContainer::~PlotDataContainer (){
+ ClearData ();
+}
+
+PlotDataBase * PlotDataContainer::GetXData (int inIndex) {
+ if (inIndex < 0 || inIndex >= mXDataList.size ()) {
+ return 0;
+ }
+ return mXDataList[inIndex];
+}
+
+PlotDataBase * PlotDataContainer::GetYData (int inIndex) {
+ if (inIndex < 0 || inIndex >= mYDataList.size ()) {
+ return 0;
+ }
+ return mYDataList[inIndex];
+}
+
+LegendData * PlotDataContainer::GetLegendData (int inIndex) {
+ if (inIndex < 0 || inIndex >= mLegendDataList.size ()) {
+ return 0;
+ }
+ return mLegendDataList[inIndex];
+}
+
+DataDrawerBase * PlotDataContainer::GetDataDrawer (int inIndex) {
+ if (inIndex < 0 || inIndex >= mDataDrawerList.size ()) {
+ return 0;
+ }
+ return mDataDrawerList[inIndex];
+}
+
+PlotDataSelection * PlotDataContainer::GetPlotDataSelection (int inIndex) {
+ if (inIndex < 0 || inIndex >= mPlotDataSelectionList.size ()) {
+ return 0;
+ }
+ return mPlotDataSelectionList[inIndex];
+}
+
+const PlotDataBase * PlotDataContainer::GetConstXData (int inIndex) const {
+ if (inIndex < 0 || inIndex >= mXDataList.size ()) {
+ return 0;
+ }
+ return mXDataList[inIndex];
+}
+
+const PlotDataBase * PlotDataContainer::GetConstYData (int inIndex) const {
+ if (inIndex < 0 || inIndex >= mYDataList.size ()) {
+ return 0;
+ }
+ return mYDataList[inIndex];
+}
+
+const LegendData * PlotDataContainer::GetConstLegendData (int inIndex) const {
+ if (inIndex < 0 || inIndex >= mLegendDataList.size ()) {
+ return 0;
+ }
+ return mLegendDataList[inIndex];
+}
+
+const DataDrawerBase * PlotDataContainer::GetConstDataDrawer (int inIndex) const {
+ if (inIndex < 0 || inIndex >= mDataDrawerList.size ()) {
+ return 0;
+ }
+ return mDataDrawerList[inIndex];
+}
+
+const PlotDataSelection * PlotDataContainer::GetConstPlotDataSelection (int inIndex) const {
+ if (inIndex < 0 || inIndex >= mPlotDataSelectionList.size ()) {
+ return 0;
+ }
+ return mPlotDataSelectionList[inIndex];
+}
+
+void PlotDataContainer::RemoveElement (int inIndex) {
+ if (!(inIndex < mXDataList.size () && inIndex < mYDataList.size () &&
+ inIndex < mLegendDataList.size () && inIndex < mDataDrawerList.size ())) {
+ // Invalid index
+ return;
+ }
+
+ PlotDataList::iterator theXI = mXDataList.begin () + inIndex;
+ PlotDataList::iterator theYI = mYDataList.begin () + inIndex;
+ LegendDataList::iterator theLI = mLegendDataList.begin () + inIndex;
+ DataDrawerList::iterator theDI = mDataDrawerList.begin () + inIndex;
+ PlotDataSelectionList::iterator thePI = mPlotDataSelectionList.begin () + inIndex;
+
+ delete *theXI;
+ delete *theYI;
+ delete *theLI;
+ delete *theDI;
+ delete *thePI;
+
+ mXDataList.erase (theXI);
+ mYDataList.erase (theYI);
+ mLegendDataList.erase (theLI);
+ mDataDrawerList.erase (theDI);
+ mPlotDataSelectionList.erase (thePI);
+}
+
+void PlotDataContainer::ClearData () {
+ PlotDataList::iterator theXI = mXDataList.begin ();
+ PlotDataList::iterator theYI = mYDataList.begin ();
+ LegendDataList::iterator theLI = mLegendDataList.begin ();
+ DataDrawerList::iterator theDI = mDataDrawerList.begin ();
+ PlotDataSelectionList::iterator thePI = mPlotDataSelectionList.begin ();
+
+ for (;theXI!=mXDataList.end () && theYI!=mYDataList.end () && theLI!=mLegendDataList.end () && theDI != mDataDrawerList.end () && thePI != mPlotDataSelectionList.end ();) {
+ PlotDataBase *theX = *theXI;
+ PlotDataBase *theY = *theYI;
+ LegendData *theL = *theLI;
+ DataDrawerBase *theD = *theDI;
+ PlotDataSelection *theP = *thePI;
+
+ delete theX;
+ delete theY;
+ delete theL;
+ delete theD;
+ delete theP;
+
+ theXI++;
+ theYI++;
+ theLI++;
+ theDI++;
+ thePI++;
+ }
+ mXDataList.clear ();
+ mYDataList.clear ();
+ mLegendDataList.clear ();
+ mDataDrawerList.clear ();
+ mPlotDataSelectionList.clear ();
+}
+
+/* M.T. - changed to return the index of the added plot; returns -1 on error */
+int PlotDataContainer::AddXYPlot (PlotDataBase *inXData, PlotDataBase *inYData, LegendData *inLegendData, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection) {
+ if (!inYData || (!inYData->GetRealPlotData () && !inYData->GetCalculatedData ())) {
+ return -1;
+ }
+ PlotDataBase *theXData = inXData;
+ if (!theXData) {
+ theXData = new DummyPlotData (inYData->GetSize ());
+ }
+ mXDataList.push_back (theXData);
+ mYDataList.push_back (inYData);
+
+ LegendData *theLegendData = inLegendData;
+ if (!theLegendData) {
+ theLegendData = new LegendData ();
+ theLegendData->SetDefaultValues (mLegendDataList.size ());
+ }
+ mLegendDataList.push_back (theLegendData);
+
+ DataDrawerBase *theDataDrawer = inDataDrawer;
+ if (!theDataDrawer) {
+ theDataDrawer = new LineDataDrawer ();
+ }
+ mDataDrawerList.push_back (theDataDrawer);
+
+ PlotDataSelection *thePlotDataSelection = inPlotDataSelection;
+ if (!thePlotDataSelection) {
+ thePlotDataSelection = new PlotDataSelection ();
+ }
+ else {
+ thePlotDataSelection->resize (inYData->GetSize ());
+ }
+ mPlotDataSelectionList.push_back (thePlotDataSelection);
+ return ( mYDataList.size() - 1 );
+}
+
+void PlotDataContainer::SetXYPlot (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, LegendData *inLegendData, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection) {
+ if (!inYData || !inYData->GetRealPlotData ()) {
+ return;
+ }
+ if (!CheckState ()) {
+ return;
+ }
+ long thePlotCount = GetPlotCount ();
+ if (inIndex<0||inIndex>thePlotCount) {
+ return;
+ }
+ PlotDataBase *theXData = inXData;
+
+ if (!theXData) {
+ theXData = new DummyPlotData (inYData->GetRealPlotData ()->size ());
+ }
+ LegendData *theLegendData = inLegendData;
+ DataDrawerBase *theDataDrawer = inDataDrawer;
+ if (!theLegendData) {
+ theLegendData = new LegendData ();
+ if (inIndex >= 0 && inIndex < mYDataList.size () ) {
+ *theLegendData = *mLegendDataList[inIndex]; // copy old values...
+ } else {
+ theLegendData->SetDefaultValues (mLegendDataList.size ());
+ }
+ }
+ if (!theDataDrawer) {
+ theDataDrawer = new LineDataDrawer ();
+ }
+ PlotDataSelection *thePlotDataSelection = inPlotDataSelection;
+ if (!thePlotDataSelection) {
+ thePlotDataSelection = new PlotDataSelection (inYData->GetSize ());
+ // thePlotDataSelection = new PlotDataSelection ();
+ }
+ if (inIndex >= 0 && inIndex < mYDataList.size () ) {
+ delete mXDataList[inIndex];
+ delete mYDataList[inIndex];
+ delete mLegendDataList[inIndex];
+ delete mDataDrawerList[inIndex];
+ delete mPlotDataSelectionList[inIndex];
+
+ mXDataList[inIndex] = theXData;
+ mYDataList[inIndex] = inYData;
+ mLegendDataList[inIndex] = theLegendData;
+ mDataDrawerList[inIndex] = theDataDrawer;
+ mPlotDataSelectionList[inIndex] = thePlotDataSelection;
+ } else { // add at end
+ mXDataList.push_back (theXData);
+ mYDataList.push_back (inYData);
+ mLegendDataList.push_back (theLegendData);
+ mDataDrawerList.push_back (theDataDrawer);
+ mPlotDataSelectionList.push_back (thePlotDataSelection);
+ }
+}
+
+bool PlotDataContainer::SetDataDrawer (int inIndex, DataDrawerBase* inDataDrawer) {
+ if (inIndex < 0 || inIndex >= mYDataList.size () ) {
+ return false;
+ }
+ DataDrawerBase* theDataDrawer = inDataDrawer;
+ if (!inDataDrawer) {
+ theDataDrawer = new LineDataDrawer;
+ }
+ delete mDataDrawerList[inIndex];
+ mDataDrawerList[inIndex] = theDataDrawer;
+ return true;
+}
+
+int PlotDataContainer::GetPlotIndexByName (const string &inName) const {
+
+ if (CheckState ()) {
+ for (int theI=0;theI<mLegendDataList.size ();theI++) {
+ LegendData *theLegendData = mLegendDataList[theI];
+ if (theLegendData->mName == inName) {
+ return theI;
+ }
+ }
+ }
+ return -1;
+}
+
+
+bool PlotDataContainer::CalculateXRange (float &outXMin, float &outXMax) const {
+ bool theFirst = true;
+ outXMin = 0;
+ outXMax = 0;
+ for (PlotDataList::const_iterator theI=mXDataList.begin();theI!=mXDataList.end ();theI++) {
+ PlotDataBase *theXDataBase = *theI;
+ if (!theXDataBase) {
+ return false;
+ }
+ if (theXDataBase->GetSize () == 0) {
+ continue;
+ }
+ float theXMin;
+ float theXMax;
+ if (!theXDataBase->CalculateRange (theXMin, theXMax)) {
+ return false;
+ }
+ if (theXMax < theXMin) {
+ return false;
+ }
+ if (theFirst) {
+ outXMin = theXMin;
+ outXMax = theXMax;
+ theFirst = false;
+ }
+ if (theXMax>outXMax) {
+ outXMax = theXMax;
+ }
+ if (theXMin<outXMin) {
+ outXMin = theXMin;
+ }
+ }
+ if (outXMin == 0 && outXMax == 0) {
+ return false;
+ }
+ return true;
+}
+
+bool PlotDataContainer::CalculateYRange (float inXMin, float inXMax, float &outYMin, float &outYMax) const {
+ outYMin = 0;
+ outYMax = 0;
+ bool theFirst = true;
+
+ for (int theI=0; theI<GetPlotCount (); theI++) {
+ const PlotDataBase *theXDataBase = GetConstXData (theI);
+ const PlotDataBase *theYDataBase = GetConstYData (theI);
+ if (!theXDataBase || !theYDataBase) {
+ return false;
+ }
+ float theYMin;
+ float theYMax;
+ if (!CalculateYRangePlot (inXMin, inXMax, *theXDataBase, *theYDataBase, theYMin,theYMax)) {
+ return false;
+ }
+ if (theFirst) {
+ outYMin = theYMin;
+ outYMax = theYMax;
+ theFirst = false;
+ }
+ if (theYMin<outYMin) {
+ outYMin = theYMin;
+ }
+ if (theYMax>outYMax) {
+ outYMax = theYMax;
+ }
+
+ }
+ return true;
+}
+
+bool PlotDataContainer::CalculateYRangePlot (float inXMin, float inXMax, const PlotDataBase &inXData, const PlotDataBase &inYData, float &outYMin, float &outYMax) const {
+ outYMin = 0;
+ outYMax = 0;
+ bool initialized = false;
+
+ if (inXData.GetSize () != inYData.GetSize ()) {
+ return false;
+ }
+
+ for (long theI = 0; theI < inXData.GetSize (); theI++) {
+ float theX = inXData.GetValue (theI);
+ float theY = inYData.GetValue (theI);
+
+ if (theX>=inXMin && theX <= inXMax) {
+ if (!initialized) {
+ initialized = true;
+ outYMin = theY;
+ outYMax = theY;
+ } else {
+ if (theY<outYMin) {
+ outYMin = theY;
+ }
+ if (theY>outYMax) {
+ outYMax = theY;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool PlotDataContainer::CheckState () const {
+ long theSize1 = mXDataList.size ();
+ long theSize2 = mYDataList.size ();
+ long theSize3 = mLegendDataList.size ();
+ long theSize4 = mDataDrawerList.size ();
+ long theSize5 = mPlotDataSelectionList.size ();
+ if (theSize1!=theSize2 || theSize1!=theSize3 || theSize1!=theSize4 || theSize1!=theSize5) {
+ return false;
+ }
+ return true;
+}
+
+float LinTrafo::Transform (float inValue) const {
+ return inValue * mSlope + mOffset;
+}
+float LinTrafo::TransformBack (float inValue) const {
+ if (mSlope != 0) {
+ return (inValue - mOffset) / mSlope;
+ } else {
+ return 0;
+ }
+}
+
+
+float LogTrafo::Transform (float inValue) const{
+ if (inValue<kLogMinClipValue) {
+ inValue = kLogMinClipValue;
+ }
+ return SafeLog (inValue, mBase, mFactor)*mSlope+mOffset;
+}
+float LogTrafo::TransformBack (float inValue) const {
+ if (mSlope != 0) {
+ return SafeExp( (inValue - mOffset)/mSlope, mBase, mFactor);
+ } else {
+ return 0;
+ }
+}
+
+
+bool LinTickIterator::Init () {
+ if (!mAxisSetup) {
+ return false;
+ }
+
+ float theMin = mAxisSetup->mMin;
+ float theMajorTickSpan = mAxisSetup->mTickInfo.mMajorTickSpan;
+ int theDiv = mAxisSetup->mTickInfo.mTickDivision;
+ mDelta = theMajorTickSpan/theDiv;
+ mCount = ceil (theMin/mDelta);
+ mCurrentTick = mCount*mDelta;
+
+ mFormatString = mAxisSetup->mTickInfo.mFormatString;
+
+ return true;
+
+}
+
+bool LinTickIterator::GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString) {
+ if (!mAxisSetup) {
+ return false;
+ }
+ if (mCurrentTick>mAxisSetup->mMax*kLittleIncrease) {
+ return false;
+ }
+ outTick = mCurrentTick;
+ outIsMajorTick = (mCount%mAxisSetup->mTickInfo.mTickDivision == 0);
+ outFormatString = mFormatString;
+
+ mCurrentTick += mDelta;
+ mCount++;
+ return true;
+}
+
+bool LinTickIterator::InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &ioTickInfo) const {
+ if (inDivGuess <= kFloatSmall) {
+ return false;
+ }
+ float thePreferredSpan = TickInfo::RoundSpan (inParRange/inDivGuess);
+ if (thePreferredSpan < 0) {
+ return false;
+ }
+
+ float thePreferredNrOfTicks = inParRange/thePreferredSpan;
+ if (thePreferredNrOfTicks <1) {
+ ioTickInfo.mMajorTickSpan = inParRange;
+ }
+ else {
+ ioTickInfo.mMajorTickSpan = thePreferredSpan;
+ }
+
+ ioTickInfo.mTickDivision = 5;
+ if (ioTickInfo.mAutoTickSize) {
+ ioTickInfo.mMinorTickScreenSize = PMax (kMinMinorTickScreenSize, PPlot::Round (inOrthoScreenRange*kRelMinorTickSize));
+ ioTickInfo.mMajorTickScreenSize = PMax (ioTickInfo.mMinorTickScreenSize+1, PPlot::Round (inOrthoScreenRange*kRelMajorTickSize));
+ }
+
+ TickInfo::MakeFormatString (ioTickInfo.mMajorTickSpan, ioTickInfo.mFormatString);
+ return true;
+}
+
+bool LogTickIterator::Init () {
+ if (!mAxisSetup) {
+ return false;
+ }
+
+ float theMin = mAxisSetup->mMin;
+ // float theMax = mAxisSetup->mMax;
+ float theMajorTickSpan = mAxisSetup->mTickInfo.mMajorTickSpan;
+ int theDiv = mAxisSetup->mTickInfo.mTickDivision;
+ mDelta = theMajorTickSpan/theDiv;
+ float theBase = mAxisSetup->mLogBase;
+ long theLogFac = 1;//mAxisSetup->mLogFactor;
+ long thePowMin = (long)floor(SafeLog(theMin, theBase, theLogFac));
+ mCurrentTick = SafeExp (thePowMin, theBase, theLogFac);
+ mCount = 0;
+
+ // walk to the first tick
+
+ if (theMin<=0) {
+ return false;
+ // error
+ }
+ else {
+ // walk forward
+ float theNext = mCurrentTick+mDelta*SafeExp (thePowMin, theBase, theLogFac);
+ while (theNext<=theMin*kLittleDecrease) {
+ mCurrentTick = theNext;
+ theNext += mDelta*SafeExp (thePowMin,theBase, theLogFac);
+ mCount++;
+ }
+ }
+ return true;
+}
+
+bool LogTickIterator::InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &ioTickInfo) const {
+ if (inDivGuess<=kFloatSmall) {
+ return false;
+ }
+ /*
+ float thePreferredSpan = TickInfo::RoundSpan (inParRange/inDivGuess);
+ float thePreferredNrOfTicks = inParRange/thePreferredSpan;
+ if (thePreferredNrOfTicks <1) {
+ ioTickInfo.mMajorTickSpan = inParRange;
+ }
+ else {
+ ioTickInfo.mMajorTickSpan = thePreferredSpan;
+ }
+ */
+ float theBase = mAxisSetup->mLogBase;
+ ioTickInfo.mMajorTickSpan = theBase-1;// relative
+
+ ioTickInfo.mTickDivision = PPlot::Round (ioTickInfo.mMajorTickSpan);
+ ioTickInfo.mMinorTickScreenSize = PMax (kMinMinorTickScreenSize, PPlot::Round (inOrthoScreenRange*kRelMinorTickSize));
+ ioTickInfo.mMajorTickScreenSize = PMax (ioTickInfo.mMinorTickScreenSize+1, PPlot::Round (inOrthoScreenRange*kRelMajorTickSize));
+
+ ioTickInfo.mFormatString = "%.1e";
+ return true;
+}
+
+bool LogTickIterator::GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString) {
+ if (!mAxisSetup) {
+ return false;
+ }
+ if (mCurrentTick>mAxisSetup->mMax*kLittleIncrease) {
+ return false;
+ }
+ outTick = mCurrentTick;
+ outIsMajorTick = (mCount%mAxisSetup->mTickInfo.mTickDivision == 0);
+ TickInfo::MakeFormatString (outTick, outFormatString);
+ float theBase = mAxisSetup->mLogBase;
+ float theLogFac = 1;//mAxisSetup->mLogFactor;
+ float theLogNow = SafeLog(mCurrentTick, theBase, theLogFac);
+ int thePowNow = (int)floor(theLogNow);
+ outIsMajorTick = false;
+ if (fabs (theLogNow-thePowNow)<kEps) {
+ outIsMajorTick = true;
+ }
+
+ if (mAxisSetup->mLogFactor>1) {
+ char theBuf[128];
+ sprintf (theBuf, "%d", thePowNow*20);
+ outFormatString = theBuf;
+ }
+
+ mCurrentTick += mDelta*SafeExp (thePowNow, theBase, theLogFac);
+ mCount++;
+
+ return true;
+}
+
+bool LogTickIterator::AdjustRange (float &ioMin, float &ioMax) const {
+
+ float theBase = mAxisSetup->mLogBase;
+ long theLogFac = 1;//mAxisSetup->mLogFactor;
+ if (mAxisSetup->mMaxDecades > 0) {
+ ioMin = ioMax/SafeExp (mAxisSetup->mMaxDecades, theBase, theLogFac);
+ }
+ if (ioMin == 0 && ioMax == 0) {
+ ioMin = kLogMinClipValue;
+ ioMax = 1.0f;
+ }
+ if (ioMin <= 0 || ioMax<=0) {
+ return false;
+ }
+ ioMin = RoundDown (ioMin*kLittleIncrease);
+ ioMax = RoundUp (ioMax*kLittleDecrease);
+
+ if (ioMin<kLogMinClipValue) {
+ ioMin = kLogMinClipValue;
+ }
+ if (mAxisSetup->mMaxDecades > 0) {
+ ioMin = ioMax/SafeExp (mAxisSetup->mMaxDecades, theBase, theLogFac);
+ }
+ return true;
+}
+
+float LogTickIterator::RoundUp (float inFloat) const {
+ float theBase = mAxisSetup->mLogBase;
+ float theLogFac = 1;//mAxisSetup->mLogFactor;
+ int thePow = (int)ceil(SafeLog(inFloat, theBase, theLogFac));
+ return pow (theBase, thePow);
+}
+
+float LogTickIterator::RoundDown (float inFloat) const {
+ float theBase = mAxisSetup->mLogBase;
+ long theLogFac = 1;//mAxisSetup->mLogFactor;
+ int thePow = (int)floor(SafeLog(inFloat,theBase, theLogFac));
+ return pow (theBase, thePow);
+}
+
+bool NamedTickIterator::GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString) {
+ if (LinTickIterator::GetNextTick (outTick, outIsMajorTick, outFormatString)) {
+ int theIndex = PPlot::Round (outTick);
+
+ // TO DO: improve this
+ if (fabs(outTick - (float)theIndex) > 0.1 ) {
+ outFormatString = "";
+ return true;
+ }
+
+ if (theIndex>=0 && theIndex < (int)mStringList.size ()) {
+ outFormatString = mStringList[theIndex];
+ return true;
+ }
+ }
+ return false;
+}
+
+bool NamedTickIterator::InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &outTickInfo) const {
+ if (LinTickIterator::InitFromRanges (inParRange, inOrthoScreenRange, inDivGuess, outTickInfo)) {
+ outTickInfo.mTickDivision = 1;
+ return true;
+ }
+ return false;
+}
+
+bool PainterTester::Draw (Painter &inPainter) {
+
+ const char * theString = "The quick brown fox...";
+ int theWidth = inPainter.CalculateTextDrawSize (theString);
+ int theOffset = theWidth/10;
+
+ // a horizontal lines
+ int theHAscent_x = theOffset+2*inPainter.GetFontHeight ();
+ int theHAscent_y = 10;
+ int theHAscent_w = theWidth;
+ inPainter.DrawLine (theHAscent_x, theHAscent_y, theHAscent_x+theHAscent_w, theHAscent_y);
+
+ int theHDescent_x = theHAscent_x;
+ int theHDescent_y = theHAscent_y+inPainter.GetFontHeight ();
+ int theHDescent_w = theHAscent_w;
+ inPainter.DrawLine (theHDescent_x, theHDescent_y, theHDescent_x+theHDescent_w, theHDescent_y);
+
+ // a vertical lines
+ int theVAscent_x = theOffset;
+ int theVAscent_y = theHAscent_y+theWidth;
+ int theVAscent_h = -theWidth;
+ inPainter.DrawLine (theVAscent_x, theVAscent_y, theVAscent_x, theVAscent_y+theVAscent_h);
+
+ int theVDescent_x = theVAscent_x+inPainter.GetFontHeight ();
+ int theVDescent_y = theVAscent_y;
+ int theVDescent_h = theVAscent_h;
+ inPainter.DrawLine (theVDescent_x, theVDescent_y, theVDescent_x, theVDescent_y+theVDescent_h);
+
+ // Draw vertical text, followed by horizontal.
+#ifdef _IUP_PPLOT_ /* M.T. - the alignment of the text is simply requested */
+ inPainter.DrawRotatedText (theVDescent_x, theVDescent_y, -90, PPLOT_NORTH_WEST, theString);
+ inPainter.DrawText (theHDescent_x, theHDescent_y, PPLOT_NORTH_WEST, theString);
+#else
+ inPainter.DrawRotatedText (theVDescent_x, theVDescent_y, -90, theString);
+ inPainter.DrawText (theHDescent_x, theHDescent_y, theString);
+#endif
+
+ return true;
+}
+
+PPlot::PPlot ():
+ mShowLegend(true), // M.T. - show|hide legend
+ mLegendPos(PPLOT_TOPRIGHT),
+ mXTrafo (&mXLinTrafo),
+ mYTrafo (&mYLinTrafo),
+ mXTickIterator (&mXLinTickIterator),
+ mYTickIterator (&mYLinTickIterator),
+ mPPlotDrawer (0),
+ mOwnsPPlotDrawer (true),
+ mHasAnyModifyingCalculatorBeenActive (false)
+{
+ mMargins = kDefaultMargins;
+ mYAxisSetup.mAscending = false;
+}
+
+PPlot::~PPlot () {
+ if (mOwnsPPlotDrawer) {
+ delete mPPlotDrawer;
+ }
+ mPPlotDrawer = 0;
+}
+
+bool PPlot::Draw (Painter &inPainter) {
+ PRect theRect;
+ theRect.mX = mMargins.mLeft;
+ theRect.mY = mMargins.mTop;
+ theRect.mW = inPainter.GetWidth () - mMargins.mLeft - mMargins.mRight;
+ theRect.mH = inPainter.GetHeight () - mMargins.mTop - mMargins.mBottom;
+
+ if (mPPlotDrawer) {
+ mPPlotDrawer->Prepare (inPainter, *this);
+ return mPPlotDrawer->Draw (inPainter);
+ }
+ if (!mPlotDataContainer.GetPlotCount ()) {
+ return true;
+ }
+
+ if (!ConfigureSelf ()) {
+ return false;
+ }
+ bool theShouldRepeat = true;
+ long theRepeatCount = 0;
+
+ while (theShouldRepeat && theRepeatCount<2) {
+ theRepeatCount++;
+
+ if (!ValidateData ()) {
+ return false;
+ }
+
+ if (!CalculateAxisRanges ()) {
+ return false;
+ }
+
+ if (!this->CheckRange (mXAxisSetup)) {
+ return false;
+ }
+
+ if (!this->CheckRange (mYAxisSetup)) {
+ return false;
+ }
+
+ if (!CalculateTickInfo (theRect, inPainter)) {
+ return false;
+ }
+
+ if (!CalculateXTransformation (theRect)) {
+ return false;
+ }
+
+ if (!CalculateYTransformation (theRect)) {
+ return false;
+ }
+ if (theRepeatCount>1) {
+ break;
+ }
+ // hooks for some final calculations
+ bool theShouldRepeat = false;
+ for (PCalculator::tList::iterator theModifyingC=mModifyingCalculatorList.begin ();theModifyingC!=mModifyingCalculatorList.end();theModifyingC++) {
+ PCalculator *theModifyingCalculator = *theModifyingC;
+ if (theModifyingCalculator->ShouldCalculate ()) {
+ theShouldRepeat = true;
+ theModifyingCalculator->Calculate (inPainter, *this);
+ mHasAnyModifyingCalculatorBeenActive = true;
+ }
+ }
+// theShouldRepeat = mModifyingCalculatorList.size ()>0;
+ }
+
+ // hooks for some final calculations
+ for (PCalculator::tList::iterator thePostC=mPostCalculatorList.begin ();thePostC!=mPostCalculatorList.end();thePostC++) {
+ PCalculator *thePostCalculator = *thePostC;
+ thePostCalculator->Calculate (inPainter, *this);
+ }
+
+ for (PDrawer::tList::iterator thePre1=mPreDrawerList.begin();thePre1!=mPreDrawerList.end ();thePre1++) {
+ PDrawer *thePreDrawer = *thePre1;
+ thePreDrawer->Prepare (inPainter, *this);
+ }
+
+ // Drawing !
+
+ inPainter.SetLineColor (0,0,0);
+ inPainter.SetClipRect (0, 0, inPainter.GetWidth (), inPainter.GetHeight ());
+
+ // draw entire background, including the margins (for scrolling...)
+ PRect fullRect;
+ fullRect.mX = 0;
+ fullRect.mY = 0;
+ fullRect.mW = inPainter.GetWidth ();
+ fullRect.mH = inPainter.GetHeight ();
+ if (!DrawPlotBackground (fullRect, inPainter)) {
+ return false;
+ }
+
+ for (PDrawer::tList::iterator thePre=mPreDrawerList.begin ();thePre!=mPreDrawerList.end();thePre++) {
+ PDrawer *thePreDrawer = *thePre;
+ thePreDrawer->Draw (inPainter);
+ }
+
+
+ if (!DrawGridXAxis (theRect, inPainter)) {
+ return false;
+ }
+
+ if (!DrawGridYAxis (theRect, inPainter)) {
+ return false;
+ }
+
+ if (!DrawXAxis (theRect, inPainter)) {
+ return false;
+ }
+
+ if (!DrawYAxis (theRect, inPainter)) {
+ return false;
+ }
+
+ // clip the plotregion while drawing plots
+ inPainter.SetClipRect (theRect.mX, theRect.mY, theRect.mW, theRect.mH);
+
+ for (int theI=0;theI<mPlotDataContainer.GetPlotCount ();theI++) {
+ if (!DrawPlot (theI, theRect, inPainter)) {
+ return false;
+ }
+ }
+
+ if (mShowLegend) {
+ if (!DrawLegend (theRect, inPainter)) {
+ return false;
+ }
+ }
+
+ inPainter.SetClipRect (0, 0, inPainter.GetWidth (), inPainter.GetHeight ());
+
+#ifdef _IUP_PPLOT_
+ if (!DrawPlotTitle (fullRect, inPainter)) {
+ return false;
+ }
+#endif
+
+ for (PDrawer::tList::iterator thePost=mPostDrawerList.begin ();thePost!=mPostDrawerList.end();thePost++) {
+ PDrawer *thePostDrawer = *thePost;
+ thePostDrawer->Draw (inPainter);
+ }
+
+ return true;
+}
+
+void PPlot::SetPPlotDrawer (PDrawer *inPDrawer) {
+ if (mOwnsPPlotDrawer) {
+ delete mPPlotDrawer;// delete (if any)
+ }
+ mOwnsPPlotDrawer = true;
+ mPPlotDrawer = inPDrawer;
+}
+
+void PPlot::SetPPlotDrawer (PDrawer &inPDrawer) {
+ mOwnsPPlotDrawer = false;
+ mPPlotDrawer = &inPDrawer;
+}
+
+bool PPlot::DrawPlotBackground (const PRect &inRect, Painter &inPainter) const {
+ if (!mPlotBackground.mTransparent) {
+ PColor theC = mPlotBackground.mPlotRegionBackColor;
+ inPainter.SetFillColor (theC.mR, theC.mG, theC.mB);
+ inPainter.FillRect (inRect.mX, inRect.mY, inRect.mW, inRect.mH);
+ }
+#ifndef _IUP_PPLOT_
+ string theTitle = mPlotBackground.mTitle;
+ if (theTitle.size ()>0) {
+ int theW = inPainter.CalculateTextDrawSize (theTitle.c_str());
+ int theX = inRect.mX + (inRect.mW-theW)/2;
+ int theY = inRect.mY + mMargins.mTop;
+ inPainter.DrawText (theX, theY, theTitle.c_str ());
+ }
+#endif
+ return true;
+}
+
+#ifdef _IUP_PPLOT_
+bool PPlot::DrawPlotTitle(const PRect &inRect, Painter &inPainter) const {
+ if (mPlotBackground.mTitle.size ()>0) {
+ inPainter.SetStyle (mPlotBackground.mStyle);
+ int theX = inRect.mX + inRect.mW/2;
+ int theY = inRect.mY + 5; // do not depend on margin
+ PColor theC = mPlotBackground.mPlotRegionBackColor;
+ inPainter.SetFillColor (theC.mR, theC.mG, theC.mB);
+ int textSize = inPainter.CalculateTextDrawSize(mPlotBackground.mTitle.c_str());
+ inPainter.FillRect (theX-textSize/2-3, theY, textSize+6, inPainter.GetFontHeight()+3);
+ theC = mPlotBackground.mTitleColor;
+ inPainter.SetFillColor (theC.mR, theC.mG, theC.mB);
+ inPainter.DrawText (theX, theY, PPLOT_NORTH, mPlotBackground.mTitle.c_str());
+ }
+ return true;
+}
+#endif
+
+bool PPlot::DrawGridXAxis (const PRect &inRect, Painter &inPainter) const {
+
+ // ticks
+ inPainter.SetStyle (mXAxisSetup.mTickInfo.mStyle);
+ if (!mXTickIterator->Init ()) {
+ return false;
+ }
+
+ float theX;
+ bool theIsMajorTick;
+ string theFormatString;
+
+/* M.T. - modified to allow customisation
+ inPainter.SetFillColor (200,200,200);
+ inPainter.SetLineColor (200,200,200);
+*/
+ inPainter.SetLineColor(mGridInfo.mGridColor.mR,
+ mGridInfo.mGridColor.mG,
+ mGridInfo.mGridColor.mB);
+ inPainter.SetStyle (mGridInfo.mStyle);
+
+ // draw gridlines
+ if (mGridInfo.mXGridOn) {
+ while (mXTickIterator->GetNextTick (theX, theIsMajorTick, theFormatString)) {
+
+ if (theIsMajorTick && mGridInfo.mXGridOn) {
+ float theScreenX = mXTrafo->Transform(theX);
+ inPainter.DrawLine (theScreenX, inRect.mY, theScreenX, inRect.mY + inRect.mH);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool PPlot::DrawGridYAxis (const PRect &inRect, Painter &inPainter) const {
+
+ // ticks
+ inPainter.SetStyle (mYAxisSetup.mTickInfo.mStyle);
+ if (!mYTickIterator->Init ()) {
+ return false;
+ }
+
+ float theY;
+ bool theIsMajorTick;
+ string theFormatString;
+ PRect theTickRect;
+
+/* M.T. - modified to allow customisation
+ inPainter.SetFillColor (200,200,200);
+ inPainter.SetLineColor (200,200,200);
+*/
+ inPainter.SetLineColor(mGridInfo.mGridColor.mR,
+ mGridInfo.mGridColor.mG,
+ mGridInfo.mGridColor.mB);
+ inPainter.SetStyle (mGridInfo.mStyle);
+
+ // draw gridlines
+ if (mYAxisSetup.mTickInfo.mTicksOn) {
+ while (mYTickIterator->GetNextTick (theY, theIsMajorTick, theFormatString)) {
+
+ if (theIsMajorTick && mGridInfo.mYGridOn) {
+ float theScreenY = mYTrafo->Transform(theY);
+ inPainter.DrawLine (inRect.mX, theScreenY, inRect.mX + inRect.mW, theScreenY);
+ }
+ }
+ }
+
+ return true;
+}
+
+#ifdef _IUP_PPLOT_
+static void DrawArrow(Painter &inPainter, float rx, float ry, int vert, int ascen, int size)
+{
+ int x = (int)(rx + 0.5);
+ int y = (int)(ry + 0.5);
+ size += 2; // to avoid too small sizes
+ int size2 = (int)(size*0.7f + 0.5);
+ if (vert)
+ {
+ y-=ascen*size;
+ inPainter.DrawLine(x, y, x, y+ascen*size);
+
+ int y2 = y+ascen*size2;
+ inPainter.FillArrow(x, y, x-size2, y2, x+size2, y2);
+ }
+ else
+ {
+ x+=ascen*size;
+ inPainter.DrawLine(x, y, x-ascen*size, y);
+
+ int x2 = x-ascen*size2;
+ inPainter.FillArrow(x, y, x2, y-size2, x2, y+size2);
+ }
+}
+#endif
+
+bool PPlot::DrawXAxis (const PRect &inRect, Painter &inPainter) const {
+ inPainter.SetStyle (mXAxisSetup.mStyle);
+
+ float theX1 = inRect.mX;
+ float theY1;
+ float theTargetY = 0;
+ if (!mXAxisSetup.mCrossOrigin) {
+ if (mYAxisSetup.mAscending) {
+ theTargetY = mYAxisSetup.mMax;
+ } else {
+ theTargetY = mYAxisSetup.mMin;
+ }
+ }
+ theY1 = mYTrafo->Transform (theTargetY);
+
+ inPainter.SetLineColor(mXAxisSetup.mColor.mR,
+ mXAxisSetup.mColor.mG,
+ mXAxisSetup.mColor.mB);
+
+ // x-axis
+ float theX2 = theX1+inRect.mW;
+ float theY2 = theY1;
+ inPainter.DrawLine (theX1, theY1, theX2, theY2);
+
+#ifdef _IUP_PPLOT_
+ if (mXAxisSetup.mAscending)
+ DrawArrow(inPainter, theX2, theY2, 0, 1, mXAxisSetup.mTickInfo.mMinorTickScreenSize);
+ else
+ DrawArrow(inPainter, theX1, theY1, 0, -1, mXAxisSetup.mTickInfo.mMinorTickScreenSize);
+#endif
+
+ // ticks
+ inPainter.SetStyle (mXAxisSetup.mTickInfo.mStyle);
+ if (!mXTickIterator->Init ()) {
+ return false;
+ }
+
+ float theX;
+ bool theIsMajorTick;
+ string theFormatString;
+
+ int theYMax = 0;
+ PRect theTickRect;
+ PRect theRect = inRect;
+
+ if (mXAxisSetup.mTickInfo.mTicksOn) {
+ while (mXTickIterator->GetNextTick (theX, theIsMajorTick, theFormatString)) {
+ if (!DrawXTick (theX, theY1, theIsMajorTick, theFormatString, inPainter, theTickRect)) {
+ return false;
+ }
+
+ if (theTickRect.mY+theTickRect.mH>theYMax) {
+ theYMax = theTickRect.mY+theTickRect.mH;
+ }
+ }
+ }
+
+ if (theYMax>theRect.mY+theRect.mH) {
+ theRect.mH = theYMax-theRect.mY;
+ }
+
+#ifdef _IUP_PPLOT_ /* M.T. - the alignment of the text is simply requested */
+ if (mXAxisSetup.mLabel.size ()>0) {
+ inPainter.SetStyle (mXAxisSetup.mStyle);
+ int theY = theRect.mY + theRect.mH + 3*inPainter.GetFontHeight()/2;
+ if (mXAxisSetup.mLabelCentered)
+ {
+ int theX = theRect.mX + theRect.mW/2;
+ inPainter.DrawText (theX, theY, PPLOT_NORTH, mXAxisSetup.mLabel.c_str ());
+ }
+ else
+ {
+ int theX = theRect.mX + theRect.mW;
+ inPainter.DrawText (theX, theY, PPLOT_NORTH_EAST, mXAxisSetup.mLabel.c_str ());
+ }
+ }
+#else
+ inPainter.SetStyle (mXAxisSetup.mStyle);
+ string theLabel = mXAxisSetup.mLabel;
+ if (theLabel.size ()>0) {
+ int theW = inPainter.CalculateTextDrawSize (theLabel.c_str ());
+ int theX = theRect.mX + (theRect.mW-theW)/2;
+ int theY = 1 + theRect.mY + theRect.mH + inPainter.GetFontHeight (); // M.T. was too close to ticks
+ inPainter.DrawText (theX, theY, theLabel.c_str ());
+ }
+#endif
+ return true;
+}
+
+bool PPlot::DrawXTick (float inX, int inScreenY, bool inMajor, const string &inFormatString, Painter &inPainter, PRect &outRect) const{
+ char theBuf[128];
+ int theTickSize;
+ float theScreenX = mXTrafo->Transform(inX);
+ outRect.mX = theScreenX;
+ outRect.mY = inScreenY;
+ outRect.mW = 0;
+ if (inMajor) {
+ theTickSize = mXAxisSetup.mTickInfo.mMajorTickScreenSize;
+ sprintf (theBuf, inFormatString.c_str (), inX);
+#ifdef _IUP_PPLOT_ /* M.T. - the alignment of the text is simply requested */
+ outRect.mH = theTickSize + mXAxisSetup.mTickInfo.mMinorTickScreenSize;
+ inPainter.DrawText (theScreenX, inScreenY+outRect.mH, PPLOT_NORTH, theBuf);
+#else
+ outRect.mH = inPainter.GetFontHeight () + theTickSize +
+ mXAxisSetup.mTickInfo.mMinorTickScreenSize;
+ inPainter.DrawText (theScreenX, inScreenY+outRect.mH, theBuf);
+#endif
+ }
+ else {
+ theTickSize = mXAxisSetup.mTickInfo.mMinorTickScreenSize;
+ outRect.mH = theTickSize;
+ }
+
+ inPainter.DrawLine (theScreenX, inScreenY,theScreenX, inScreenY+theTickSize);
+ return true;
+}
+
+bool PPlot::DrawYAxis (const PRect &inRect, Painter &inPainter) const {
+ inPainter.SetStyle (mYAxisSetup.mStyle);
+ float theX1;
+ float theTargetX = 0;
+ if (!mYAxisSetup.mCrossOrigin) {
+ if (mXAxisSetup.mAscending) {
+ theTargetX = mXAxisSetup.mMin;
+ }
+ else {
+ theTargetX = mXAxisSetup.mMax;
+ }
+ }
+ if (mXAxisSetup.mDiscrete)
+ theTargetX -= 0.5;
+
+ theX1 = mXTrafo->Transform (theTargetX);
+
+ int theY1 = inRect.mY;
+ float theX2 = theX1;
+ int theY2 = theY1+inRect.mH;
+
+ inPainter.SetLineColor(mYAxisSetup.mColor.mR,
+ mYAxisSetup.mColor.mG,
+ mYAxisSetup.mColor.mB);
+
+ // draw y axis
+ inPainter.DrawLine (theX1, theY1, theX2, theY2);
+
+#ifdef _IUP_PPLOT_
+ if (mYAxisSetup.mAscending)
+ DrawArrow(inPainter, theX2, theY2, 1, -1, mYAxisSetup.mTickInfo.mMinorTickScreenSize);
+ else
+ DrawArrow(inPainter, theX1, theY1, 1, 1, mYAxisSetup.mTickInfo.mMinorTickScreenSize);
+#endif
+
+ // ticks
+ inPainter.SetStyle (mYAxisSetup.mTickInfo.mStyle);
+ if (!mYTickIterator->Init ()) {
+ return false;
+ }
+
+ float theY;
+ bool theIsMajorTick;
+ string theFormatString;
+ PRect theTickRect;
+ PRect theRect = inRect;
+
+ if (mYAxisSetup.mTickInfo.mTicksOn) {
+ while (mYTickIterator->GetNextTick (theY, theIsMajorTick, theFormatString)) {
+ if (!DrawYTick (theY, theX1, theIsMajorTick, theFormatString, inPainter, theTickRect)) {
+ return false;
+ }
+
+ if (theTickRect.mX < theRect.mX) {
+ theRect.mX = theTickRect.mX;
+ }
+ }
+ }
+
+ // draw label
+#ifdef _IUP_PPLOT_ /* M.T. - the alignment of the text is simply requested */
+ if (mYAxisSetup.mLabel.size ()>0) {
+ inPainter.SetStyle (mYAxisSetup.mStyle);
+ int theX = theRect.mX - 3*inPainter.GetFontHeight()/2;
+ if (mYAxisSetup.mLabelCentered)
+ {
+ int theY = theRect.mY + theRect.mH/2;
+ inPainter.DrawRotatedText (theX, theY, -90, PPLOT_NORTH, mYAxisSetup.mLabel.c_str ());
+ }
+ else
+ {
+ int theY = theRect.mY;
+ inPainter.DrawRotatedText (theX, theY, -90, PPLOT_NORTH_EAST, mYAxisSetup.mLabel.c_str ());
+ }
+ }
+#else
+ inPainter.SetStyle (mYAxisSetup.mStyle);
+ string theLabel = mYAxisSetup.mLabel;
+ if (theLabel.size ()>0) {
+ int theW = inPainter.CalculateTextDrawSize (theLabel.c_str ());
+ int theX = theRect.mX - 1; // M.T. - was too close to ticks
+ int theY = theRect.mY + theRect.mH - (theRect.mH-theW)/2;
+ inPainter.DrawRotatedText (theX, theY, -90, theLabel.c_str ());
+ }
+#endif
+
+ return true;
+}
+
+bool PPlot::DrawYTick (float inY, int inScreenX, bool inMajor, const string &inFormatString, Painter &inPainter, PRect &outRect) const {
+ char theBuf[128];
+ int theTickSize;
+ float theScreenY = mYTrafo->Transform(inY);
+ outRect.mX = inScreenX;
+ outRect.mY = theScreenY;
+ outRect.mW = 0;// not used
+ outRect.mH = 0;// not used
+ if (inMajor) {
+ theTickSize = mYAxisSetup.mTickInfo.mMajorTickScreenSize;
+ sprintf (theBuf, inFormatString.c_str (), inY);
+#ifdef _IUP_PPLOT_ /* M.T. - the alignment of the text is simply requested */
+ outRect.mX -= (theTickSize + mYAxisSetup.mTickInfo.mMinorTickScreenSize);
+ inPainter.DrawText (outRect.mX, theScreenY, PPLOT_EAST, theBuf);
+ outRect.mX -= inPainter.CalculateTextDrawSize (theBuf); // update the position
+#else
+ int theStringWidth = inPainter.CalculateTextDrawSize (theBuf);
+ outRect.mX -= (theStringWidth+theTickSize+mYAxisSetup.mTickInfo.mMinorTickScreenSize);
+ int theHalfFontHeight = inPainter.GetFontHeight ()/2;// for sort of vertical centralizing
+ inPainter.DrawText (outRect.mX, theScreenY+theHalfFontHeight, theBuf);
+#endif
+
+ }
+ else {
+ theTickSize = mYAxisSetup.mTickInfo.mMinorTickScreenSize;
+ outRect.mX -= theTickSize;
+ }
+
+ inPainter.DrawLine (inScreenX, theScreenY, inScreenX-theTickSize, theScreenY);
+ return true;
+}
+
+#ifdef _IUP_PPLOT_
+static void DrawRect(Painter &inPainter, int inX, int inY, int inW, int inH)
+{
+ inPainter.DrawLine(inX, inY, inX+inW-1, inY);
+ inPainter.DrawLine(inX+inW-1, inY, inX+inW-1, inY+inH-1);
+ inPainter.DrawLine(inX+inW-1, inY+inH-1, inX, inY+inH-1);
+ inPainter.DrawLine(inX, inY+inH-1, inX, inY);
+}
+
+bool PPlot::DrawLegend (const PRect &inRect, Painter &inPainter) const {
+ PColor theC;
+ int theI;
+
+ int theHeight = inPainter.GetFontHeight();
+ int margin = theHeight/2;
+ int plotCount = mPlotDataContainer.GetPlotCount();
+ int totalHeight = plotCount*(1.2*theHeight) - 0.2*theHeight + 2*margin;
+
+ int maxWidth = 0;
+ for (theI=0; theI<plotCount; theI++)
+ {
+ const LegendData *theLegendData = mPlotDataContainer.GetConstLegendData(theI);
+ if (theLegendData && theLegendData->mShow) {
+ inPainter.SetStyle (theLegendData->mStyle);
+ int size = inPainter.CalculateTextDrawSize(theLegendData->mName.c_str());
+
+ const DataDrawerBase* drawer = mPlotDataContainer.GetConstDataDrawer(theI);
+ if (drawer->mHasMarks)
+ {
+ LineDataDrawer* linedrawer = (LineDataDrawer*)drawer;
+ if (linedrawer->mDrawPoint)
+ size += linedrawer->mStyle.mMarkSize+8;
+ }
+
+ if (size > maxWidth)
+ maxWidth = size;
+ }
+ }
+
+ if (maxWidth == 0)
+ return false;
+
+ maxWidth += 2*margin;
+
+ int theX = inRect.mX;
+ int theY = inRect.mY;
+
+ switch (mLegendPos)
+ {
+ case PPLOT_TOPLEFT:
+ theX += 2;
+ theY += 2;
+ break;
+ case PPLOT_BOTTOMLEFT:
+ theX += 2;
+ theY += inRect.mH - totalHeight - 2;
+ break;
+ case PPLOT_BOTTOMRIGHT:
+ theX += inRect.mW - maxWidth - 2;
+ theY += inRect.mH - totalHeight - 2;
+ break;
+ default: // PPLOT_TOPRIGHT
+ theX += inRect.mW - maxWidth - 2;
+ theY += 2;
+ break;
+ }
+
+ theC = mPlotBackground.mPlotRegionBackColor;
+ inPainter.SetFillColor (theC.mR, theC.mG, theC.mB);
+ inPainter.FillRect(theX, theY, maxWidth, totalHeight);
+ inPainter.SetLineColor (theC.mR/1.5, theC.mG/1.5, theC.mB/1.5);
+ DrawRect(inPainter, theX, theY, maxWidth, totalHeight);
+
+ for (theI=0; theI<plotCount; theI++) {
+ const LegendData *theLegendData = mPlotDataContainer.GetConstLegendData(theI);
+ if (theLegendData && theLegendData->mShow) {
+ theC = theLegendData->mColor;
+ inPainter.SetLineColor (theC.mR, theC.mG, theC.mB);
+
+ int X = theX + margin;
+ int Y = theY + theI*(theHeight*1.2) + margin;
+
+ int mark_size = 0;
+ const DataDrawerBase* drawer = mPlotDataContainer.GetConstDataDrawer(theI);
+ if (drawer->mHasMarks)
+ {
+ LineDataDrawer* linedrawer = (LineDataDrawer*)drawer;
+ if (linedrawer->mDrawPoint)
+ {
+ mark_size = linedrawer->mStyle.mMarkSize+8;
+ inPainter.SetStyle (linedrawer->mStyle);
+ linedrawer->DrawPoint(X+mark_size/2, Y+3*inPainter.GetFontHeight()/4, inRect, inPainter);
+ }
+ }
+
+ inPainter.SetStyle (theLegendData->mStyle);
+ inPainter.DrawText (X+mark_size, Y, PPLOT_NORTH_WEST, theLegendData->mName.c_str ());
+ }
+ }
+ return true;
+}
+#else
+bool PPlot::DrawLegend (const PRect &inRect, Painter &inPainter) const {
+ const int kXoffsetLegend(20);
+
+ for (int theI=0; theI<mPlotDataContainer.GetPlotCount (); theI++) {
+ PColor theC;
+ string theText;
+ const LegendData *theLegendData = mPlotDataContainer.GetConstLegendData (theI);
+ if (theLegendData) {
+ inPainter.SetStyle (theLegendData->mStyle);
+ theC = theLegendData->mColor;
+ if (theLegendData->mShow) {
+ theText = theLegendData->mName;
+ }
+ }
+ inPainter.SetLineColor (theC.mR, theC.mG, theC.mB);
+
+ // cut legend if it doesn't fit in plot
+ int theSize (0);
+ if (inPainter.CalculateTextDrawSize (theText.c_str ()) >= inRect.mW - kXoffsetLegend) {
+ theText.insert(0, "...");
+ while (inPainter.CalculateTextDrawSize (theText.c_str ()) >= inRect.mW - kXoffsetLegend) {
+ theSize = theText.size ();
+ // display dots and at least 3 characters
+ if (theSize >= 9) {
+ theText.erase (3, 3);
+ }
+ else if (theSize >= 7) {
+ theText.erase (3, theSize - 6);
+ } else {
+ // keep dots only
+ theText.erase (3, theSize - 3);
+ break;
+ }
+ }
+ }
+
+ int theHeight = inPainter.GetFontHeight ();
+ int theX = inRect.mX + kXoffsetLegend;
+ int theY = inRect.mY + theI*(theHeight*2)+theHeight;
+ inPainter.DrawText (theX, theY, theText.c_str ());
+ }
+ return true;
+}
+#endif
+
+static float GetMaxFromRange (const PlotDataBase &inData, long inStartIndex, long inEndIndex) {
+ float max = 0;
+ float fabsMax = 0;
+ for (long theI = inStartIndex; theI <= inEndIndex; theI++) {
+ if (theI == inStartIndex) {
+ max = inData.GetValue (theI);
+ fabsMax = fabs (max);
+ }
+ else {
+ float data = inData.GetValue (theI);
+ if (fabs (data) > fabsMax) {
+ max = data;
+ fabsMax = fabs (data);
+ }
+ }
+ }
+
+ return max;
+}
+
+static void FindRange (const PlotDataBase &inData, float inMin, float inMax, long& outStartIndex, long& outEndIndex) {
+ outStartIndex = 0;
+ while (outStartIndex < inData.GetSize () && inData.GetValue (outStartIndex) <= inMin) {
+ outStartIndex++;
+ }
+
+ if (outStartIndex == inData.GetSize ()) {
+ outStartIndex = inData.GetSize () - 1;
+ outEndIndex = outStartIndex;
+ assert (outStartIndex>-1);
+ return;
+ }
+
+ // We want the value at outStartIndex smaller than or equal to inMin
+ if (outStartIndex > 0) {
+ outStartIndex--;
+ }
+
+ outEndIndex = outStartIndex;
+ while (outEndIndex < inData.GetSize () && inData.GetValue (outEndIndex) < inMax) {
+ outEndIndex++;
+ }
+
+ if (outEndIndex == inData.GetSize ()) {
+ outEndIndex--;
+ }
+ assert (outStartIndex>-1);
+}
+
+static void DrawValue(int theTraX, int theTraY, float theX, float theY, const PlotDataBase &inXData, const AxisSetup &inXAxisSetup, Painter &inPainter)
+{
+ char theBuf[128];
+ string FormatString;
+ if (inXData.IsString())
+ {
+ const StringPlotData *theStringXData = (const StringPlotData *)(&inXData);
+ FormatString = "(%s, " + inXAxisSetup.mTickInfo.mFormatString + ")";
+ const StringData* stdata = theStringXData->GetStringData();
+ sprintf (theBuf, FormatString.c_str(), (*stdata)[(int)theX].c_str(), theY);
+ }
+ else
+ {
+ FormatString = "(" + inXAxisSetup.mTickInfo.mFormatString + ", " + inXAxisSetup.mTickInfo.mFormatString + ")";
+ sprintf (theBuf, FormatString.c_str(), theX, theY);
+ }
+ inPainter.DrawRotatedText (theTraX, theTraY-10, -45, PPLOT_WEST, theBuf);
+}
+
+bool LineDataDrawer::DrawData (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const {
+ if (!mXTrafo || !mYTrafo) {
+ return false;
+ }
+ if ((inXData.GetSize () == 0) || (inYData.GetSize () == 0)) {
+ return false;
+ }
+ long theXSize = inXData.GetSize ();
+ long theYSize = inYData.GetSize ();
+ if (theXSize>theYSize) {
+ return false;
+ }
+ inPainter.SetStyle (mStyle);
+ float thePrevX = 0;
+ float thePrevY = 0;
+ bool theFirst = true;
+ float theTraX, theTraY;
+
+ long theStart = 0;
+ long theEnd = inXData.GetSize () - 1;
+ int theStride = 1;
+ if (mDrawFast) {
+ FindRange (inXData, inXAxisSetup.mMin, inXAxisSetup.mMax, theStart, theEnd);
+
+ theStride = (theEnd - theStart + 1) / inPainter.GetWidth ();
+ if (theStride == 0) {
+ theStride = 1;
+ }
+ }
+
+ for (int theI = theStart; theI <= theEnd; theI+=theStride) {
+
+ float theY;
+ float theX = inXData.GetValue (theI);
+ theTraX = mXTrafo->Transform (theX);
+ if (theStride > 1) {
+ long theLast = theI + theStride - 1;
+ if (theLast>theEnd) {
+ theLast = theEnd;
+ }
+ theY = GetMaxFromRange (inYData, theI, theLast);
+ }
+ else {
+ theY = inYData.GetValue (theI);
+ }
+ theTraY = mYTrafo->Transform (theY);
+
+ if (!theFirst && mDrawLine) {
+ inPainter.DrawLine (thePrevX, thePrevY, theTraX, theTraY);
+ }
+ else {
+ theFirst = false;
+ }
+ bool theDrawPoint = mDrawPoint;
+
+ if (theDrawPoint && !DrawPoint (theTraX, theTraY, inRect, inPainter)) {
+ return false;
+ }
+ if (inPlotDataSelection.IsSelected (theI) && !DrawSelection (theTraX, theTraY, inRect, inPainter)) {
+ return false;
+ }
+#ifdef _IUP_PPLOT_
+ if (mShowValues)
+ DrawValue(theTraX, theTraY, theX, theY, inXData, inXAxisSetup, inPainter);
+#endif
+ thePrevX = theTraX;
+ thePrevY = theTraY;
+ }
+ return true;
+}
+
+DataDrawerBase* LineDataDrawer::Clone () const {
+ return new LineDataDrawer (*this);
+}
+
+bool LineDataDrawer::DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const {
+ inPainter.DrawLine (inScreenX-5, inScreenY+5, inScreenX+5, inScreenY-5);
+ inPainter.DrawLine (inScreenX-5, inScreenY-5, inScreenX+5, inScreenY+5);
+ return true;
+}
+
+bool LineDataDrawer::DrawSelection (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const {
+// inPainter.DrawLine (inScreenX-5, inScreenY+5, inScreenX+5, inScreenY-5);
+// inPainter.DrawLine (inScreenX-5, inScreenY-5, inScreenX+5, inScreenY+5);
+ inPainter.FillRect (inScreenX-5, inScreenY-5, 10, 10);
+ return true;
+}
+
+bool DotDataDrawer::DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const {
+ inPainter.DrawLine (inScreenX, inScreenY, inScreenX + 1, inScreenY);
+ return true;
+}
+
+bool BarDataDrawer::DrawData (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const {
+ if (!mXTrafo || !mYTrafo) {
+ return false;
+ }
+ if (inXData.GetSize ()>inYData.GetSize ()) {
+ return false;
+ }
+ if (!mPlotCount) {
+ return false;
+ }
+ if (mDrawOnlyLastPoint) {
+ return DrawOnlyLastPoint (inXData, inYData, inPlotDataSelection, inXAxisSetup, inRect, inPainter);
+ }
+
+ int theTraX, theTraY;
+ int theTraY0 = mYTrafo->Transform (0);
+
+ int theLeft, theTop, theWidth, theHeight;
+
+ theWidth = inRect.mW/inXData.GetSize ();
+ theWidth *= 0.9f;
+
+ for (long theI=0;theI<inXData.GetSize ();theI++) {
+ float theX = inXData.GetValue (theI);
+ float theY = inYData.GetValue (theI);
+ theTraX = mXTrafo->Transform (theX);
+ theTraY = mYTrafo->Transform (theY);
+
+ theLeft = theTraX-theWidth/2;
+ theTop = theTraY;
+ theHeight = theTraY0-theTop;
+
+ inPainter.FillRect (theLeft, theTop, theWidth, theHeight);
+
+#ifdef _IUP_PPLOT_
+ if (mShowValues)
+ DrawValue(theTraX, theTraY, theX, theY, inXData, inXAxisSetup, inPainter);
+#endif
+ }
+ return true;
+}
+
+
+bool BarDataDrawer::DrawOnlyLastPoint (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const {
+
+ PRect theRect = inRect;
+ theRect.mW = inRect.mW / mPlotCount;
+ theRect.mX = inRect.mX + mPlotIndex * theRect.mW;
+
+ int theTraX, theTraY;
+ int theTraY0 = mYTrafo->Transform (0);
+
+ int theLeft, theTop, theWidth, theHeight;
+
+ theWidth = theRect.mW;
+
+ // only draw last point:
+ long theI = inXData.GetSize () - 1;
+ if (theI >= 0) {
+ theTraX = mXTrafo->Transform (inXData.GetValue (theI));
+ theTraY = mYTrafo->Transform (inYData.GetValue (theI));
+
+ theLeft = theRect.mX;
+ theTop = theTraY;
+ theHeight = theTraY0-theTop;
+
+ inPainter.FillRect (theLeft, theTop, theWidth, theHeight);
+ }
+ return true;
+}
+
+
+DataDrawerBase* BarDataDrawer::Clone () const {
+ return new BarDataDrawer (*this);
+}
+
+bool PPlot::DrawPlot (int inIndex, const PRect &inRect, Painter &inPainter) const {
+
+ if (inIndex>=mPlotDataContainer.GetPlotCount ()) {
+ return false;
+ }
+
+ const PlotDataBase *theXData = mPlotDataContainer.GetConstXData (inIndex);
+ const PlotDataBase *theYData = mPlotDataContainer.GetConstYData (inIndex);
+ if (!theXData || !theYData) {
+ return false;
+ }
+ const LegendData *theLegendData = mPlotDataContainer.GetConstLegendData (inIndex);
+ PColor theC;
+ if (theLegendData) {
+ theC = theLegendData->mColor;
+ }
+ inPainter.SetLineColor (theC.mR, theC.mG, theC.mB);
+ inPainter.SetFillColor (theC.mR, theC.mG, theC.mB);
+
+ const DataDrawerBase *theD = mPlotDataContainer.GetConstDataDrawer (inIndex);
+ if (!theD) {
+ return false;
+ }
+ const PlotDataSelection *thePlotDataSelection = mPlotDataContainer.GetConstPlotDataSelection (inIndex);
+ if (!thePlotDataSelection) {
+ return false;
+ }
+
+ return theD->DrawData (*theXData, *theYData, *thePlotDataSelection, mXAxisSetup, inRect, inPainter);
+ }
+
+bool PPlot::ConfigureSelf () {
+ long thePlotCount = mPlotDataContainer.GetPlotCount ();
+ if (thePlotCount == 0) {
+ return false;
+ }
+ if (mXAxisSetup.mLogScale) {
+ mXTickIterator = &mXLogTickIterator;
+ mXTrafo = &mXLogTrafo;
+ mYAxisSetup.mCrossOrigin = false;
+ }
+ else {
+ const PlotDataBase *theGlue = mPlotDataContainer.GetConstXData (0);
+ if (theGlue->IsString()) {
+ const StringPlotData *theStringXData = (const StringPlotData *)(theGlue);
+ mXTickIterator = &mXNamedTickIterator;
+ mXNamedTickIterator.SetStringList (*(theStringXData->GetStringData ()));
+ }
+ else {
+ mXTickIterator = &mXLinTickIterator;
+ }
+ mXTrafo = &mXLinTrafo;
+ }
+ if (mYAxisSetup.mLogScale) {
+ mYTickIterator = &mYLogTickIterator;
+ mYTrafo = &mYLogTrafo;
+ mXAxisSetup.mCrossOrigin = false;
+ }
+ else {
+ mYTickIterator = &mYLinTickIterator;
+ mYTrafo = &mYLinTrafo;
+ }
+ mXTickIterator->SetAxisSetup (&mXAxisSetup);
+ mYTickIterator->SetAxisSetup (&mYAxisSetup);
+
+ // set trafo's for data drawers
+ for (int theI=0; theI<mPlotDataContainer.GetPlotCount ();theI++) {
+ DataDrawerBase *theD = (mPlotDataContainer.GetDataDrawer (theI));
+ if (theD) {
+ theD->SetXTrafo (mXTrafo);
+ theD->SetYTrafo (mYTrafo);
+ theD->SetPlotCount (mPlotDataContainer.GetPlotCount ());
+ theD->SetPlotIndex (theI);
+ }
+ }
+
+ return true;
+}
+
+bool PPlot::ValidateData () {
+
+ /* check x data ascending
+ for (int theI=0; theI<mPlotDataContainer.GetPlotCount ();theI++) {
+ const RealData *theX = dynamic_cast <const RealData *> (mPlotDataContainer.GetConstXData (theI));
+ if (theX && theX->size ()>0) {
+ float thePrev = (*theX)[0];
+ for (RealData::const_iterator theJ=theX->begin ();theJ!=theX->end ();theJ++) {
+ float theNext = *theJ;
+ if (theNext<thePrev) {
+ return false;
+ }
+ }
+ }
+ } */
+ return true;
+}
+
+bool PPlot::CalculateAxisRanges () {
+
+ float theXMin;
+ float theXMax;
+
+ mPlotDataContainer.CalculateXRange (theXMin, theXMax);
+ if (mXAxisSetup.mAutoScaleMin || mXAxisSetup.mAutoScaleMax) {
+
+ if (mXAxisSetup.mAutoScaleMin) {
+ mXAxisSetup.mMin = theXMin;
+ if (mXAxisSetup.mLogScale && (theXMin < kLogMinClipValue) ) {
+ mXAxisSetup.mMin = kLogMinClipValue;
+ }
+ }
+
+ if (mXAxisSetup.mAutoScaleMax) {
+ mXAxisSetup.mMax = theXMax;
+ }
+
+ if (!mXTickIterator->AdjustRange (mXAxisSetup.mMin, mXAxisSetup.mMax)) {
+ return false;
+ }
+ }
+
+ if (mYAxisSetup.mAutoScaleMin || mYAxisSetup.mAutoScaleMax) {
+ float theYMin;
+ float theYMax;
+
+ mPlotDataContainer.CalculateYRange (mXAxisSetup.mMin, mXAxisSetup.mMax,
+ theYMin, theYMax);
+
+ if (mYAxisSetup.mAutoScaleMin) {
+ mYAxisSetup.mMin = theYMin;
+ if (mYAxisSetup.mLogScale && (theYMin < kLogMinClipValue) ) {
+ mYAxisSetup.mMin = kLogMinClipValue;
+ }
+ }
+ if (mYAxisSetup.mAutoScaleMax) {
+ mYAxisSetup.mMax = theYMax;
+ }
+
+ if (!mYTickIterator->AdjustRange (mYAxisSetup.mMin, mYAxisSetup.mMax)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PPlot::CheckRange (const AxisSetup &inAxisSetup) const {
+ if (inAxisSetup.mLogScale) {
+ if (inAxisSetup.mMin < kLogMinClipValue) {
+ return false;
+ }
+
+ }
+ return true;
+}
+
+bool PPlot::CalculateTickInfo (const PRect &inRect, Painter &inPainter) {
+ float theXRange = mXAxisSetup.mMax - mXAxisSetup.mMin;
+ float theYRange = mYAxisSetup.mMax - mYAxisSetup.mMin;
+
+ if (theXRange <= 0 || theYRange < 0) {
+ return false;
+ }
+
+ if ((mYAxisSetup.mMax != 0 && fabs (theYRange / mYAxisSetup.mMax) < kRangeVerySmall) ||
+ theYRange == 0) {
+ float delta = 0.1f;
+ if (mYAxisSetup.mMax != 0) {
+ delta *= fabs(mYAxisSetup.mMax);
+ }
+
+ mYAxisSetup.mMax += delta;
+ mYAxisSetup.mMin -= delta;
+ theYRange = mYAxisSetup.mMax - mYAxisSetup.mMin;
+ }
+
+ if (mXAxisSetup.mTickInfo.mAutoTick) {
+ inPainter.SetStyle(mXAxisSetup.mTickInfo.mStyle);
+ int theTextWidth = inPainter.CalculateTextDrawSize ("12345");
+ float theDivGuess = inRect.mW/(kMajorTickXInitialFac*theTextWidth);
+ if (!mXTickIterator->InitFromRanges (theXRange, inRect.mH, theDivGuess, mXAxisSetup.mTickInfo)) {
+ return false;
+ }
+ }
+ if (mYAxisSetup.mTickInfo.mAutoTick) {
+ float theTextHeight = inPainter.GetFontHeight ();
+ float theDivGuess = inRect.mH/(kMajorTickYInitialFac*theTextHeight);
+ if (!mYTickIterator->InitFromRanges (theYRange, inRect.mW, theDivGuess, mYAxisSetup.mTickInfo)) {
+ return false;
+ }
+ }
+
+ SetTickSizes (inPainter.GetFontHeight (), mXAxisSetup.mTickInfo);
+ SetTickSizes (inPainter.GetFontHeight (), mYAxisSetup.mTickInfo);
+
+ return true;
+}
+
+void PPlot::SetTickSizes (int inFontHeight, TickInfo &ioTickInfo) {
+ if (ioTickInfo.mAutoTickSize) {
+ float theFac = kRelMinorTickSize/kRelMajorTickSize;
+ float theMax = Round (inFontHeight*kMaxMajorTickSizeInFontHeight);
+ if (ioTickInfo.mMajorTickScreenSize>theMax) {
+ ioTickInfo.mMajorTickScreenSize = theMax;
+ }
+ ioTickInfo.mMinorTickScreenSize = Round (ioTickInfo.mMajorTickScreenSize*theFac);
+ }
+}
+
+
+bool PPlot::CalculateLogTransformation (int inBegin, int inEnd, const AxisSetup& inAxisSetup, LogTrafo& outTrafo) {
+
+ float theBase = inAxisSetup.mLogBase;
+ long theLogFac = 1;//inAxisSetup.mLogFactor;
+ float theDataRange = SafeLog (inAxisSetup.mMax, theBase, theLogFac) - SafeLog(inAxisSetup.mMin, theBase, theLogFac);
+ if (theDataRange < kFloatSmall) {
+ return false;
+ }
+ float theTargetRange = inEnd - inBegin;
+ float theScale = theTargetRange / theDataRange;
+
+ if (inAxisSetup.mAscending ) {
+ outTrafo.mOffset = inBegin - SafeLog(inAxisSetup.mMin, theBase, theLogFac) * theScale;
+ } else {
+ outTrafo.mOffset = inEnd + SafeLog(inAxisSetup.mMin, theBase, theLogFac) * theScale;
+ }
+ outTrafo.mSlope = -theScale;
+ outTrafo.mBase = theBase;
+// outTrafo.mFactor = inAxisSetup.mLogFactor;
+
+ if (inAxisSetup.mAscending) {
+ outTrafo.mSlope *= -1;
+ }
+ return true;
+}
+
+bool PPlot::CalculateLinTransformation (int inBegin, int inEnd, const AxisSetup& inAxisSetup, LinTrafo& outTrafo) {
+ float theDataRange = inAxisSetup.mMax - inAxisSetup.mMin;
+ if (theDataRange < kFloatSmall) {
+ return false;
+ }
+ float theMin = inAxisSetup.mMin;
+ if (inAxisSetup.mDiscrete)
+ {
+ theDataRange++;
+ theMin -= 0.5f;
+ }
+
+ float theTargetRange = inEnd - inBegin;
+ float theScale = theTargetRange / theDataRange;
+
+ if (inAxisSetup.mAscending) {
+ outTrafo.mOffset = inBegin - theMin * theScale;
+ } else {
+ outTrafo.mOffset = inEnd + theMin * theScale;
+ }
+ outTrafo.mSlope = -theScale;
+
+ if (inAxisSetup.mAscending) {
+ outTrafo.mSlope *= -1;
+ }
+ return true;
+}
+
+bool PPlot::CalculateXTransformation (const PRect &inRect) {
+ if (mXAxisSetup.mLogScale) {
+ return CalculateLogTransformation (inRect.mX, inRect.mX + inRect.mW, mXAxisSetup, mXLogTrafo);
+ }
+ else {
+ return CalculateLinTransformation (inRect.mX, inRect.mX + inRect.mW, mXAxisSetup, mXLinTrafo);
+ }
+}
+
+bool PPlot::CalculateYTransformation (const PRect &inRect) {
+ if (mYAxisSetup.mLogScale) {
+ return CalculateLogTransformation (inRect.mY, inRect.mY + inRect.mH, mYAxisSetup, mYLogTrafo);
+ }
+ else {
+ return CalculateLinTransformation (inRect.mY, inRect.mY + inRect.mH, mYAxisSetup, mYLinTrafo);
+ }
+}
+
+#ifndef _IUP_PPLOT_
+bool MakeExamplePlot (int inExample, PPlot &ioPPlot) {
+ switch (inExample) {
+ case 1:
+ MakeExamplePlot1 (ioPPlot);
+ return true;
+ break;
+ case 2:
+ MakeExamplePlot2 (ioPPlot);
+ return true;
+ break;
+ case 3:
+ MakeExamplePlot3 (ioPPlot);
+ return true;
+ break;
+ case 4:
+ MakeExamplePlot4 (ioPPlot);
+ return true;
+ break;
+ case 5:
+ MakeExamplePlot5 (ioPPlot);
+ return true;
+ break;
+ case 6:
+ MakeExamplePlot6 (ioPPlot);
+ return true;
+ break;
+ case 7:
+ MakeExamplePlot7 (ioPPlot);
+ return true;
+ break;
+ case 8:
+ MakeExamplePlot8 (ioPPlot);
+ return true;
+ break;
+ }
+ return false;
+}
+
+void MakeExamplePlot1 (PPlot &ioPPlot) {
+
+ int theI;
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = (float)1.0/(100*100*100);
+ for (theI=-100;theI<=100;theI++) {
+ theX1->push_back (theI+50);
+ theY1->push_back (theFac*theI*theI*theI);
+ }
+ LineDataDrawer *theDataDrawer1 = new LineDataDrawer ();
+ theDataDrawer1->mStyle.mPenWidth = 3;
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, 0, theDataDrawer1);
+ ioPPlot.mPlotBackground.mTitle = "Bar";
+ ioPPlot.mPlotBackground.mStyle.mFontSize = 20;
+ ioPPlot.mMargins.mTop = 60;
+ ioPPlot.mXAxisSetup.mLabel = "gnu (Foo)";
+ ioPPlot.mYAxisSetup.mLabel = "Space (m^3)";
+ ioPPlot.mYAxisSetup.mStyle.mFontSize = 9;
+ ioPPlot.mYAxisSetup.mTickInfo.mStyle.mFontSize = 5;
+ ioPPlot.mYAxisSetup.mStyle.mPenWidth = 2;
+ ioPPlot.mXAxisSetup.mStyle = ioPPlot.mYAxisSetup.mStyle;
+ ioPPlot.mXAxisSetup.mTickInfo.mStyle = ioPPlot.mYAxisSetup.mTickInfo.mStyle;
+
+ PlotData *theX2 = new PlotData ();
+ PlotData *theY2 = new PlotData ();
+ theFac = (float)2.0/100;
+ for (theI=-100;theI<=100;theI++) {
+ theX2->push_back (theI);
+ theY2->push_back (-theFac*theI);
+ }
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX2, theY2);
+ LegendData *theLegendData2 = ioPPlot.mPlotDataContainer.GetLegendData (1);
+ theLegendData2->mStyle.mFontSize = 9;
+
+ PlotData *theX3 = new PlotData ();
+ PlotData *theY3 = new PlotData ();
+ for (theI=-100;theI<=100;theI++) {
+ theY3->push_back (0.01*theI);
+ theX3->push_back (0.01*theI*theI-30);
+ }
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX3, theY3);
+}
+
+void MakeExamplePlot2 (PPlot &ioPPlot) {
+
+ int theI;
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = (float)1.0/(100*100*100);
+ for (theI=0;theI<=100;theI++) {
+ theX1->push_back (theI);
+ theY1->push_back (theFac*theI*theI*theI);
+ }
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, 0);
+
+ PlotData *theX2 = new PlotData ();
+ PlotData *theY2 = new PlotData ();
+ theFac = (float)2.0/100;
+ for (theI=0;theI<=100;theI++) {
+ theX2->push_back (theI);
+ theY2->push_back (-theFac*theI);
+ }
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX2, theY2, 0);
+
+ ioPPlot.mPlotBackground.mTitle = "no autoscale";
+ ioPPlot.mPlotBackground.mStyle.mFontSize = 15;
+ ioPPlot.mPlotBackground.mTransparent = false;
+ ioPPlot.mPlotBackground.mPlotRegionBackColor = PColor (200,200,200);
+ ioPPlot.mMargins.mTop = 60;
+ ioPPlot.mMargins.mRight = 30;
+ ioPPlot.mXAxisSetup.mLabel = "Tg (X)";
+ ioPPlot.mXAxisSetup.SetAutoScale (false);
+ ioPPlot.mXAxisSetup.mMin = 10;
+ ioPPlot.mXAxisSetup.mMax = 60;
+ ioPPlot.mYAxisSetup.SetAutoScale (false);
+ ioPPlot.mYAxisSetup.mMin = -0.5;
+ ioPPlot.mYAxisSetup.mMax = 0.5;
+
+ ioPPlot.mXAxisSetup.mCrossOrigin = false;
+ ioPPlot.mYAxisSetup.mCrossOrigin = false;
+ ioPPlot.mXAxisSetup.mAscending = false;
+ ioPPlot.mYAxisSetup.mAscending = true;
+
+ // M.T. - use a color different from background
+ ioPPlot.mGridInfo.mGridColor = PColor(128,255,128); // some sort of green
+}
+
+void MakeExamplePlot3 (PPlot &ioPPlot) {
+
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = 1.0f/(100*100*100);
+ for (int theI=0;theI<=100;theI++) {
+ // theX1->push_back (theI*0.001);
+ theX1->push_back (theI);
+ theY1->push_back (theFac*theI*theI*theI);
+ }
+ ioPPlot.mPlotDataContainer.AddXYPlot (0, theY1, 0);
+
+ ioPPlot.mPlotBackground.mTitle = "narrow margins";
+ ioPPlot.mPlotBackground.mTransparent = false;
+ ioPPlot.mPlotBackground.mPlotRegionBackColor = PColor (200,200,200);
+ ioPPlot.mMargins.mTop = 50;
+ ioPPlot.mMargins.mRight = 10;
+ ioPPlot.mMargins.mLeft = 10;
+ ioPPlot.mMargins.mBottom = 10;
+
+ // M.T. - use a color different from background
+ ioPPlot.mGridInfo.mGridColor = PColor(128,255,128); // some sort of green
+}
+
+void MakeExamplePlot4 (PPlot &ioPPlot) {
+
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = 100.0f/(100*100*100);
+ for (int theI=0;theI<=100;theI++) {
+ theX1->push_back (0.0001+theI*0.001);
+ theY1->push_back (0.01+theFac*theI*theI*theI);
+ }
+ LegendData *theLegend = new LegendData ();
+ theLegend->mName = "foo";
+ theLegend->mColor = PColor (100,100,200);
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, theLegend);
+ ioPPlot.mXAxisSetup.mLogScale = true;
+ ioPPlot.mYAxisSetup.mLogScale = true;
+ ioPPlot.mYAxisSetup.mLogBase = 2;
+ ioPPlot.mMargins.mLeft = 50;
+ ioPPlot.mMargins.mTop = 20;
+
+ ioPPlot.mGridInfo.mXGridOn = true;
+ ioPPlot.mGridInfo.mYGridOn = true;
+}
+
+void MakeExamplePlot5 (PPlot &ioPPlot) {
+
+ const char * kLables[12] = {"jan","feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
+ const float kData[12] = {1,2,3,4,5,6,7,8,9,0,1,2};
+
+ StringPlotData *theX1 = new StringPlotData ();
+ PlotData *theY1 = new PlotData ();
+ for (int theI=0;theI<12;theI++) {
+ theX1->AddItem (kLables[theI]);
+ theY1->push_back (kData[theI]);
+ }
+ LegendData *theLegend = new LegendData ();
+ theLegend->mName = "bar";
+ theLegend->mColor = PColor (100,100,200);
+ BarDataDrawer *theDataDrawer = new BarDataDrawer ();
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, theLegend, theDataDrawer);
+ ioPPlot.mMargins.mLeft = 50;
+ ioPPlot.mMargins.mTop = 20;
+}
+
+void MakeExamplePlot6 (PPlot &ioPPlot) {
+
+ int theI;
+
+ ioPPlot.mPlotBackground.mTitle = "line styles";
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = 100.0f/(100*100*100);
+ for (theI=0;theI<=10;theI++) {
+ theX1->push_back (0.0001+theI*0.001);
+ theY1->push_back (0.01+theFac*theI*theI);
+ }
+ LineDataDrawer *theDataDrawer1 = new LineDataDrawer ();
+ theDataDrawer1->mDrawPoint = true;
+ theDataDrawer1->mStyle.mPenWidth = 3;
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, 0, theDataDrawer1);
+
+ PlotData *theX2 = new PlotData ();
+ PlotData *theY2 = new PlotData ();
+ for (theI=0;theI<=10;theI++) {
+ theX2->push_back (0.0001+theI*0.001);
+ theY2->push_back (0.2-theFac*theI*theI);
+ }
+ LineDataDrawer *theDataDrawer2 = new LineDataDrawer ();
+ theDataDrawer2->mDrawPoint = true;
+ theDataDrawer2->mDrawLine = false;
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX2, theY2, 0, theDataDrawer2);
+
+ ioPPlot.mMargins.mLeft = 50;
+ ioPPlot.mMargins.mTop = 40;
+}
+
+void MakeExamplePlot7 (PPlot &ioPPlot) {
+
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = 100.0f/(100*100*100);
+ for (int theI=0;theI<=100;theI++) {
+ theX1->push_back (0.0001+theI*0.001);
+ theY1->push_back (0.01+theFac*theI*theI*theI);
+ }
+ LegendData *theLegend = new LegendData ();
+ theLegend->mName = "foo";
+ theLegend->mColor = PColor (100,100,200);
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, theLegend);
+ ioPPlot.mYAxisSetup.mLogScale = true;
+ ioPPlot.mYAxisSetup.mLogFactor = 20;
+ ioPPlot.mMargins.mLeft = 50;
+ ioPPlot.mMargins.mTop = 20;
+
+ ioPPlot.mGridInfo.mXGridOn = true;
+ ioPPlot.mGridInfo.mYGridOn = true;
+}
+
+void MakeExamplePlot8 (PPlot &ioPPlot) {
+
+ ioPPlot.mPlotBackground.mTitle = "data selection and editing";
+ PlotData *theX1 = new PlotData ();
+ PlotData *theY1 = new PlotData ();
+ float theFac = 100.0f/(100*100*100);
+ for (int theI=-10;theI<=10;theI++) {
+ theX1->push_back (0.001*theI);
+ theY1->push_back (0.01+theFac*theI*theI*theI);
+ }
+ LegendData *theLegend = new LegendData ();
+ theLegend->mName = "foo";
+ theLegend->mColor = PColor (100,100,200);
+
+ PlotDataSelection *thePlotDataSelection = new PlotDataSelection ();
+ ioPPlot.mPlotDataContainer.AddXYPlot (theX1, theY1, theLegend, 0, thePlotDataSelection);
+ ioPPlot.mMargins.mLeft = 30;
+ ioPPlot.mMargins.mTop = 30;
+ ioPPlot.mMargins.mBottom = 30;
+ ioPPlot.mMargins.mRight = 30;
+}
+
+void MakePainterTester (PPlot &ioPPlot) {
+ ioPPlot.SetPPlotDrawer (new PainterTester ());
+}
+
+static PPlot *sCurrentPPlot=0;
+
+void SetCurrentPPlot (PPlot *inPPlot) {
+ sCurrentPPlot = inPPlot;
+}
+#include <assert.h>
+PPlot & GetCurrentPPlot () {
+ fprintf (stderr, "getplot\n");
+ if (sCurrentPPlot) {
+ return *sCurrentPPlot;
+ }
+ assert (0);
+ fprintf (stderr, "aargh\n");
+
+ return *sCurrentPPlot;// this should not happen
+}
+
+
+
+void MakeCopy (const PPlot &inPPlot, PPlot &outPPlot) {
+ // copy settings
+ outPPlot.mGridInfo = inPPlot.mGridInfo;
+ outPPlot.mMargins = inPPlot.mMargins;
+ outPPlot.mXAxisSetup = inPPlot.mXAxisSetup;
+ outPPlot.mYAxisSetup = inPPlot.mYAxisSetup;
+ outPPlot.mPlotBackground = inPPlot.mPlotBackground;
+
+ // now the data
+ for (int theI=0;theI<inPPlot.mPlotDataContainer.GetPlotCount ();theI++) {
+ const PlotDataBase *theXData = inPPlot.mPlotDataContainer.GetConstXData (theI);
+ const PlotDataBase *theYData = inPPlot.mPlotDataContainer.GetConstYData (theI);
+ const LegendData *theLegendData = inPPlot.mPlotDataContainer.GetConstLegendData (theI);
+ const DataDrawerBase* theDrawer = inPPlot.mPlotDataContainer.GetConstDataDrawer (theI);
+
+ PlotDataBase *theNewXData = new PlotDataPointer (theXData);
+ PlotDataBase *theNewYData = new PlotDataPointer (theYData);
+ LegendData *theNewLegendData = new LegendData ();
+ *theNewLegendData = *theLegendData;
+ DataDrawerBase* theNewDrawer = theDrawer->Clone ();
+
+ outPPlot.mPlotDataContainer.AddXYPlot (theNewXData, theNewYData, theNewLegendData, theNewDrawer);
+
+ }
+
+}
+#endif
diff --git a/iup/srcpplot/iupPPlot.h b/iup/srcpplot/iupPPlot.h
new file mode 100755
index 0000000..bab2f94
--- /dev/null
+++ b/iup/srcpplot/iupPPlot.h
@@ -0,0 +1,645 @@
+/***************************************************************************
+ * *
+ * Copyright notice: *
+ * *
+ * This is free Pier ware. You may do whatever you want with this code. *
+ * You may cont(r)act me by email: pierphil@xs4all.nl *
+ * *
+ ***************************************************************************/
+
+#ifndef __PPLOT_H__
+#define __PPLOT_H__
+
+
+#pragma warning (disable: 4786)
+
+#include <algorithm>
+#include <vector>
+#include <string>
+#include <map>
+#include <stack>
+using namespace std;
+
+#ifdef __WATCOMC__ /* M.T. - 2006-09-26 - hacked to compile with OW ver. 1.5 */
+#pragma off (unreferenced);
+#endif
+
+/* M.T. - these are text alignment values usable here */
+#ifdef _IUP_PPLOT_
+// Text alignment
+enum { /* text alignment */
+ PPLOT_NORTH,
+ PPLOT_SOUTH,
+ PPLOT_EAST,
+ PPLOT_WEST,
+ PPLOT_NORTH_EAST,
+ PPLOT_NORTH_WEST,
+ PPLOT_SOUTH_EAST,
+ PPLOT_SOUTH_WEST,
+ PPLOT_CENTER,
+ PPLOT_BASE_LEFT,
+ PPLOT_BASE_CENTER,
+ PPLOT_BASE_RIGHT
+};
+
+// Legend Position
+enum PLegendPos {PPLOT_TOPLEFT, PPLOT_TOPRIGHT, PPLOT_BOTTOMLEFT, PPLOT_BOTTOMRIGHT};
+#endif
+
+typedef vector<float> RealData;
+typedef vector<string> StringData;
+
+class PStyle {
+ public:
+#ifdef _IUP_PPLOT_
+ PStyle (): mFontSize(0), mFontStyle(-1), mPenWidth(1), mPenStyle(0), mMarkSize(7), mMarkStyle(3) {};
+ int mFontSize;
+ int mFontStyle;
+ int mPenWidth;
+ int mPenStyle;
+ int mMarkStyle;
+ int mMarkSize;
+#else
+ PStyle (): mFontSize(10), mPenWidth(1) {};
+ int mFontSize;
+ string mFont;
+ int mPenWidth;
+ string mPenStyle;
+ map<string,string> mVar;
+#endif
+};
+
+class CalculatedDataBase {
+ public:
+ virtual float GetValue (long inIndex) const = 0;
+ virtual long GetSize () const = 0;
+};
+
+// data
+class PlotDataBase {
+ public:
+ PlotDataBase(): mIsString(false) {};
+ virtual ~PlotDataBase ();
+ virtual const RealData * GetRealPlotData () const = 0;
+ virtual const CalculatedDataBase * GetCalculatedData () const {return 0;}
+ bool IsString () const {return mIsString;}
+ long GetSize () const;
+ float GetValue (long inIndex) const;
+ virtual bool CalculateRange (float &outMin, float &outMax);
+protected:
+ bool mIsString;
+};
+
+typedef vector<PlotDataBase *> PlotDataList;
+
+class PlotDataPointer: public PlotDataBase {
+ public:
+ PlotDataPointer (const PlotDataBase *inPlotData):mPlotData (inPlotData){};// does not own them
+ virtual const RealData * GetRealPlotData () const {return mPlotData->GetRealPlotData ();};
+ virtual const CalculatedDataBase * GetCalculatedData () const {return mPlotData->GetCalculatedData ();}
+ private:
+ const PlotDataBase *mPlotData;
+};
+
+// default data class
+class PlotData: public RealData, public PlotDataBase {
+ public:
+ virtual const RealData * GetRealPlotData () const {return this;};
+};
+
+class CalculatedData: public CalculatedDataBase {
+ public:
+ CalculatedData (float inMin, float inDelta, long inSize):
+ mMin (inMin), mDelta (inDelta), mSize (inSize) {}
+ virtual float GetValue (long inIndex) const { return mMin + inIndex * mDelta; }
+ virtual long GetSize () const { return mSize; }
+
+ float mMin;
+ float mDelta;
+ long mSize;
+};
+
+class CalculatedPlotData: public PlotDataBase {
+ public:
+ CalculatedPlotData (CalculatedDataBase* inCalculatedData):
+ mCalculatedData (inCalculatedData) {}
+ ~CalculatedPlotData () {delete mCalculatedData;}
+ virtual const RealData * GetRealPlotData () const {return 0;}
+ virtual const CalculatedDataBase * GetCalculatedData () const {return mCalculatedData;}
+
+ CalculatedDataBase* mCalculatedData;
+};
+
+class DummyPlotData: public PlotDataBase {
+ public:
+ DummyPlotData (long inSize=0);
+ virtual const RealData * GetRealPlotData () const {return &mRealPlotData;};
+ private:
+ RealData mRealPlotData;
+};
+
+class StringPlotData: public PlotDataBase {
+ public:
+ StringPlotData() {mIsString = true;}
+ void AddItem (const char *inString);
+ void InsertItem (int inIndex, const char *inString);
+ const StringData * GetStringData () const {return &mStringPlotData;};
+ virtual const RealData * GetRealPlotData () const {return &mRealPlotData;};
+// private:
+ RealData mRealPlotData;
+ StringData mStringPlotData;
+};
+
+
+float SafeLog (float inFloat, float inBase, float inFac=1);
+float SafeExp (float inFloat, float inBase, float inFac=1);
+
+class PRect {
+ public:
+ PRect ():mX(0),mY(0),mW(0),mH(0){};
+ long mX;
+ long mY;
+ long mW;
+ long mH;
+};
+
+class PMargins {
+ public:
+ PMargins ():mLeft (0), mRight(0), mTop (0), mBottom (0){};
+ PMargins (long inLeft, long inRight, long inTop, long inBottom):mLeft (inLeft), mRight (inRight), mTop(inTop), mBottom (inBottom) {};
+ long mLeft;
+ long mRight;
+ long mTop;
+ long mBottom;
+};
+
+class PColor {
+ public:
+ PColor (): mR(0), mG(0), mB(0){};
+ PColor (int inR, int inG, int inB): mR((unsigned char)inR), mG((unsigned char)inG), mB((unsigned char)inB){}; // M.T. added typecast
+ unsigned char mR;
+ unsigned char mG;
+ unsigned char mB;
+};
+
+class LegendData {
+ public:
+ LegendData (): mShow (true) {};
+ string mName;
+ PColor mColor;
+ bool mShow;
+
+ void SetDefaultColor (int inPlotIndex);
+ void SetDefaultValues (int inPlotIndex);
+ static PColor GetDefaultColor (int inPlotIndex);
+
+ PStyle mStyle;
+};
+
+typedef vector<LegendData *> LegendDataList;
+
+class PlotDataSelection: public vector<int> {
+ public:
+ PlotDataSelection (long inSize=0):vector<int>(inSize){};
+ bool IsSelected (long inIndex) const;
+ long GetSelectedCount () const;
+};
+
+typedef vector<PlotDataSelection *> PlotDataSelectionList;
+
+class Painter {
+ public:
+ virtual void DrawLine (float inX1, float inY1, float inX2, float inY2)=0;
+ virtual void FillRect (int inX, int inY, int inW, int inH)=0;
+ virtual void InvertRect (int inX, int inY, int inW, int inH)=0;
+ virtual void SetClipRect (int inX, int inY, int inW, int inH)=0;
+ virtual long GetWidth () const=0;
+ virtual long GetHeight () const=0;
+ virtual void SetLineColor (int inR, int inG, int inB)=0;
+ virtual void SetFillColor (int inR, int inG, int inB)=0;
+ virtual long CalculateTextDrawSize (const char *inString)=0;
+ virtual long GetFontHeight () const =0;
+#ifdef _IUP_PPLOT_
+ virtual void FillArrow (int inX1, int inY1, int inX2, int inY2, int inX3, int inY3)=0;
+ virtual void DrawText (int inX, int inY, short align, const char *inString)=0;
+ virtual void DrawRotatedText (int inX, int inY, float inDegrees,
+ short align, const char *inString)=0;
+#else
+ virtual void DrawText (int inX, int inY, const char *inString)=0;
+ virtual void DrawRotatedText (int inX, int inY, float inDegrees, const char *inString)=0;
+#endif
+ virtual void SetStyle (const PStyle &inStyle){};
+};
+
+class DummyPainter: public Painter {
+ public:
+ virtual void DrawLine (float inX1, float inY1, float inX2, float inY2){};
+ virtual void FillRect (int inX, int inY, int inW, int inH){};
+ virtual void InvertRect (int inX, int inY, int inW, int inH){};
+ virtual void SetClipRect (int inX, int inY, int inW, int inH){};
+ virtual long GetWidth () const {return 100;};
+ virtual long GetHeight () const {return 100;};
+ virtual void SetLineColor (int inR, int inG, int inB){};
+ virtual void SetFillColor (int inR, int inG, int inB){};
+ virtual long CalculateTextDrawSize (const char *inString){return 0;};
+ virtual long GetFontHeight () const {return 10;};
+#ifdef _IUP_PPLOT_
+ virtual void FillArrow (int inX1, int inY1, int inX2, int inY2, int inX3, int inY3){};
+ virtual void DrawText (int inX, int inY, short align, const char *inString){};
+ virtual void DrawRotatedText (int inX, int inY, float inDegrees,
+ short align, const char *inString){};
+#else
+ virtual void DrawText (int inX, int inY, const char *inString){};
+ virtual void DrawRotatedText (int inX, int inY, float inDegrees, const char *inString){};
+#endif
+};
+
+class Trafo;
+class AxisSetup;
+
+class DataDrawerBase {
+ public:
+ DataDrawerBase (): mXTrafo (0), mYTrafo (0), mDrawFast (false), mPlotCount (1), mPlotIndex (0), mHasMarks(false), mShowValues(false), mMode(0) {};
+ virtual ~DataDrawerBase (){};
+ void SetXTrafo (Trafo *inTrafo) {mXTrafo = inTrafo;};
+ void SetYTrafo (Trafo *inTrafo) {mYTrafo = inTrafo;};
+ void SetDrawFast (bool inDrawFast) {mDrawFast = inDrawFast;}
+ void SetPlotCount (int inPlotCount) {mPlotCount = inPlotCount;}
+ void SetPlotIndex (int inPlotIndex) {mPlotIndex = inPlotIndex;}
+ virtual bool DrawData (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const =0;
+ virtual DataDrawerBase* Clone () const = 0;
+ bool mHasMarks;
+ bool mShowValues;
+ PStyle mStyle;
+ const char* mMode;
+ protected:
+ Trafo *mXTrafo;
+ Trafo *mYTrafo;
+ bool mDrawFast;
+ int mPlotCount;
+ int mPlotIndex;
+};
+
+typedef vector<DataDrawerBase *> DataDrawerList;
+
+class LineDataDrawer: public DataDrawerBase {
+ public:
+ LineDataDrawer ():mDrawLine (true), mDrawPoint (false) {mMode = "LINE"; mHasMarks = true;};
+ virtual bool DrawData (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const;
+
+ virtual DataDrawerBase* Clone () const;
+ virtual bool DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const;
+ virtual bool DrawSelection (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const;
+
+ bool mDrawLine;
+ bool mDrawPoint;
+};
+
+class DotDataDrawer: public LineDataDrawer {
+ public:
+ DotDataDrawer () { mDrawLine = false; mDrawPoint = true;};
+ virtual bool DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const;
+};
+
+class BarDataDrawer: public DataDrawerBase {
+ public:
+ BarDataDrawer (bool inDrawOnlyLastPoint = false):mDrawOnlyLastPoint (inDrawOnlyLastPoint){ mMode = "BAR"; };
+ virtual bool DrawData (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const;
+ virtual DataDrawerBase* Clone () const;
+
+ protected:
+ bool mDrawOnlyLastPoint;// special mode
+ virtual bool DrawOnlyLastPoint (const PlotDataBase &inXData, const PlotDataBase &inYData, const PlotDataSelection &inPlotDataSelection, const AxisSetup &inXAxisSetup, const PRect &inRect, Painter &inPainter) const;
+};
+
+
+class PlotDataContainer {
+ public:
+ PlotDataContainer ();
+ ~PlotDataContainer ();
+
+ void RemoveElement (int inIndex);
+ void ClearData ();
+
+ /* M.T. - changed to return the index of the added plot; returns -1 on error */
+ int AddXYPlot (PlotDataBase *inXData, PlotDataBase *inYData, LegendData *inLegendData=0, DataDrawerBase *inDataDrawer=0, PlotDataSelection *inPlotDataSelection=0);//takes ownership
+ void SetXYPlot (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, LegendData *inLegendData=0, DataDrawerBase *inDataDrawer=0, PlotDataSelection *inPlotDataSelection=0);//takes ownership
+
+ int GetPlotCount () const {return mYDataList.size ();};
+
+ PlotDataBase * GetXData (int inIndex);
+ PlotDataBase * GetYData (int inIndex);
+ LegendData * GetLegendData (int inIndex);
+ DataDrawerBase * GetDataDrawer (int inIndex);
+ PlotDataSelection * GetPlotDataSelection (int inIndex);
+ bool SetDataDrawer (int inIndex, DataDrawerBase* inDataDrawer); // takes ownership
+
+ int GetPlotIndexByName (const string &inName) const;// negative value: not found
+
+ const PlotDataBase * GetConstXData (int inIndex) const;
+ const PlotDataBase * GetConstYData (int inIndex) const;
+ const LegendData * GetConstLegendData (int inIndex) const;
+ const DataDrawerBase * GetConstDataDrawer (int inIndex) const;
+ const PlotDataSelection * GetConstPlotDataSelection (int inIndex) const;
+
+ bool CalculateXRange (float &outXMin, float &outXMax) const;
+ bool CalculateYRange (float inXMin, float inXMax, float &outYMin, float &outYMax) const;
+ bool CalculateYRangePlot (float inXMin, float inXMax, const PlotDataBase &inXData, const PlotDataBase &inYData, float &outYMin, float &outYMax) const;
+
+ protected:
+ bool CheckState () const;
+ PlotDataList mXDataList;
+ PlotDataList mYDataList;
+ LegendDataList mLegendDataList;
+ DataDrawerList mDataDrawerList;
+ PlotDataSelectionList mPlotDataSelectionList;
+};
+
+// M.T. - added custom grid color - was (200,200,200)
+class GridInfo {
+ public:
+ GridInfo (const bool inXGridOn = false, const bool inYGridOn = false) : mXGridOn (inXGridOn), mYGridOn (inYGridOn), mGridColor(200,200,200) {};
+
+ bool mXGridOn;
+ bool mYGridOn;
+ PColor mGridColor;
+ PStyle mStyle;
+};
+
+class TickInfo {
+ public:
+ TickInfo ():mAutoTick (true), mAutoTickSize (true), mTickDivision(1), mMajorTickSpan(1), mMajorTickScreenSize (1), mMinorTickScreenSize (1), mFormatString ("%.0f"), mTicksOn (true) {};
+
+
+ static float RoundSpan (float inSpan);
+ static void MakeFormatString (float inValue, string &outFormatString);
+
+ bool mAutoTick;
+ bool mAutoTickSize;
+ bool mTicksOn;
+
+ int mTickDivision;
+ float mMajorTickSpan; // in plot units
+ int mMajorTickScreenSize;
+ int mMinorTickScreenSize;
+ string mFormatString;
+ PStyle mStyle;
+};
+
+class AxisSetup {
+
+ public:
+ AxisSetup (): mMin(0),mMax(0), mAutoScaleMin(true), mAutoScaleMax (true), mAscending (true), mLogScale(false), mCrossOrigin(true), mMaxDecades(-1), mLogFactor (1), mLogBase (10), mLabelCentered(true), mDiscrete(false) {};
+
+ void SetMin (float inMin) {mMin = inMin;};
+ void SetMax (float inMax) {mMax = inMax;};
+ void SetAutoScale (bool inBool) {mAutoScaleMin = mAutoScaleMax = inBool;};
+ bool IsAutoScale () const {return mAutoScaleMin && mAutoScaleMax;};
+
+ float mMin;
+ float mMax;
+ bool mAutoScaleMin;
+ bool mAutoScaleMax;
+ bool mAscending; // not Ascending: Descending
+ bool mLogScale;
+ bool mCrossOrigin;
+ long mMaxDecades;// property for auto logscale
+ long mLogFactor;// to make db possible with logscale
+ float mLogBase;
+ bool mDiscrete;
+
+ bool mLabelCentered;
+ PColor mColor;
+ string mLabel;
+ PStyle mStyle;
+
+ TickInfo mTickInfo;
+
+ private:
+};
+
+class Trafo {
+ public:
+ virtual ~Trafo (){};
+ virtual float Transform (float inValue) const=0;
+ virtual float TransformBack (float inValue) const = 0;
+};
+
+class LinTrafo: public Trafo {
+ public:
+ LinTrafo ():mOffset (0), mSlope(0){};
+ virtual float Transform (float inValue) const;
+ virtual float TransformBack (float inValue) const;
+
+ float mOffset;
+ float mSlope;
+};
+
+class LogTrafo: public Trafo {
+ public:
+ LogTrafo ():mOffset (0), mSlope(0), mBase (10), mFactor (1){};
+ virtual float Transform (float inValue) const;
+ virtual float TransformBack (float inValue) const;
+
+ float mOffset;
+ float mSlope;
+ float mBase;
+ float mFactor;
+};
+
+class TickIterator {
+ public:
+ TickIterator ():mAxisSetup (0){};
+ virtual ~TickIterator () {};
+ virtual bool Init ()=0;
+ virtual bool GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString)=0;
+
+ virtual bool InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &outTickInfo) const=0;
+ virtual bool AdjustRange (float &ioMin, float &ioMax) const{return true;};
+ void SetAxisSetup (const AxisSetup *inAxisSetup) {mAxisSetup = inAxisSetup;};
+
+ protected:
+ const AxisSetup *mAxisSetup;
+};
+
+class LinTickIterator: public TickIterator {
+ public:
+ LinTickIterator ():mCurrentTick (0), mDelta (0){}
+ virtual bool Init ();
+ virtual bool GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString);
+ bool InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &outTickInfo) const;
+ protected:
+ float mCurrentTick;
+ long mCount;
+ float mDelta;
+ string mFormatString;
+};
+
+class LogTickIterator: public TickIterator {
+ public:
+ LogTickIterator ():mCurrentTick (0), mDelta (0){}
+ virtual bool Init ();
+ virtual bool GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString);
+
+ bool InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &outTickInfo) const;
+ virtual bool AdjustRange (float &ioMin, float &ioMax) const;
+ float RoundUp (float inFloat) const;
+ float RoundDown (float inFloat) const;
+
+ protected:
+ float mCurrentTick;
+ long mCount;
+ float mDelta;
+};
+
+class NamedTickIterator: public LinTickIterator {
+ public:
+ NamedTickIterator (){}
+ void SetStringList (const StringData &inStringList) {mStringList = inStringList;};
+
+ // virtual bool Init ();
+ virtual bool GetNextTick (float &outTick, bool &outIsMajorTick, string &outFormatString);
+ bool InitFromRanges (float inParRange, float inOrthoScreenRange, float inDivGuess, TickInfo &outTickInfo) const;
+ protected:
+ StringData mStringList;
+};
+
+class PlotBackground {
+ public:
+ PlotBackground ():mTransparent (true), mPlotRegionBackColor (255,255,255) {};
+ bool mTransparent;
+ PColor mPlotRegionBackColor;
+ string mTitle;
+ PStyle mStyle;
+#ifdef _IUP_PPLOT_
+ PColor mTitleColor;
+#endif
+};
+
+class PPlot;
+
+class PDrawer {
+ public:
+ typedef vector<PDrawer *> tList;
+
+ virtual ~PDrawer (){};
+ virtual bool Prepare (Painter &inPainter, PPlot& inPPlot) {return true;};
+ virtual bool Draw (Painter &inPainter)=0;
+};
+
+class PCalculator {// base class to do additional calculations on a PPlot
+ public:
+ typedef vector<PCalculator *> tList;
+
+ virtual ~PCalculator (){};
+
+ virtual bool ShouldCalculate () const {return true;};
+ virtual bool Calculate (Painter &inPainter, PPlot& inPPlot) {return true;};
+};
+
+
+class PainterTester: public PDrawer {
+ public:
+ virtual bool Draw (Painter &inPainter);
+};
+
+class PPlot: public PDrawer {
+ public:
+ PPlot ();
+ virtual ~PPlot ();
+
+ virtual bool Draw (Painter &inPainter);
+
+ PlotDataContainer mPlotDataContainer;
+ AxisSetup mXAxisSetup;
+ AxisSetup mYAxisSetup;
+ GridInfo mGridInfo;
+ PMargins mMargins;// [pixels]
+ PlotBackground mPlotBackground;
+ bool mShowLegend; // M.T. - hide|show legend
+ PLegendPos mLegendPos;
+
+ void SetPPlotDrawer (PDrawer *inPDrawer);// taker ownership. Used to bypass normal Draw function, i.e., set Draw function by composition.
+ void SetPPlotDrawer (PDrawer &inPDrawer);// same as above: does not take ownership
+
+ bool mHasAnyModifyingCalculatorBeenActive;
+ PCalculator::tList mModifyingCalculatorList;
+ PCalculator::tList mPostCalculatorList;
+ PDrawer::tList mPreDrawerList;
+ PDrawer::tList mPostDrawerList;
+
+ TickIterator *mXTickIterator;
+ TickIterator *mYTickIterator;
+
+ virtual bool CalculateXTransformation (const PRect &inRect);
+ virtual bool CalculateYTransformation (const PRect &inRect);
+ virtual bool DrawGridXAxis (const PRect &inRect, Painter &inPainter) const;
+ virtual bool DrawGridYAxis (const PRect &inRect, Painter &inPainter) const;
+ virtual bool DrawXAxis (const PRect &inRect, Painter &inPainter) const;
+ virtual bool DrawYAxis (const PRect &inRect, Painter &inPainter) const;
+ virtual bool CalculateTickInfo (const PRect &inRect, Painter &inPainter);
+
+ Trafo *mXTrafo;
+ Trafo *mYTrafo;
+
+ static int Round (float inFloat);
+ static const float kRangeVerySmall;
+
+ protected:
+ PPlot (const PPlot&);
+ PPlot& operator=(const PPlot&);
+
+ static bool CalculateLogTransformation (int inBegin, int inEnd, const AxisSetup& inAxisSetup, LogTrafo& outTrafo);
+ static bool CalculateLinTransformation (int inBegin, int inEnd, const AxisSetup& inAxisSetup, LinTrafo& outTrafo);
+
+ virtual bool DrawPlotBackground (const PRect &inRect, Painter &inPainter) const;
+#ifdef _IUP_PPLOT_
+ virtual bool DrawPlotTitle(const PRect &inRect, Painter &inPainter) const;
+#endif
+ virtual bool DrawXTick (float inX, int inScreenY, bool inMajor, const string &inFormatString, Painter &inPainter, PRect &outRect) const;
+ virtual bool DrawYTick (float inY, int inScreenX, bool inMajor, const string &inFormatString, Painter &inPainter, PRect &outRect) const;
+ virtual bool DrawLegend (const PRect &inRect, Painter &inPainter) const;
+ virtual bool DrawPlot (int inIndex, const PRect &inRect, Painter &inPainter) const;
+ virtual bool ConfigureSelf ();// change here implementations of interfaces
+ virtual bool ValidateData ();// check preconditions here things like x is ascending
+ virtual bool CalculateAxisRanges ();
+ virtual bool CheckRange (const AxisSetup &inAxisSetup) const;
+
+ void SetTickSizes (int inFontHeight, TickInfo &ioTickInfo);
+
+ // trafo's between plot coordinates and screen coordinates.
+ LinTrafo mXLinTrafo;
+ LinTrafo mYLinTrafo;
+ LogTrafo mXLogTrafo;
+ LogTrafo mYLogTrafo;
+
+ LinTickIterator mXLinTickIterator;
+ LinTickIterator mYLinTickIterator;
+ LogTickIterator mXLogTickIterator;
+ LogTickIterator mYLogTickIterator;
+ NamedTickIterator mXNamedTickIterator;
+
+ PDrawer * mPPlotDrawer;
+ bool mOwnsPPlotDrawer;
+};
+
+#ifndef _IUP_PPLOT_
+bool MakeExamplePlot (int inExample, PPlot &ioPPlot);
+void MakeExamplePlot1 (PPlot &ioPPlot);
+void MakeExamplePlot2 (PPlot &ioPPlot);
+void MakeExamplePlot3 (PPlot &ioPPlot);
+void MakeExamplePlot4 (PPlot &ioPPlot);
+void MakeExamplePlot5 (PPlot &ioPPlot);
+void MakeExamplePlot6 (PPlot &ioPPlot);
+void MakeExamplePlot7 (PPlot &ioPPlot);
+void MakeExamplePlot8 (PPlot &ioPPlot);
+void MakePainterTester (PPlot &ioPPlot);
+
+void MakeCopy (const PPlot &inPPlot, PPlot &outPPlot);
+
+// following functions can be used to interface with scripts
+void SetCurrentPPlot (PPlot *inPPlot);
+PPlot & GetCurrentPPlot ();
+#endif
+
+#endif
diff --git a/iup/srcpplot/iupPPlotInteraction.cpp b/iup/srcpplot/iupPPlotInteraction.cpp
new file mode 100755
index 0000000..389dbcc
--- /dev/null
+++ b/iup/srcpplot/iupPPlotInteraction.cpp
@@ -0,0 +1,832 @@
+/***************************************************************************
+ * *
+ * Copyright notice: *
+ * *
+ * This is free Pier ware. You may do whatever you want with this code. *
+ * You may cont(r)act me by email: pierphil@xs4all.nl *
+ * *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+
+#include "iupPPlotInteraction.h"
+
+const float kHitDistance = (float)10.0;//pixels
+
+float pmax (float inX1, float inX2) {
+ if (inX1>inX2) {
+ return inX1;
+ }
+ return inX2;
+}
+float pmin (float inX1, float inX2) {
+ if (inX1<inX2) {
+ return inX1;
+ }
+ return inX2;
+}
+
+PMouseEvent::PMouseEvent (int inX, int inY, EType inType, int inModifierKeys):
+ PModifierKeys(inModifierKeys),
+ mX(inX),
+ mY(inY),
+ mType(inType)
+{
+}
+
+PKeyEvent::PKeyEvent (EKey inKey, int inRepeatCount, int inModifierKeys, char inChar):
+ PModifierKeys (inModifierKeys),
+ mKey (inKey),
+ mChar (inChar),
+ mRepeatCount (inRepeatCount)
+{
+}
+
+PPlotInteraction::PPlotInteraction (PPlot &inPPlot):
+ mPPlot (inPPlot),
+ mIsEnabled (true)
+{
+}
+
+
+PZoomInteraction::PZoomInteraction (PPlot &inPPlot):
+ PPlotInteraction (inPPlot),
+ mDragging (false),
+ mZoomMode (kZoom_Region)
+{
+ inPPlot.mPostDrawerList.push_back (this);
+}
+
+bool PZoomInteraction::HandleMouseEvent (const PMouseEvent &inEvent) {
+ if (!mDragging) {
+ if (inEvent.IsMouseDown ()) {
+ /* if (inEvent.IsOnlyShiftKeyDown ()) {
+ DoZoomOut ();
+ return true;
+ }*/
+ if (inEvent.HasModifierKeys ()) {
+ return false;
+ }
+ mDragging = true;
+ mX1 = mX2 = inEvent.mX;
+ mY1 = mY2 = inEvent.mY;
+ return true;
+ }
+ }
+ else {
+ if (inEvent.IsMouseUp ()) {
+ // here we should zoom
+
+ if (mX1 == mX2 && mY1 == mY2) {
+ mDragging = false;
+ DoZoomOut ();
+ return true;
+ // return false;// emtpy area
+ }
+
+ DoZoomIn ();
+ mDragging = false;
+ return true;
+ }
+ if (inEvent.IsMouseMove ()) {
+ mX2 = inEvent.mX;
+ mY2 = inEvent.mY;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PZoomInteraction::HandleKeyEvent (const PKeyEvent &inEvent) {
+
+ if (inEvent.IsOnlyControlKeyDown () && inEvent.IsChar ()) {
+ switch (inEvent.GetChar ()) {
+ case 'r':
+ mZoomMode = kZoom_Region;
+ return true;
+ break;
+ case 'x':
+ mZoomMode = kZoom_X;
+ return true;
+ break;
+ case 'y':
+ mZoomMode = kZoom_Y;
+ return true;
+ break;
+ }
+ }
+ return false;
+};
+
+bool PZoomInteraction::Draw (Painter &inPainter) {
+ if (mDragging) {
+ inPainter.SetLineColor (255, 0, 0);
+
+ float theX1 = mX1;
+ float theX2 = mX2;
+ float theY1 = mY1;
+ float theY2 = mY2;
+
+ bool theDrawInverse = true;
+
+ switch (mZoomMode) {
+ case kZoom_Region:
+ // theDrawInverse = false;
+ break;
+ case kZoom_X:
+ theY1 = mPPlot.mMargins.mTop;
+ theY2 = inPainter.GetHeight ()-mPPlot.mMargins.mBottom;
+ break;
+ case kZoom_Y:
+ theX1 = mPPlot.mMargins.mLeft;
+ theX2 = inPainter.GetWidth ()-mPPlot.mMargins.mRight;
+ break;
+ }
+
+ // draw rectangle
+ inPainter.DrawLine (theX1, theY1, theX2, theY1);
+ inPainter.DrawLine (theX2, theY1, theX2, theY2);
+ inPainter.DrawLine (theX2, theY2, theX1, theY2);
+ inPainter.DrawLine (theX1, theY2, theX1, theY1);
+
+ if (theDrawInverse) {
+ float theX = pmin (theX1, theX2);
+ float theY = pmin (theY1, theY2);
+ float theW = fabs (theX1-theX2);
+ float theH = fabs (theY1-theY2);
+ inPainter.InvertRect (theX, theY, theW, theH);
+ }
+ }
+ return true;
+
+}
+
+bool PZoomInteraction::CheckRange (float inFloat1, float inFloat2) {
+ if (fabs(inFloat1-inFloat2) < 1e-5) {
+ return false;
+ }
+ int abs1 = (int) log10(fabs (inFloat1));
+ int abs2 = (int) log10(fabs (inFloat2));
+ if ( abs1 == abs2) {
+ float theVal1 = (inFloat1 / pow (10., abs1)); /* M.T. changed to force a double cast */
+ float theVal2 = (inFloat2 / pow (10., abs2));
+ float theValDif = fabs(theVal1 - theVal2);
+ if (theValDif < 1e-5) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// hmmm... copied from PPlot.cpp
+void PZoomInteraction::DoZoomIn (float inX1, float inX2, float inY1, float inY2) {
+ if (!CheckRange (inX1, inX2)) {
+ return;
+ }
+ if (!CheckRange (inY1, inY2)) {
+ return;
+ }
+ // also use the following criterium that is used in PPlot::CalculateTickInfo to
+ // avoid strange zoom in / zoom out behaviour
+ float theYRange = fabs (inY1 - inY2);
+ float theYMax = (inY1 > inY2) ? inY1 : inY2;
+ if (fabs (theYRange / theYMax) < PPlot::kRangeVerySmall) {
+ return;
+ }
+
+ StoreCurrentAxisSetup ();
+
+ if (IsZoomRegion () || IsZoomX ()) {
+ mPPlot.mXAxisSetup.SetAutoScale (false);
+ mPPlot.mXAxisSetup.mMin = pmin (inX1, inX2);
+ mPPlot.mXAxisSetup.mMax = pmax (inX1, inX2);
+ }
+ if (IsZoomRegion () || IsZoomY ()) {
+ mPPlot.mYAxisSetup.SetAutoScale (false);
+ mPPlot.mYAxisSetup.mMin = pmin (inY1, inY2);
+ mPPlot.mYAxisSetup.mMax = pmax (inY1, inY2);
+ }
+
+ return;
+}
+
+void PZoomInteraction::StoreCurrentAxisSetup () {
+ PAxisInfo theInfo;// store the current axis setup
+
+ theInfo.mXAxisSetup = mPPlot.mXAxisSetup;
+ theInfo.mYAxisSetup = mPPlot.mYAxisSetup;
+
+ mZoomHistory.push (theInfo);
+}
+
+void PZoomInteraction::DoZoomIn () {
+ float theX1 = mPPlot.mXTrafo->TransformBack (mX1);
+ float theX2 = mPPlot.mXTrafo->TransformBack (mX2);
+ float theY1 = mPPlot.mYTrafo->TransformBack (mY1);
+ float theY2 = mPPlot.mYTrafo->TransformBack (mY2);
+
+ DoZoomIn (theX1, theX2, theY1, theY2);
+};
+
+// arguments allow us to zoom out in X direction but change the Y-axis
+void PZoomInteraction::DoZoomOut (float inY1, float inY2) {
+ if (mZoomHistory.size () == 0) {
+ return;
+ }
+ PAxisInfo theInfo = mZoomHistory.top ();
+ mZoomHistory.pop ();
+
+ mPPlot.mXAxisSetup = theInfo.mXAxisSetup;
+ if (inY1 != -1) {
+ mPPlot.mYAxisSetup.mMin = pmin (inY1, inY2);
+ mPPlot.mYAxisSetup.mMax = pmax (inY1, inY2);
+ } else {
+ mPPlot.mYAxisSetup = theInfo.mYAxisSetup;
+ }
+}
+
+PSelectionInteraction::PSelectionInteraction (PPlot &inPPlot):
+ PPlotInteraction (inPPlot),
+ mCommand (kNone),
+ mListener (0)
+{
+ inPPlot.mPostCalculatorList.push_back (this);
+}
+
+
+bool PSelectionInteraction::HandleKeyEvent (const PKeyEvent &inEvent) {
+
+ mCommand = kNone;
+ if (inEvent.IsOnlyControlKeyDown () && inEvent.IsChar () && inEvent.GetChar () == 'a') {
+// mCalculate = true;
+ mCommand = kSelectAll;
+ mKeyEvent = inEvent;
+ }
+ return mCommand != kNone;
+};
+
+void PSelectionInteraction::UpdateSelection (int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, PlotDataSelection *inPlotDataSelection) {
+ if ((*inPlotDataSelection)[inSampleIndex] != inHit)
+ {
+ if (SelectNotify(inIndex, inSampleIndex, inXData, inYData, inHit))
+ (*inPlotDataSelection)[inSampleIndex] = inHit;
+ }
+}
+
+void PSelectionInteraction::SelectAll (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, PlotDataSelection *inPlotDataSelection) {
+ for (long theI=0;theI<inPlotDataSelection->size ();theI++) {
+ UpdateSelection (inIndex, theI, inXData, inYData, true, inPlotDataSelection);
+ }
+}
+
+
+bool PSelectionInteraction::HandleMouseEvent (const PMouseEvent &inEvent) {
+
+ mCommand = kNone;
+ if (inEvent.IsMouseDown ()) {
+ if (!(inEvent.IsOnlyControlKeyDown () || inEvent.IsOnlyShiftKeyDown ())) {
+ return false;
+ }
+// fprintf (stderr, "selection\n");
+// mCalculate = true;
+ if (inEvent.IsOnlyControlKeyDown ()) {
+ mCommand = kPointwiseSelection;
+ }
+ else if (inEvent.IsOnlyShiftKeyDown ()) {
+ mCommand = kGlobalSelection;
+ }
+ mMouseEvent = inEvent;
+ return true;
+ }
+ return false;
+}
+
+bool PSelectionInteraction::Calculate (Painter &inPainter, PPlot& inPPlot) {
+
+ if (mCommand == kNone) {
+ return true;
+ }
+
+ PlotDataContainer &theContainer = inPPlot.mPlotDataContainer;
+ long thePlotCount = theContainer.GetPlotCount ();
+ float theDist = -1;
+
+ for (long theI=0;theI<thePlotCount;theI++) {
+ PlotDataBase *theXData = theContainer.GetXData (theI);
+ PlotDataBase *theYData = theContainer.GetYData (theI);
+ DataDrawerBase *theDataDrawer = theContainer.GetDataDrawer (theI);
+ PlotDataSelection *thePlotDataSelection = theContainer.GetPlotDataSelection (theI);
+
+
+
+ long theNearestPointIndex;
+ float theLocalDist = CalculateDistanceToPlot (theXData, theYData, theNearestPointIndex);
+
+// fprintf (stderr, "dist %f\n", theLocalDist);
+
+ bool theHit = theLocalDist < kHitDistance;
+
+ if (!SelectNotify(-1, 0, NULL, NULL, false))
+ return true;
+
+ if (mCommand == kPointwiseSelection) {
+ HandlePointwiseInteraction (theI, theXData, theYData, theHit, theNearestPointIndex, theDataDrawer, thePlotDataSelection);
+ }
+ else if (mCommand == kGlobalSelection){
+ HandleGlobalInteraction (theI, theXData, theYData, theHit, theNearestPointIndex, theDataDrawer, thePlotDataSelection);
+ }
+ else if (mCommand == kSelectAll) {
+ SelectAll (theI, theXData, theYData, thePlotDataSelection);
+ }
+
+ SelectNotify(-2, 0, NULL, NULL, false);
+
+ if (theHit) {
+// fprintf (stderr, "hit/n");
+ }
+ }
+ if (mListener) {
+ mListener->HandlePSelectionInteraction ();
+ }
+
+ mCommand = kNone;
+
+ return true;
+}
+
+void PSelectionInteraction::HandleGlobalInteraction (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, long inNearestPointIndex, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection) {
+ if (inPlotDataSelection->size ()>0) {
+ for (int theI=0;theI<inPlotDataSelection->size ();theI++) {
+ UpdateSelection (inIndex, theI, inXData, inYData, inHit, inPlotDataSelection);
+ }
+ }
+}
+
+void PSelectionInteraction::HandlePointwiseInteraction (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, long inNearestPointIndex, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection) {
+ if (!inHit) {
+ return;
+ }
+ if (inPlotDataSelection->size ()>inNearestPointIndex) {
+ bool theWasHit = (*inPlotDataSelection)[inNearestPointIndex] !=0;
+ UpdateSelection (inIndex, inNearestPointIndex, inXData, inYData, !theWasHit, inPlotDataSelection);
+ /*
+ for (int theI=0;theI<inPlotDataSelection->size ();theI++) {
+ bool theWasHit = (*inPlotDataSelection)[theI] !=0;
+ bool theIsHit = false;
+ if (theI==inNearestPointIndex) {
+ theIsHit = !theWasHit;
+ }
+ (*inPlotDataSelection)[theI] = theIsHit;
+ }*/
+ }
+}
+
+float PSelectionInteraction::CalculateDistanceToPlot (const PlotDataBase *inXData, const PlotDataBase *inYData, long &outNearestPointIndex) {
+
+// const RealData *theXData = inXData->GetRealPlotData ();
+// const RealData *theYData = inYData->GetRealPlotData ();
+ outNearestPointIndex = -1;
+ float theDist = -1;
+ for (int theI=0;theI<inXData->GetSize ();theI++) {
+// float theX = (*theXData)[theI];
+// float theY = (*theYData)[theI];
+ float theX = inXData->GetValue (theI);
+ float theY = inYData->GetValue (theI);
+ // transform to pixels
+ theX = mPPlot.mXTrafo->Transform (theX)-mMouseEvent.mX;
+ theY = mPPlot.mYTrafo->Transform (theY)-mMouseEvent.mY;
+
+ float theTmp = theX*theX+theY*theY;
+
+ if (theTmp<theDist||theDist<0) {
+ theDist = theTmp;
+ outNearestPointIndex = theI;
+ }
+ }
+
+ return sqrt (theDist);
+}
+
+
+PlotDataIncrementerBounds::PlotDataIncrementerBounds ():
+ mLowerBoundEnabled (false),
+ mLowerBound (0),
+ mUpperBoundEnabled (false),
+ mUpperBound (0)
+{
+}
+
+bool PlotDataIncrementerBounds::CheckBounds (float inValue) const {
+ if (mLowerBoundEnabled && inValue<mLowerBound) {
+ return false;
+ }
+ if (mUpperBoundEnabled && inValue>mUpperBound) {
+ return false;
+ }
+ return true;
+}
+
+
+bool PlotDataIncrementer::Increment (const vector<float> &inIncrementList, vector<float *> &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector<PlotDataIncrementerBounds> &inBoundList) const {
+ bool theDontChange = true;
+
+ if (!Impl_Increment (inIncrementList, inData, inGlobalBounds, inBoundList, theDontChange)) {
+ return false;
+ }
+ theDontChange = false;
+ Impl_Increment (inIncrementList, inData, inGlobalBounds, inBoundList, theDontChange);
+ return true;
+}
+
+bool PlotDataIncrementer::Impl_Increment (const vector<float> &inIncrementList, vector<float *> &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector<PlotDataIncrementerBounds> &inBoundList, bool inDontChange) const {
+
+ if (inBoundList.size ()>0 && inBoundList.size () != inData.size ()) {
+ return false;
+ }
+ if (inIncrementList.size () != inData.size ()) {
+ return false;
+ }
+
+ for (int theI=0;theI<inData.size ();theI++) {
+ float *theValue = inData[theI];
+ float theIncrement = inIncrementList[theI];
+ float theIncrementedValue = *theValue+theIncrement;
+ if (!inGlobalBounds.CheckBounds (theIncrementedValue)) {
+ return false;
+ }
+ if (inBoundList.size ()>0) {
+ if (!inBoundList[theI].CheckBounds (theIncrementedValue)) {
+ return false;
+ }
+ }
+ if (!inDontChange) {
+ *theValue = theIncrementedValue;
+ }
+ }
+ return true;
+}
+
+
+
+PEditInteraction::PEditInteraction (PPlot &inPPlot):
+ PPlotInteraction (inPPlot),
+ mCalculate (false),
+ mListener (0)
+{
+ inPPlot.mModifyingCalculatorList.push_back (this);
+}
+
+bool PEditInteraction::HandleKeyEvent (const PKeyEvent &inEvent) {
+
+ mCalculate = Impl_HandleKeyEvent (inEvent);
+ mKeyEvent = inEvent;
+ return mCalculate;
+};
+
+bool PEditInteraction::Calculate (Painter &inPainter, PPlot& inPPlot) {
+ if (!mCalculate) {
+ return true;
+ }
+
+ Impl_Calculate (inPainter, inPPlot);
+
+ if (mListener) {
+ mListener->HandlePEditInteraction ();
+ }
+ mCalculate = false;
+ return true;
+}
+
+
+
+PVerticalCursorInteraction::PVerticalCursorInteraction (PPlot &inPPlot):
+ PEditInteraction (inPPlot)
+{
+}
+
+bool PVerticalCursorInteraction::Impl_HandleKeyEvent (const PKeyEvent &inEvent) {
+
+ if (inEvent.IsArrowDown () || inEvent.IsArrowUp ()) {
+ return true;
+ }
+ return false;
+};
+
+bool PVerticalCursorInteraction::Impl_Calculate (Painter &inPainter, PPlot& inPPlot) {
+
+ PlotDataContainer &theContainer = inPPlot.mPlotDataContainer;
+ long thePlotCount = theContainer.GetPlotCount ();
+ for (long theI=0;theI<thePlotCount;theI++) {
+ PlotDataBase *theXData = theContainer.GetXData (theI);
+ PlotDataBase *theYData = theContainer.GetYData (theI);
+ DataDrawerBase *theDataDrawer = theContainer.GetDataDrawer (theI);
+ PlotDataSelection *thePlotDataSelection = theContainer.GetPlotDataSelection (theI);
+
+ if (mKeyEvent.IsArrowUp () || mKeyEvent.IsArrowDown () ) {
+ HandleVerticalCursorKey (thePlotDataSelection, theYData);
+ }
+ }
+ return true;
+}
+
+void PVerticalCursorInteraction::HandleVerticalCursorKey (const PlotDataSelection *inPlotDataSelection, PlotDataBase *inYData) {
+ class PlotData *theYData = dynamic_cast<PlotData *>(inYData);
+ if (!theYData) {
+ return;
+ }
+ vector<float> theIncrementList (inPlotDataSelection->GetSelectedCount ());
+ vector<float *> theSelectedData (inPlotDataSelection->GetSelectedCount ());
+ float theDelta = 1;// pixels
+ if (mKeyEvent.IsArrowDown ()) {
+ theDelta *= -1;
+ }
+ if (mKeyEvent.IsOnlyControlKeyDown ()) {
+ theDelta *= 10;
+ }
+ long theIndex = 0;
+ for (int theI=0;theI<theYData->GetSize ();theI++) {
+ if (inPlotDataSelection->IsSelected (theI)) {
+ float *theNow = &((*theYData)[theI]);
+ float theNowPixels = mPPlot.mYTrafo->Transform (*theNow);
+ float theNow2 = mPPlot.mYTrafo->TransformBack (theNowPixels);
+ theNowPixels -= theDelta;
+ float theShiftedNow = mPPlot.mYTrafo->TransformBack (theNowPixels);
+ float theDeltaData = theShiftedNow-*theNow;
+ theIncrementList[theIndex] = theDeltaData;
+ theSelectedData[theIndex] = theNow;
+// float theNew = theNow + theDelta;
+// (*theYData)[theI] = theNew;
+ theIndex++;
+ }
+ }
+ PlotDataIncrementer theIncremter;
+ vector<PlotDataIncrementerBounds> theDummyList;
+ theIncremter.Increment (theIncrementList, theSelectedData, mGlobalBounds, theDummyList);
+}
+
+
+PDeleteInteraction::PDeleteInteraction (PPlot &inPPlot):
+ PEditInteraction (inPPlot)
+{
+}
+
+bool PDeleteInteraction::Impl_HandleKeyEvent (const PKeyEvent &inEvent) {
+
+ if (inEvent.IsDelete ()) {
+ return true;
+ }
+ return false;
+};
+
+bool PDeleteInteraction::Impl_Calculate (Painter &inPainter, PPlot& inPPlot) {
+
+ PlotDataContainer &theContainer = inPPlot.mPlotDataContainer;
+ long thePlotCount = theContainer.GetPlotCount ();
+
+ if (!DeleteNotify(-1, 0, NULL, NULL))
+ return true;
+
+ for (long theI=0;theI<thePlotCount;theI++) {
+ PlotDataBase *theXData = theContainer.GetXData (theI);
+ PlotDataBase *theYData = theContainer.GetYData (theI);
+ DataDrawerBase *theDataDrawer = theContainer.GetDataDrawer (theI);
+ PlotDataSelection *thePlotDataSelection = theContainer.GetPlotDataSelection (theI);
+
+ if (mKeyEvent.IsDelete () ) {
+ HandleDeleteKey (theXData, theYData, thePlotDataSelection, theI);
+ }
+ }
+
+ DeleteNotify(-2, 0, NULL, NULL);
+
+ return true;
+}
+
+#ifdef __WATCOMC__
+// M.T. - can't get it, otherwise... (anybody any clue ???)
+typedef vector<int> vectorOfInt;
+
+template<class T> bool Erase (const vectorOfInt &inEraseList, T &ioVec) {
+ vectorOfInt theSortedList = inEraseList;
+ sort (theSortedList.begin (), theSortedList.end ());
+ reverse (theSortedList.begin (), theSortedList.end ());
+// M.T. this is missing in OW: unique (theSortedList.begin (), theSortedList.end ());// remove duplicates
+ for (vectorOfInt::iterator theI=theSortedList.begin();theI!=theSortedList.end ();theI++) {
+ int theEraseIndex = *theI;
+ // vector <T> ::iterator theX;
+ // theX = ioVec[theEraseIndex];
+ // T *theX = &(ioVec[theEraseIndex]);
+ ioVec.erase (ioVec.begin ()+theEraseIndex);
+ }
+
+ return true;
+}
+
+/*
+
+bool Erase (const vectorOfInt &inEraseList, PlotData &ioVec) {
+ vectorOfInt theSortedList = inEraseList;
+ sort (theSortedList.begin (), theSortedList.end ());
+ reverse (theSortedList.begin (), theSortedList.end ());
+// unique (theSortedList.begin (), theSortedList.end ());// remove duplicates
+ for (vectorOfInt::iterator theI=theSortedList.begin();theI!=theSortedList.end ();theI++) {
+ int theEraseIndex = *theI;
+ ioVec.erase (ioVec.begin ()+theEraseIndex);
+ }
+
+ return true;
+}
+
+bool Erase (const vectorOfInt &inEraseList, PlotDataSelection &ioVec)
+ {
+ vectorOfInt theSortedList = inEraseList;
+ sort (theSortedList.begin (), theSortedList.end ());
+ reverse (theSortedList.begin (), theSortedList.end ());
+// unique (theSortedList.begin (), theSortedList.end ());// remove duplicates
+ for (vectorOfInt::iterator theI=theSortedList.begin();theI!=theSortedList.end ();theI++) {
+ int theEraseIndex = *theI;
+ ioVec.erase (ioVec.begin ()+theEraseIndex);
+ }
+
+ return true;
+}
+*/
+#else
+template<class T> bool Erase (const vector<int> &inEraseList, vector <T> &ioVec) {
+ vector<int> theSortedList = inEraseList;
+ sort (theSortedList.begin (), theSortedList.end ());
+ reverse (theSortedList.begin (), theSortedList.end ());
+ unique (theSortedList.begin (), theSortedList.end ());// remove duplicates
+ for (vector<int>::iterator theI=theSortedList.begin();theI!=theSortedList.end ();theI++) {
+ int theEraseIndex = *theI;
+ // vector <T> ::iterator theX;
+ // theX = ioVec[theEraseIndex];
+ // T *theX = &(ioVec[theEraseIndex]);
+ ioVec.erase (ioVec.begin ()+theEraseIndex);
+ }
+
+ return true;
+}
+#endif
+
+void PDeleteInteraction::HandleDeleteKey (PlotDataBase *inXData, PlotDataBase *inYData, PlotDataSelection *inPlotDataSelection, int inIndex) {
+ vector<int> theDeleteList (inPlotDataSelection->GetSelectedCount ());
+ long theIndex = 0;
+ for (int theI=0;theI<inYData->GetSize ();theI++) {
+ if (inPlotDataSelection->IsSelected (theI)) {
+ if (DeleteNotify(inIndex, theI, inXData, inYData))
+ {
+ theDeleteList[theIndex] = theI;
+ theIndex++;
+ }
+ }
+ }
+
+ if (inXData->IsString())
+ {
+ StringPlotData *theXData = (StringPlotData*)(inXData);
+ PlotData *theYData = (PlotData*)(inYData);
+ Erase (theDeleteList, theXData->mRealPlotData);
+ Erase (theDeleteList, theXData->mStringPlotData);
+ Erase (theDeleteList, *theYData);
+ Erase (theDeleteList, *inPlotDataSelection);
+ }
+ else
+ {
+ PlotData *theXData = (PlotData*)(inXData);
+ PlotData *theYData = (PlotData*)(inYData);
+ Erase (theDeleteList, *theXData);
+ Erase (theDeleteList, *theYData);
+ Erase (theDeleteList, *inPlotDataSelection);
+ }
+}
+
+PCrosshairInteraction::PCrosshairInteraction (PPlot &inPPlot):
+ PPlotInteraction (inPPlot),
+ mActive (false),
+ mX (0),
+ mListener (0)
+{
+ inPPlot.mPostDrawerList.push_back (this);
+}
+
+bool PCrosshairInteraction::HandleMouseEvent (const PMouseEvent &inEvent) {
+ if (!mActive) {
+ if (inEvent.IsMouseDown ()) {
+ if (inEvent.IsShiftKeyDown () && inEvent.IsControlKeyDown ()) {
+ mActive = true;
+ mX = inEvent.mX;
+ return true;
+ }
+ }
+ }
+ else {
+ if (inEvent.IsMouseUp ()) {
+ mActive = false;
+ return true;
+ }
+ if (inEvent.IsMouseMove ()) {
+ mX = inEvent.mX;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PCrosshairInteraction::Draw (Painter &inPainter) {
+ if (mActive) {
+ float theX1 = mX;
+ float theY1 = mPPlot.mMargins.mTop;
+ float theX2 = mX;
+ float theY2 = inPainter.GetHeight () - mPPlot.mMargins.mBottom;
+
+ inPainter.SetLineColor (0, 0, 0);
+ inPainter.DrawLine (theX1, theY1, theX2, theY2);
+
+ PlotDataContainer &theContainer = mPPlot.mPlotDataContainer;
+ long thePlotCount = theContainer.GetPlotCount ();
+
+ for (long theI=0;theI<thePlotCount;theI++) {
+ PlotDataBase *theXData = theContainer.GetXData (theI);
+ PlotDataBase *theYData = theContainer.GetYData (theI);
+ LegendData *theLegendData = theContainer.GetLegendData (theI);
+
+ float theY;
+ if (GetCrossPoint (theXData, theYData, theY)) {
+ if (mListener) {
+ float theXTarget = mPPlot.mXTrafo->TransformBack (mX);
+ float theYTarget = mPPlot.mYTrafo->TransformBack (theY);
+ mListener->HandleCrosshair (theI, thePlotCount, theXTarget, theYTarget);
+ }
+ theX1 = mPPlot.mMargins.mLeft;
+ theX2 = inPainter.GetWidth ()-mPPlot.mMargins.mLeft;
+ theY1 = theY2 = theY;
+ PColor theC = theLegendData->mColor;
+ inPainter.SetLineColor (theC.mR, theC.mG, theC.mB);
+ inPainter.DrawLine (theX1, theY1, theX2, theY2);
+ }
+ }
+ }
+ return true;
+}
+
+bool PCrosshairInteraction::GetCrossPoint (const PlotDataBase *inXData, const PlotDataBase *inYData, float &outY) {
+ if (inXData->GetSize ()==0 ){
+ return false;
+ }
+ float theXTarget = mPPlot.mXTrafo->TransformBack (mX);
+ bool theFirstIsLess = inXData->GetValue (0) < theXTarget;
+ for (int theI=0;theI<inXData->GetSize ();theI++) {
+ float theX = inXData->GetValue (theI);
+ float theY = inYData->GetValue (theI);
+ bool theCurrentIsLess = theX < theXTarget;
+
+ if (theCurrentIsLess != theFirstIsLess) {
+ outY = mPPlot.mYTrafo->Transform (theY);// transform to pixels
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool InteractionContainer::HandleMouseEvent (const PMouseEvent &inEvent) {
+ for (int theI=0;theI<mList.size ();theI++) {
+ PPlotInteraction *theInteraction = mList[theI];
+ if (theInteraction->IsEnabled () && theInteraction->HandleMouseEvent (inEvent)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool InteractionContainer::HandleKeyEvent (const PKeyEvent &inEvent) {
+ for (int theI=0;theI<mList.size ();theI++) {
+ PPlotInteraction *theInteraction = mList[theI];
+ if (theInteraction->IsEnabled () && theInteraction->HandleKeyEvent (inEvent)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+DefaultInteractionContainer::DefaultInteractionContainer (PPlot &inPPlot):
+ mZoomInteraction (inPPlot),
+ mSelectionInteraction (inPPlot),
+ mVerticalCursorInteraction (inPPlot),
+ mDeleteInteraction (inPPlot),
+ mCrosshairInteraction (inPPlot)
+{
+ AddInteraction (mZoomInteraction);
+ AddInteraction (mSelectionInteraction);
+ AddInteraction (mVerticalCursorInteraction);
+ AddInteraction (mDeleteInteraction);
+ AddInteraction (mCrosshairInteraction);
+/*
+ mVerticalCursorInteraction.mGlobalBounds.mLowerBoundEnabled = true;
+ mVerticalCursorInteraction.mGlobalBounds.mLowerBound = 0;
+ mVerticalCursorInteraction.mGlobalBounds.mUpperBoundEnabled = true;
+ mVerticalCursorInteraction.mGlobalBounds.mUpperBound = 10;*/
+}
diff --git a/iup/srcpplot/iupPPlotInteraction.h b/iup/srcpplot/iupPPlotInteraction.h
new file mode 100755
index 0000000..eacf790
--- /dev/null
+++ b/iup/srcpplot/iupPPlotInteraction.h
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * *
+ * Copyright notice: *
+ * *
+ * This is free Pier ware. You may do whatever you want with this code. *
+ * You may cont(r)act me by email: pierphil@xs4all.nl *
+ * *
+ ***************************************************************************/
+
+#ifndef __PPLOTINTERACTION_H__
+#define __PPLOTINTERACTION_H__
+
+#include "iupPPlot.h"
+
+class PModifierKeys {
+public:
+ enum {
+ kShift=1,
+ kControl=2,
+ kAlt=4
+ };
+ PModifierKeys (int inModifierKeys=0):mModifierKeys (inModifierKeys) {};
+
+
+ bool IsShiftKeyDown () const {return mModifierKeys & kShift? true: false;};
+ bool IsControlKeyDown () const {return mModifierKeys & kControl? true: false;};
+ bool IsAltKeyDown () const {return mModifierKeys & kAlt? true: false;};
+ bool IsOnlyShiftKeyDown () const {return mModifierKeys == kShift? true: false;};
+ bool IsOnlyControlKeyDown () const {return mModifierKeys == kControl? true: false;};
+ bool IsOnlyAltKeyDown () const {return mModifierKeys == kAlt? true: false;};
+
+ bool HasModifierKeys () const {return mModifierKeys != 0;};
+
+ void SetModifierKeys (int inModifierKeys) {mModifierKeys = inModifierKeys;};
+private:
+ int mModifierKeys;// values like kShift | kAlt
+};
+
+class PMouseEvent: public PModifierKeys {
+public:
+ enum EType {
+ kNone,
+ kDown,
+ kUp,
+ kMove
+ };
+
+ PMouseEvent (int inX=0, int inY=0, EType inType=kNone, int inModifierKeys=0);
+
+ int mX;
+ int mY;
+
+
+ EType mType;
+
+ bool IsNone () const {return mType == kNone;};
+ bool IsMouseDown () const {return mType == kDown;};
+ bool IsMouseUp () const {return mType == kUp;};
+ bool IsMouseMove () const {return mType == kMove;};
+};
+
+class PKeyEvent: public PModifierKeys {
+public:
+
+ enum EKey {
+ kNone,
+ kArrowUp,
+ kArrowDown,
+ kArrowLeft,
+ kArrowRight,
+ kDelete,
+ kChar
+ };
+
+ PKeyEvent (EKey inKey=kNone, int inRepeatCount=0, int inModifierKeys=0, char inChar=0);
+
+
+ bool IsNone () const {return mKey == kNone;};
+ bool IsArrowUp () const {return mKey == kArrowUp;};
+ bool IsArrowDown () const {return mKey == kArrowDown;};
+ bool IsArrowLeft () const {return mKey == kArrowLeft;};
+ bool IsArrowRight () const {return mKey == kArrowRight;};
+ bool IsDelete () const {return mKey == kDelete;};
+ bool IsChar () const {return mKey == kChar;};
+
+ int GetRepeatCount () const {return mRepeatCount;};
+ char GetChar () const {return mChar;};
+protected:
+ EKey mKey;
+ char mChar;
+
+ int mRepeatCount;
+};
+
+
+class PPlotInteraction {
+ public:
+
+ typedef vector<PPlotInteraction *>tList;
+
+ PPlotInteraction (PPlot &inPPlot);
+
+ virtual bool HandleMouseEvent (const PMouseEvent &inEvent)=0;
+ virtual bool HandleKeyEvent (const PKeyEvent &inEvent) {return false;};
+
+ void SetEnabled (bool inBool) {mIsEnabled = inBool;};
+ bool IsEnabled () const {return mIsEnabled;};
+protected:
+ PPlot &mPPlot;
+ bool mIsEnabled;
+};
+
+class PAxisInfo {
+public:
+ typedef vector<AxisSetup> tList;
+ AxisSetup mXAxisSetup;
+ AxisSetup mYAxisSetup;
+};
+
+class PZoomInteraction: public PPlotInteraction, public PDrawer {
+public:
+
+ enum EZoomMode {
+ kZoom_Region,
+ kZoom_X,
+ kZoom_Y
+ };
+
+ PZoomInteraction (PPlot &inPPlot);
+
+ virtual bool HandleMouseEvent (const PMouseEvent &inEvent);
+ virtual bool HandleKeyEvent (const PKeyEvent &inEvent);
+
+ void DoZoomIn (float inX1, float inX2, float inY1, float inY2);
+ void DoZoomOut (float inY1 = -1, float inY2 = -1);
+ bool CanZoomOut () { return !mZoomHistory.empty (); };
+ int GetZoomStackSize () { return mZoomHistory.size (); };
+
+ stack<PAxisInfo> mZoomHistory;
+ EZoomMode mZoomMode;
+
+ bool IsZoomRegion () const {return mZoomMode == kZoom_Region;};
+ bool IsZoomX () const {return mZoomMode == kZoom_X;};
+ bool IsZoomY () const {return mZoomMode == kZoom_Y;};
+protected:
+ void StoreCurrentAxisSetup ();
+ virtual bool Draw (Painter &inPainter);
+ bool CheckRange (float inFloat1, float inFloat2);
+
+ void DoZoomIn ();
+
+ bool mDragging;
+ int mX1;
+ int mY1;
+ int mX2;
+ int mY2;
+
+};
+
+class PlotDataIncrementerBounds {
+public:
+ PlotDataIncrementerBounds ();
+
+ bool CheckBounds (float inValue) const;
+
+ bool mLowerBoundEnabled;
+ float mLowerBound;
+ bool mUpperBoundEnabled;
+ float mUpperBound;
+};
+
+class PlotDataIncrementer {
+public:
+
+ // all are none are incremented
+ bool Increment (const vector<float> &inIncrementList, vector<float *> &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector<PlotDataIncrementerBounds> &inBoundList) const;
+
+protected:
+ bool Impl_Increment (const vector<float> &inIncrementList, vector<float *> &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector<PlotDataIncrementerBounds> &inBoundList, bool inDontChange) const;
+};
+
+class PSelectionInteractionListener {
+public:
+ virtual void HandlePSelectionInteraction ()=0;
+};
+
+class PSelectionInteraction: public PPlotInteraction, public PCalculator {
+public:
+
+ enum ECommand {
+ kNone,
+ kPointwiseSelection,
+ kGlobalSelection,
+ kSelectAll
+ };
+
+ PSelectionInteraction (PPlot &inPPlot);
+
+ virtual bool HandleKeyEvent (const PKeyEvent &inEvent);
+ virtual bool HandleMouseEvent (const PMouseEvent &inEvent);
+ virtual bool Calculate (Painter &inPainter, PPlot& inPPlot);
+
+ void SetCommand (ECommand inCommand, const PKeyEvent &inKeyEvent, const PMouseEvent &inMouseEvent);
+ void SetListener (PSelectionInteractionListener *inListener) {mListener = inListener;};
+protected:
+ PSelectionInteractionListener *mListener;
+
+ virtual bool SelectNotify(int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inSelect) {return true;}
+ void UpdateSelection (int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, PlotDataSelection *inPlotDataSelection);
+ void HandleGlobalInteraction (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, long inNearestPointIndex, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection);
+ void HandlePointwiseInteraction (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inHit, long inNearestPointIndex, DataDrawerBase *inDataDrawer, PlotDataSelection *inPlotDataSelection);
+ float CalculateDistanceToPlot (const PlotDataBase *inXData, const PlotDataBase *inYData, long &outNearestPointIndex);
+ void SelectAll (int inIndex, PlotDataBase *inXData, PlotDataBase *inYData, PlotDataSelection *inPlotDataSelection);
+// int mX;
+// int mY;
+ ECommand mCommand;
+ PMouseEvent mMouseEvent;
+ PKeyEvent mKeyEvent;
+};
+
+
+class PKeySelectionInteraction: public PPlotInteraction, public PCalculator {
+public:
+ PKeySelectionInteraction (PPlot &inPPlot);
+
+ virtual bool Calculate (Painter &inPainter, PPlot& inPPlot);
+
+protected:
+
+ bool mCalculate;
+};
+
+class PEditInteractionListener {
+public:
+ virtual void HandlePEditInteraction ()=0;
+};
+
+class PEditInteraction: public PPlotInteraction, public PCalculator {
+public:
+ PEditInteraction (PPlot &inPPlot);
+
+ virtual bool HandleMouseEvent (const PMouseEvent &inEvent) {return false;};
+ virtual bool HandleKeyEvent (const PKeyEvent &inEvent);
+ virtual bool ShouldCalculate () const {return mCalculate;};
+ virtual bool Calculate (Painter &inPainter, PPlot& inPPlot);
+
+ virtual bool Impl_HandleKeyEvent (const PKeyEvent &inEvent)=0;
+ virtual bool Impl_Calculate (Painter &inPainter, PPlot& inPPlot)=0;
+ void SetListener (PEditInteractionListener *inListener) {mListener = inListener;};
+protected:
+ PEditInteractionListener *mListener;
+ PKeyEvent mKeyEvent;
+private:
+ bool mCalculate;
+};
+
+class PVerticalCursorInteraction: public PEditInteraction {
+public:
+
+ PVerticalCursorInteraction (PPlot &inPPlot);
+
+ virtual bool Impl_HandleKeyEvent (const PKeyEvent &inEvent);
+ virtual bool Impl_Calculate (Painter &inPainter, PPlot& inPPlot);
+
+ PlotDataIncrementerBounds mGlobalBounds;
+protected:
+ void HandleVerticalCursorKey (const PlotDataSelection *inPlotDataSelection, PlotDataBase *inYData);
+};
+
+class PDeleteInteraction: public PEditInteraction {
+public:
+
+ PDeleteInteraction (PPlot &inPPlot);
+
+ virtual bool Impl_HandleKeyEvent (const PKeyEvent &inEvent);
+ virtual bool Impl_Calculate (Painter &inPainter, PPlot& inPPlot);
+
+protected:
+ void HandleDeleteKey (PlotDataBase *inXData, PlotDataBase *inYData, PlotDataSelection *inPlotDataSelection, int inIndex);
+ virtual bool DeleteNotify(int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData) {return true;}
+};
+
+class PCrosshairInteractionListener {
+public:
+ virtual void HandleCrosshair (int inIndex, int inPlotCount, float inX, float inY)=0;
+};
+
+class PCrosshairInteraction: public PPlotInteraction, public PDrawer {
+public:
+ PCrosshairInteraction (PPlot &inPPlot);
+
+ void SetListener (PCrosshairInteractionListener *inListener) {mListener = inListener;};
+protected:
+ virtual bool HandleMouseEvent (const PMouseEvent &inEvent);
+ virtual bool Draw (Painter &inPainter);
+
+ bool GetCrossPoint (const PlotDataBase *inXData, const PlotDataBase *inYData, float &outY);
+ bool mActive;
+ int mX;
+ PCrosshairInteractionListener *mListener;
+};
+
+class InteractionContainer {
+public:
+ InteractionContainer (){};
+ virtual ~InteractionContainer (){};
+
+ bool HandleMouseEvent (const PMouseEvent &inEvent);
+ bool HandleKeyEvent (const PKeyEvent &inEvent);
+
+ void AddInteraction (PPlotInteraction &inInteraction){mList.push_back(&inInteraction);};
+
+protected:
+ PPlotInteraction::tList mList;
+};
+
+class DefaultInteractionContainer: public InteractionContainer {
+public:
+ DefaultInteractionContainer (PPlot &inPPlot);
+
+ PZoomInteraction mZoomInteraction;
+ PSelectionInteraction mSelectionInteraction;
+ PVerticalCursorInteraction mVerticalCursorInteraction;
+ PDeleteInteraction mDeleteInteraction;
+ PCrosshairInteraction mCrosshairInteraction;
+};
+
+#endif
diff --git a/iup/srcpplot/iup_pplot.cpp b/iup/srcpplot/iup_pplot.cpp
new file mode 100755
index 0000000..6f5c93a
--- /dev/null
+++ b/iup/srcpplot/iup_pplot.cpp
@@ -0,0 +1,2959 @@
+/*
+ * IupPPlot component
+ *
+ * Description : A component, derived from PPlot and IUP canvas
+ * Remark : Depend on libs IUP, CD, IUPCD
+ */
+
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4100)
+#pragma warning(disable: 4512)
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+#include "iup_pplot.h"
+#include "iupkey.h"
+
+#include <cd.h>
+#include <cdiup.h>
+#include <cddbuf.h>
+#include <cdirgb.h>
+#include <cdgdiplus.h>
+
+#include "iup_class.h"
+#include "iup_register.h"
+#include "iup_object.h"
+#include "iup_attrib.h"
+#include "iup_str.h"
+#include "iup_drv.h"
+#include "iup_stdcontrols.h"
+#include "iup_assert.h"
+
+#include "iupPPlot.h"
+#include "iupPPlotInteraction.h"
+#include "iuppplot.hpp"
+
+
+#ifndef M_E
+#define M_E 2.71828182846
+#endif
+
+struct _IcontrolData
+{
+ iupCanvas canvas; /* from IupCanvas (must reserve it) */
+ PPainterIup* plt;
+};
+
+
+static int iPPlotGetCDFontStyle(const char* value);
+
+
+/* PPlot function pointer typedefs. */
+typedef int (*IFnC)(Ihandle*, cdCanvas*); /* postdraw_cb, predraw_cb */
+typedef int (*IFniiff)(Ihandle*, int, int, float, float); /* delete_cb */
+typedef int (*IFniiffi)(Ihandle*, int, int, float, float, int); /* select_cb */
+typedef int (*IFniiffff)(Ihandle*, int, int, float, float, float*, float*); /* edit_cb */
+
+
+/* callback: forward redraw request to PPlot object */
+static int iPPlotRedraw_CB(Ihandle* ih)
+{
+ ih->data->plt->Draw(0); /* full redraw only if nothing changed */
+ return IUP_DEFAULT;
+}
+
+/* callback: forward resize request to PPlot object */
+static int iPPlotResize_CB(Ihandle* ih)
+{
+ ih->data->plt->Resize();
+ return IUP_DEFAULT;
+}
+
+/* callback: forward mouse button events to PPlot object */
+static int iPPlotMouseButton_CB(Ihandle* ih, int btn, int stat, int x, int y, char* r)
+{
+ ih->data->plt->MouseButton(btn, stat, x, y, r);
+ return IUP_DEFAULT;
+}
+
+/* callback: forward mouse button events to PPlot object */
+static int iPPlotMouseMove_CB(Ihandle* ih, int x, int y)
+{
+ ih->data->plt->MouseMove(x, y);
+ return IUP_DEFAULT;
+}
+
+/* callback: forward keyboard events to PPlot object */
+static int iPPlotKeyPress_CB(Ihandle* ih, int c, int press)
+{
+ ih->data->plt->KeyPress(c, press);
+ return IUP_DEFAULT;
+}
+
+/* user level call: add dataset to plot */
+void IupPPlotBegin(Ihandle* ih, int strXdata)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ PlotDataBase* inXData = (PlotDataBase*)iupAttribGet(ih, "_IUP_PPLOT_XDATA");
+ PlotDataBase* inYData = (PlotDataBase*)iupAttribGet(ih, "_IUP_PPLOT_YDATA");
+
+ if (inXData) delete inXData;
+ if (inYData) delete inYData;
+
+ if (strXdata)
+ inXData = (PlotDataBase*)(new StringPlotData());
+ else
+ inXData = (PlotDataBase*)(new PlotData());
+
+ inYData = (PlotDataBase*)new PlotData();
+
+ iupAttribSetStr(ih, "_IUP_PPLOT_XDATA", (char*)inXData);
+ iupAttribSetStr(ih, "_IUP_PPLOT_YDATA", (char*)inYData);
+ iupAttribSetStr(ih, "_IUP_PPLOT_STRXDATA", (char*)(strXdata? "1": "0"));
+}
+
+void IupPPlotAdd(Ihandle* ih, float x, float y)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ PlotData* inXData = (PlotData*)iupAttribGet(ih, "_IUP_PPLOT_XDATA");
+ PlotData* inYData = (PlotData*)iupAttribGet(ih, "_IUP_PPLOT_YDATA");
+ int strXdata = iupAttribGetInt(ih, "_IUP_PPLOT_STRXDATA");
+
+ if (!inYData || !inXData || strXdata)
+ return;
+
+ inXData->push_back(x);
+ inYData->push_back(y);
+}
+
+void IupPPlotAddStr(Ihandle* ih, const char* x, float y)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ StringPlotData *inXData = (StringPlotData*)iupAttribGet(ih, "_IUP_PPLOT_XDATA");
+ PlotData *inYData = (PlotData*)iupAttribGet(ih, "_IUP_PPLOT_YDATA");
+ int strXdata = iupAttribGetInt(ih, "_IUP_PPLOT_STRXDATA");
+
+ if (!inYData || !inXData || !strXdata)
+ return;
+
+ inXData->AddItem(x);
+ inYData->push_back(y);
+}
+
+void IupPPlotInsertStr(Ihandle* ih, int inIndex, int inSampleIndex, const char* inX, float inY)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ PlotDataBase* theXDataBase = ih->data->plt->_plot.mPlotDataContainer.GetXData(inIndex);
+ PlotDataBase* theYDataBase = ih->data->plt->_plot.mPlotDataContainer.GetYData(inIndex);
+ StringPlotData *theXData = (StringPlotData*)theXDataBase;
+ PlotData *theYData = (PlotData*)theYDataBase;
+ if (!theYData || !theXData)
+ return;
+
+ theXData->InsertItem(inSampleIndex, inX);
+ theYData->insert(theYData->begin()+inSampleIndex, inY);
+}
+
+void IupPPlotInsert(Ihandle* ih, int inIndex, int inSampleIndex, float inX, float inY)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ PlotDataBase* theXDataBase = ih->data->plt->_plot.mPlotDataContainer.GetXData(inIndex);
+ PlotDataBase* theYDataBase = ih->data->plt->_plot.mPlotDataContainer.GetYData(inIndex);
+ PlotData* theXData = (PlotData*)theXDataBase;
+ PlotData* theYData = (PlotData*)theYDataBase;
+ if (!theYData || !theXData)
+ return;
+
+ theXData->insert(theXData->begin()+inSampleIndex, inX);
+ theYData->insert(theYData->begin()+inSampleIndex, inY);
+}
+
+int IupPPlotEnd(Ihandle* ih)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return -1;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return -1;
+
+ PlotDataBase* inXData = (PlotDataBase*)iupAttribGet(ih, "_IUP_PPLOT_XDATA");
+ PlotDataBase* inYData = (PlotDataBase*)iupAttribGet(ih, "_IUP_PPLOT_YDATA");
+ if (!inYData || !inXData)
+ return -1;
+
+ /* add to plot */
+ ih->data->plt->_currentDataSetIndex = ih->data->plt->_plot.mPlotDataContainer.AddXYPlot(inXData, inYData);
+
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ih->data->plt->_currentDataSetIndex);
+ legend->mStyle.mFontStyle = iPPlotGetCDFontStyle(IupGetAttribute(ih, "LEGENDFONTSTYLE"));
+ legend->mStyle.mFontSize = IupGetInt(ih, "LEGENDFONTSIZE");
+
+ iupAttribSetStr(ih, "_IUP_PPLOT_XDATA", NULL);
+ iupAttribSetStr(ih, "_IUP_PPLOT_YDATA", NULL);
+
+ ih->data->plt->_redraw = 1;
+ return ih->data->plt->_currentDataSetIndex;
+}
+
+void IupPPlotTransform(Ihandle* ih, float x, float y, int *ix, int *iy)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ if (ix) *ix = ih->data->plt->_plot.Round(ih->data->plt->_plot.mXTrafo->Transform(x));
+ if (iy) *iy = ih->data->plt->_plot.Round(ih->data->plt->_plot.mYTrafo->Transform(y));
+}
+
+/* user level call: plot on the given device */
+void IupPPlotPaintTo(Ihandle* ih, void* _cnv)
+{
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+
+ if (ih->iclass->nativetype != IUP_TYPECANVAS ||
+ !iupStrEqual(ih->iclass->name, "pplot"))
+ return;
+
+ ih->data->plt->DrawTo((cdCanvas *)_cnv);
+}
+
+/* --------------------------------------------------------------------
+ class implementation
+ -------------------------------------------------------------------- */
+
+PostPainterCallbackIup::PostPainterCallbackIup (PPlot &inPPlot, Ihandle* inHandle):
+ _ih(inHandle)
+{
+ inPPlot.mPostDrawerList.push_back (this);
+}
+
+bool PostPainterCallbackIup::Draw(Painter &inPainter)
+{
+ IFnC cb = (IFnC)IupGetCallback(_ih, "POSTDRAW_CB");
+
+ if (cb)
+ {
+ PPainterIup* iupPainter = (PPainterIup*)(&inPainter);
+ cb(_ih, iupPainter->_cddbuffer);
+ }
+
+ return true;
+}
+
+PrePainterCallbackIup::PrePainterCallbackIup (PPlot &inPPlot, Ihandle* inHandle):
+ _ih(inHandle)
+{
+ inPPlot.mPreDrawerList.push_back (this);
+}
+
+bool PrePainterCallbackIup::Draw(Painter &inPainter)
+{
+ IFnC cb = (IFnC)IupGetCallback(_ih, "PREDRAW_CB");
+ if (cb)
+ {
+ PPainterIup* iupPainter = (PPainterIup*)(&inPainter);
+ cb(_ih, iupPainter->_cddbuffer);
+ }
+
+ return true;
+}
+
+bool PDeleteInteractionIup::DeleteNotify(int inIndex, int inSampleIndex, PlotDataBase* inXData, PlotDataBase* inYData)
+{
+ IFniiff cb = (IFniiff)IupGetCallback(_ih, "DELETE_CB");
+ if (cb)
+ {
+ if (inIndex == -1)
+ {
+ Icallback cbb = IupGetCallback(_ih, "DELETEBEGIN_CB");
+ if (cbb && cbb(_ih) == IUP_IGNORE)
+ return false;
+ }
+ else if (inIndex == -2)
+ {
+ Icallback cbb = IupGetCallback(_ih, "DELETEEND_CB");
+ if (cbb)
+ cbb(_ih);
+ }
+ else
+ {
+ float theX = inXData->GetValue(inSampleIndex);
+ float theY = inYData->GetValue(inSampleIndex);
+ int ret = cb(_ih, inIndex, inSampleIndex, theX, theY);
+ if (ret == IUP_IGNORE)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PSelectionInteractionIup::SelectNotify(int inIndex, int inSampleIndex, PlotDataBase* inXData, PlotDataBase* inYData, bool inSelect)
+{
+ IFniiffi cb = (IFniiffi)IupGetCallback(_ih, "SELECT_CB");
+ if (cb)
+ {
+ if (inIndex == -1)
+ {
+ Icallback cbb = IupGetCallback(_ih, "SELECTBEGIN_CB");
+ if (cbb && cbb(_ih) == IUP_IGNORE)
+ return false;
+ }
+ else if (inIndex == -2)
+ {
+ Icallback cbb = IupGetCallback(_ih, "SELECTEND_CB");
+ if (cbb)
+ cbb(_ih);
+ }
+ else
+ {
+ float theX = inXData->GetValue(inSampleIndex);
+ float theY = inYData->GetValue(inSampleIndex);
+ int ret = cb(_ih, inIndex, inSampleIndex, theX, theY, (int)inSelect);
+ if (ret == IUP_IGNORE)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PEditInteractionIup::Impl_HandleKeyEvent (const PKeyEvent &inEvent)
+{
+ if (inEvent.IsArrowDown () || inEvent.IsArrowUp () ||
+ inEvent.IsArrowLeft () || inEvent.IsArrowRight ())
+ return true;
+
+ return false;
+};
+
+bool PEditInteractionIup::Impl_Calculate (Painter &inPainter, PPlot& inPPlot)
+{
+ PlotDataContainer &theContainer = inPPlot.mPlotDataContainer;
+ long thePlotCount = theContainer.GetPlotCount();
+
+ if (!EditNotify(-1, 0, 0, 0, NULL, NULL))
+ return false;
+
+ for (long theI=0;theI<thePlotCount;theI++)
+ {
+ PlotDataBase* theXData = theContainer.GetXData (theI);
+ PlotDataBase* theYData = theContainer.GetYData (theI);
+ PlotDataSelection *thePlotDataSelection = theContainer.GetPlotDataSelection (theI);
+
+ if (mKeyEvent.IsArrowDown () || mKeyEvent.IsArrowUp () ||
+ mKeyEvent.IsArrowLeft () || mKeyEvent.IsArrowRight ())
+ HandleCursorKey (thePlotDataSelection, theXData, theYData, theI);
+ }
+
+ EditNotify(-2, 0, 0, 0, NULL, NULL);
+
+ return true;
+}
+
+void PEditInteractionIup::HandleCursorKey (const PlotDataSelection *inPlotDataSelection, PlotDataBase* inXData, PlotDataBase* inYData, int inIndex)
+{
+ float theXDelta = 0; // pixels
+ if (mKeyEvent.IsArrowLeft () || mKeyEvent.IsArrowRight ())
+ {
+ theXDelta = 1;
+
+ if (mKeyEvent.IsArrowLeft ())
+ theXDelta *= -1;
+
+ if (mKeyEvent.IsOnlyControlKeyDown ())
+ theXDelta *= 10;
+ }
+
+ float theYDelta = 0; // pixels
+ if (mKeyEvent.IsArrowDown () || mKeyEvent.IsArrowUp ())
+ {
+ theYDelta = 1;
+
+ if (mKeyEvent.IsArrowDown ())
+ theYDelta *= -1;
+
+ if (mKeyEvent.IsOnlyControlKeyDown ())
+ theYDelta *= 10;
+ }
+
+ for (int theI=0;theI<inYData->GetSize ();theI++)
+ {
+ if (inPlotDataSelection->IsSelected (theI))
+ {
+ float theX = inXData->GetValue(theI);
+ float newX = theX;
+
+ if (theXDelta)
+ {
+ float theXPixels = mPPlot.mXTrafo->Transform(theX);
+ theXPixels += theXDelta;
+ newX = mPPlot.mXTrafo->TransformBack(theXPixels);
+ }
+
+ float theY = inYData->GetValue(theI);
+ float newY = theY;
+ if (theYDelta)
+ {
+ float theYPixels = mPPlot.mYTrafo->Transform(theY);
+ theYPixels -= theYDelta; // in pixels Y is descending
+ newY = mPPlot.mYTrafo->TransformBack(theYPixels);
+ }
+
+ if (!EditNotify(inIndex, theI, theX, theY, &newX, &newY))
+ return;
+
+ if (inXData->IsString())
+ {
+ StringPlotData *theXData = (StringPlotData*)(inXData);
+ PlotData* theYData = (PlotData*)(inYData);
+ theXData->mRealPlotData[theI] = newX;
+ (*theYData)[theI] = newY;
+ }
+ else
+ {
+ PlotData* theXData = (PlotData*)(inXData);
+ PlotData* theYData = (PlotData*)(inYData);
+ (*theXData)[theI] = newX;
+ (*theYData)[theI] = newY;
+ }
+ }
+ }
+}
+
+bool PEditInteractionIup::EditNotify(int inIndex, int inSampleIndex, float inX, float inY, float *inNewX, float *inNewY)
+{
+ IFniiffff cb = (IFniiffff)IupGetCallback(_ih, "EDIT_CB");
+ if (cb)
+ {
+ if (inIndex == -1)
+ {
+ Icallback cbb = IupGetCallback(_ih, "EDITBEGIN_CB");
+ if (cbb && cbb(_ih) == IUP_IGNORE)
+ return false;
+ }
+ else if (inIndex == -2)
+ {
+ Icallback cbb = IupGetCallback(_ih, "EDITEND_CB");
+ if (cbb)
+ cbb(_ih);
+ }
+ else
+ {
+ int ret = cb(_ih, inIndex, inSampleIndex, inX, inY, inNewX, inNewY);
+ if (ret == IUP_IGNORE)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+InteractionContainerIup::InteractionContainerIup(PPlot &inPPlot, Ihandle* inHandle):
+ mZoomInteraction (inPPlot),
+ mSelectionInteraction (inPPlot, inHandle),
+ mEditInteraction (inPPlot, inHandle),
+ mDeleteInteraction (inPPlot, inHandle),
+ mCrosshairInteraction (inPPlot),
+ mPostPainterCallback(inPPlot, inHandle),
+ mPrePainterCallback(inPPlot, inHandle)
+{
+ AddInteraction (mZoomInteraction);
+ AddInteraction (mSelectionInteraction);
+ AddInteraction (mEditInteraction);
+ AddInteraction (mDeleteInteraction);
+ AddInteraction (mCrosshairInteraction);
+}
+
+PPainterIup::PPainterIup(Ihandle *ih) :
+ Painter(),
+ _ih(ih),
+ _cdcanvas(NULL),
+ _cddbuffer(NULL),
+ _mouseDown(0),
+ _currentDataSetIndex(-1),
+ _redraw(1)
+{
+ _plot.mShowLegend = false; // change default to hidden
+ _plot.mPlotBackground.mTransparent = false; // always draw the background
+ _plot.mMargins.mLeft = 15;
+ _plot.mMargins.mBottom = 15;
+ _plot.mMargins.mTop = 30;
+ _plot.mMargins.mRight = 15;
+ _plot.mXAxisSetup.mTickInfo.mTickDivision = 5;
+ _plot.mYAxisSetup.mTickInfo.mTickDivision = 5;
+ _plot.mXAxisSetup.mTickInfo.mMinorTickScreenSize = 5;
+ _plot.mYAxisSetup.mTickInfo.mMinorTickScreenSize = 5;
+ _plot.mXAxisSetup.mTickInfo.mMajorTickScreenSize = 8;
+ _plot.mYAxisSetup.mTickInfo.mMajorTickScreenSize = 8;
+
+ _InteractionContainer = new InteractionContainerIup(_plot, _ih);
+
+} /* c-tor */
+
+
+PPainterIup::~PPainterIup()
+{
+ if (_cddbuffer != NULL)
+ cdKillCanvas(_cddbuffer);
+
+ delete _InteractionContainer;
+} /* d-tor */
+
+class MarkDataDrawer: public LineDataDrawer
+{
+ public:
+ MarkDataDrawer (bool inDrawLine)
+ {
+ mDrawLine = inDrawLine;
+ mDrawPoint = true;
+ mMode = inDrawLine ? "MARKLINE" : "MARK";
+ };
+ virtual bool DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const;
+};
+
+bool MarkDataDrawer::DrawPoint (int inScreenX, int inScreenY, const PRect &inRect, Painter &inPainter) const
+{
+ PPainterIup* painter = (PPainterIup*)&inPainter;
+ cdCanvasMark(painter->_cddbuffer, inScreenX, cdCanvasInvertYAxis(painter->_cddbuffer, inScreenY));
+
+ return true;
+}
+
+static void RemoveSample(PPlot& inPPlot, int inIndex, int inSampleIndex)
+{
+ PlotDataBase* theXDataBase = inPPlot.mPlotDataContainer.GetXData(inIndex);
+ PlotDataBase* theYDataBase = inPPlot.mPlotDataContainer.GetYData(inIndex);
+
+ if (theXDataBase->IsString())
+ {
+ StringPlotData *theXData = (StringPlotData *)theXDataBase;
+ PlotData* theYData = (PlotData*)theYDataBase;
+ theXData->mRealPlotData.erase(theXData->mRealPlotData.begin()+inSampleIndex);
+ theXData->mStringPlotData.erase(theXData->mStringPlotData.begin()+inSampleIndex);
+ theYData->erase(theYData->begin()+inSampleIndex);
+ }
+ else
+ {
+ PlotData* theXData = (PlotData*)theXDataBase;
+ PlotData* theYData = (PlotData*)theYDataBase;
+ theXData->erase(theXData->begin()+inSampleIndex);
+ theYData->erase(theYData->begin()+inSampleIndex);
+ }
+}
+
+/* --------------------------------------------------------------------
+ CD Gets - size and style
+ -------------------------------------------------------------------- */
+
+static int iPPlotGetCDFontStyle(const char* value)
+{
+ if (!value)
+ return -1;
+ if (iupStrEqualNoCase(value, "PLAIN"))
+ return CD_PLAIN;
+ if (iupStrEqualNoCase(value, "BOLD"))
+ return CD_BOLD;
+ if (iupStrEqualNoCase(value, "ITALIC"))
+ return CD_ITALIC;
+ if (iupStrEqualNoCase(value, "BOLDITALIC"))
+ return CD_BOLD_ITALIC;
+ return -1;
+}
+
+static char* iPPlotGetPlotFontSize(int size)
+{
+ if (size)
+ {
+ char* buffer = iupStrGetMemory(50);
+ sprintf(buffer, "%d", size);
+ return buffer;
+ }
+ else
+ return NULL;
+}
+
+static char* iPPlotGetPlotFontStyle(int style)
+{
+ if (style >= CD_PLAIN && style <= CD_BOLD_ITALIC)
+ {
+ char* style_str[4] = {"PLAIN", "BOLD", "ITALIC", "BOLDITALIC"};
+ return style_str[style];
+ }
+ else
+ return NULL;
+}
+
+static char* iPPlotGetPlotPenStyle(int style)
+{
+ if (style >= CD_CONTINUOUS && style <= CD_DASH_DOT_DOT)
+ {
+ char* style_str[5] = {"CONTINUOUS", "DASHED", "DOTTED", "DASH_DOT", "DASH_DOT_DOT"};
+ return style_str[style];
+ }
+ else
+ return NULL;
+}
+
+static int iPPlotGetCDPenStyle(const char* value)
+{
+ if (!value || iupStrEqualNoCase(value, "CONTINUOUS"))
+ return CD_CONTINUOUS;
+ else if (iupStrEqualNoCase(value, "DASHED"))
+ return CD_DASHED;
+ else if (iupStrEqualNoCase(value, "DOTTED"))
+ return CD_DOTTED;
+ else if (iupStrEqualNoCase(value, "DASH_DOT"))
+ return CD_DASH_DOT;
+ else if (iupStrEqualNoCase(value, "DASH_DOT_DOT"))
+ return CD_DASH_DOT_DOT;
+ else
+ return CD_CONTINUOUS;
+}
+
+static char* iPPlotGetPlotMarkStyle(int style)
+{
+ if (style >= CD_PLUS && style <= CD_HOLLOW_DIAMOND)
+ {
+ char* style_str[9] = {"PLUS", "STAR", "CIRCLE", "X", "BOX", "DIAMOND", "HOLLOW_CIRCLE", "HOLLOW_BOX", "HOLLOW_DIAMOND"};
+ return style_str[style];
+ }
+ else
+ return NULL;
+}
+
+static int iPPlotGetCDMarkStyle(const char* value)
+{
+ if (!value || iupStrEqualNoCase(value, "PLUS"))
+ return CD_PLUS;
+ else if (iupStrEqualNoCase(value, "STAR"))
+ return CD_STAR;
+ else if (iupStrEqualNoCase(value, "CIRCLE"))
+ return CD_CIRCLE;
+ else if (iupStrEqualNoCase(value, "X"))
+ return CD_X;
+ else if (iupStrEqualNoCase(value, "BOX"))
+ return CD_BOX;
+ else if (iupStrEqualNoCase(value, "DIAMOND"))
+ return CD_DIAMOND;
+ else if (iupStrEqualNoCase(value, "HOLLOW_CIRCLE"))
+ return CD_HOLLOW_CIRCLE;
+ else if (iupStrEqualNoCase(value, "HOLLOW_BOX"))
+ return CD_HOLLOW_BOX;
+ else if (iupStrEqualNoCase(value, "HOLLOW_DIAMOND"))
+ return CD_HOLLOW_DIAMOND;
+ else
+ return CD_PLUS;
+}
+
+/*****************************************************************************/
+/***** SET AND GET ATTRIBUTES ************************************************/
+/*****************************************************************************/
+
+/* refresh plot window (write only) */
+static int iPPlotSetRedrawAttrib(Ihandle* ih, const char* value)
+{
+ (void)value; /* not used */
+ ih->data->plt->Draw(1); /* force a full redraw here */
+ return 0;
+}
+
+/* total number of datasets (read only) */
+static char* iPPlotGetCountAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_plot.mPlotDataContainer.GetPlotCount());
+ return att_buffer;
+}
+
+/* legend box visibility */
+static int iPPlotSetLegendShowAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ ih->data->plt->_plot.mShowLegend = true;
+ else
+ ih->data->plt->_plot.mShowLegend = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetLegendShowAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_plot.mShowLegend)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* legend box visibility */
+static int iPPlotSetLegendPosAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "TOPLEFT"))
+ ih->data->plt->_plot.mLegendPos = PPLOT_TOPLEFT;
+ if (iupStrEqualNoCase(value, "BOTTOMLEFT"))
+ ih->data->plt->_plot.mLegendPos = PPLOT_BOTTOMLEFT;
+ if (iupStrEqualNoCase(value, "BOTTOMRIGHT"))
+ ih->data->plt->_plot.mLegendPos = PPLOT_BOTTOMRIGHT;
+ else
+ ih->data->plt->_plot.mLegendPos = PPLOT_TOPRIGHT;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetLegendPosAttrib(Ihandle* ih)
+{
+ char* legendpos_str[4] = {"TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"};
+
+ return legendpos_str[ih->data->plt->_plot.mLegendPos];
+}
+
+/* background color */
+static int iPPlotSetBGColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ ih->data->plt->_plot.mPlotBackground.mPlotRegionBackColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetBGColorAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d",
+ ih->data->plt->_plot.mPlotBackground.mPlotRegionBackColor.mR,
+ ih->data->plt->_plot.mPlotBackground.mPlotRegionBackColor.mG,
+ ih->data->plt->_plot.mPlotBackground.mPlotRegionBackColor.mB);
+ return att_buffer;
+}
+
+
+/* title color */
+static int iPPlotSetFGColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ ih->data->plt->_plot.mPlotBackground.mTitleColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetFGColorAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d",
+ ih->data->plt->_plot.mPlotBackground.mTitleColor.mR,
+ ih->data->plt->_plot.mPlotBackground.mTitleColor.mG,
+ ih->data->plt->_plot.mPlotBackground.mTitleColor.mB);
+ return att_buffer;
+}
+
+
+/* plot title */
+static int iPPlotSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (value && value[0] != 0)
+ ih->data->plt->_plot.mPlotBackground.mTitle = value;
+ else
+ ih->data->plt->_plot.mPlotBackground.mTitle.resize(0);
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetTitleAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, ih->data->plt->_plot.mPlotBackground.mTitle.c_str(), 256);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+
+/* plot title font size */
+static int iPPlotSetTitleFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mPlotBackground.mStyle.mFontSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetTitleFontSizeAttrib(Ihandle* ih)
+{
+ return iPPlotGetPlotFontSize(ih->data->plt->_plot.mPlotBackground.mStyle.mFontSize);
+}
+
+
+/* plot title font style */
+static int iPPlotSetTitleFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int style = iPPlotGetCDFontStyle(value);
+ if (style != -1)
+ {
+ ih->data->plt->_plot.mPlotBackground.mStyle.mFontStyle = style;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+/* legend font size */
+static int iPPlotSetLegendFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii, xx;
+ if (!iupStrToInt(value, &xx))
+ return 0;
+
+ for (ii = 0; ii < ih->data->plt->_plot.mPlotDataContainer.GetPlotCount(); ii++)
+ {
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ii);
+ legend->mStyle.mFontSize = xx;
+ }
+
+ ih->data->plt->_redraw = 1;
+ return 1;
+}
+
+/* legend font style */
+static int iPPlotSetLegendFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ int style = iPPlotGetCDFontStyle(value);
+ if (style == -1)
+ return 0;
+
+ for (ii = 0; ii < ih->data->plt->_plot.mPlotDataContainer.GetPlotCount(); ii++)
+ {
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ii);
+ legend->mStyle.mFontStyle = style;
+ }
+
+ ih->data->plt->_redraw = 1;
+ return 1;
+}
+
+/* plot margins */
+static int iPPlotSetMarginLeftAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mMargins.mLeft = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetMarginRightAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mMargins.mRight = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetMarginTopAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mMargins.mTop = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetMarginBottomAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mMargins.mBottom = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetMarginLeftAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_plot.mMargins.mLeft);
+ return att_buffer;
+}
+
+static char* iPPlotGetMarginRightAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_plot.mMargins.mRight);
+ return att_buffer;
+}
+
+static char* iPPlotGetMarginTopAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_plot.mMargins.mTop);
+ return att_buffer;
+}
+
+static char* iPPlotGetMarginBottomAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_plot.mMargins.mBottom);
+ return att_buffer;
+}
+
+/* plot grid color */
+static int iPPlotSetGridColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ ih->data->plt->_plot.mGridInfo.mGridColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetGridColorAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d",
+ ih->data->plt->_plot.mGridInfo.mGridColor.mR,
+ ih->data->plt->_plot.mGridInfo.mGridColor.mG,
+ ih->data->plt->_plot.mGridInfo.mGridColor.mB);
+ return att_buffer;
+}
+
+/* plot grid line style */
+static int iPPlotSetGridLineStyleAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->plt->_plot.mGridInfo.mStyle.mPenStyle = iPPlotGetCDPenStyle(value);
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetGridLineStyleAttrib(Ihandle* ih)
+{
+ return iPPlotGetPlotPenStyle(ih->data->plt->_plot.mGridInfo.mStyle.mPenStyle);
+}
+
+/* grid */
+static int iPPlotSetGridAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrEqualNoCase(value, "VERTICAL")) /* vertical grid - X axis */
+ {
+ ih->data->plt->_plot.mGridInfo.mXGridOn = true;
+ ih->data->plt->_plot.mGridInfo.mYGridOn = false;
+ }
+ else if (iupStrEqualNoCase(value, "HORIZONTAL")) /* horizontal grid - Y axis */
+ {
+ ih->data->plt->_plot.mGridInfo.mYGridOn = true;
+ ih->data->plt->_plot.mGridInfo.mXGridOn = false;
+ }
+ else if (iupStrEqualNoCase(value, "YES"))
+ {
+ ih->data->plt->_plot.mGridInfo.mXGridOn = true;
+ ih->data->plt->_plot.mGridInfo.mYGridOn = true;
+ }
+ else
+ {
+ ih->data->plt->_plot.mGridInfo.mYGridOn = false;
+ ih->data->plt->_plot.mGridInfo.mXGridOn = false;
+ }
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetGridAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_plot.mGridInfo.mXGridOn && ih->data->plt->_plot.mGridInfo.mYGridOn)
+ return "YES";
+ else if (ih->data->plt->_plot.mGridInfo.mYGridOn)
+ return "HORIZONTAL";
+ else if (ih->data->plt->_plot.mGridInfo.mXGridOn)
+ return "VERTICAL";
+ else
+ return "NO";
+}
+
+/* current dataset index */
+static int iPPlotSetCurrentAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ int imax = ih->data->plt->_plot.mPlotDataContainer.GetPlotCount();
+ ih->data->plt->_currentDataSetIndex = ( (ii>=0) && (ii<imax) ? ii : -1);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetCurrentAttrib(Ihandle* ih)
+{
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", ih->data->plt->_currentDataSetIndex);
+ return att_buffer;
+}
+
+/* remove a dataset */
+static int iPPlotSetRemoveAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ ih->data->plt->_plot.mPlotDataContainer.RemoveElement(ii);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+/* clear all datasets */
+static int iPPlotSetClearAttrib(Ihandle* ih, const char* value)
+{
+ ih->data->plt->_plot.mPlotDataContainer.ClearData();
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+/* =============================== */
+/* current plot dataset attributes */
+/* =============================== */
+
+/* current plot line style */
+static int iPPlotSetDSLineStyleAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ drawer->mStyle.mPenStyle = iPPlotGetCDPenStyle(value);
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSLineStyleAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+
+ return iPPlotGetPlotPenStyle(drawer->mStyle.mPenStyle);
+}
+
+/* current plot line width */
+static int iPPlotSetDSLineWidthAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ if (iupStrToInt(value, &ii))
+ {
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ drawer->mStyle.mPenWidth = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetDSLineWidthAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", drawer->mStyle.mPenWidth);
+ return att_buffer;
+}
+
+/* current plot mark style */
+static int iPPlotSetDSMarkStyleAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ drawer->mStyle.mMarkStyle = iPPlotGetCDMarkStyle(value);
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSMarkStyleAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+
+ return iPPlotGetPlotMarkStyle(drawer->mStyle.mMarkStyle);
+}
+
+/* current plot mark size */
+static int iPPlotSetDSMarkSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ if (iupStrToInt(value, &ii))
+ {
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ drawer->mStyle.mMarkSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetDSMarkSizeAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", drawer->mStyle.mMarkSize);
+ return att_buffer;
+}
+
+/* current dataset legend */
+static int iPPlotSetDSLegendAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ih->data->plt->_currentDataSetIndex);
+
+ if (value)
+ legend->mName = value;
+ else
+ legend->mName.resize(0);
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSLegendAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ih->data->plt->_currentDataSetIndex);
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, legend->mName.c_str(), 255);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+/* current dataset line and legend color */
+static int iPPlotSetDSColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ih->data->plt->_currentDataSetIndex);
+ legend->mColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetDSColorAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ LegendData* legend = ih->data->plt->_plot.mPlotDataContainer.GetLegendData(ih->data->plt->_currentDataSetIndex);
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d", legend->mColor.mR, legend->mColor.mG, legend->mColor.mB);
+ return att_buffer;
+}
+
+/* show values */
+static int iPPlotSetDSShowValuesAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+
+ if (iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ drawer->mShowValues = true;
+ else
+ drawer->mShowValues = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSShowValuesAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+ if (drawer->mShowValues)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* current dataset drawing mode */
+static int iPPlotSetDSModeAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ DataDrawerBase *theDataDrawer = NULL;
+ ih->data->plt->_plot.mXAxisSetup.mDiscrete = false;
+
+ if(iupStrEqualNoCase(value, "BAR"))
+ {
+ theDataDrawer = new BarDataDrawer();
+ ih->data->plt->_plot.mXAxisSetup.mDiscrete = true;
+ }
+ else if(iupStrEqualNoCase(value, "MARK"))
+ theDataDrawer = new MarkDataDrawer(0);
+ else if(iupStrEqualNoCase(value, "MARKLINE"))
+ theDataDrawer = new MarkDataDrawer(1);
+ else /* LINE */
+ theDataDrawer = new LineDataDrawer();
+
+ ih->data->plt->_plot.mPlotDataContainer.SetDataDrawer(ih->data->plt->_currentDataSetIndex, theDataDrawer);
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSModeAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ DataDrawerBase* drawer = ih->data->plt->_plot.mPlotDataContainer.GetDataDrawer(ih->data->plt->_currentDataSetIndex);
+
+ return (char*)drawer->mMode;
+}
+
+/* allows selection and editing */
+static int iPPlotSetDSEditAttrib(Ihandle* ih, const char* value)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ PlotDataSelection* dataselect = ih->data->plt->_plot.mPlotDataContainer.GetPlotDataSelection(ih->data->plt->_currentDataSetIndex);
+
+ if (iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ dataselect->resize(ih->data->plt->_plot.mPlotDataContainer.GetConstYData(ih->data->plt->_currentDataSetIndex)->GetSize());
+ else
+ dataselect->clear();
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetDSEditAttrib(Ihandle* ih)
+{
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return NULL;
+
+ PlotDataSelection* dataselect = ih->data->plt->_plot.mPlotDataContainer.GetPlotDataSelection(ih->data->plt->_currentDataSetIndex);
+ if (dataselect->empty())
+ return "NO";
+ else
+ return "YES";
+}
+
+/* remove a sample */
+static int iPPlotSetDSRemoveAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+
+ if (ih->data->plt->_currentDataSetIndex < 0 ||
+ ih->data->plt->_currentDataSetIndex >= ih->data->plt->_plot.mPlotDataContainer.GetPlotCount())
+ return 0;
+
+ if (iupStrToInt(value, &ii))
+ {
+ RemoveSample(ih->data->plt->_plot, ih->data->plt->_currentDataSetIndex, ii);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+/* ========== */
+/* axis props */
+/* ========== */
+
+/* ========== */
+/* axis props */
+/* ========== */
+
+/* axis title */
+static int iPPlotSetAXSXLabelAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (value)
+ axis->mLabel = value;
+ else
+ axis->mLabel = "";
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYLabelAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (value)
+ axis->mLabel = value;
+ else
+ axis->mLabel = "";
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXLabelAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, axis->mLabel.c_str(), 255);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYLabelAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, axis->mLabel.c_str(), 255);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+/* axis title position */
+static int iPPlotSetAXSXLabelCenteredAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mLabelCentered = true;
+ else
+ axis->mLabelCentered = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYLabelCenteredAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mLabelCentered = true;
+ else
+ axis->mLabelCentered = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXLabelCenteredAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mLabelCentered)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYLabelCenteredAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mLabelCentered)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* axis, ticks and label color */
+static int iPPlotSetAXSXColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYColorAttrib(Ihandle* ih, const char* value)
+{
+ unsigned char rr, gg, bb;
+ if (iupStrToRGB(value, &rr, &gg, &bb))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mColor = PColor(rr, gg, bb);
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXColorAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d",
+ axis->mColor.mR,
+ axis->mColor.mG,
+ axis->mColor.mB);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYColorAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d %d %d",
+ axis->mColor.mR,
+ axis->mColor.mG,
+ axis->mColor.mB);
+ return att_buffer;
+}
+
+/* autoscaling */
+static int iPPlotSetAXSXAutoMinAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAutoScaleMin = true;
+ else
+ axis->mAutoScaleMin = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYAutoMinAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAutoScaleMin = true;
+ else
+ axis->mAutoScaleMin = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXAutoMinAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mAutoScaleMin)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYAutoMinAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mAutoScaleMin)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* autoscaling */
+static int iPPlotSetAXSXAutoMaxAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAutoScaleMax = true;
+ else
+ axis->mAutoScaleMax = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYAutoMaxAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAutoScaleMax = true;
+ else
+ axis->mAutoScaleMax = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXAutoMaxAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mAutoScaleMax)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYAutoMaxAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mAutoScaleMax)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* min visible val */
+static int iPPlotSetAXSXMinAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mMin = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYMinAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mMin = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXMinAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mMin);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYMinAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mMin);
+ return att_buffer;
+}
+
+/* max visible val */
+static int iPPlotSetAXSXMaxAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mMax = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYMaxAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mMax = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXMaxAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mMax);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYMaxAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mMax);
+ return att_buffer;
+}
+
+/* values from left/top to right/bottom */
+static int iPPlotSetAXSXReverseAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAscending = false; // inverted
+ else
+ axis->mAscending = true;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYReverseAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mAscending = false; // inverted
+ else
+ axis->mAscending = true;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXReverseAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mAscending)
+ return "NO"; /* inverted */
+ else
+ return "YES";
+}
+
+static char* iPPlotGetAXSYReverseAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mAscending)
+ return "NO"; /* inverted */
+ else
+ return "YES";
+}
+
+/* axis mode */
+static int iPPlotSetAXSXCrossOriginAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mCrossOrigin = true;
+ else
+ axis->mCrossOrigin = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYCrossOriginAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mCrossOrigin = true;
+ else
+ axis->mCrossOrigin = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXCrossOriginAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mCrossOrigin)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYCrossOriginAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mCrossOrigin)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* log/lin scale */
+static int iPPlotSetAXSXScaleAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "LIN"))
+ {
+ axis->mLogScale = false;
+ }
+ else if(iupStrEqualNoCase(value, "LOG10"))
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = 10.0;
+ }
+ else if(iupStrEqualNoCase(value, "LOG2"))
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = 2.0;
+ }
+ else
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = (float)M_E;
+ }
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYScaleAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "LIN"))
+ {
+ axis->mLogScale = false;
+ }
+ else if(iupStrEqualNoCase(value, "LOG10"))
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = 10.0;
+ }
+ else if(iupStrEqualNoCase(value, "LOG2"))
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = 2.0;
+ }
+ else
+ {
+ axis->mLogScale = true;
+ axis->mLogBase = (float)M_E;
+ }
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXScaleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+
+ if (axis->mLogScale)
+ {
+ if (axis->mLogBase == 10.0)
+ strcpy(att_buffer, "LOG10");
+ else if (axis->mLogBase == 2.0)
+ strcpy(att_buffer, "LOG2");
+ else
+ strcpy(att_buffer, "LOGN");
+ }
+ else
+ strcpy(att_buffer, "LIN");
+
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYScaleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+
+ if (axis->mLogScale)
+ {
+ if (axis->mLogBase == 10.0)
+ strcpy(att_buffer, "LOG10");
+ else if (axis->mLogBase == 2.0)
+ strcpy(att_buffer, "LOG2");
+ else
+ strcpy(att_buffer, "LOGN");
+ }
+ else
+ strcpy(att_buffer, "LIN");
+
+ return att_buffer;
+}
+
+/* axis label font size */
+static int iPPlotSetAXSXFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mStyle.mFontSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mStyle.mFontSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXFontSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ return iPPlotGetPlotFontSize(axis->mStyle.mFontSize);
+}
+
+static char* iPPlotGetAXSYFontSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ return iPPlotGetPlotFontSize(axis->mStyle.mFontSize);
+}
+
+/* axis label font style */
+static int iPPlotSetAXSXFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int style = iPPlotGetCDFontStyle(value);
+ if (style != -1)
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mStyle.mFontStyle = style;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int style = iPPlotGetCDFontStyle(value);
+ if (style != -1)
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mStyle.mFontStyle = style;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXFontStyleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ return iPPlotGetPlotFontStyle(axis->mStyle.mFontStyle);
+}
+
+static char* iPPlotGetAXSYFontStyleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ return iPPlotGetPlotFontStyle(axis->mStyle.mFontStyle);
+}
+
+/* automatic tick size */
+static int iPPlotSetAXSXAutoTickSizeAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mAutoTickSize = true;
+ else
+ axis->mTickInfo.mAutoTickSize = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYAutoTickSizeAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mAutoTickSize = true;
+ else
+ axis->mTickInfo.mAutoTickSize = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXAutoTickSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mTickInfo.mAutoTickSize)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYAutoTickSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mTickInfo.mAutoTickSize)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* size of ticks (in pixels) */
+static int iPPlotSetAXSXTickSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mMinorTickScreenSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mMinorTickScreenSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mMinorTickScreenSize);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYTickSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mMinorTickScreenSize);
+ return att_buffer;
+}
+
+/* size of major ticks (in pixels) */
+static int iPPlotSetAXSXTickMajorSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mMajorTickScreenSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickMajorSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mMajorTickScreenSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickMajorSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mMajorTickScreenSize);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYTickMajorSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mMajorTickScreenSize);
+ return att_buffer;
+}
+
+/* axis ticks font size */
+static int iPPlotSetAXSXTickFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mStyle.mFontSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickFontSizeAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mStyle.mFontSize = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickFontSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ return iPPlotGetPlotFontSize(axis->mTickInfo.mStyle.mFontSize);
+}
+
+static char* iPPlotGetAXSYTickFontSizeAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ return iPPlotGetPlotFontSize(axis->mTickInfo.mStyle.mFontSize);
+}
+
+/* axis ticks number font style */
+static int iPPlotSetAXSXTickFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int style = iPPlotGetCDFontStyle(value);
+ if (style != -1)
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mStyle.mFontStyle = style;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickFontStyleAttrib(Ihandle* ih, const char* value)
+{
+ int style = iPPlotGetCDFontStyle(value);
+ if (style != -1)
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mStyle.mFontStyle = style;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickFontStyleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ return iPPlotGetPlotFontSize(axis->mTickInfo.mStyle.mFontStyle);
+}
+
+static char* iPPlotGetAXSYTickFontStyleAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ return iPPlotGetPlotFontSize(axis->mTickInfo.mStyle.mFontStyle);
+}
+
+/* axis ticks number format */
+static int iPPlotSetAXSXTickFormatAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (value && value[0]!=0)
+ axis->mTickInfo.mFormatString = value;
+ else
+ axis->mTickInfo.mFormatString = "%.0f";
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYTickFormatAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (value && value[0]!=0)
+ axis->mTickInfo.mFormatString = value;
+ else
+ axis->mTickInfo.mFormatString = "%.0f";
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickFormatAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, axis->mTickInfo.mFormatString.c_str(), 255);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYTickFormatAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(256);
+ strncpy(att_buffer, axis->mTickInfo.mFormatString.c_str(), 255);
+ att_buffer[255]='\0';
+ return att_buffer;
+}
+
+/* axis ticks */
+static int iPPlotSetAXSXTickAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mTicksOn = true;
+ else
+ axis->mTickInfo.mTicksOn = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYTickAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mTicksOn = true;
+ else
+ axis->mTickInfo.mTicksOn = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mTickInfo.mTicksOn)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYTickAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mTickInfo.mTicksOn)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* major tick spacing */
+static int iPPlotSetAXSXTickMajorSpanAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mMajorTickSpan = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickMajorSpanAttrib(Ihandle* ih, const char* value)
+{
+ float xx;
+ if (iupStrToFloat(value, &xx))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mMajorTickSpan = xx;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickMajorSpanAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mTickInfo.mMajorTickSpan);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYTickMajorSpanAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%g", axis->mTickInfo.mMajorTickSpan);
+ return att_buffer;
+}
+
+/* number of ticks between major ticks */
+static int iPPlotSetAXSXTickDivisionAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ axis->mTickInfo.mTickDivision = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static int iPPlotSetAXSYTickDivisionAttrib(Ihandle* ih, const char* value)
+{
+ int ii;
+ if (iupStrToInt(value, &ii))
+ {
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ axis->mTickInfo.mTickDivision = ii;
+ ih->data->plt->_redraw = 1;
+ }
+ return 0;
+}
+
+static char* iPPlotGetAXSXTickDivisionAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mTickDivision);
+ return att_buffer;
+}
+
+static char* iPPlotGetAXSYTickDivisionAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+ char* att_buffer = iupStrGetMemory(30);
+ sprintf(att_buffer, "%d", axis->mTickInfo.mTickDivision);
+ return att_buffer;
+}
+
+/* auto tick spacing */
+static int iPPlotSetAXSXAutoTickAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mAutoTick = true;
+ else
+ axis->mTickInfo.mAutoTick = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static int iPPlotSetAXSYAutoTickAttrib(Ihandle* ih, const char* value)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if(iupStrEqualNoCase(value, "YES") || iupStrEqualNoCase(value, "ON"))
+ axis->mTickInfo.mAutoTick = true;
+ else
+ axis->mTickInfo.mAutoTick = false;
+
+ ih->data->plt->_redraw = 1;
+ return 0;
+}
+
+static char* iPPlotGetAXSXAutoTickAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mXAxisSetup;
+
+ if (axis->mTickInfo.mAutoTick)
+ return "YES";
+ else
+ return "NO";
+}
+
+static char* iPPlotGetAXSYAutoTickAttrib(Ihandle* ih)
+{
+ AxisSetup* axis = &ih->data->plt->_plot.mYAxisSetup;
+
+ if (axis->mTickInfo.mAutoTick)
+ return "YES";
+ else
+ return "NO";
+}
+
+/* MouseButton */
+void PPainterIup::MouseButton(int btn, int stat, int x, int y, char *r)
+{
+ PMouseEvent theEvent;
+ int theModifierKeys = 0;
+
+ theEvent.mX = x;
+ theEvent.mY = y;
+
+ if(btn == IUP_BUTTON1)
+ {
+ theEvent.mType = ( stat!=0 ? (PMouseEvent::kDown) : (PMouseEvent::kUp) );
+ _mouseDown = ( stat!=0 ? 1 : 0 );
+ }
+ else return;
+
+ _mouse_ALT = 0;
+ _mouse_SHIFT = 0;
+ _mouse_CTRL = 0;
+
+ if (iup_isalt(r)) /* signal Alt */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kAlt);
+ _mouse_ALT = 1;
+ }
+ if (iup_iscontrol(r)) /* signal Ctrl */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kControl);
+ _mouse_SHIFT = 1;
+ }
+ if (iup_isshift(r)) /* signal Shift */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kShift);
+ _mouse_CTRL = 1;
+ }
+ theEvent.SetModifierKeys (theModifierKeys);
+
+ if( _InteractionContainer->HandleMouseEvent(theEvent))
+ {
+ this->Draw(1);
+ }
+ else
+ {
+ /* ignore the event */
+ }
+}
+
+/* MouseMove */
+void PPainterIup::MouseMove(int x, int y)
+{
+ PMouseEvent theEvent;
+ int theModifierKeys = 0;
+
+ if(!_mouseDown ) return;
+
+ theEvent.mX = x;
+ theEvent.mY = y;
+
+ theEvent.mType = PMouseEvent::kMove;
+ if(_mouse_ALT) /* signal Alt */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kAlt);
+ }
+ if(_mouse_SHIFT) /* signal Shift */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kControl);
+ }
+ if(_mouse_CTRL) /* signal Ctrl */
+ {
+ theModifierKeys = (theModifierKeys | PMouseEvent::kShift);
+ }
+ theEvent.SetModifierKeys (theModifierKeys);
+
+ if(_InteractionContainer->HandleMouseEvent(theEvent))
+ {
+ this->Draw(1);
+ }
+ else
+ {
+ /* ignore the event */
+ }
+}
+
+/* KeyPress */
+void PPainterIup::KeyPress(int c, int press)
+{
+ int theModifierKeys = 0;
+ int theRepeatCount = 0;
+ PKeyEvent::EKey theKeyCode = PKeyEvent::kNone;
+ char theChar = 0;
+
+ if(!press) return;
+
+ switch(c)
+ {
+ case K_cX: /* CTRL + X */
+ theModifierKeys = PMouseEvent::kControl;
+ theKeyCode = PKeyEvent::kChar;
+ theChar = 'x';
+ break;
+ case K_cY: /* CTRL + Y */
+ theModifierKeys = PMouseEvent::kControl;
+ theKeyCode = PKeyEvent::kChar;
+ theChar = 'y';
+ break;
+ case K_cR: /* CTRL + R */
+ theModifierKeys = PMouseEvent::kControl;
+ theKeyCode = PKeyEvent::kChar;
+ theChar = 'r';
+ break;
+ case K_cUP: /* CTRL + Arrow */
+ theModifierKeys = PMouseEvent::kControl;
+ case K_UP: /* Arrow */
+ theKeyCode = PKeyEvent::kArrowUp;
+ break;
+ case K_cDOWN: /* CTRL + Arrow */
+ theModifierKeys = PMouseEvent::kControl;
+ case K_DOWN: /* Arrow */
+ theKeyCode = PKeyEvent::kArrowDown;
+ break;
+ case K_cLEFT: /* CTRL + Arrow */
+ theModifierKeys = PMouseEvent::kControl;
+ case K_LEFT: /* Arrow */
+ theKeyCode = PKeyEvent::kArrowLeft;
+ break;
+ case K_cRIGHT: /* CTRL + Arrow */
+ theModifierKeys = PMouseEvent::kControl;
+ case K_RIGHT: /* Arrow */
+ theKeyCode = PKeyEvent::kArrowRight;
+ break;
+ case K_cDEL: /* CTRL + Arrow */
+ theModifierKeys = PMouseEvent::kControl;
+ case K_DEL: /* Arrow */
+ theKeyCode = PKeyEvent::kDelete;
+ break;
+ }
+
+ PKeyEvent theEvent (theKeyCode, theRepeatCount, theModifierKeys, theChar);
+
+ if(_InteractionContainer->HandleKeyEvent(theEvent))
+ {
+ this->Draw(1);
+ }
+ else
+ {
+ /* ignore the event */
+ }
+}
+
+/* Draw */
+void PPainterIup::Draw(int force)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasActivate(_cddbuffer);
+
+ if (force || _redraw)
+ {
+ cdCanvasClear(_cddbuffer);
+ _plot.Draw(*this);
+ _redraw = 0;
+ }
+
+ cdCanvasFlush(_cddbuffer);
+}
+
+/* Resize */
+void PPainterIup::Resize()
+{
+ if (!_cddbuffer)
+ {
+ /* update canvas size */
+ cdCanvasActivate(_cdcanvas);
+
+ /* this can fail if canvas size is zero */
+ if (IupGetInt(_ih, "USE_IMAGERGB"))
+ _cddbuffer = cdCreateCanvas(CD_DBUFFERRGB, _cdcanvas);
+ else
+ _cddbuffer = cdCreateCanvas(CD_DBUFFER, _cdcanvas);
+ }
+
+ if (!_cddbuffer)
+ return;
+
+ /* update canvas size */
+ cdCanvasActivate(_cddbuffer);
+
+ _redraw = 1;
+
+ return;
+}
+
+/* send plot to some other device */
+void PPainterIup::DrawTo(cdCanvas *usrCnv)
+{
+ cdCanvas *old_cddbuffer = _cddbuffer;
+ cdCanvas *old_cdcanvas = _cdcanvas;
+
+ _cdcanvas = _cddbuffer = usrCnv;
+
+ if(!_cddbuffer)
+ return;
+
+ Draw(1);
+
+ _cddbuffer = old_cddbuffer;
+ _cdcanvas = old_cdcanvas;
+}
+
+void PPainterIup::FillArrow(int inX1, int inY1, int inX2, int inY2, int inX3, int inY3)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasBegin(_cddbuffer, CD_FILL);
+ cdCanvasVertex(_cddbuffer, inX1, cdCanvasInvertYAxis(_cddbuffer, inY1));
+ cdCanvasVertex(_cddbuffer, inX2, cdCanvasInvertYAxis(_cddbuffer, inY2));
+ cdCanvasVertex(_cddbuffer, inX3, cdCanvasInvertYAxis(_cddbuffer, inY3));
+ cdCanvasEnd(_cddbuffer);
+}
+
+/* DrawLine */
+void PPainterIup::DrawLine(float inX1, float inY1, float inX2, float inY2)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdfCanvasLine(_cddbuffer, inX1, cdfCanvasInvertYAxis(_cddbuffer, inY1),
+ inX2, cdfCanvasInvertYAxis(_cddbuffer, inY2));
+}
+
+/* FillRect */
+void PPainterIup::FillRect(int inX, int inY, int inW, int inH)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasBox(_cddbuffer, inX, inX+inW,
+ cdCanvasInvertYAxis(_cddbuffer, inY),
+ cdCanvasInvertYAxis(_cddbuffer, inY + inH - 1));
+}
+
+/* InvertRect */
+void PPainterIup::InvertRect(int inX, int inY, int inW, int inH)
+{
+ long cprev;
+
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasWriteMode(_cddbuffer, CD_XOR);
+ cprev = cdCanvasForeground(_cddbuffer, CD_WHITE);
+ cdCanvasRect(_cddbuffer, inX, inX + inW - 1,
+ cdCanvasInvertYAxis(_cddbuffer, inY),
+ cdCanvasInvertYAxis(_cddbuffer, inY + inH - 1));
+ cdCanvasWriteMode(_cddbuffer, CD_REPLACE);
+ cdCanvasForeground(_cddbuffer, cprev);
+}
+
+/* SetClipRect */
+void PPainterIup::SetClipRect(int inX, int inY, int inW, int inH)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasClipArea(_cddbuffer, inX, inX + inW - 1,
+ cdCanvasInvertYAxis(_cddbuffer, inY),
+ cdCanvasInvertYAxis(_cddbuffer, inY + inH - 1));
+ cdCanvasClip(_cddbuffer, CD_CLIPAREA);
+}
+
+/* GetWidth */
+long PPainterIup::GetWidth() const
+{
+ int iret;
+
+ if (!_cddbuffer)
+ return IUP_DEFAULT;
+
+ cdCanvasGetSize(_cddbuffer, &iret, NULL, NULL, NULL);
+
+ return (long)iret;
+}
+
+/* GetHeight */
+long PPainterIup::GetHeight() const
+{
+ int iret;
+
+ if (!_cddbuffer)
+ return IUP_NOERROR;
+
+ cdCanvasGetSize(_cddbuffer, NULL, &iret, NULL, NULL);
+
+ return (long)iret;
+}
+
+/* SetLineColor */
+void PPainterIup::SetLineColor(int inR, int inG, int inB)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasForeground(_cddbuffer, cdEncodeColor((unsigned char)inR,
+ (unsigned char)inG,
+ (unsigned char)inB));
+}
+
+/* SetFillColor */
+void PPainterIup::SetFillColor(int inR, int inG, int inB)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasForeground(_cddbuffer, cdEncodeColor((unsigned char)inR,
+ (unsigned char)inG,
+ (unsigned char)inB));
+}
+
+/* CalculateTextDrawSize */
+long PPainterIup::CalculateTextDrawSize(const char *inString)
+{
+ int iw;
+
+ if (!_cddbuffer)
+ return IUP_NOERROR;
+
+ cdCanvasGetTextSize(_cddbuffer, const_cast<char *>(inString), &iw, NULL);
+
+ return iw;
+}
+
+/* GetFontHeight */
+long PPainterIup::GetFontHeight() const
+{
+ int ih;
+
+ if (!_cddbuffer)
+ return IUP_NOERROR;
+
+ cdCanvasGetFontDim(_cddbuffer, NULL, &ih, NULL, NULL);
+
+ return ih;
+}
+
+/* DrawText */
+/* this call leave all the hard job of alignment on painter side */
+void PPainterIup::DrawText(int inX, int inY, short align, const char *inString)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasTextAlignment(_cddbuffer, align);
+ cdCanvasText(_cddbuffer, inX, cdCanvasInvertYAxis(_cddbuffer, inY), const_cast<char *>(inString));
+}
+
+/* DrawRotatedText */
+void PPainterIup::DrawRotatedText(int inX, int inY, float inDegrees, short align, const char *inString)
+{
+ double aprev;
+
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasTextAlignment(_cddbuffer, align);
+ aprev = cdCanvasTextOrientation(_cddbuffer, -inDegrees);
+ cdCanvasText(_cddbuffer, inX, cdCanvasInvertYAxis(_cddbuffer, inY), const_cast<char *>(inString));
+ cdCanvasTextOrientation(_cddbuffer, aprev);
+}
+
+void PPainterIup::SetStyle(const PStyle &inStyle)
+{
+ if (!_cddbuffer)
+ return;
+
+ cdCanvasLineWidth(_cddbuffer, inStyle.mPenWidth);
+ cdCanvasLineStyle(_cddbuffer, inStyle.mPenStyle);
+
+ cdCanvasNativeFont(_cddbuffer, IupGetAttribute(_ih, "FONT"));
+
+ if (inStyle.mFontStyle != -1 || inStyle.mFontSize != 0)
+ cdCanvasFont(_cddbuffer, NULL, inStyle.mFontStyle, inStyle.mFontSize);
+
+ cdCanvasMarkType(_cddbuffer, inStyle.mMarkStyle);
+ cdCanvasMarkSize(_cddbuffer, inStyle.mMarkSize);
+}
+
+int iPPlotMapMethod(Ihandle* ih)
+{
+ int old_gdi = 0;
+
+ if (IupGetInt(ih, "USE_GDI+"))
+ old_gdi = cdUseContextPlus(1);
+
+ ih->data->plt->_cdcanvas = cdCreateCanvas(CD_IUP, ih);
+ if (!ih->data->plt->_cdcanvas)
+ return IUP_ERROR;
+
+ /* this can fail if canvas size is zero */
+ if (IupGetInt(ih, "USE_IMAGERGB"))
+ ih->data->plt->_cddbuffer = cdCreateCanvas(CD_DBUFFERRGB, ih->data->plt->_cdcanvas);
+ else
+ ih->data->plt->_cddbuffer = cdCreateCanvas(CD_DBUFFER, ih->data->plt->_cdcanvas);
+
+ if (IupGetInt(ih, "USE_GDI+"))
+ cdUseContextPlus(old_gdi);
+
+ ih->data->plt->_redraw = 1;
+
+ return IUP_NOERROR;
+}
+
+void iPPlotDestroyMethod(Ihandle* ih)
+{
+ delete ih->data->plt;
+}
+
+int iPPlotCreateMethod(Ihandle* ih, void **params)
+{
+ (void)params;
+
+ /* free the data alocated by IupCanvas */
+ if (ih->data) free(ih->data);
+ ih->data = iupALLOCCTRLDATA();
+
+ /* Initializing object with no cd canvases */
+ ih->data->plt = new PPainterIup(ih);
+
+ /* IupCanvas callbacks */
+ IupSetCallback(ih, "ACTION", (Icallback)iPPlotRedraw_CB);
+ IupSetCallback(ih, "RESIZE_CB", (Icallback)iPPlotResize_CB);
+ IupSetCallback(ih, "BUTTON_CB", (Icallback)iPPlotMouseButton_CB);
+ IupSetCallback(ih, "MOTION_CB", (Icallback)iPPlotMouseMove_CB);
+ IupSetCallback(ih, "KEYPRESS_CB", (Icallback)iPPlotKeyPress_CB);
+
+ return IUP_NOERROR;
+}
+
+static Iclass* iupPPlotGetClass(void)
+{
+ Iclass* ic = iupClassNew(iupCanvasGetClass());
+
+ ic->name = "pplot";
+ ic->format = NULL; /* none */
+ ic->nativetype = IUP_TYPECANVAS;
+ ic->childtype = IUP_CHILDNONE;
+ ic->is_interactive = 1;
+ ic->has_attrib_id = 1; /* has attributes with IDs that must be parsed */
+
+ /* Class functions */
+ ic->Create = iPPlotCreateMethod;
+ ic->Destroy = iPPlotDestroyMethod;
+ ic->Map = iPPlotMapMethod;
+
+ /* IupPPlot Callbacks */
+ iupClassRegisterCallback(ic, "POSTDRAW_CB", "v");
+ iupClassRegisterCallback(ic, "PREDRAW_CB", "v");
+ iupClassRegisterCallback(ic, "DELETE_CB", "iiff");
+ iupClassRegisterCallback(ic, "DELETEBEGIN_CB", "");
+ iupClassRegisterCallback(ic, "DELETEEND_CB", "");
+ iupClassRegisterCallback(ic, "SELECT_CB", "iiffi");
+ iupClassRegisterCallback(ic, "SELECTBEGIN_CB", "");
+ iupClassRegisterCallback(ic, "SELECTEND_CB", "");
+ iupClassRegisterCallback(ic, "EDIT_CB", "iiffvv");
+ iupClassRegisterCallback(ic, "EDITBEGIN_CB", "");
+ iupClassRegisterCallback(ic, "EDITEND_CB", "");
+
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", iPPlotGetBGColorAttrib, iPPlotSetBGColorAttrib, IUPAF_SAMEASSYSTEM, "255 255 255", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "FGCOLOR", iPPlotGetFGColorAttrib, iPPlotSetFGColorAttrib, IUPAF_SAMEASSYSTEM, "0 0 0", IUPAF_NOT_MAPPED);
+
+ /* IupPPlot only */
+
+ iupClassRegisterAttribute(ic, "REDRAW", NULL, iPPlotSetRedrawAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TITLE", iPPlotGetTitleAttrib, iPPlotSetTitleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TITLEFONTSIZE", iPPlotGetTitleFontSizeAttrib, iPPlotSetTitleFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "TITLEFONTSTYLE", NULL, iPPlotSetTitleFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LEGENDSHOW", iPPlotGetLegendShowAttrib, iPPlotSetLegendShowAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LEGENDPOS", iPPlotGetLegendPosAttrib, iPPlotSetLegendPosAttrib, IUPAF_SAMEASSYSTEM, "TOPRIGHT", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LEGENDFONTSIZE", NULL, iPPlotSetLegendFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "LEGENDFONTSTYLE", NULL, iPPlotSetLegendFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARGINLEFT", iPPlotGetMarginLeftAttrib, iPPlotSetMarginLeftAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARGINRIGHT", iPPlotGetMarginRightAttrib, iPPlotSetMarginRightAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARGINTOP", iPPlotGetMarginTopAttrib, iPPlotSetMarginTopAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARGINBOTTOM", iPPlotGetMarginBottomAttrib, iPPlotSetMarginBottomAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "GRIDLINESTYLE", iPPlotGetGridLineStyleAttrib, iPPlotSetGridLineStyleAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "GRIDCOLOR", iPPlotGetGridColorAttrib, iPPlotSetGridColorAttrib, IUPAF_SAMEASSYSTEM, "200 200 200", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "GRID", iPPlotGetGridAttrib, iPPlotSetGridAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "DS_LINESTYLE", iPPlotGetDSLineStyleAttrib, iPPlotSetDSLineStyleAttrib, IUPAF_SAMEASSYSTEM, "CONTINUOUS", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_LINEWIDTH", iPPlotGetDSLineWidthAttrib, iPPlotSetDSLineWidthAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_MARKSTYLE", iPPlotGetDSMarkStyleAttrib, iPPlotSetDSMarkStyleAttrib, IUPAF_SAMEASSYSTEM, "X", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_MARKSIZE", iPPlotGetDSMarkSizeAttrib, iPPlotSetDSMarkSizeAttrib, IUPAF_SAMEASSYSTEM, "7", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_LEGEND", iPPlotGetDSLegendAttrib, iPPlotSetDSLegendAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_COLOR", iPPlotGetDSColorAttrib, iPPlotSetDSColorAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_SHOWVALUES", iPPlotGetDSShowValuesAttrib, iPPlotSetDSShowValuesAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_MODE", iPPlotGetDSModeAttrib, iPPlotSetDSModeAttrib, IUPAF_SAMEASSYSTEM, "LINE", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_EDIT", iPPlotGetDSEditAttrib, iPPlotSetDSEditAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DS_REMOVE", NULL, iPPlotSetDSRemoveAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "AXS_XLABEL", iPPlotGetAXSXLabelAttrib, iPPlotSetAXSXLabelAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YLABEL", iPPlotGetAXSYLabelAttrib, iPPlotSetAXSYLabelAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XLABELCENTERED", iPPlotGetAXSXLabelCenteredAttrib, iPPlotSetAXSXLabelCenteredAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YLABELCENTERED", iPPlotGetAXSYLabelCenteredAttrib, iPPlotSetAXSYLabelCenteredAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XCOLOR", iPPlotGetAXSXColorAttrib, iPPlotSetAXSXColorAttrib, IUPAF_SAMEASSYSTEM, "0 0 0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YCOLOR", iPPlotGetAXSYColorAttrib, iPPlotSetAXSYColorAttrib, IUPAF_SAMEASSYSTEM, "0 0 0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XAUTOMIN", iPPlotGetAXSXAutoMinAttrib, iPPlotSetAXSXAutoMinAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YAUTOMIN", iPPlotGetAXSYAutoMinAttrib, iPPlotSetAXSYAutoMinAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XAUTOMAX", iPPlotGetAXSXAutoMaxAttrib, iPPlotSetAXSXAutoMaxAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YAUTOMAX", iPPlotGetAXSYAutoMaxAttrib, iPPlotSetAXSYAutoMaxAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XMIN", iPPlotGetAXSXMinAttrib, iPPlotSetAXSXMinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YMIN", iPPlotGetAXSYMinAttrib, iPPlotSetAXSYMinAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XMAX", iPPlotGetAXSXMaxAttrib, iPPlotSetAXSXMaxAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YMAX", iPPlotGetAXSYMaxAttrib, iPPlotSetAXSYMaxAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XREVERSE", iPPlotGetAXSXReverseAttrib, iPPlotSetAXSXReverseAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YREVERSE", iPPlotGetAXSYReverseAttrib, iPPlotSetAXSYReverseAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XCROSSORIGIN", iPPlotGetAXSXCrossOriginAttrib, iPPlotSetAXSXCrossOriginAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YCROSSORIGIN", iPPlotGetAXSYCrossOriginAttrib, iPPlotSetAXSYCrossOriginAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XSCALE", iPPlotGetAXSXScaleAttrib, iPPlotSetAXSXScaleAttrib, IUPAF_SAMEASSYSTEM, "LIN", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YSCALE", iPPlotGetAXSYScaleAttrib, iPPlotSetAXSYScaleAttrib, IUPAF_SAMEASSYSTEM, "LIN", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XFONTSIZE", iPPlotGetAXSXFontSizeAttrib, iPPlotSetAXSXFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YFONTSIZE", iPPlotGetAXSYFontSizeAttrib, iPPlotSetAXSYFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XFONTSTYLE", iPPlotGetAXSXFontStyleAttrib, iPPlotSetAXSXFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YFONTSTYLE", iPPlotGetAXSYFontStyleAttrib, iPPlotSetAXSYFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICK", iPPlotGetAXSXTickAttrib, iPPlotSetAXSXTickAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICK", iPPlotGetAXSYTickAttrib, iPPlotSetAXSYTickAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKSIZE", iPPlotGetAXSXTickSizeAttrib, iPPlotSetAXSXTickSizeAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKSIZE", iPPlotGetAXSYTickSizeAttrib, iPPlotSetAXSYTickSizeAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKFORMAT", iPPlotGetAXSXTickFormatAttrib, iPPlotSetAXSXTickFormatAttrib, IUPAF_SAMEASSYSTEM, "%.0f", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKFORMAT", iPPlotGetAXSYTickFormatAttrib, iPPlotSetAXSYTickFormatAttrib, IUPAF_SAMEASSYSTEM, "%.0f", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKFONTSIZE", iPPlotGetAXSXTickFontSizeAttrib, iPPlotSetAXSXTickFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKFONTSIZE", iPPlotGetAXSYTickFontSizeAttrib, iPPlotSetAXSYTickFontSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKFONTSTYLE", iPPlotGetAXSXTickFontStyleAttrib, iPPlotSetAXSXTickFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKFONTSTYLE", iPPlotGetAXSYTickFontStyleAttrib, iPPlotSetAXSYTickFontStyleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XAUTOTICK", iPPlotGetAXSXAutoTickAttrib, iPPlotSetAXSXAutoTickAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YAUTOTICK", iPPlotGetAXSYAutoTickAttrib, iPPlotSetAXSYAutoTickAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XAUTOTICKSIZE", iPPlotGetAXSXAutoTickSizeAttrib, iPPlotSetAXSXAutoTickSizeAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YAUTOTICKSIZE", iPPlotGetAXSYAutoTickSizeAttrib, iPPlotSetAXSYAutoTickSizeAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKMAJORSPAN", iPPlotGetAXSXTickMajorSpanAttrib, iPPlotSetAXSXTickMajorSpanAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKMAJORSPAN", iPPlotGetAXSYTickMajorSpanAttrib, iPPlotSetAXSYTickMajorSpanAttrib, IUPAF_SAMEASSYSTEM, "1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKDIVISION", iPPlotGetAXSXTickDivisionAttrib, iPPlotSetAXSXTickDivisionAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKDIVISION", iPPlotGetAXSYTickDivisionAttrib, iPPlotSetAXSYTickDivisionAttrib, IUPAF_SAMEASSYSTEM, "5", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XAUTOTICKSIZE", iPPlotGetAXSXAutoTickSizeAttrib, iPPlotSetAXSXAutoTickSizeAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YAUTOTICKSIZE", iPPlotGetAXSYAutoTickSizeAttrib, iPPlotSetAXSYAutoTickSizeAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_XTICKMAJORSIZE", iPPlotGetAXSXTickMajorSizeAttrib, iPPlotSetAXSXTickMajorSizeAttrib, IUPAF_SAMEASSYSTEM, "8", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "AXS_YTICKMAJORSIZE", iPPlotGetAXSYTickMajorSizeAttrib, iPPlotSetAXSYTickMajorSizeAttrib, IUPAF_SAMEASSYSTEM, "8", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ iupClassRegisterAttribute(ic, "REMOVE", NULL, iPPlotSetRemoveAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CLEAR", NULL, iPPlotSetClearAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "COUNT", iPPlotGetCountAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CURRENT", iPPlotGetCurrentAttrib, iPPlotSetCurrentAttrib, IUPAF_SAMEASSYSTEM, "-1", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+
+ return ic;
+}
+
+/* user level call: create control */
+Ihandle* IupPPlot(void)
+{
+ return IupCreate("pplot");
+}
+
+void IupPPlotOpen(void)
+{
+ if (!IupGetGlobal("_IUP_PPLOT_OPEN"))
+ {
+ iupRegisterClass(iupPPlotGetClass());
+ IupSetGlobal("_IUP_PPLOT_OPEN", "1");
+ }
+}
diff --git a/iup/srcpplot/iup_pplot.def b/iup/srcpplot/iup_pplot.def
new file mode 100755
index 0000000..8143bab
--- /dev/null
+++ b/iup/srcpplot/iup_pplot.def
@@ -0,0 +1,11 @@
+EXPORTS
+ IupPPlotOpen
+ IupPPlot
+ IupPPlotBegin
+ IupPPlotAdd
+ IupPPlotAddStr
+ IupPPlotEnd
+ IupPPlotInsertStr
+ IupPPlotInsert
+ IupPPlotTransform
+ IupPPlotPaintTo
diff --git a/iup/srcpplot/iup_pplot.dep b/iup/srcpplot/iup_pplot.dep
new file mode 100644
index 0000000..6542ce3
--- /dev/null
+++ b/iup/srcpplot/iup_pplot.dep
@@ -0,0 +1,12 @@
+$(OBJDIR)/iupPPlot.o: iupPPlot.cpp iupPPlot.h
+$(OBJDIR)/iupPPlotInteraction.o: iupPPlotInteraction.cpp iupPPlotInteraction.h \
+ iupPPlot.h
+$(OBJDIR)/iup_pplot.o: iup_pplot.cpp ../include/iup.h ../include/iupkey.h \
+ ../include/iupdef.h ../include/iupcbs.h ../include/iup_pplot.h \
+ ../../cd/include/cd.h ../../cd/include/cdiup.h \
+ ../../cd/include/cddbuf.h ../../cd/include/cdirgb.h \
+ ../../cd/include/cdgdiplus.h ../src/iup_class.h ../src/iup_table.h \
+ ../src/iup_classbase.h ../src/iup_register.h ../src/iup_object.h \
+ ../src/iup_class.h ../src/iup_attrib.h ../src/iup_str.h \
+ ../src/iup_drv.h ../src/iup_stdcontrols.h ../src/iup_assert.h \
+ iupPPlot.h iupPPlotInteraction.h iuppplot.hpp
diff --git a/iup/srcpplot/iuppplot.hpp b/iup/srcpplot/iuppplot.hpp
new file mode 100755
index 0000000..62e3db7
--- /dev/null
+++ b/iup/srcpplot/iuppplot.hpp
@@ -0,0 +1,137 @@
+/*
+ * IupPPlot component - private include file
+ *
+ * Description : A component, derived from PPlot and IUP canvas
+ * Remark : Depend on libs IUP, CD, IUPCD
+ */
+
+
+#ifndef __IUP_PPLOT_H
+#define __IUP_PPLOT_H
+
+/*
+ PPainterIup class definition
+*/
+
+
+class PostPainterCallbackIup: public PDrawer
+{
+ public:
+ PostPainterCallbackIup(PPlot &inPPlot, Ihandle* inHandle);
+ virtual bool Draw (Painter &inPainter);
+ protected:
+ Ihandle *_ih; // IUP handle
+};
+
+class PrePainterCallbackIup: public PDrawer
+{
+ public:
+ PrePainterCallbackIup(PPlot &inPPlot, Ihandle* inHandle);
+ virtual bool Draw (Painter &inPainter);
+ protected:
+ Ihandle *_ih; // IUP handle
+};
+
+class PDeleteInteractionIup: public PDeleteInteraction
+{
+ public:
+ PDeleteInteractionIup(PPlot &inPPlot, Ihandle* inHandle):
+ PDeleteInteraction(inPPlot), _ih(inHandle) {}
+
+ protected:
+ Ihandle *_ih; // IUP handle
+ bool DeleteNotify(int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData);
+};
+
+class PSelectionInteractionIup: public PSelectionInteraction
+{
+ public:
+ PSelectionInteractionIup(PPlot &inPPlot, Ihandle* inHandle):
+ PSelectionInteraction(inPPlot), _ih(inHandle) {}
+
+ protected:
+ Ihandle *_ih; // IUP handle
+ bool SelectNotify(int inIndex, int inSampleIndex, PlotDataBase *inXData, PlotDataBase *inYData, bool inSelect);
+};
+
+class PEditInteractionIup: public PEditInteraction
+{
+ public:
+ PEditInteractionIup (PPlot &inPPlot, Ihandle* inHandle):
+ PEditInteraction(inPPlot), _ih(inHandle) {}
+
+ virtual bool Impl_HandleKeyEvent (const PKeyEvent &inEvent);
+ virtual bool Impl_Calculate (Painter &inPainter, PPlot& inPPlot);
+
+ protected:
+ Ihandle *_ih; // IUP handle
+ void HandleCursorKey (const PlotDataSelection *inPlotDataSelection, PlotDataBase *inXData, PlotDataBase *inYData, int inIndex);
+ bool EditNotify(int inIndex, int inSampleIndex, float inX, float inY, float *inNewX, float *inNewY);
+};
+
+class InteractionContainerIup: public InteractionContainer
+{
+ public:
+ InteractionContainerIup(PPlot &inPPlot, Ihandle* inHandle);
+
+ PZoomInteraction mZoomInteraction;
+ PSelectionInteractionIup mSelectionInteraction;
+ PEditInteractionIup mEditInteraction;
+ PDeleteInteractionIup mDeleteInteraction;
+ PCrosshairInteraction mCrosshairInteraction;
+
+ PostPainterCallbackIup mPostPainterCallback;
+ PrePainterCallbackIup mPrePainterCallback;
+};
+
+class PPainterIup: public Painter
+{
+ public:
+ PPainterIup(Ihandle *ih);
+ virtual ~PPainterIup();
+ cdCanvas *_cdcanvas; /* iup drawing surface */
+ cdCanvas *_cddbuffer; /* double buffer drawing surface */
+ PPlot _plot; /* plot data holder */
+ int _redraw; /* must update the double buffer before flush */
+ int _currentDataSetIndex; /* dataset index used for DS_ attributes in SetAttribute and GetAttribute */
+
+ // Called from C functions
+ void Draw(int force); // paint the stuff
+ void Resize(); // called when resizing
+ void MouseButton(int btn, int stat, int x, int y, char *r); // mouse event
+ void MouseMove(int x, int y); // mouse event
+ void KeyPress(int c, int press); // keyboard event
+ void DrawTo(cdCanvas *usrCnv); // send plot to some user defined device
+
+ protected:
+ InteractionContainer *_InteractionContainer;
+ Ihandle *_ih; // IUP handle
+ short int _mouseDown;
+ short int _mouse_ALT;
+ short int _mouse_SHIFT;
+ short int _mouse_CTRL;
+
+ PPainterIup() { };
+
+ virtual void FillArrow(int inX1, int inY1, int inX2, int inY2, int inX3, int inY3);
+ virtual void DrawLine(float inX1, float inY1, float inX2, float inY2);
+ virtual void FillRect(int inX, int inY, int inW, int inH);
+ virtual void InvertRect(int inX, int inY, int inW, int inH);
+ virtual void SetClipRect(int inX, int inY, int inW, int inH);
+ virtual long GetWidth() const;
+ virtual long GetHeight() const;
+ virtual void SetLineColor(int inR, int inG, int inB);
+ virtual void SetFillColor(int inR, int inG, int inB);
+ virtual long CalculateTextDrawSize(const char *inString);
+ virtual long GetFontHeight() const;
+ virtual void DrawText(int inX, int inY, short align, const char *inString);
+ virtual void DrawRotatedText(int inX, int inY, float inDegrees,
+ short align, const char *inString);
+ virtual void SetStyle(const PStyle &inStyle);
+
+ private:
+
+}; // PPainterIup
+
+
+#endif /* #ifndef __IUP_PPLOT_HPP */
diff --git a/iup/srcpplot/make_uname b/iup/srcpplot/make_uname
new file mode 100755
index 0000000..cc4b881
--- /dev/null
+++ b/iup/srcpplot/make_uname
@@ -0,0 +1,3 @@
+#This builds all the libraries of the folder for 1 uname
+
+tecmake $1 $2 $3 $4 $5 $6 $7
diff --git a/iup/srcpplot/make_uname.bat b/iup/srcpplot/make_uname.bat
new file mode 100755
index 0000000..f0a0722
--- /dev/null
+++ b/iup/srcpplot/make_uname.bat
@@ -0,0 +1,4 @@
+@echo off
+REM This builds all the libraries of the folder for 1 uname
+
+call tecmake %1 %2 %3 %4 %5 %6