Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CATGUI/CATKnob.cpp Source File

CATKnob.cpp

Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 /// \file CATKnob.cpp
00003 /// \brief Knob control for GUI
00004 /// \ingroup CATGUI
00005 /// 
00006 /// Copyright (c) 2003-2008 by Michael Ellison.
00007 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00008 ///
00009 // $Author: mikeellison $
00010 // $Date: 2008-01-23 01:43:25 -0600 (Wed, 23 Jan 2008) $
00011 // $Revision:   $
00012 // $NoKeywords: $
00013 //
00014 //---------------------------------------------------------------------------
00015 #include <math.h>
00016 
00017 #include "CATKnob.h"
00018 #include "CATWindow.h"
00019 #include "CATFilterEWMA.h"
00020 #include "CATCursor.h"
00021 #include "CATUtil.h"
00022 #include "CATEditBox.h"
00023 
00024 // base resolution of knob
00025 const CATFloat32 kKNOBSTEP       = 0.001f;
00026 const CATFloat32 kCIRCLEFILTER   = 0.7f;
00027 const CATFloat32 kVERTICALFILTER = 0.5f;
00028 
00029 //---------------------------------------------------------------------------
00030 // CATKnob constructor (inherited from CATControl->CATXMLObject)
00031 // \param element - Type name ("Button")
00032 // \param attribs - attribute information for the window
00033 // \param rootDir - root directory of skin
00034 // \param parent - parent XML object (should be a "Window" element)
00035 //---------------------------------------------------------------------------
00036 CATKnob::CATKnob(      const CATString&             element, 
00037                  const CATString&             rootDir)
00038                  : CATControl(element,  rootDir)
00039 {   
00040     // Defaults
00041     fCursorHidden   = false;
00042     fValueType      = CATVALUE_LINEAR;
00043     fLastKnob      = 0;
00044     fKnobStyle     = CATKNOB_VERTICAL;
00045     fLastKnobStyle  = fKnobStyle;
00046     fFilterCoef    = kVERTICALFILTER;
00047     fFilter        = new CATFilterEWMA(kVERTICALFILTER);
00048     fCommandTrack  = false;   
00049     fMinDegree     = 10.0f;
00050     fMaxDegree     = 350.0f;
00051     fCursor.SetType(CATCURSOR_TOPBOTTOM);
00052 }
00053 
00054 //---------------------------------------------------------------------------
00055 // CATKnob destructor
00056 //---------------------------------------------------------------------------
00057 CATKnob::~CATKnob()
00058 {
00059     if (fFilter)
00060     {
00061         delete fFilter;
00062         fFilter = 0;
00063     }
00064 
00065 }
00066 
00067 void CATKnob::TrackMouseDown(const CATPOINT& point, CATMODKEY modKey)
00068 {
00069 
00070     CATControl::TrackMouseDown(point,modKey);
00071 
00072     fFilter->Reset();
00073     fStartPoint = point;      
00074     fLastPoint = point;
00075     fLastMove = point;
00076     fPressed = true;
00077 
00078     // If we're keeping the mouse in the center, set the point and hide mouse
00079     switch (GetActiveStyle(modKey))
00080     {
00081     case CATKNOB_CIRCLE:            
00082         fFilter->SetCoefficient(fFilterCoef);
00083         this->SetValueFromPoint(point, modKey);
00084         break;
00085 
00086     case CATKNOB_VERTICAL:
00087     default:
00088         {
00089             fFilter->SetCoefficient(fFilterCoef);
00090             this->fCursor.SetType(CATCURSOR_HIDE);
00091             fCursorHidden = true;
00092             CATPOINT cursorPoint = fStartPoint;
00093             this->GetWindow()->WidgetToWindow(this,cursorPoint);
00094             this->GetWindow()->OSSetMouse(cursorPoint,fCursor);
00095         }
00096         break;
00097     }
00098 
00099 
00100 }
00101 
00102 void CATKnob::TrackMouseRelease(const CATPOINT& point, CATMODKEY modKey)
00103 {   
00104     // If we're keeping the mouse in the center, set the point and restore mouse
00105     switch (GetActiveStyle(modKey))
00106     {
00107     case CATKNOB_CIRCLE:
00108         if (fCursorHidden)
00109         {
00110             this->ResetCursorToDefault();   
00111             this->GetWindow()->OSSetCursor(fCursor);
00112         }
00113         break;
00114 
00115     case CATKNOB_VERTICAL:
00116     default:
00117         {
00118             CATPOINT cursorPoint = fStartPoint;
00119             this->ResetCursorToDefault();   
00120             this->GetWindow()->WidgetToWindow(this,cursorPoint);
00121             this->GetWindow()->OSSetMouse(cursorPoint,fCursor);         
00122             fCursorHidden = false;
00123         }
00124         break;
00125     }
00126 
00127     this->fPressed = false;
00128     this->fActive = true;
00129     this->MarkDirty();
00130     this->OnMouseClick();
00131 }
00132 
00133 void CATKnob::TrackMouseMove(const CATPOINT& point, bool left, CATMODKEY modKey)
00134 {   
00135     if (left)
00136     {
00137         fLastMove = point;
00138 
00139         switch (GetActiveStyle(modKey))
00140         {
00141         case CATKNOB_CIRCLE:
00142             {
00143                 if (fCursorHidden)
00144                 {
00145                     ResetCursorToDefault();
00146                     this->GetWindow()->OSSetCursor(fCursor);
00147                     fCursorHidden = false;
00148                 }
00149 
00150                 SetValueFromPoint(point,modKey);
00151             }                        
00152             break;
00153 
00154         case CATKNOB_VERTICAL:
00155         default:
00156             {
00157                 if (!fCursorHidden)
00158                 {
00159                     this->fCursor.SetType(CATCURSOR_HIDE);
00160                     fCursorHidden = true;
00161                 }
00162                 CATInt32 diffY = fLastPoint.y - point.y;
00163                 CATFloat32 keyStep = (modKey & CATMODKEY_SHIFT)?0.1f:1.0f;      
00164                 CATFloat32 delta = diffY*kKNOBSTEP*keyStep*GetValRange();
00165 
00166                 this->fValue += (float)this->fFilter->Filter(delta);
00167 
00168                 // If we're keeping the mouse in the control             
00169                 CATPOINT cursorPoint = fStartPoint;
00170                 this->GetWindow()->WidgetToWindow(this,cursorPoint);
00171                 this->GetWindow()->OSSetMouse(cursorPoint,fCursor);      
00172                 fLastPoint = fStartPoint;
00173             }
00174             break;
00175         }
00176 
00177 
00178         BoundsCheckValue();
00179 
00180         // fLastPoint = point;
00181         CATInt32 knobNumber = (int)((47 * GetValPercent() ) + 0.5);
00182         if (knobNumber != this->fLastKnob)
00183         {
00184             this->MarkDirty();
00185         }
00186 
00187         if (this->fCommandTrack)
00188         {      
00189             this->OnMouseClick();
00190             // Maintain pressed state...
00191             fPressed = true;
00192         }
00193     }
00194 }
00195 
00196 
00197 void CATKnob::OnMouseWheel(    const CATPOINT& point,
00198                            CATFloat32        wheelMove,
00199                            CATMODKEY            modKey)
00200 {
00201 
00202     CATFloat32 keyStep = (modKey & CATMODKEY_SHIFT)?10.0f:100.0f;
00203     CATFloat32 delta = (wheelMove*kKNOBSTEP)*keyStep*GetValRange();
00204     this->fValue += (CATFloat32)this->fFilter->Filter(delta);
00205 
00206     BoundsCheckValue();
00207 
00208     this->MarkDirty();      
00209     this->OnMouseClick();
00210 }
00211 //---------------------------------------------------------------------------
00212 void CATKnob::OnKeyPress(const CATKeystroke& keystroke)
00213 {
00214     CATControl::OnKeyPress(keystroke);
00215 }
00216 
00217 void CATKnob::OnKeyDown(const CATKeystroke& keystroke)
00218 {   
00219     if (keystroke.IsSpecial())
00220     {
00221         CATFloat32 delta = 0;
00222 
00223         switch (keystroke.GetSpecialKey())
00224         {
00225         case CATKEY_LEFT:
00226             delta = -kKNOBSTEP * GetValRange();
00227             break;      
00228         case CATKEY_RIGHT:
00229             delta = kKNOBSTEP * GetValRange();
00230             break;
00231         case CATKEY_UP:
00232             delta = kKNOBSTEP * 10 * GetValRange();
00233             break;
00234         case CATKEY_DOWN:
00235             delta = -kKNOBSTEP * 10 * GetValRange();
00236             break;
00237         case CATKEY_NEXT:
00238             delta = -kKNOBSTEP * 100 * GetValRange();
00239             break;
00240         case CATKEY_PRIOR:
00241             delta = kKNOBSTEP * 100 * GetValRange();
00242             break;
00243 
00244         case CATKEY_HOME:
00245             fValue = fMinValue;
00246             this->MarkDirty();
00247             this->OnMouseClick();
00248             return;
00249             break;
00250 
00251         case CATKEY_END:
00252             fValue = fMaxValue;
00253             this->MarkDirty();
00254             this->OnMouseClick();
00255             return;
00256             break;
00257         }      
00258 
00259         if (delta != 0)
00260         {
00261             fValue += delta;
00262             this->BoundsCheckValue();
00263             this->MarkDirty();      
00264             this->OnMouseClick();
00265         }
00266     }
00267 
00268     // Allow default handling on stuff we don't do.
00269     CATControl::OnKeyDown(keystroke);
00270 }
00271 
00272 //---------------------------------------------------------------------------
00273 CATResult CATKnob::RectFromAttribs()
00274 {
00275     CATResult result = CAT_SUCCESS;
00276     CATRect parentRect;
00277     if (this->fParent != 0)
00278     {
00279         // Right now, the order is:
00280         // Skin->Window->Control.
00281         // Skins have a null rectangle (0,0,0,0),
00282         // Windows have a rectangle in screen coordinates,
00283         // Controls have a rectangle that's relative to their window.
00284         //
00285         // So... 
00286         // Skins don't have a parent or the positioning, so they
00287         // just kinda ignore this function.
00288         //
00289         // Windows get the null rectangle from the skin, so they ignore
00290         // the parent rectangle.
00291         //
00292         // Controls get the parent window's rectangle. 
00293         // Since we zero the origin, it's in the proper coordinates for the 
00294         // control.
00295         //
00296         // In otherwords, this code works for the way it's currently designed,
00297         // but if you change the heirarchy, have embedded controls inside controls,
00298         // or some crazyness like that, it'll need to change.
00299         parentRect = ((CATGuiObj*)fParent)->GetRect();
00300         parentRect.ZeroOrigin();
00301     }
00302 
00303 
00304     CATInt32 xPos       = (CATInt32)this->GetAttribute(L"XPos");
00305     CATInt32 yPos       = (CATInt32)this->GetAttribute(L"YPos");
00306     CATInt32 width      = (CATInt32)this->GetAttribute(L"Width");
00307     CATInt32 height     = (CATInt32)this->GetAttribute(L"Height");
00308 
00309     CATInt32 xMin       = (CATInt32)this->GetAttribute(L"XMin");
00310     CATInt32 yMin       = (CATInt32)this->GetAttribute(L"YMin");
00311     CATInt32 xMax       = (CATInt32)this->GetAttribute(L"XMax");
00312     CATInt32 yMax       = (CATInt32)this->GetAttribute(L"YMax");
00313 
00314     fMinWidth   = (CATInt32)this->GetAttribute(L"MinWidth");
00315     fMinHeight  = (CATInt32)this->GetAttribute(L"MinHeight");
00316     fMaxWidth   = (CATInt32)this->GetAttribute(L"MaxWidth");
00317     fMaxHeight  = (CATInt32)this->GetAttribute(L"MaxHeight");
00318 
00319 
00320     // XPin and YPin may be zero, but we need to know if they are 
00321     // specified.
00322     bool xPinUsed = false;
00323     bool yPinUsed = false;
00324     CATInt32 xPin   = 0;
00325     CATInt32 yPin   = 0;
00326 
00327 
00328     // Get XPin and YPin and flag if present
00329     CATString tmpString = this->GetAttribute(L"XPin");
00330     if (tmpString.IsEmpty() == false)
00331     {
00332         xPin = (CATInt32)tmpString;
00333         xPinUsed = true;
00334     }
00335 
00336     tmpString = this->GetAttribute(L"YPin");
00337     if (tmpString.IsEmpty() == false)
00338     {
00339         yPin = (CATInt32)tmpString;
00340         yPinUsed = true;
00341     }
00342 
00343 
00344     // Sanity check the pins
00345     if (xPinUsed)
00346     {
00347         if ((xPin > 0) || (width != 0) || (xPos < 0))
00348         {
00349             CATString misuseInfo;
00350             misuseInfo << L"Error in skin XML for control: " << this->GetName();
00351             result = CATRESULTDESC(CAT_ERR_SKIN_XPIN_MISUSE,misuseInfo);
00352             xPin = 0;
00353         }
00354     }
00355 
00356     if (yPinUsed)
00357     {
00358         if ((yPin > 0) || (height != 0) || (yPos < 0))
00359         {
00360             CATString misuseInfo;
00361             misuseInfo << L"Error in skin XML for control: " << this->GetName();
00362             result = CATRESULTDESC(CAT_ERR_SKIN_YPIN_MISUSE,misuseInfo);
00363             yPin = 0;
00364         }
00365     }
00366 
00367 
00368     // Image defaults
00369     if (this->fImage)
00370     {      
00371         if (width == 0)
00372         {
00373             width = fImage->Width() / 4;
00374         }
00375 
00376         if (height == 0)
00377         {
00378             height = fImage->Height() / 12;
00379         }
00380     }   
00381 
00382 
00383     // Get the basic rect
00384     //
00385     // If xPinUsed is true, then it's scaled in relation to left/right.
00386     //
00387     // If the parentRect's width is zero, then it's a window
00388     // or skin and negative values are treated as negative values.
00389     //
00390     // If the parentRect's width != 0, then it's a control
00391     // and negative values mean measure from the right of the
00392     // parent for location.
00393     //
00394     // See comments above for design notes.... 
00395     if (xPinUsed)
00396     {
00397         fRect.left    = xPos;
00398         fRect.right   = parentRect.right + xPin + 1;
00399         if ((xMax) && (xMax < fRect.right))
00400         {
00401             fRect.right = xMax;
00402         }      
00403     }
00404     else if ((xPos >= 0) || (parentRect.Width() == 0))
00405     {
00406         fRect.left    = xPos;
00407         fRect.right   = width + xPos;
00408     }
00409     else
00410     {      
00411         fRect.right   = parentRect.right + xPos;
00412         fRect.left    = fRect.right - width;
00413         if ((xMin) && (fRect.left < xMin))
00414         {
00415             fRect.left = xMin;
00416             fRect.right = fRect.left + width;
00417         }
00418     }
00419 
00420     if (yPinUsed)
00421     {
00422         fRect.top     = xPos;
00423         fRect.bottom  = parentRect.bottom + yPin + 1;
00424         if ((yMax) && (yMax < fRect.bottom))
00425         {
00426             fRect.bottom = yMax;
00427         }      
00428     }
00429     else if ((yPos >= 0) || (parentRect.Height() == 0))
00430     {
00431         fRect.top     = yPos;
00432         fRect.bottom  = height + yPos;
00433     }
00434     else
00435     {
00436         fRect.bottom  = parentRect.bottom + yPos;
00437         fRect.top     = fRect.bottom - height;
00438         if ((yMin) && (fRect.top < yMin))
00439         {
00440             fRect.top = yMin;
00441             fRect.bottom = fRect.top + height;
00442         }
00443     }
00444 
00445 
00446 
00447 
00448 
00449     // Check min/max width and height
00450     if (fMinWidth != 0)
00451     {
00452         if (fRect.Width() < fMinWidth)
00453         {
00454             fRect.right = fRect.left + fMinWidth;
00455         }
00456     }
00457     // Don't let rect go negative even if fMinWidth isn't there
00458     else if (fRect.Width() < 1)
00459     {
00460         fRect.right = fRect.left + 1;
00461     }
00462 
00463     if (fMaxWidth != 0)
00464     {
00465         if (fRect.Width() > fMaxWidth)
00466         {
00467             fRect.right = fRect.left + fMaxWidth;
00468         }
00469     }
00470 
00471     // Now for height
00472     if (fMinHeight != 0)
00473     {
00474         if (fRect.Height() < fMinHeight)
00475         {
00476             fRect.bottom = fRect.top + fMinHeight;
00477         }
00478     }
00479     // Don't let rect go negative even if fMinHeight isn't there
00480     else if (fRect.Height() < 1)
00481     {
00482         fRect.bottom = fRect.top + 1;
00483     }
00484 
00485 
00486     if (fMaxHeight != 0)
00487     {
00488         if (fRect.Height() > fMaxHeight)
00489         {
00490             fRect.bottom = fRect.top + fMaxHeight;
00491         }
00492     }   
00493 
00494 
00495     // Implement sizeable controls later or override for them.
00496     // Most controls will be satisfied by the above.
00497     if (fParent)
00498     {
00499         ((CATGuiObj*)fParent)->MarkDirty();
00500     }
00501 
00502     return result;
00503 }
00504 
00505 //---------------------------------------------------------------------------
00506 // Draw() draws the control into the parent window
00507 // \param dirtyRect - portion of control (in window coordinates)
00508 //        that requires redrawing.
00509 //---------------------------------------------------------------------------
00510 void CATKnob::Draw(CATImage* image, const CATRect& dirtyRect)
00511 {
00512     if (this->IsVisible() == false)
00513     {
00514         return;
00515     }
00516 
00517     // sanity check parent image / dirty rectangle
00518     CATRect imgRect(0,0,image->Width(), image->Height());
00519     CATASSERT(imgRect.Inside(dirtyRect), "Update rect is outside of img rect!");
00520 
00521     // Find intersection between dirty rect and us
00522     CATRect drawRect;
00523     bool   drawn = false;
00524 
00525     CATInt32 knobNumber = (int)((47 * GetValPercent() ) + 0.5);
00526     fLastKnob = knobNumber;
00527     CATInt32 knobCol = knobNumber % 4;
00528     CATInt32 knobRow = knobNumber / 4;
00529     CATInt32 knobX = fRect.Width() * knobCol;
00530     CATInt32 knobY = fRect.Height() * knobRow;
00531 
00532 
00533     // Gracefully degrade depending on flags and whether the images are
00534     // available.
00535     if (this->fRect.Intersect(dirtyRect, &drawRect))
00536     {  
00537         CATRect ourRect;
00538         if ( (this->IsEnabled() == false) && (this->fImageDisabled))
00539         {
00540             if (drawRect.Intersect(CATRect(fRect.left, 
00541                 fRect.top, 
00542                 fRect.left + fImageDisabled->Width()/4,
00543                 fRect.top  + fImageDisabled->Height()/12),
00544                 &ourRect))
00545             {
00546                 ourRect.Offset(-fRect.left, -fRect.top);
00547 
00548                 image->Overlay(   this->fImageDisabled,
00549                     drawRect.left, 
00550                     drawRect.top, 
00551                     ourRect.left + knobX,
00552                     ourRect.top + knobY,
00553                     ourRect.Width(),
00554                     ourRect.Height());
00555                 drawn = true;
00556             }        
00557         }
00558         else 
00559         {
00560             if (this->IsPressed() && (this->fImagePressed))
00561             {
00562                 if (drawRect.Intersect(CATRect(fRect.left, 
00563                     fRect.top, 
00564                     fRect.left + fImagePressed->Width()/4,
00565                     fRect.top  + fImagePressed->Height()/12),
00566                     &ourRect))
00567                 {
00568                     ourRect.Offset(-fRect.left, -fRect.top);
00569 
00570                     image->Overlay(   this->fImagePressed,
00571                         drawRect.left, 
00572                         drawRect.top, 
00573                         ourRect.left + knobX,
00574                         ourRect.top + knobY,
00575                         ourRect.Width(),
00576                         ourRect.Height());
00577                     drawn = true;
00578                 }        
00579             }
00580 
00581             if ((!drawn) && (IsFocused() || IsPressed()) && (this->fImageFocus))
00582             {
00583                 if (drawRect.Intersect(CATRect(fRect.left, 
00584                     fRect.top, 
00585                     fRect.left + fImageFocus->Width()/4,
00586                     fRect.top  + fImageFocus->Height()/12),
00587                     &ourRect))
00588                 {
00589                     ourRect.Offset(-fRect.left, -fRect.top);
00590 
00591                     image->Overlay(   this->fImageFocus,
00592                         drawRect.left, 
00593                         drawRect.top, 
00594                         ourRect.left + knobX,
00595                         ourRect.top + knobY,
00596                         ourRect.Width(),
00597                         ourRect.Height());
00598                     drawn = true;
00599                 }        
00600             }
00601 
00602             if ((!drawn) && (IsActive()) && (this->fImageActive))
00603             {
00604                 if (drawRect.Intersect(CATRect(fRect.left, 
00605                     fRect.top, 
00606                     fRect.left + fImageActive->Width()/4,
00607                     fRect.top  + fImageActive->Height()/12),
00608                     &ourRect))
00609                 {
00610                     ourRect.Offset(-fRect.left, -fRect.top);
00611 
00612                     image->Overlay(   this->fImageActive,
00613                         drawRect.left, 
00614                         drawRect.top, 
00615                         ourRect.left + knobX,
00616                         ourRect.top + knobY,
00617                         ourRect.Width(),
00618                         ourRect.Height());
00619                     drawn = true;
00620                 }        
00621             }
00622 
00623         }
00624 
00625         if ((!drawn) && (this->fImage != 0))
00626         {
00627             if (drawRect.Intersect(CATRect(fRect.left, 
00628                 fRect.top, 
00629                 fRect.left + fImage->Width()/4,
00630                 fRect.top  + fImage->Height()/12),
00631                 &ourRect))
00632             {
00633                 ourRect.Offset(-fRect.left, -fRect.top);
00634 
00635                 image->Overlay(   this->fImage,
00636                     drawRect.left, 
00637                     drawRect.top, 
00638                     ourRect.left + knobX,
00639                     ourRect.top + knobY,
00640                     ourRect.Width(),
00641                     ourRect.Height());
00642                 drawn = true;
00643             }        
00644         }
00645 
00646         if (!drawn)
00647         {
00648 
00649             // Right now, just make a big red rectangle where we should go.
00650             image->FillRect(drawRect, fBackgroundColor);
00651         }
00652     }
00653 }
00654 
00655 /// ParseAttributes() parses the known attributes for an object.
00656 CATResult CATKnob::ParseAttributes()
00657 {
00658     CATResult result = CATControl::ParseAttributes();
00659     CATString attrib;
00660 
00661     fCommandTrack = GetAttribute(L"CommandTrack",fCommandTrack);
00662 
00663     attrib = GetAttribute(L"ValueType");
00664     if (attrib.IsEmpty() == false)
00665     {
00666         if (attrib.Compare("dB") == 0)
00667         {
00668             this->fValueType = CATVALUE_DB;         
00669         }
00670         else
00671         {
00672             this->fValueType = CATVALUE_LINEAR;
00673         }       
00674     }
00675 
00676     attrib = GetAttribute(L"KnobStyle");
00677     if (!attrib.IsEmpty())
00678     {
00679         if (attrib.Compare("V",1) == 0)
00680         {
00681             // vertical
00682             fKnobStyle = CATKNOB_VERTICAL;         
00683         }
00684         else if (attrib.Compare("C",1) == 0)
00685         {
00686             // circular
00687             fKnobStyle = CATKNOB_CIRCLE;         
00688         }      
00689     }
00690 
00691     fFilterCoef = GetAttribute(L"Filter",fFilterCoef);
00692     fMinDegree  = GetAttribute(L"MinDegree",fMinDegree);
00693     fMaxDegree = GetAttribute(L"MaxDegree",fMaxDegree);
00694 
00695     return result;
00696 }
00697 
00698 CATKNOB_STYLE CATKnob::GetKnobStyle()
00699 {
00700     return fKnobStyle;
00701 }
00702 
00703 void CATKnob::SetKnobStyle(CATKNOB_STYLE style)
00704 {
00705     fKnobStyle = style;
00706     // IF manually set, override cursor 
00707     switch (fKnobStyle)
00708     {
00709     case CATKNOB_CIRCLE:
00710         fCursor.SetType(CATCURSOR_HAND);
00711         break;
00712     case CATKNOB_VERTICAL:         
00713     default:
00714         fCursor.SetType(CATCURSOR_TOPBOTTOM);
00715         break;
00716     }
00717 }
00718 
00719 void CATKnob::SetValueFromPoint(const CATPOINT& point, CATMODKEY modKey)
00720 {
00721     CATFloat32  curDegree  = (fMaxDegree - fMinDegree) * fValue;
00722     CATInt32   xCenter    = (fRect.right + fRect.left)/2;
00723     CATInt32   yCenter    = (fRect.bottom + fRect.top)/2;
00724 
00725     CATInt32 xDist = point.x - xCenter;
00726     CATInt32 yDist = yCenter - point.y;
00727 
00728     CATFloat32 newDegree   = curDegree;
00729 
00730     if ((xDist == 0) && (yDist == 0))
00731     {
00732         // Don't do anything. the mouse is centered.
00733     }
00734     else if (xDist == 0)
00735     {
00736         // X is 0. y can be pos or neg, but not zero
00737         if (yDist > 0)
00738         {
00739             newDegree = 180;
00740         }
00741         else
00742         {
00743             newDegree = 0;
00744         }                  
00745     }
00746     else if (xDist > 0)
00747     {
00748         // Positive X
00749         if (yDist == 0)
00750         {
00751             newDegree = 270;
00752         }
00753         else if (yDist > 0)
00754         {
00755             newDegree = 180 + ((CATFloat32)atan2((CATFloat32)xDist,(CATFloat32)yDist) * kCATRADTODEG);
00756         }
00757         else
00758         {
00759             newDegree = 180 + ((CATFloat32)atan2((CATFloat32)xDist,(CATFloat32)yDist) * kCATRADTODEG);
00760         }
00761     }
00762     else
00763     {
00764         // Negative X                  
00765         if (yDist == 0)
00766         {
00767             newDegree = 90;
00768         }
00769         else if (yDist > 0)
00770         {
00771             newDegree = 180 + ((CATFloat32)atan2((CATFloat32)xDist,(CATFloat32)yDist) * kCATRADTODEG);
00772         }
00773         else
00774         {
00775             newDegree = 180 + ((CATFloat32)atan2((CATFloat32)xDist,(CATFloat32)yDist) * kCATRADTODEG);
00776         }
00777     }
00778 
00779     if (newDegree < fMinDegree)
00780         newDegree = fMinDegree;
00781 
00782     if (newDegree > fMaxDegree)
00783         newDegree = fMaxDegree;
00784 
00785     fValue = (CATFloat32)fFilter->Filter(((newDegree - fMinDegree)/(fMaxDegree - fMinDegree)));
00786 }
00787 
00788 // PostDraw() draws any stuff that requires an OS-specific draw
00789 // context.
00790 void CATKnob::PostDraw(CATDRAWCONTEXT drawContext, const CATRect& dirtyRect)
00791 {
00792 
00793     switch (fLastKnobStyle)
00794     {
00795     case CATKNOB_CIRCLE:            
00796         CATControl::PostDraw(drawContext,dirtyRect);
00797         break;
00798 
00799     case CATKNOB_VERTICAL:
00800     default:
00801         {  
00802             CATControl::PostDraw(drawContext,dirtyRect);
00803             if (this->fPressed)
00804             {
00805                 CATCursor curs(CATCURSOR_TOPBOTTOM);
00806                 CATPOINT cursP;
00807                 CATRect absRect = this->GetRectAbs();
00808                 cursP.x = (absRect.left + absRect.right)/2 - 5;
00809                 cursP.y = (absRect.top+ absRect.bottom)/2 - 5;
00810                 GetWindow()->OSDrawCursor(drawContext, cursP, curs);
00811             }
00812         }
00813         break;
00814     }
00815 }
00816 
00817 void CATKnob::TrackMouseTimer(CATMODKEY modKey)
00818 {
00819     if (fKnobStyle == CATKNOB_CIRCLE)
00820     {
00821         CATFloat32 tmpVal = fValue;
00822         SetValueFromPoint(this->fLastMove, modKey);
00823         if (fabs(tmpVal - fValue) > 0.001)
00824         {
00825             CATInt32 knobNumber = (int)((47 * GetValPercent() ) + 0.5);
00826             if (knobNumber != this->fLastKnob)
00827             {         
00828                 MarkDirty();
00829             }
00830 
00831             if (this->fCommandTrack)
00832             {
00833                 this->OnMouseClick();
00834                 // Maintain pressed state...
00835                 fPressed = true;
00836             }
00837         }
00838     }
00839 }
00840 
00841 
00842 CATString CATKnob::GetHint() const
00843 {
00844     CATString retString = CATControl::GetHint();
00845     if (fShowHintValue)
00846     {
00847         CATString hintVal;
00848         if (fValueType == CATVALUE_DB)
00849         {
00850             if (fValue == 0.0f)
00851             {
00852                 hintVal.Format(" ( Off )");
00853             }
00854             else
00855             {
00856                 CATFloat32 dbValue = CATLinearToDBValue(fValue);
00857                 hintVal.Format(" ( %c%.2fdB - %.2f - %.2f)",(dbValue > 0)?'+':'-', fabs(dbValue), CATLinearToDBGain(fValue), fValue );
00858             }
00859         }
00860         else
00861         {
00862             hintVal.Format(" ( %.2f )",this->GetValue());
00863         }
00864         retString << hintVal;
00865     }
00866     return retString;
00867 }
00868 
00869 // OnMouseDoubleClick() is called the mouse is double clicked.
00870 //
00871 // \param modKey - Key state modifiers for ctrl/shift/alt/etc.
00872 void CATKnob::OnMouseDoubleClick( CATMODKEY modKey)
00873 {
00874     this->SetValue(fDefValue);
00875     this->MarkDirty();
00876 }
00877 
00878 CATKNOB_STYLE CATKnob::GetActiveStyle( CATMODKEY modKey )
00879 {
00880     CATKNOB_STYLE curStyle = fKnobStyle;
00881     // Alt key inverts knob style
00882     if (modKey & CATMODKEY_ALT)
00883     {
00884         switch (fKnobStyle)
00885         {
00886         case CATKNOB_CIRCLE:
00887             curStyle = CATKNOB_VERTICAL;
00888             break;
00889         case CATKNOB_VERTICAL:
00890         default:
00891             curStyle = CATKNOB_CIRCLE;
00892             break;
00893         }
00894     }
00895     fLastKnobStyle = curStyle;
00896     return curStyle;
00897 }
00898 

Generated on Mon Feb 11 04:09:54 2008 for Game Accessibility Suite by doxygen 1.5.4