Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

ZoomShiftRuler.h

Go to the documentation of this file.
00001 //345678901234567890123456789012345678901234567890123456789012345678901234567890
00002 // ZoomShiftRuler:
00003 //  - Ruler based on the abtract concept of integer units.
00004 //  - Class specializations can give meaning to the units.
00005 //      Example of such a specialization is the WindowTimeLine class,
00006 //      which defines unit to be 1 ms, and handles the drawing of ticks
00007 //      showing the time.
00008 //  - ZoomShiftRuler allows the user to shift the ruler horizontally by
00009 //    dragging the mouse while holding the SHIFT key down.
00010 //  - ZoomShiftRuler allows the user to zoom in on the ruler by
00011 //    dragging the mouse while holding the CONTROL key down.
00012 //  - ZoomShiftRuler maintains the notion of a current value, which the
00013 //    user can change with the mouse. This feature can be used for example
00014 //    to steer a parameter of another component, like the frame position
00015 //    of a VideoPlayer.
00016 //  - ZoomShiftRuler is based on the DocDimensions interface, allowing
00017 //    other components, like the DocScroller, to scroll and zoom it.
00018 //  - ZoomshiftRuler uses the RepeatTimer interface to propagate scrolling
00019 //    when the user holds down the mouse before the first mPropagateMargin pixels, or after
00020 //    the last mPropagateMargin pixels of its window.
00021 //  - In its basic form the ZoomShiftRuler draws simple ticks without any text.
00022 //    It does, however, support the notion of drawing text in a single
00023 //    color or shadowed. Other classes that do draw text at the ticks
00024 //    are supposed to honor the text settings maintained in this class.
00025 //
00026 //  ToDo:   - Make it optional whether the user can shift and/or zoom.
00027 //          - Optional buttons indicating what happens when the mouse
00028 //            is used without modifier keys, to allow use without
00029 //            knowledge of the CONTROL and SHIFT modifiers.
00030 //
00031 // Author: Richard van Balen
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 //static int cnt = 0;
00220 //printf("propMouse %d\n", cnt++);
00221                 MouseFunc(oglMouseMove, oglLeftButton, mMouseState, lastX, 10);
00222 //printf("propMouse done %d\n", --cnt);
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) // Overflow
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         //Alternative:
00354         //double  quanta[9]= {.5,.25,.1, .025,.02,.01, .0025,.002,.001};
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 } // namespace OglGui
00439 
00440 #endif

Generated on Fri Mar 19 09:31:42 2010 for ImpalaSrc by  doxygen 1.5.1