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