00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 #ifndef OglGui_ZoomShiftRuler_h
00033 #define OglGui_ZoomShiftRuler_h
00034 
00035 #ifndef OglGui_Window_h
00036 #include "OglGui/Window.h"
00037 #endif
00038 
00039 #ifndef OglGui_DocDimensions_h
00040 #include "OglGui/DocDimensions.h"
00041 #endif
00042 
00043 #ifndef OglGui_RepeatTimer_h
00044 #include "OglGui/RepeatTimer.h"
00045 #endif
00046 
00047 #ifndef OglGui_ZoomShiftRulerListener_h
00048 #include "OglGui/ZoomShiftRulerListener.h"
00049 #endif
00050 
00051 namespace OglGui
00052 {
00053 
00054 class ZoomShiftRuler :  public Window,
00055                         public DocDimensions,
00056                         public RepeatTimer
00057 {
00058 public:
00059     ZoomShiftRuler(int x, int y, int w, int h, long start=0, long span=10000) :
00060         Window(x,y,w,h)
00061     {
00062         Init(w,h,start,span);
00063     }
00064 
00065     ZoomShiftRuler(Window* parent, int w, int h, long start=0, long span=10000) :
00066         Window(parent,w,h)
00067     {
00068         Init(w,h,start,span);
00069     }
00070 
00071     ZoomShiftRuler(Window* parent, int x, int y, int w, int h,
00072                    long start=0, long span=10000) :
00073         Window(parent,x,y,w,h)
00074     {
00075         Init(w,h,start,span);
00076     }
00077 
00078     void
00079     SetListener(ZoomShiftRulerListener* listener, void* listenerData = 0)
00080     {
00081         mListener = listener;
00082         mZoomShiftListenerData = listenerData;
00083     }
00084 
00085     virtual void PublishCurrentChanged()
00086     {
00087         if (mListener)
00088             mListener->CurrentChanged(this, mCurrent, mZoomShiftListenerData);
00089     }
00090 
00091     void SetMinMaxDocWidth(long minW=-1, long maxW=-1)
00092     {
00093         mMinDocWidth = (minW == -1) ? 20 : minW;
00094         mMaxDocWidth = (maxW == -1) ? (1<<30) : maxW;
00095         mDocW = (mDocW < mMinDocWidth) ? mMinDocWidth : mDocW;
00096         mDocW = (mDocW > mMaxDocWidth) ? mMaxDocWidth : mDocW;
00097     }
00098     void GetMinMaxDocWidth(long& minW, long& maxW)
00099     {
00100         minW = mMinDocWidth;
00101         maxW = mMaxDocWidth;
00102     }
00103 
00104     void  SetNeedleColor(ULONG col) { mNeedleColor = col; }
00105     ULONG GetNeedleColor()          { return mNeedleColor; }
00106 
00107     void  ShowNeedle(bool show)     { mShowNeedle = show; }
00108     bool  ShowNeedle()              { return mShowNeedle; }
00109 
00110     void  SetSpan(long span)        { mSpan = span; }
00111     long  GetSpan()                 { return mSpan; }
00112 
00113     void  SetStart(long start)      { mStart = start; }
00114     long  GetStart()                { return mStart; }
00115 
00116     bool  IsDragging()              { return mDragging; }
00117 
00118     void  SetAxisY(int y)           { mAxisY = y; }
00119     int   GetAxisY()                { return mAxisY; }
00120 
00121     void  SetTextColor(ULONG col)   { mTextColor = col; }
00122     ULONG GetTextColor()            { return mTextColor; }
00123 
00124     void  SetTextShaded(bool mode)  { mTextShaded = mode; }
00125     bool  GetTextShaded()           { return mTextShaded; }
00126 
00127     void SetTextShadowColors(ULONG shadBg, ULONG shadFg)
00128     {
00129         mTextShadowFg = shadFg;
00130         mTextShadowBg = shadBg;
00131     }
00132     void GetTextShadowColors(ULONG& shadBg, ULONG shadFg)
00133     {
00134         shadFg = mTextShadowFg;
00135         shadBg = mTextShadowBg;
00136     }
00137 
00138     void SetNeedleUpDownHeight(int upH, int downH)
00139     {
00140         mNeedleUpH   = upH;
00141         mNeedleDownH = downH;
00142     }
00143     void GetNeedleUpDownHeight(int& upH, int &downH)
00144     {
00145         upH = mNeedleUpH;
00146         downH = mNeedleDownH;
00147     }
00148 
00149     void SetRange(long start, long span)
00150     {
00151         mStart = start;
00152         mSpan = span;
00153     }
00154     void GetRange(long& start, long& span)
00155     {
00156         start = mStart;
00157         span = mSpan;
00158     }
00159 
00160     void Current(long cur)
00161     {
00162         long oldCur = mCurrent;
00163 
00164         if (cur > mStart + mSpan)
00165             cur = mStart + mSpan;
00166         if (cur < mStart)
00167             cur = mStart;
00168         if ((mCurrent = cur) != oldCur)
00169             PublishCurrentChanged();
00170     }
00171     long Current()
00172     {
00173         return mCurrent;
00174     }
00175 
00176     void ShowCurrentAt(long x)
00177     {
00178         int presX = Unit2Pixel(mCurrent);
00179         mDocX += x-presX;
00180     }
00181 
00182     void MakeCurrentVisible()
00183     {
00184         int presX = Unit2Pixel(mCurrent);
00185         if (presX < mPropagateMargin)
00186             ShowCurrentAt(mPropagateMargin);
00187         if (presX > W()-mPropagateMargin)
00188             ShowCurrentAt(W()-mPropagateMargin);
00189     }
00190 
00191     long Pixel2Unit(int pX)
00192     {
00193         return mStart + ((pX-mDocX)/(double)mDocW)*mSpan;
00194     }
00195 
00196     int Unit2Pixel(long u)
00197     {
00198         u -= mStart;
00199         return mDocX + (u/(double)mSpan)*mDocW;
00200     }
00201 
00202     virtual void DrawNeedle()
00203     {
00204         int curX = Unit2Pixel(mCurrent);
00205         SetSolidLineColor(mNeedleColor);
00206         DrawLine(curX,mAxisY-mNeedleDownH,curX,mAxisY+mNeedleUpH);
00207     }
00208 
00209     virtual void DisplayFunc()
00210     {
00211         Window::DisplayFunc();
00212 
00213         if (mPropagateScrolling && RepeatTime())
00214         {
00215             if (!(mMouseState & (oglShift | oglControl)))
00216             {
00217                 int lastX = mLastX;
00218                 mLastX += (mLastX < mPropagateMargin) ? -40 : 40;
00219 
00220 
00221                 MouseFunc(oglMouseMove, oglLeftButton, mMouseState, lastX, 10);
00222 
00223             }
00224         }
00225 
00226         OGC myOGC;
00227         OGCSave(&myOGC);
00228 
00229         SetStipple((short)oglSolid);
00230         SetSolidLineColor(mForeGroundColor);
00231         DrawLine(mDocX, mAxisY, mDocX+mDocW, mAxisY);
00232         DrawTicks();
00233 
00234         if (mShowNeedle)
00235             DrawNeedle();
00236 
00237         OGCRestore(&myOGC);
00238     }
00239 
00240     void SetDocXClamped(int x)
00241     {
00242         int w = W();
00243         if (x > w/2)
00244             x = w/2;
00245         if (x+mDocW < w/2)
00246             x = -mDocW + w/2;
00247         mDocX = x;
00248     }
00249 
00250     void CheckPropagateScrolling(int x)
00251     {
00252         mPropagateScrolling = (x > W()-mPropagateMargin || x < mPropagateMargin);
00253         oglSys.SetAlwaysDraw(mOglWnd,mPropagateScrolling);
00254     }
00255 
00256     virtual void MouseFunc(int msg, int btn, int state, int x, int y)
00257     {
00258         Window::MouseFunc(msg,btn,state,x,y);
00259 
00260         if (state & oglAlt) return;
00261 
00262         bool shift   = (state & oglShift) != 0;
00263         bool control = (state & oglControl) != 0;
00264 
00265         mMouseState = state;
00266 
00267         if ((msg==oglMouseDown && btn==oglLeftButton) || (!mScaling && control)) 
00268         {
00269             StartRepeatTime();
00270             CheckPropagateScrolling(x);
00271             mClickedUnit = Pixel2Unit(x);
00272             if (!(shift||control))
00273                 Current(mClickedUnit);
00274             mLastX = mClickedX = x;
00275             mDragging = true;
00276             if (control)
00277                 mScaling = true;
00278         }
00279 
00280         if (mScaling && !control)
00281             mScaling = false;
00282 
00283         if (msg == oglMouseUp)
00284         {
00285             mPropagateScrolling = mDragging = mScaling = false;
00286             oglSys.SetAlwaysDraw(mOglWnd, 0);
00287         }
00288     
00289         if (msg == oglMouseMove && mDragging)
00290         {
00291             CheckPropagateScrolling(x);
00292             int dx = x - mLastX;
00293             if (mScaling)
00294             {
00295                 int oldDocW = mDocW;
00296                 mDocW *= (1 + .02*dx);
00297                 if (oldDocW > 0 && mDocW<0) 
00298                     mDocW = oldDocW;
00299 
00300                 if (mDocW < mMinDocWidth)
00301                     mDocW = mMinDocWidth;
00302                 if (mDocW > mMaxDocWidth)
00303                     mDocW = mMaxDocWidth;
00304 
00305                 long clickedPixelNow = Unit2Pixel(mClickedUnit);
00306                 mDocX += mLastX - clickedPixelNow;
00307                 mDocX -= mLastX - mClickedX;
00308             }
00309             else if (shift)
00310                 SetDocXClamped(mDocX+dx);
00311             else
00312                 Current(Pixel2Unit(x));
00313 
00314             mLastX = x;
00315         }
00316     }
00317 
00318 protected:
00319     virtual void DrawTick(long val,int x,int y,long tickSpan,int tickLen=6)
00320     {
00321         DrawLine(x, y-tickLen, x, y);
00322     }
00323 
00324     virtual void DrawMicroTicks(long x, long nextX)
00325     {
00326         long    minX = Unit2Pixel(mStart);
00327         long    maxX = Unit2Pixel(mStart+mSpan);
00328         int     cnt  = 0;
00329 
00330         if (nextX-x <= 0)
00331             nextX = x + 1;
00332 
00333         for (double j=x; j<nextX; j+= (nextX-x)/10.)
00334         {
00335             if (j>minX && j<maxX)
00336                 DrawLine(j,mAxisY-((++cnt%6)?2:4),j,mAxisY);
00337         }
00338     }
00339 
00340     virtual void DrawTicks()
00341     {
00342         int startUnit = Pixel2Unit(0);
00343         int endUnit   = Pixel2Unit(W());
00344 
00345         if (startUnit < mStart)
00346             startUnit = mStart;
00347 
00348         int     pixRange = Unit2Pixel(endUnit) - Unit2Pixel(startUnit);
00349         double  range    = endUnit - startUnit;
00350         double  order    = floor(log10(range));
00351         double  tmpSpan  = mTickSpan = pow(10.,order);
00352         double  quanta[9]= {.5,.2,.1, .05,.02,.01, .005,.002,.001};
00353         
00354         
00355 
00356         int     i = 0;
00357         while (i<9 && range/tmpSpan < (pixRange/140))
00358             tmpSpan = mTickSpan * quanta[i++];
00359         mTickSpan = tmpSpan;
00360         int firstTick = ceil(startUnit / mTickSpan);
00361         int tickCount = floor(endUnit / mTickSpan) - firstTick + 1;
00362 
00363         SetStipple((short)oglSolid);
00364         DrawTick(startUnit, Unit2Pixel(startUnit), mAxisY, mTickSpan);
00365 
00366         int startI = Unit2Pixel(mStart)<0 ? -1 : 0;
00367         for (i=startI; i<tickCount; i++)
00368         {
00369             long val     = (i+firstTick) * mTickSpan;
00370             long x       = Unit2Pixel(val);
00371             long nextX   = Unit2Pixel(val+mTickSpan);
00372 
00373             if (val > mStart+mSpan || x>W())
00374                 break;
00375             DrawMicroTicks(x, nextX);
00376             DrawTick(val, x, mAxisY, mTickSpan);
00377         }
00378     }
00379 
00380 protected:
00381     int                     mAxisY;
00382 
00383     long                    mStart;   
00384     long                    mSpan;    
00385     double                  mTickSpan;
00386 
00387     long                    mCurrent;
00388     bool                    mShowNeedle;
00389     ULONG                   mNeedleColor;
00390     int                     mNeedleUpH;
00391     int                     mNeedleDownH;
00392 
00393     bool                    mDragging;
00394     bool                    mScaling;
00395 
00396     long                    mMinDocWidth;
00397     long                    mMaxDocWidth;
00398 
00399     int                     mMouseState;
00400     int                     mPropagateMargin;
00401     bool                    mPropagateScrolling;
00402     long                    mClickedUnit;
00403     int                     mClickedX;
00404     int                     mLastX;
00405 
00406     bool                    mTextShaded;
00407     ULONG                   mTextShadowFg;
00408     ULONG                   mTextShadowBg;
00409     ULONG                   mTextColor;
00410 
00411 private:
00412     void Init(int w, int h, long start, long span)
00413     {
00414         mListener = 0;
00415         SetDocDimensions(0,0,w,h);
00416         SetMinMaxDocWidth(-1,-1);
00417         SetRange(start,span);
00418         mDragging = mScaling = false;
00419         mCurrent = start;
00420         mShowNeedle = true;
00421         mNeedleColor = oglRED;
00422         mNeedleUpH = mNeedleDownH = 8;
00423         mTextShadowFg = oglDARKGREY;
00424         mTextShadowBg = oglWHITE;
00425         mTextColor = oglBLACK;
00426         mTextShaded = true;
00427         mAxisY = 20;
00428         SetRepeatDelays(40,10);
00429         mPropagateMargin = 50;
00430         mPropagateScrolling = false;
00431         SetDisableOGLViewKeys(true);
00432         SetDisableOGLViewMouse(true);
00433     }
00434 
00435     ZoomShiftRulerListener* mListener;
00436     void*                   mZoomShiftListenerData;
00437 };
00438 } 
00439 
00440 #endif