1*2a97ec55SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*2a97ec55SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*2a97ec55SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*2a97ec55SAndrew Rist * distributed with this work for additional information 6*2a97ec55SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*2a97ec55SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*2a97ec55SAndrew Rist * "License"); you may not use this file except in compliance 9*2a97ec55SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*2a97ec55SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*2a97ec55SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*2a97ec55SAndrew Rist * software distributed under the License is distributed on an 15*2a97ec55SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*2a97ec55SAndrew Rist * KIND, either express or implied. See the License for the 17*2a97ec55SAndrew Rist * specific language governing permissions and limitations 18*2a97ec55SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*2a97ec55SAndrew Rist *************************************************************/ 21*2a97ec55SAndrew Rist 22*2a97ec55SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_extensions.hxx" 26cdf0e10cSrcweir #include <grid.hrc> 27cdf0e10cSrcweir #include <cstdio> 28cdf0e10cSrcweir #include <math.h> // for M_LN10 and M_E 29cdf0e10cSrcweir 30cdf0e10cSrcweir #define _USE_MATH_DEFINES 31cdf0e10cSrcweir #include <cmath> 32cdf0e10cSrcweir #undef _USE_MATH_DEFINES 33cdf0e10cSrcweir 34cdf0e10cSrcweir #include <grid.hxx> 35cdf0e10cSrcweir 36cdf0e10cSrcweir // for ::std::sort 37cdf0e10cSrcweir #include <algorithm> 38cdf0e10cSrcweir 39cdf0e10cSrcweir ResId SaneResId( sal_uInt32 ); 40cdf0e10cSrcweir 41cdf0e10cSrcweir /*********************************************************************** 42cdf0e10cSrcweir * 43cdf0e10cSrcweir * GridWindow 44cdf0e10cSrcweir * 45cdf0e10cSrcweir ***********************************************************************/ 46cdf0e10cSrcweir 47cdf0e10cSrcweir // --------------------------------------------------------------------- 48cdf0e10cSrcweir 49cdf0e10cSrcweir GridWindow::GridWindow(double* pXValues, double* pYValues, int nValues, Window* pParent, sal_Bool bCutValues ) 50cdf0e10cSrcweir : ModalDialog( pParent, SaneResId( GRID_DIALOG ) ), 51cdf0e10cSrcweir m_aGridArea( 50, 15, 100, 100 ), 52cdf0e10cSrcweir m_pXValues( pXValues ), 53cdf0e10cSrcweir m_pOrigYValues( pYValues ), 54cdf0e10cSrcweir m_nValues( nValues ), 55cdf0e10cSrcweir m_pNewYValues( NULL ), 56cdf0e10cSrcweir m_bCutValues( bCutValues ), 57cdf0e10cSrcweir m_aHandles(), 58cdf0e10cSrcweir m_nDragIndex( 0xffffffff ), 59cdf0e10cSrcweir m_aMarkerBitmap( Bitmap( SaneResId( GRID_DIALOG_HANDLE_BMP ) ), Color( 255, 255, 255 ) ), 60cdf0e10cSrcweir m_aOKButton( this, SaneResId( GRID_DIALOG_OK_BTN ) ), 61cdf0e10cSrcweir m_aCancelButton( this, SaneResId( GRID_DIALOG_CANCEL_BTN ) ), 62cdf0e10cSrcweir m_aResetTypeBox( this, SaneResId( GRID_DIALOG_TYPE_BOX ) ), 63cdf0e10cSrcweir m_aResetButton( this, SaneResId( GRID_DIALOG_RESET_BTN ) ) 64cdf0e10cSrcweir { 65cdf0e10cSrcweir sal_uInt16 nPos = m_aResetTypeBox.InsertEntry( String( SaneResId( RESET_TYPE_LINEAR_ASCENDING ) ) ); 66cdf0e10cSrcweir m_aResetTypeBox.SetEntryData( nPos, (void *)RESET_TYPE_LINEAR_ASCENDING ); 67cdf0e10cSrcweir 68cdf0e10cSrcweir nPos = m_aResetTypeBox.InsertEntry( String( SaneResId( RESET_TYPE_LINEAR_DESCENDING ) ) ); 69cdf0e10cSrcweir m_aResetTypeBox.SetEntryData( nPos, (void *)RESET_TYPE_LINEAR_DESCENDING ); 70cdf0e10cSrcweir 71cdf0e10cSrcweir nPos = m_aResetTypeBox.InsertEntry( String( SaneResId( RESET_TYPE_RESET ) ) ); 72cdf0e10cSrcweir m_aResetTypeBox.SetEntryData( nPos, (void *)RESET_TYPE_RESET ); 73cdf0e10cSrcweir 74cdf0e10cSrcweir nPos = m_aResetTypeBox.InsertEntry( String( SaneResId( RESET_TYPE_EXPONENTIAL ) ) ); 75cdf0e10cSrcweir m_aResetTypeBox.SetEntryData( nPos, (void *)RESET_TYPE_EXPONENTIAL ); 76cdf0e10cSrcweir 77cdf0e10cSrcweir m_aResetTypeBox.SelectEntryPos( 0 ); 78cdf0e10cSrcweir 79cdf0e10cSrcweir m_aResetButton.SetClickHdl( LINK( this, GridWindow, ClickButtonHdl ) ); 80cdf0e10cSrcweir 81cdf0e10cSrcweir SetMapMode( MapMode( MAP_PIXEL ) ); 82cdf0e10cSrcweir Size aSize = GetOutputSizePixel(); 83cdf0e10cSrcweir Size aBtnSize = m_aOKButton.GetOutputSizePixel(); 84cdf0e10cSrcweir m_aGridArea.setWidth( aSize.Width() - aBtnSize.Width() - 80 ); 85cdf0e10cSrcweir m_aGridArea.setHeight( aSize.Height() - 40 ); 86cdf0e10cSrcweir 87cdf0e10cSrcweir if( m_pOrigYValues && m_nValues ) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir m_pNewYValues = new double[ m_nValues ]; 90cdf0e10cSrcweir memcpy( m_pNewYValues, m_pOrigYValues, sizeof( double ) * m_nValues ); 91cdf0e10cSrcweir } 92cdf0e10cSrcweir 93cdf0e10cSrcweir setBoundings( 0, 0, 1023, 1023 ); 94cdf0e10cSrcweir computeExtremes(); 95cdf0e10cSrcweir 96cdf0e10cSrcweir // create left and right marker as first and last entry 97cdf0e10cSrcweir m_BmOffX = sal_uInt16(m_aMarkerBitmap.GetSizePixel().Width() >> 1); 98cdf0e10cSrcweir m_BmOffY = sal_uInt16(m_aMarkerBitmap.GetSizePixel().Height() >> 1); 99cdf0e10cSrcweir m_aHandles.push_back(impHandle(transform(findMinX(), findMinY()), m_BmOffX, m_BmOffY)); 100cdf0e10cSrcweir m_aHandles.push_back(impHandle(transform(findMaxX(), findMaxY()), m_BmOffX, m_BmOffY)); 101cdf0e10cSrcweir 102cdf0e10cSrcweir FreeResource(); 103cdf0e10cSrcweir } 104cdf0e10cSrcweir 105cdf0e10cSrcweir // --------------------------------------------------------------------- 106cdf0e10cSrcweir 107cdf0e10cSrcweir GridWindow::~GridWindow() 108cdf0e10cSrcweir { 109cdf0e10cSrcweir if( m_pNewYValues ) 110cdf0e10cSrcweir delete [] m_pNewYValues; 111cdf0e10cSrcweir } 112cdf0e10cSrcweir 113cdf0e10cSrcweir // --------------------------------------------------------------------- 114cdf0e10cSrcweir 115cdf0e10cSrcweir double GridWindow::findMinX() 116cdf0e10cSrcweir { 117cdf0e10cSrcweir if( ! m_pXValues ) 118cdf0e10cSrcweir return 0.0; 119cdf0e10cSrcweir double fMin = m_pXValues[0]; 120cdf0e10cSrcweir for( int i = 1; i < m_nValues; i++ ) 121cdf0e10cSrcweir if( m_pXValues[ i ] < fMin ) 122cdf0e10cSrcweir fMin = m_pXValues[ i ]; 123cdf0e10cSrcweir return fMin; 124cdf0e10cSrcweir } 125cdf0e10cSrcweir 126cdf0e10cSrcweir // --------------------------------------------------------------------- 127cdf0e10cSrcweir 128cdf0e10cSrcweir double GridWindow::findMinY() 129cdf0e10cSrcweir { 130cdf0e10cSrcweir if( ! m_pNewYValues ) 131cdf0e10cSrcweir return 0.0; 132cdf0e10cSrcweir double fMin = m_pNewYValues[0]; 133cdf0e10cSrcweir for( int i = 1; i < m_nValues; i++ ) 134cdf0e10cSrcweir if( m_pNewYValues[ i ] < fMin ) 135cdf0e10cSrcweir fMin = m_pNewYValues[ i ]; 136cdf0e10cSrcweir return fMin; 137cdf0e10cSrcweir } 138cdf0e10cSrcweir 139cdf0e10cSrcweir // --------------------------------------------------------------------- 140cdf0e10cSrcweir 141cdf0e10cSrcweir double GridWindow::findMaxX() 142cdf0e10cSrcweir { 143cdf0e10cSrcweir if( ! m_pXValues ) 144cdf0e10cSrcweir return 0.0; 145cdf0e10cSrcweir double fMax = m_pXValues[0]; 146cdf0e10cSrcweir for( int i = 1; i < m_nValues; i++ ) 147cdf0e10cSrcweir if( m_pXValues[ i ] > fMax ) 148cdf0e10cSrcweir fMax = m_pXValues[ i ]; 149cdf0e10cSrcweir return fMax; 150cdf0e10cSrcweir } 151cdf0e10cSrcweir 152cdf0e10cSrcweir // --------------------------------------------------------------------- 153cdf0e10cSrcweir 154cdf0e10cSrcweir double GridWindow::findMaxY() 155cdf0e10cSrcweir { 156cdf0e10cSrcweir if( ! m_pNewYValues ) 157cdf0e10cSrcweir return 0.0; 158cdf0e10cSrcweir double fMax = m_pNewYValues[0]; 159cdf0e10cSrcweir for( int i = 1; i < m_nValues; i++ ) 160cdf0e10cSrcweir if( m_pNewYValues[ i ] > fMax ) 161cdf0e10cSrcweir fMax = m_pNewYValues[ i ]; 162cdf0e10cSrcweir return fMax; 163cdf0e10cSrcweir } 164cdf0e10cSrcweir 165cdf0e10cSrcweir // --------------------------------------------------------------------- 166cdf0e10cSrcweir 167cdf0e10cSrcweir void GridWindow::computeExtremes() 168cdf0e10cSrcweir { 169cdf0e10cSrcweir if( m_nValues && m_pXValues && m_pOrigYValues ) 170cdf0e10cSrcweir { 171cdf0e10cSrcweir m_fMaxX = m_fMinX = m_pXValues[0]; 172cdf0e10cSrcweir m_fMaxY = m_fMinY = m_pOrigYValues[0]; 173cdf0e10cSrcweir for( int i = 1; i < m_nValues; i++ ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir if( m_pXValues[ i ] > m_fMaxX ) 176cdf0e10cSrcweir m_fMaxX = m_pXValues[ i ]; 177cdf0e10cSrcweir else if( m_pXValues[ i ] < m_fMinX ) 178cdf0e10cSrcweir m_fMinX = m_pXValues[ i ]; 179cdf0e10cSrcweir if( m_pOrigYValues[ i ] > m_fMaxY ) 180cdf0e10cSrcweir m_fMaxY = m_pOrigYValues[ i ]; 181cdf0e10cSrcweir else if( m_pOrigYValues[ i ] < m_fMinY ) 182cdf0e10cSrcweir m_fMinY = m_pOrigYValues[ i ]; 183cdf0e10cSrcweir } 184cdf0e10cSrcweir setBoundings( m_fMinX, m_fMinY, m_fMaxX, m_fMaxY ); 185cdf0e10cSrcweir } 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir // --------------------------------------------------------------------- 189cdf0e10cSrcweir 190cdf0e10cSrcweir Point GridWindow::transform( double x, double y ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir Point aRet; 193cdf0e10cSrcweir 194cdf0e10cSrcweir aRet.X() = (long)( ( x - m_fMinX ) * 195cdf0e10cSrcweir (double)m_aGridArea.GetWidth() / ( m_fMaxX - m_fMinX ) 196cdf0e10cSrcweir + m_aGridArea.Left() ); 197cdf0e10cSrcweir aRet.Y() = (long)( 198cdf0e10cSrcweir m_aGridArea.Bottom() - 199cdf0e10cSrcweir ( y - m_fMinY ) * 200cdf0e10cSrcweir (double)m_aGridArea.GetHeight() / ( m_fMaxY - m_fMinY ) ); 201cdf0e10cSrcweir return aRet; 202cdf0e10cSrcweir } 203cdf0e10cSrcweir 204cdf0e10cSrcweir // --------------------------------------------------------------------- 205cdf0e10cSrcweir 206cdf0e10cSrcweir void GridWindow::transform( const Point& rOriginal, double& x, double& y ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir x = ( rOriginal.X() - m_aGridArea.Left() ) * (m_fMaxX - m_fMinX) / (double)m_aGridArea.GetWidth() + m_fMinX; 209cdf0e10cSrcweir y = ( m_aGridArea.Bottom() - rOriginal.Y() ) * (m_fMaxY - m_fMinY) / (double)m_aGridArea.GetHeight() + m_fMinY; 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir // --------------------------------------------------------------------- 213cdf0e10cSrcweir 214cdf0e10cSrcweir void GridWindow::drawLine( double x1, double y1, double x2, double y2 ) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir DrawLine( transform( x1, y1 ), transform( x2, y2 ) ); 217cdf0e10cSrcweir } 218cdf0e10cSrcweir 219cdf0e10cSrcweir // --------------------------------------------------------------------- 220cdf0e10cSrcweir 221cdf0e10cSrcweir void GridWindow::computeChunk( double fMin, double fMax, double& fChunkOut, double& fMinChunkOut ) 222cdf0e10cSrcweir { 223cdf0e10cSrcweir // get a nice chunk size like 10, 100, 25 or such 224cdf0e10cSrcweir fChunkOut = ( fMax - fMin ) / 6.0; 225cdf0e10cSrcweir int logchunk = (int)std::log10( fChunkOut ); 226cdf0e10cSrcweir int nChunk = (int)( fChunkOut / std::exp( (double)(logchunk-1) * M_LN10 ) ); 227cdf0e10cSrcweir if( nChunk >= 75 ) 228cdf0e10cSrcweir nChunk = 100; 229cdf0e10cSrcweir else if( nChunk >= 35 ) 230cdf0e10cSrcweir nChunk = 50; 231cdf0e10cSrcweir else if ( nChunk > 20 ) 232cdf0e10cSrcweir nChunk = 25; 233cdf0e10cSrcweir else if ( nChunk >= 13 ) 234cdf0e10cSrcweir nChunk = 20; 235cdf0e10cSrcweir else if( nChunk > 5 ) 236cdf0e10cSrcweir nChunk = 10; 237cdf0e10cSrcweir else 238cdf0e10cSrcweir nChunk = 5; 239cdf0e10cSrcweir fChunkOut = (double) nChunk * exp( (double)(logchunk-1) * M_LN10 ); 240cdf0e10cSrcweir // compute whole chunks fitting into fMin 241cdf0e10cSrcweir nChunk = (int)( fMin / fChunkOut ); 242cdf0e10cSrcweir fMinChunkOut = (double)nChunk * fChunkOut; 243cdf0e10cSrcweir while( fMinChunkOut < fMin ) 244cdf0e10cSrcweir fMinChunkOut += fChunkOut; 245cdf0e10cSrcweir } 246cdf0e10cSrcweir 247cdf0e10cSrcweir // --------------------------------------------------------------------- 248cdf0e10cSrcweir 249cdf0e10cSrcweir void GridWindow::computeNew() 250cdf0e10cSrcweir { 251cdf0e10cSrcweir if(2L == m_aHandles.size()) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir // special case: only left and right markers 254cdf0e10cSrcweir double xleft, yleft; 255cdf0e10cSrcweir double xright, yright; 256cdf0e10cSrcweir transform(m_aHandles[0L].maPos, xleft, yleft); 257cdf0e10cSrcweir transform(m_aHandles[1L].maPos, xright, yright ); 258cdf0e10cSrcweir double factor = (yright-yleft)/(xright-xleft); 259cdf0e10cSrcweir for( int i = 0; i < m_nValues; i++ ) 260cdf0e10cSrcweir { 261cdf0e10cSrcweir m_pNewYValues[ i ] = yleft + ( m_pXValues[ i ] - xleft )*factor; 262cdf0e10cSrcweir } 263cdf0e10cSrcweir } 264cdf0e10cSrcweir else 265cdf0e10cSrcweir { 266cdf0e10cSrcweir // sort markers 267cdf0e10cSrcweir std::sort(m_aHandles.begin(), m_aHandles.end()); 268cdf0e10cSrcweir const int nSorted = m_aHandles.size(); 269cdf0e10cSrcweir int i; 270cdf0e10cSrcweir 271cdf0e10cSrcweir // get node arrays 272cdf0e10cSrcweir double* nodex = new double[ nSorted ]; 273cdf0e10cSrcweir double* nodey = new double[ nSorted ]; 274cdf0e10cSrcweir 275cdf0e10cSrcweir for( i = 0L; i < nSorted; i++ ) 276cdf0e10cSrcweir transform( m_aHandles[i].maPos, nodex[ i ], nodey[ i ] ); 277cdf0e10cSrcweir 278cdf0e10cSrcweir for( i = 0; i < m_nValues; i++ ) 279cdf0e10cSrcweir { 280cdf0e10cSrcweir double x = m_pXValues[ i ]; 281cdf0e10cSrcweir m_pNewYValues[ i ] = interpolate( x, nodex, nodey, nSorted ); 282cdf0e10cSrcweir if( m_bCutValues ) 283cdf0e10cSrcweir { 284cdf0e10cSrcweir if( m_pNewYValues[ i ] > m_fMaxY ) 285cdf0e10cSrcweir m_pNewYValues[ i ] = m_fMaxY; 286cdf0e10cSrcweir else if( m_pNewYValues[ i ] < m_fMinY ) 287cdf0e10cSrcweir m_pNewYValues[ i ] = m_fMinY; 288cdf0e10cSrcweir } 289cdf0e10cSrcweir } 290cdf0e10cSrcweir 291cdf0e10cSrcweir delete [] nodex; 292cdf0e10cSrcweir delete [] nodey; 293cdf0e10cSrcweir } 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 296cdf0e10cSrcweir // --------------------------------------------------------------------- 297cdf0e10cSrcweir 298cdf0e10cSrcweir double GridWindow::interpolate( 299cdf0e10cSrcweir double x, 300cdf0e10cSrcweir double* pNodeX, 301cdf0e10cSrcweir double* pNodeY, 302cdf0e10cSrcweir int nNodes ) 303cdf0e10cSrcweir { 304cdf0e10cSrcweir // compute Lagrange interpolation 305cdf0e10cSrcweir double ret = 0; 306cdf0e10cSrcweir for( int i = 0; i < nNodes; i++ ) 307cdf0e10cSrcweir { 308cdf0e10cSrcweir double sum = pNodeY[ i ]; 309cdf0e10cSrcweir for( int n = 0; n < nNodes; n++ ) 310cdf0e10cSrcweir { 311cdf0e10cSrcweir if( n != i ) 312cdf0e10cSrcweir { 313cdf0e10cSrcweir sum *= x - pNodeX[ n ]; 314cdf0e10cSrcweir sum /= pNodeX[ i ] - pNodeX[ n ]; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } 317cdf0e10cSrcweir ret += sum; 318cdf0e10cSrcweir } 319cdf0e10cSrcweir return ret; 320cdf0e10cSrcweir } 321cdf0e10cSrcweir 322cdf0e10cSrcweir // --------------------------------------------------------------------- 323cdf0e10cSrcweir 324cdf0e10cSrcweir void GridWindow::setBoundings( double fMinX, double fMinY, double fMaxX, double fMaxY ) 325cdf0e10cSrcweir { 326cdf0e10cSrcweir m_fMinX = fMinX; 327cdf0e10cSrcweir m_fMinY = fMinY; 328cdf0e10cSrcweir m_fMaxX = fMaxX; 329cdf0e10cSrcweir m_fMaxY = fMaxY; 330cdf0e10cSrcweir 331cdf0e10cSrcweir computeChunk( m_fMinX, m_fMaxX, m_fChunkX, m_fMinChunkX ); 332cdf0e10cSrcweir computeChunk( m_fMinY, m_fMaxY, m_fChunkY, m_fMinChunkY ); 333cdf0e10cSrcweir } 334cdf0e10cSrcweir 335cdf0e10cSrcweir // --------------------------------------------------------------------- 336cdf0e10cSrcweir 337cdf0e10cSrcweir void GridWindow::drawGrid() 338cdf0e10cSrcweir { 339cdf0e10cSrcweir char pBuf[256]; 340cdf0e10cSrcweir SetLineColor( Color( COL_BLACK ) ); 341cdf0e10cSrcweir // draw vertical lines 342cdf0e10cSrcweir for( double fX = m_fMinChunkX; fX < m_fMaxX; fX += m_fChunkX ) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir drawLine( fX, m_fMinY, fX, m_fMaxY ); 345cdf0e10cSrcweir // draw tickmarks 346cdf0e10cSrcweir Point aPt = transform( fX, m_fMinY ); 347cdf0e10cSrcweir std::sprintf( pBuf, "%g", fX ); 348cdf0e10cSrcweir String aMark( pBuf, gsl_getSystemTextEncoding() ); 349cdf0e10cSrcweir Size aTextSize( GetTextWidth( aMark ), GetTextHeight() ); 350cdf0e10cSrcweir aPt.X() -= aTextSize.Width()/2; 351cdf0e10cSrcweir aPt.Y() += aTextSize.Height()/2; 352cdf0e10cSrcweir DrawText( aPt, aMark ); 353cdf0e10cSrcweir } 354cdf0e10cSrcweir // draw horizontal lines 355cdf0e10cSrcweir for( double fY = m_fMinChunkY; fY < m_fMaxY; fY += m_fChunkY ) 356cdf0e10cSrcweir { 357cdf0e10cSrcweir drawLine( m_fMinX, fY, m_fMaxX, fY ); 358cdf0e10cSrcweir // draw tickmarks 359cdf0e10cSrcweir Point aPt = transform( m_fMinX, fY ); 360cdf0e10cSrcweir std::sprintf( pBuf, "%g", fY ); 361cdf0e10cSrcweir String aMark( pBuf, gsl_getSystemTextEncoding() ); 362cdf0e10cSrcweir Size aTextSize( GetTextWidth( aMark ), GetTextHeight() ); 363cdf0e10cSrcweir aPt.X() -= aTextSize.Width() + 2; 364cdf0e10cSrcweir aPt.Y() -= aTextSize.Height()/2; 365cdf0e10cSrcweir DrawText( aPt, aMark ); 366cdf0e10cSrcweir } 367cdf0e10cSrcweir 368cdf0e10cSrcweir // draw boundings 369cdf0e10cSrcweir drawLine( m_fMinX, m_fMinY, m_fMaxX, m_fMinY ); 370cdf0e10cSrcweir drawLine( m_fMinX, m_fMaxY, m_fMaxX, m_fMaxY ); 371cdf0e10cSrcweir drawLine( m_fMinX, m_fMinY, m_fMinX, m_fMaxY ); 372cdf0e10cSrcweir drawLine( m_fMaxX, m_fMinY, m_fMaxX, m_fMaxY ); 373cdf0e10cSrcweir } 374cdf0e10cSrcweir 375cdf0e10cSrcweir // --------------------------------------------------------------------- 376cdf0e10cSrcweir 377cdf0e10cSrcweir void GridWindow::drawOriginal() 378cdf0e10cSrcweir { 379cdf0e10cSrcweir if( m_nValues && m_pXValues && m_pOrigYValues ) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir SetLineColor( Color( COL_RED ) ); 382cdf0e10cSrcweir for( int i = 0; i < m_nValues-1; i++ ) 383cdf0e10cSrcweir { 384cdf0e10cSrcweir drawLine( m_pXValues[ i ], m_pOrigYValues[ i ], 385cdf0e10cSrcweir m_pXValues[ i+1 ], m_pOrigYValues[ i+1 ] ); 386cdf0e10cSrcweir } 387cdf0e10cSrcweir } 388cdf0e10cSrcweir } 389cdf0e10cSrcweir 390cdf0e10cSrcweir // --------------------------------------------------------------------- 391cdf0e10cSrcweir 392cdf0e10cSrcweir void GridWindow::drawNew() 393cdf0e10cSrcweir { 394cdf0e10cSrcweir if( m_nValues && m_pXValues && m_pNewYValues ) 395cdf0e10cSrcweir { 396cdf0e10cSrcweir SetClipRegion( m_aGridArea ); 397cdf0e10cSrcweir SetLineColor( Color( COL_YELLOW ) ); 398cdf0e10cSrcweir for( int i = 0; i < m_nValues-1; i++ ) 399cdf0e10cSrcweir { 400cdf0e10cSrcweir drawLine( m_pXValues[ i ], m_pNewYValues[ i ], 401cdf0e10cSrcweir m_pXValues[ i+1 ], m_pNewYValues[ i+1 ] ); 402cdf0e10cSrcweir } 403cdf0e10cSrcweir SetClipRegion(); 404cdf0e10cSrcweir } 405cdf0e10cSrcweir } 406cdf0e10cSrcweir 407cdf0e10cSrcweir // --------------------------------------------------------------------- 408cdf0e10cSrcweir 409cdf0e10cSrcweir void GridWindow::drawHandles() 410cdf0e10cSrcweir { 411cdf0e10cSrcweir for(sal_uInt32 i(0L); i < m_aHandles.size(); i++) 412cdf0e10cSrcweir { 413cdf0e10cSrcweir m_aHandles[i].draw(*this, m_aMarkerBitmap); 414cdf0e10cSrcweir } 415cdf0e10cSrcweir } 416cdf0e10cSrcweir 417cdf0e10cSrcweir // --------------------------------------------------------------------- 418cdf0e10cSrcweir 419cdf0e10cSrcweir void GridWindow::Paint( const Rectangle& rRect ) 420cdf0e10cSrcweir { 421cdf0e10cSrcweir ModalDialog::Paint( rRect ); 422cdf0e10cSrcweir drawGrid(); 423cdf0e10cSrcweir drawOriginal(); 424cdf0e10cSrcweir drawNew(); 425cdf0e10cSrcweir drawHandles(); 426cdf0e10cSrcweir } 427cdf0e10cSrcweir 428cdf0e10cSrcweir // --------------------------------------------------------------------- 429cdf0e10cSrcweir 430cdf0e10cSrcweir void GridWindow::MouseMove( const MouseEvent& rEvt ) 431cdf0e10cSrcweir { 432cdf0e10cSrcweir if( rEvt.GetButtons() == MOUSE_LEFT && m_nDragIndex != 0xffffffff ) 433cdf0e10cSrcweir { 434cdf0e10cSrcweir Point aPoint( rEvt.GetPosPixel() ); 435cdf0e10cSrcweir 436cdf0e10cSrcweir if( m_nDragIndex == 0L || m_nDragIndex == m_aHandles.size() - 1L) 437cdf0e10cSrcweir { 438cdf0e10cSrcweir aPoint.X() = m_aHandles[m_nDragIndex].maPos.X(); 439cdf0e10cSrcweir } 440cdf0e10cSrcweir else 441cdf0e10cSrcweir { 442cdf0e10cSrcweir if(aPoint.X() < m_aGridArea.Left()) 443cdf0e10cSrcweir aPoint.X() = m_aGridArea.Left(); 444cdf0e10cSrcweir else if(aPoint.X() > m_aGridArea.Right()) 445cdf0e10cSrcweir aPoint.X() = m_aGridArea.Right(); 446cdf0e10cSrcweir } 447cdf0e10cSrcweir 448cdf0e10cSrcweir if( aPoint.Y() < m_aGridArea.Top() ) 449cdf0e10cSrcweir aPoint.Y() = m_aGridArea.Top(); 450cdf0e10cSrcweir else if( aPoint.Y() > m_aGridArea.Bottom() ) 451cdf0e10cSrcweir aPoint.Y() = m_aGridArea.Bottom(); 452cdf0e10cSrcweir 453cdf0e10cSrcweir if( aPoint != m_aHandles[m_nDragIndex].maPos ) 454cdf0e10cSrcweir { 455cdf0e10cSrcweir m_aHandles[m_nDragIndex].maPos = aPoint; 456cdf0e10cSrcweir Invalidate( m_aGridArea ); 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir 460cdf0e10cSrcweir ModalDialog::MouseMove( rEvt ); 461cdf0e10cSrcweir } 462cdf0e10cSrcweir 463cdf0e10cSrcweir // --------------------------------------------------------------------- 464cdf0e10cSrcweir 465cdf0e10cSrcweir void GridWindow::MouseButtonUp( const MouseEvent& rEvt ) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir if( rEvt.GetButtons() == MOUSE_LEFT ) 468cdf0e10cSrcweir { 469cdf0e10cSrcweir if( m_nDragIndex != 0xffffffff ) 470cdf0e10cSrcweir { 471cdf0e10cSrcweir m_nDragIndex = 0xffffffff; 472cdf0e10cSrcweir computeNew(); 473cdf0e10cSrcweir Invalidate( m_aGridArea ); 474cdf0e10cSrcweir Paint( m_aGridArea ); 475cdf0e10cSrcweir } 476cdf0e10cSrcweir } 477cdf0e10cSrcweir 478cdf0e10cSrcweir ModalDialog::MouseButtonUp( rEvt ); 479cdf0e10cSrcweir } 480cdf0e10cSrcweir 481cdf0e10cSrcweir // --------------------------------------------------------------------- 482cdf0e10cSrcweir 483cdf0e10cSrcweir void GridWindow::MouseButtonDown( const MouseEvent& rEvt ) 484cdf0e10cSrcweir { 485cdf0e10cSrcweir Point aPoint( rEvt.GetPosPixel() ); 486cdf0e10cSrcweir sal_uInt32 nMarkerIndex = 0xffffffff; 487cdf0e10cSrcweir 488cdf0e10cSrcweir for(sal_uInt32 a(0L); nMarkerIndex == 0xffffffff && a < m_aHandles.size(); a++) 489cdf0e10cSrcweir { 490cdf0e10cSrcweir if(m_aHandles[a].isHit(*this, aPoint)) 491cdf0e10cSrcweir { 492cdf0e10cSrcweir nMarkerIndex = a; 493cdf0e10cSrcweir } 494cdf0e10cSrcweir } 495cdf0e10cSrcweir 496cdf0e10cSrcweir if( rEvt.GetButtons() == MOUSE_LEFT ) 497cdf0e10cSrcweir { 498cdf0e10cSrcweir // user wants to drag a button 499cdf0e10cSrcweir if( nMarkerIndex != 0xffffffff ) 500cdf0e10cSrcweir { 501cdf0e10cSrcweir m_nDragIndex = nMarkerIndex; 502cdf0e10cSrcweir } 503cdf0e10cSrcweir } 504cdf0e10cSrcweir else if( rEvt.GetButtons() == MOUSE_RIGHT ) 505cdf0e10cSrcweir { 506cdf0e10cSrcweir // user wants to add/delete a button 507cdf0e10cSrcweir if( nMarkerIndex != 0xffffffff ) 508cdf0e10cSrcweir { 509cdf0e10cSrcweir if( nMarkerIndex != 0L && nMarkerIndex != m_aHandles.size() - 1L) 510cdf0e10cSrcweir { 511cdf0e10cSrcweir // delete marker under mouse 512cdf0e10cSrcweir if( m_nDragIndex == nMarkerIndex ) 513cdf0e10cSrcweir m_nDragIndex = 0xffffffff; 514cdf0e10cSrcweir 515cdf0e10cSrcweir m_aHandles.erase(m_aHandles.begin() + nMarkerIndex); 516cdf0e10cSrcweir } 517cdf0e10cSrcweir } 518cdf0e10cSrcweir else 519cdf0e10cSrcweir { 520cdf0e10cSrcweir m_BmOffX = sal_uInt16(m_aMarkerBitmap.GetSizePixel().Width() >> 1); 521cdf0e10cSrcweir m_BmOffY = sal_uInt16(m_aMarkerBitmap.GetSizePixel().Height() >> 1); 522cdf0e10cSrcweir m_aHandles.push_back(impHandle(aPoint, m_BmOffX, m_BmOffY)); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir 525cdf0e10cSrcweir computeNew(); 526cdf0e10cSrcweir Invalidate( m_aGridArea ); 527cdf0e10cSrcweir Paint( m_aGridArea ); 528cdf0e10cSrcweir } 529cdf0e10cSrcweir 530cdf0e10cSrcweir ModalDialog::MouseButtonDown( rEvt ); 531cdf0e10cSrcweir } 532cdf0e10cSrcweir 533cdf0e10cSrcweir // --------------------------------------------------------------------- 534cdf0e10cSrcweir 535cdf0e10cSrcweir IMPL_LINK( GridWindow, ClickButtonHdl, Button*, pButton ) 536cdf0e10cSrcweir { 537cdf0e10cSrcweir if( pButton == &m_aResetButton ) 538cdf0e10cSrcweir { 539cdf0e10cSrcweir int nType = (int)(sal_IntPtr)m_aResetTypeBox.GetEntryData( m_aResetTypeBox.GetSelectEntryPos() ); 540cdf0e10cSrcweir switch( nType ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir case RESET_TYPE_LINEAR_ASCENDING: 543cdf0e10cSrcweir { 544cdf0e10cSrcweir for( int i = 0; i < m_nValues; i++ ) 545cdf0e10cSrcweir { 546cdf0e10cSrcweir m_pNewYValues[ i ] = m_fMinY + (m_fMaxY-m_fMinY)/(m_fMaxX-m_fMinX)*(m_pXValues[i]-m_fMinX); 547cdf0e10cSrcweir } 548cdf0e10cSrcweir } 549cdf0e10cSrcweir break; 550cdf0e10cSrcweir case RESET_TYPE_LINEAR_DESCENDING: 551cdf0e10cSrcweir { 552cdf0e10cSrcweir for( int i = 0; i < m_nValues; i++ ) 553cdf0e10cSrcweir { 554cdf0e10cSrcweir m_pNewYValues[ i ] = m_fMaxY - (m_fMaxY-m_fMinY)/(m_fMaxX-m_fMinX)*(m_pXValues[i]-m_fMinX); 555cdf0e10cSrcweir } 556cdf0e10cSrcweir } 557cdf0e10cSrcweir break; 558cdf0e10cSrcweir case RESET_TYPE_RESET: 559cdf0e10cSrcweir { 560cdf0e10cSrcweir if( m_pOrigYValues && m_pNewYValues && m_nValues ) 561cdf0e10cSrcweir memcpy( m_pNewYValues, m_pOrigYValues, m_nValues*sizeof(double) ); 562cdf0e10cSrcweir } 563cdf0e10cSrcweir break; 564cdf0e10cSrcweir case RESET_TYPE_EXPONENTIAL: 565cdf0e10cSrcweir { 566cdf0e10cSrcweir for( int i = 0; i < m_nValues; i++ ) 567cdf0e10cSrcweir { 568cdf0e10cSrcweir m_pNewYValues[ i ] = m_fMinY + (m_fMaxY-m_fMinY)*(std::exp((m_pXValues[i]-m_fMinX)/(m_fMaxX-m_fMinX))-1.0)/(M_E-1.0); 569cdf0e10cSrcweir } 570cdf0e10cSrcweir } 571cdf0e10cSrcweir break; 572cdf0e10cSrcweir 573cdf0e10cSrcweir default: 574cdf0e10cSrcweir break; 575cdf0e10cSrcweir } 576cdf0e10cSrcweir 577cdf0e10cSrcweir for(sal_uInt32 i(0L); i < m_aHandles.size(); i++) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir // find nearest xvalue 580cdf0e10cSrcweir double x, y; 581cdf0e10cSrcweir transform( m_aHandles[i].maPos, x, y ); 582cdf0e10cSrcweir int nIndex = 0; 583cdf0e10cSrcweir double delta = std::fabs( x-m_pXValues[0] ); 584cdf0e10cSrcweir for( int n = 1; n < m_nValues; n++ ) 585cdf0e10cSrcweir { 586cdf0e10cSrcweir if( delta > std::fabs( x - m_pXValues[ n ] ) ) 587cdf0e10cSrcweir { 588cdf0e10cSrcweir delta = std::fabs( x - m_pXValues[ n ] ); 589cdf0e10cSrcweir nIndex = n; 590cdf0e10cSrcweir } 591cdf0e10cSrcweir } 592cdf0e10cSrcweir if( 0 == i ) 593cdf0e10cSrcweir m_aHandles[i].maPos = transform( m_fMinX, m_pNewYValues[ nIndex ] ); 594cdf0e10cSrcweir else if( m_aHandles.size() - 1L == i ) 595cdf0e10cSrcweir m_aHandles[i].maPos = transform( m_fMaxX, m_pNewYValues[ nIndex ] ); 596cdf0e10cSrcweir else 597cdf0e10cSrcweir m_aHandles[i].maPos = transform( m_pXValues[ nIndex ], m_pNewYValues[ nIndex ] ); 598cdf0e10cSrcweir } 599cdf0e10cSrcweir 600cdf0e10cSrcweir Invalidate( m_aGridArea ); 601cdf0e10cSrcweir Paint(Rectangle()); 602cdf0e10cSrcweir } 603cdf0e10cSrcweir return 0; 604cdf0e10cSrcweir } 605