From d577d991b97ae2b5ee1af23641bcffc3f83af5b2 Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 4 Nov 2009 11:56:41 -0800 Subject: Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux. --- iup/srcpplot/iupPPlotInteraction.cpp | 832 +++++++++++++++++++++++++++++++++++ 1 file changed, 832 insertions(+) create mode 100755 iup/srcpplot/iupPPlotInteraction.cpp (limited to 'iup/srcpplot/iupPPlotInteraction.cpp') 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 +#include + +#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 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;theIsize ();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;theIHandlePSelectionInteraction (); + } + + 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;theIsize ();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;theIsize ();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;theIGetSize ();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 (theTmpmUpperBound) { + return false; + } + return true; +} + + +bool PlotDataIncrementer::Increment (const vector &inIncrementList, vector &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector &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 &inIncrementList, vector &inData, const PlotDataIncrementerBounds &inGlobalBounds, const vector &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;theI0) { + 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(inYData); + if (!theYData) { + return; + } + vector theIncrementList (inPlotDataSelection->GetSelectedCount ()); + vector theSelectedData (inPlotDataSelection->GetSelectedCount ()); + float theDelta = 1;// pixels + if (mKeyEvent.IsArrowDown ()) { + theDelta *= -1; + } + if (mKeyEvent.IsOnlyControlKeyDown ()) { + theDelta *= 10; + } + long theIndex = 0; + for (int theI=0;theIGetSize ();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 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 vectorOfInt; + +template 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 ::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 bool Erase (const vector &inEraseList, vector &ioVec) { + vector theSortedList = inEraseList; + sort (theSortedList.begin (), theSortedList.end ()); + reverse (theSortedList.begin (), theSortedList.end ()); + unique (theSortedList.begin (), theSortedList.end ());// remove duplicates + for (vector::iterator theI=theSortedList.begin();theI!=theSortedList.end ();theI++) { + int theEraseIndex = *theI; + // vector ::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 theDeleteList (inPlotDataSelection->GetSelectedCount ()); + long theIndex = 0; + for (int theI=0;theIGetSize ();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;theITransformBack (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;theIGetSize ();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;theIIsEnabled () && theInteraction->HandleMouseEvent (inEvent)) { + return true; + } + } + return false; +} + +bool InteractionContainer::HandleKeyEvent (const PKeyEvent &inEvent) { + for (int theI=0;theIIsEnabled () && 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;*/ +} -- cgit v1.2.3