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

CATWindow.cpp

Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 /// \file CATWindow.cpp
00003 /// \brief Basic windowing class
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-31 09:36:59 -0600 (Thu, 31 Jan 2008) $
00011 // $Revision:   $
00012 // $NoKeywords: $
00013 //---------------------------------------------------------------------------
00014 #include <math.h>
00015 
00016 #include "CATWindow.h"
00017 #include "CATOSFuncs.h"
00018 #include "CATApp.h"
00019 #include "CATControl.h"
00020 #include "CATControlWnd.h"
00021 #include "CATEventDefs.h"
00022 #include "CATLabel.h"
00023 #include "CATPrefs.h"
00024 #include "CATSwitch.h"
00025 
00026 /// Docking distance - if autodock is on, and we are within this number
00027 /// of pixels of an edge, we dock.
00028 const CATInt32 kDOCKDISTANCE = 10;
00029 
00030 //---------------------------------------------------------------------------
00031 // CATWindow constructor (inherited from CATXMLObject)
00032 // \param element - Type name ("Window")
00033 // \param attribs - attribute information for the window
00034 // \param parent - parent XML object (should be a "Skin" element)
00035 //---------------------------------------------------------------------------
00036 CATWindow::CATWindow(  const CATString&             element, 
00037                        const CATString&             rootDir)
00038 : CATGuiObj(element,  rootDir)
00039 {
00040     // Remember that these come after the attribute translation.
00041     // If a variable needs to be initialized for the attrib translation,
00042     // then do it in the constructor list before CATGuiObj()'s
00043     fIsOverlapped     = false;
00044     fIsTemplate       = false;
00045     fMaximized        = false;
00046     fAutoDock         = true;
00047     fRightTrack         = 0;
00048     fMouseInWindow    = 0;
00049     fMouseTrackTarget = 0;
00050     fActiveControl    = 0;
00051     fFocusControl     = 0;
00052     fLastMouseUpdate  = 0;
00053     fStatusLabel      = 0;   
00054     fScreenPos.x      = 0;
00055     fScreenPos.y      = 0;
00056     fUserIcon         = 0;
00057 
00058     fBaseSize.cx      = 0;
00059     fBaseSize.cy      = 0;
00060     fToolTip          = 0;
00061     fCurTool          = 0;
00062     fUseToolTips      = true;
00063     fToolTipFore      = CATColor(0,0,0);
00064     fToolTipBg        = CATColor(255,255,255);
00065 
00066     fLeftSlack        = fRightSlack = fTopSlack = fBottomSlack = 0;
00067 
00068     fPrimary          = false;
00069     fCaptionBar       = true;
00070 
00071     fDragAnywhere     = false;
00072     fDragging         = false;
00073     fDragLastPoint.x  = fDragLastPoint.y = 0;
00074 
00075     fSizeable         = true;
00076     fPostRegion       = 0;
00077     fImageCopy        = 0;
00078     fRegistered       = false;
00079     fVisible          = false;
00080     fWindow           = 0;   
00081     fSkin             = 0;
00082     fExiting          = false;
00083     fExitThread       = false;
00084 
00085     fCmdThread = 0;
00086 }
00087 
00088 CATResult CATWindow::PostThreadedCommand(CATCommand& cmd)
00089 {
00090     CATResult result = CAT_SUCCESS;
00091 
00092     if (CATFAILED(result = fThreadedCmdLock.Wait()))
00093         return result;
00094 
00095     result = fThreadedCmdQueue.Queue(cmd);
00096 
00097     fThreadedCmdLock.Release();
00098 
00099     if  (CATSUCCEEDED(result))
00100     {
00101         fThreadedCmdSignal.Fire();
00102     }
00103 
00104     return result;
00105 }
00106 
00107 void CATWindow::ThreadedCmdThread()
00108 {
00109     while (true)
00110     {
00111         fThreadedCmdSignal.Wait();
00112         if (fExitThread)
00113         {
00114             CATTRACE("Received posted exit for window.");
00115             return;
00116         }
00117 
00118         fThreadedCmdLock.Wait();
00119         while (fThreadedCmdQueue.Size())
00120         {
00121             CATCommand curCommand;
00122             if (CATSUCCEEDED(fThreadedCmdQueue.Next(curCommand)))
00123             {
00124                 // Release lock on commands to allow new commands issued 
00125                 fThreadedCmdLock.Release();
00126 
00127 
00128                 this->OnThreadedCommand(curCommand);
00129 
00130 
00131                 // Re-aquire lock on commands after command has processed for loop
00132                 fThreadedCmdLock.Wait();
00133             }           
00134         }       
00135 
00136         // Currently own lock, so size won't change
00137         fThreadedCmdSignal.Reset();
00138 
00139         // Release lock.
00140         fThreadedCmdLock.Release();
00141     }
00142 }
00143 
00144 //---------------------------------------------------------------------------
00145 // Load() loads the skin in
00146 //---------------------------------------------------------------------------
00147 CATResult CATWindow::Load(CATPROGRESSCB             progressCB,
00148                           void*                     progressParam,
00149                           CATFloat32                        progMin,
00150                           CATFloat32                        progMax)
00151 {
00152     CATResult testResult = CAT_SUCCESS;
00153     CATResult result = CAT_SUCCESS;
00154 
00155     if (CATFAILED(result = CATGuiObj::Load(progressCB, progressParam, progMin, progMax)))
00156     {
00157         return result;
00158     }   
00159 
00160     // Attempt to register this window - throw on failure
00161     fClassName  = gApp->GetAppName() << "_" << fName;
00162 
00163     if (CATFAILED(testResult = RegWindow()))
00164     {
00165         return testResult;
00166     }
00167     fRegistered = true;
00168     fStatusBarHint = fHintText;   
00169     testResult = ResetBackground();
00170     if (CATFAILED(testResult))
00171     {
00172         return testResult;
00173     }
00174 
00175     fStatusLabel = (CATLabel*)this->FindControlAndVerify("StatusLabel","Label");
00176     EnableObject("MaximizeSwitch",fSizeable);
00177 
00178 
00179     return result;
00180 }
00181 
00182 //---------------------------------------------------------------------------
00183 //---------------------------------------------------------------------------
00184 CATResult CATWindow::ResetBackground()
00185 {
00186     CATResult result = CAT_SUCCESS;
00187     if (fImageCopy)
00188     {
00189         CATImage::ReleaseImage(fImageCopy);
00190     }
00191 
00192     if (CATFAILED(result = CATImage::CreateImage(   fImageCopy, 
00193                                                     fRect.Width(), 
00194                                                     fRect.Height(), 
00195                                                     false, 
00196                                                     false)))
00197     {
00198         return result;
00199     }
00200 
00201     // If we have an image, copy it or tile it into the background
00202     if (fImage)
00203     {
00204         if ((fImage->Width() == fImageCopy->Width()) && 
00205             (fImage->Height() == fImageCopy->Height()))
00206         {
00207             // Window is same size as image. Good. Just do a copy.
00208             result =fImageCopy->CopyOver(fImage,0,0,0,0,0,0);
00209         }
00210         else
00211         {
00212             // OK... gotta do tiling of the background                
00213             CATInt32 yPos = 0;
00214             CATInt32 totalHeight = fImageCopy->Height();
00215             while (totalHeight > 0)
00216             {
00217                 CATInt32 xPos = 0;
00218                 CATInt32 copyHeight = CATMin(fImage->Height(), totalHeight);
00219                 CATInt32 totalWidth = fImageCopy->Width();
00220 
00221                 while (totalWidth > 0)
00222                 {
00223                     CATInt32 copyWidth = CATMin(fImage->Width(), totalWidth);               
00224                     result = fImageCopy->CopyOver(fImage,xPos,yPos,0,0,copyWidth,copyHeight);
00225                     xPos += copyWidth;
00226                     totalWidth -= copyWidth;
00227                 }
00228 
00229                 yPos += copyHeight;
00230                 totalHeight -= copyHeight;
00231             }
00232         }
00233     }
00234     else
00235     {
00236         // No image - 
00237         result = fImageCopy->FillRect(fRect,this->fBackgroundColor);
00238     }
00239 
00240     // Reset region information
00241     if (fPostRegion)
00242     {
00243         OSFreeRegion(fPostRegion);
00244         fPostRegion = 0;
00245     }
00246 
00247     // Generate new region
00248     CATStack<CATRect> postRects;
00249     if (this->GetPostRects(postRects))
00250     {
00251         // Got some post rects...
00252         this->fPostRegion = this->OSGenRegion(postRects);      
00253     }
00254 
00255     return result;
00256 }
00257 
00258 //---------------------------------------------------------------------------
00259 /// CleanBackground() cleans the dirty rectangle in the background
00260 //---------------------------------------------------------------------------
00261 CATResult CATWindow::CleanBackground( CATRect* dirtyRect )
00262 {
00263     CATResult result = CAT_SUCCESS;
00264 
00265     // If no background copy to clean, reset it.
00266     if (fImageCopy == 0)
00267     {
00268         return this->ResetBackground();
00269     }
00270 
00271     // If no rectangle was passed, do the whole thing.
00272     CATRect cleanRect(fRect);
00273     if (dirtyRect != 0)
00274     {
00275         cleanRect = *dirtyRect;
00276     }
00277 
00278     // If no background image, just fill with red.
00279     if (fImage == 0)
00280     {
00281         return fImageCopy->FillRect(cleanRect, fBackgroundColor);
00282     }
00283 
00284 
00285     // Got an image - copy or tile it
00286     if ((fImage->Width() == fImageCopy->Width()) && 
00287         (fImage->Height() == fImageCopy->Height()))
00288     {
00289         CATRect drawRect;
00290         CATRect imageRect(0,0,fImage->Width(), fImage->Height());
00291         cleanRect.Intersect(imageRect,&drawRect);
00292         // Window is same size as image. Good. Just do a copy.
00293         result = fImageCopy->CopyOver( fImage,
00294             drawRect.left,
00295             drawRect.top,
00296             drawRect.left,
00297             drawRect.top,
00298             drawRect.Width(),
00299             drawRect.Height());
00300     }
00301     else
00302     {
00303         // OK... gotta do tiling of the background, but only within the
00304         // rectangle.
00305         CATInt32 yPos = cleanRect.top;
00306         CATInt32 totalHeight = cleanRect.Height();
00307         CATInt32 offsetY = yPos % fImage->Height();
00308 
00309         while (totalHeight > 0)
00310         {
00311             CATInt32 xPos = cleanRect.left;
00312             CATInt32 copyHeight = CATMin(fImage->Height() - offsetY, totalHeight);
00313             CATInt32 totalWidth = cleanRect.Width();
00314             CATInt32 offsetX = xPos % fImage->Width();
00315 
00316             while (totalWidth > 0)
00317             {
00318                 CATInt32 copyWidth = CATMin(fImage->Width() - offsetX, totalWidth);               
00319                 result = fImageCopy->CopyOver(fImage,xPos,yPos,offsetX,offsetY,copyWidth,copyHeight);
00320                 xPos += copyWidth;
00321                 totalWidth -= copyWidth;
00322                 offsetX = 0;
00323             }
00324 
00325             offsetY = 0;
00326             yPos += copyHeight;
00327             totalHeight -= copyHeight;
00328         }
00329     }
00330 
00331     return result;
00332 }
00333 
00334 //---------------------------------------------------------------------------
00335 // CATWindow destructor
00336 //---------------------------------------------------------------------------
00337 CATWindow::~CATWindow()
00338 {
00339 
00340     fExiting = true;
00341 
00342     // Kill any events.
00343     fEventLock.Wait();
00344     while (fEventQueue.Size() > 0)
00345     {
00346         CATEvent* event = 0;
00347         if (CATSUCCEEDED(fEventQueue.Next(event)))
00348         {
00349             delete event;
00350         }
00351     }
00352     fEventLock.Release();
00353 
00354     // If the window is still visible when we're deleted, we need to
00355     // nuke it.
00356     if (fWindow)
00357     {
00358         this->Hide(true);
00359     }
00360 
00361     if (fPostRegion)
00362     {
00363         OSFreeRegion(fPostRegion);
00364         fPostRegion = 0;
00365     }
00366 
00367     if (fImageCopy)
00368     {
00369         CATImage::ReleaseImage(fImageCopy);
00370     }
00371 
00372     if (fRegistered)
00373     {
00374         GGUnregWindow();
00375         fRegistered = false;
00376     }
00377 }
00378 
00379 //---------------------------------------------------------------------------
00380 //---------------------------------------------------------------------------
00381 void CATWindow::MarkDirty(CATRect* dirtyRect, bool force )
00382 {
00383     // even if force is true, on a window we ignore if not visible.
00384     if (!fVisible)
00385         return;
00386 
00387     CATRect invRect(this->fRect);
00388 
00389     if (dirtyRect != 0)
00390     {
00391         invRect = *dirtyRect;
00392     }
00393 
00394     if (fWindow != 0)
00395     {
00396         CATInvalidateRect( this->fWindow, invRect);
00397     }
00398 }
00399 
00400 
00401 //---------------------------------------------------------------------------
00402 void CATWindow::Draw(CATImage* image, const CATRect& dirtyRect)
00403 {
00404     CATXMLObject* curChild = 0;
00405     CATUInt32 index;
00406     CATUInt32 numChildren = this->GetNumChildren();
00407     for (index = 0; index < numChildren; index++)
00408     {
00409         if (0 != (curChild = GetChild(index)))
00410         {
00411             CATWidget* curControl = (CATWidget*)curChild;            
00412             curControl->Draw(image,dirtyRect);         
00413         }
00414     }
00415 }
00416 //---------------------------------------------------------------------------
00417 void CATWindow::PostDraw(CATDRAWCONTEXT context, const CATRect& dirtyRect)
00418 {
00419     CATXMLObject* curChild = 0;
00420     CATUInt32 numChildren = this->GetNumChildren();
00421 
00422     for (CATUInt32 i = 0; i < numChildren; i++)
00423     {
00424         if (0 != (curChild = GetChild(i)))
00425         {
00426             CATWidget* curControl = (CATWidget*)curChild;
00427             curControl->PostDraw(context,dirtyRect);               
00428         }
00429     }   
00430 }
00431 
00432 
00433 //---------------------------------------------------------------------------
00434 //---------------------------------------------------------------------------
00435 void CATWindow::OnCreate()
00436 {
00437     // Let children know and respond to creation if they need to.
00438     CATUInt32 numControls = this->GetNumChildren();
00439     for (CATUInt32 i = 0; i < numControls; i++)
00440     {
00441         CATXMLObject* curChild = 0;
00442         if (0 != (curChild = GetChild(i)))
00443         {
00444             CATWidget* curControl = (CATWidget*)curChild;
00445             curControl->OnParentCreate();
00446         }
00447     }
00448     OSBuildToolTips();
00449 
00450     this->OSStartCmdThread();
00451 }
00452 
00453 void CATWindow::OnDestroy()
00454 {
00455     // Finish any pending commands
00456     OSWaitOnCmdThread();
00457 
00458     OSHideToolTip();
00459     if (fToolTip != 0)
00460     {
00461         DestroyWindow(fToolTip);
00462         fToolTip = 0;
00463     }
00464 
00465     if (this->fSizeable)
00466     {
00467         SetPref("Width", fRect.Width());
00468         SetPref("Height", fRect.Height());         
00469     }
00470 
00471     SetPref("XPos", fScreenPos.x);
00472     SetPref("YPos", fScreenPos.y);
00473 
00474     this->fCWT.clear();
00475 
00476     // Let children know and respond to destruction if they need to.
00477     CATUInt32 numControls = this->GetNumChildren();
00478     for (CATUInt32 i = 0; i < numControls; i++)
00479     {
00480         CATXMLObject* curChild = 0;
00481         if (0 != (curChild = GetChild(i)))
00482         {
00483             CATWidget* curControl = (CATWidget*)curChild;
00484             curControl->OnParentDestroy();
00485         }
00486     }
00487 
00488     this->fVisible = false;
00489     this->fWindow = 0;
00490 
00491     // Let everyone know we're hidden now
00492     CATInt32 lRes = 0;
00493     gApp->OnEvent( CATEvent(CATEVENT_WINDOW_HIDDEN,0,0,0,0,0,this->fName,"","",this),lRes);
00494 }
00495 //---------------------------------------------------------------------------
00496 //---------------------------------------------------------------------------
00497 void CATWindow::OnMove(const CATPOINT& newPos)
00498 {   
00499     fScreenPos = newPos;
00500 }
00501 //---------------------------------------------------------------------------
00502 //
00503 //---------------------------------------------------------------------------
00504 bool CATWindow::CalcSlack(  CATInt32&  movePos, 
00505                           CATInt32&  opposite,
00506                           const    CATInt32& dockPos, 
00507                           CATInt32&  slackCounter,
00508                           bool     inside)
00509 {
00510 
00511     // Are we within docking range?
00512     CATInt32 diff = (movePos - dockPos) * (inside?1:-1);
00513     if ( CATAbs(diff) < kDOCKDISTANCE)
00514     {
00515         // In docking range
00516         slackCounter += diff;
00517         if (CATAbs(slackCounter) < kDOCKDISTANCE)
00518         {
00519             movePos -= diff;
00520             opposite -= diff;
00521             return true;
00522         }
00523         else
00524         {
00525             movePos += slackCounter;
00526             opposite += slackCounter;
00527             slackCounter = 0;
00528             return true;
00529         }
00530     }
00531     else
00532     {
00533         if (slackCounter)
00534         {
00535             movePos += slackCounter;
00536             opposite += slackCounter;
00537             slackCounter = 0;
00538             return true;
00539         }
00540     }
00541     return false;
00542 }
00543 
00544 //---------------------------------------------------------------------------
00545 bool CATWindow::OnMoving(CATRect& moveRect, const CATRect& wndRect)
00546 {
00547     if (fAutoDock == false)
00548     {
00549         return false;
00550     }
00551 
00552     // AutoDocking...
00553     bool dockChanged = false;
00554     CATRect dockRect = OSGetDockRect();   
00555 
00556     // Dock to screen for baseline..
00557     CATRect tmpRect = moveRect;
00558     dockChanged |= CalcSlack(moveRect.left,   moveRect.right,   dockRect.left,    fLeftSlack,      true);
00559     dockChanged |= CalcSlack(moveRect.top,    moveRect.bottom,  dockRect.top,     fTopSlack,       true);
00560     dockChanged |= CalcSlack(moveRect.right,  moveRect.left,    dockRect.right,   fRightSlack,     true);
00561     dockChanged |= CalcSlack(moveRect.bottom, moveRect.top,     dockRect.bottom,  fBottomSlack,    true);
00562 
00563     // dock to other windows in skin? feature for later....
00564 
00565     return dockChanged;
00566 }
00567 //---------------------------------------------------------------------------
00568 //---------------------------------------------------------------------------
00569 CATResult CATWindow::OnEvent(const CATEvent& event, CATInt32& retVal)
00570 {
00571     CATResult result = CAT_SUCCESS;
00572     CATResult testResult = CAT_SUCCESS;
00573 
00574     switch (event.fEventCode)
00575     {
00576     case CATEVENT_GUI_UPDATE:
00577         // Window Update request.
00578         this->Update();
00579         // increment result value
00580         retVal++;
00581         return CAT_SUCCESS;
00582         break;
00583 
00584     default:
00585         break;
00586     }
00587 
00588     if (CAT_SUCCESS != (testResult = CATGuiObj::OnEvent(event,retVal)))
00589     {
00590         result = testResult;
00591     }
00592 
00593     return result;
00594 }
00595 
00596 //---------------------------------------------------------------------------
00597 //---------------------------------------------------------------------------
00598 void CATWindow::Show( CATWND parentWnd)
00599 {
00600     fVisible = false;
00601     if (fWindow == 0)
00602     {      
00603         CATResult result;
00604         if (CATFAILED(result = OSCreateWnd(parentWnd)))
00605         {
00606             DisplayError(result);
00607             return;
00608         }
00609         SetFocusNext();
00610     }
00611 
00612     if (fWindow != 0)
00613     {  
00614         OSShowWnd();
00615         fVisible = true;
00616     }
00617 
00618     // Let everyone know we're showing now.
00619     CATInt32 lRes = 0;
00620     gApp->OnEvent( CATEvent(CATEVENT_WINDOW_SHOWN,0,0,0,0,0,this->fName,"","",this),lRes);
00621 }
00622 
00623 
00624 void CATWindow::Show( CATWindow* parent, CATPOINT* origin)
00625 {
00626     fVisible = false;
00627     HWND parentWnd = 0;
00628     if (parent)
00629         parentWnd = parent->OSGetWnd();
00630 
00631     if (fWindow == 0)
00632     {
00633         CATResult result;        
00634         if (CATFAILED(result = OSCreateWnd(parentWnd)))
00635         {
00636             DisplayError(result);
00637             return;
00638         }
00639         SetFocusNext();
00640     }
00641 
00642     if (fWindow != 0)
00643     {  
00644         if (origin)
00645         {
00646             CATRect wndRect = OSGetWndRect();
00647             wndRect.SetOrigin(*origin);
00648             this->OSMoveWnd(wndRect);
00649         }
00650         OSShowWnd();
00651         fVisible = true;
00652     }
00653 
00654     // Let everyone know we're showing now.
00655     CATInt32 lRes = 0;
00656     gApp->OnEvent( CATEvent(CATEVENT_WINDOW_SHOWN,0,0,0,0,0,this->fName,"","",this),lRes);
00657 }
00658 
00659 //---------------------------------------------------------------------------
00660 //---------------------------------------------------------------------------
00661 void CATWindow::Hide(bool destroyWnd)
00662 {
00663     OSHideToolTip();
00664     if (fWindow)
00665     {
00666         if (!destroyWnd)
00667         {
00668             if (fVisible)
00669             {
00670                 OSHideWnd();
00671                 // Let everyone know we're hidden now
00672                 CATInt32 lRes = 0;
00673                 gApp->OnEvent( CATEvent(CATEVENT_WINDOW_HIDDEN,0,0,0,0,0,this->fName,"","",this),lRes);
00674             }
00675         }
00676         else
00677         {
00678             OSDestroyWnd();
00679         }
00680     }
00681 
00682     fVisible = false;
00683 }
00684 //---------------------------------------------------------------------------
00685 //---------------------------------------------------------------------------
00686 bool CATWindow::IsVisible(const CATGuiObj* child) const
00687 {
00688     return fVisible;
00689 }
00690 
00691 void CATWindow::OnSize(const CATRect& newRect)
00692 {   
00693     CATResult result = CAT_SUCCESS;
00694     if ((newRect.Width() == 0) && (newRect.Height() == 0))
00695         return;
00696 
00697     // Set our new size
00698     this->fRect = newRect;
00699 
00700     // Let the kids know...
00701     CATXMLObject* curChild = 0;
00702     CATUInt32 numChildren = this->GetNumChildren();
00703     for (CATUInt32 i = 0; i < numChildren; i++)
00704     {
00705         if (0 != (curChild = GetChild(i)))
00706         {
00707             CATWidget* curControl = (CATWidget*)curChild;
00708 
00709 
00710             if (CATFAILED(result = curControl->RectFromAttribs()))
00711             {
00712                 DisplayError(result);
00713             }
00714 
00715         }
00716     }
00717     
00718     // Reset the background
00719     if (CATFAILED(result = this->ResetBackground()))
00720     {
00721         //DisplayError(result);
00722     }
00723 }
00724 
00725 bool CATWindow::OnClose()
00726 {   
00727     // Default behavior is to notify the app and use its response.
00728     CATInt32 result = 1;
00729     gApp->OnEvent( CATEvent(CATEVENT_WINDOW_CLOSE,0,0,0,0,0,this->fName,"","",this), result);
00730 
00731     // True allows the window to close, which is default behaviour.
00732     return (result != 0);  
00733 }
00734 
00735 
00736 // RectFromAttribs() recalculates the control's rectangle from
00737 // the attributes.  This can only be called after ParseAttributes() has
00738 // loaded the images.
00739 CATResult CATWindow::RectFromAttribs()
00740 {
00741 
00742     CATResult result = CATGuiObj::RectFromAttribs();
00743     if (CATFAILED(result))
00744     {
00745         return result;
00746     }
00747 
00748     // Adjust position and height from
00749     fScreenPos.x = fRect.left;
00750     fScreenPos.y = fRect.top;
00751 
00752     fRect.ZeroOrigin();
00753 
00754     CATInt32 left = 0;
00755     CATInt32 top = 0;
00756 
00757     // Sizeable windows save their size, too.
00758     if (this->fSizeable)
00759     {
00760         CATInt32 width = fRect.Width();
00761         CATInt32 height = fRect.Height();
00762 
00763         if (GetPref("Width",width))
00764         {
00765             fRect.right = width;
00766         }
00767 
00768         if (GetPref("Height",height))
00769         {
00770             fRect.bottom = height;
00771         }
00772     }
00773     
00774     if (fBaseSize.cx == 0)
00775         fBaseSize.cx = fRect.Width();
00776     
00777     if (fBaseSize.cy == 0)
00778         fBaseSize.cy = fRect.Height();
00779 
00780     return result;
00781 }
00782 
00783 /// ParseAttributes() parses the known attributes for an object.
00784 CATResult CATWindow::ParseAttributes()
00785 {
00786     if (this->fParent)
00787     {
00788         if (0 == wcscmp(L"Skin",fParent->GetType()))
00789         {
00790             this->fSkin = (CATSkin*)this->fParent;
00791         }
00792     }
00793 
00794     CATResult result = CATGuiObj::ParseAttributes();
00795     CATString attrib;
00796 
00797     fPrimary     = GetAttribute(L"Primary",     fPrimary);
00798     fSizeable    = GetAttribute(L"Sizeable",    fSizeable);
00799     fScale       = GetAttribute(L"Scale",       fScale);
00800     fBaseSize.cx = GetAttribute(L"BaseWidth",   fBaseSize.cx);
00801     fBaseSize.cy = GetAttribute(L"BaseHeight",  fBaseSize.cy);
00802 
00803 
00804     fCaptionBar = GetAttribute(L"CaptionBar",fCaptionBar);
00805     if (fCaptionBar == false)
00806         fDragAnywhere = true;
00807 
00808     fDragAnywhere   = GetAttribute(L"DragAnywhere",fDragAnywhere);
00809     fAutoDock       = GetAttribute(L"AutoDock",    fAutoDock);
00810     fUseToolTips    = GetAttribute(L"ToolTips",    fUseToolTips);
00811 
00812     attrib = GetAttribute(L"ToolTipFore");  
00813     if (!attrib.IsEmpty())
00814     {
00815         CATUInt32 rawColor = attrib.FromHex();
00816         this->fToolTipFore.r = (CATUInt8)((rawColor & 0xff0000) >>16);
00817         this->fToolTipFore.g = (CATUInt8)((rawColor & 0xff00) >> 8);
00818         this->fToolTipFore.b = (CATUInt8)(rawColor & 0xff);
00819         this->fToolTipFore.a = 255;
00820     }
00821 
00822     fIconPath = GetAttribute(L"Icon");
00823 
00824     attrib = GetAttribute(L"ToolTipBg");    
00825     if (!attrib.IsEmpty())
00826     {
00827         CATUInt32 rawColor = attrib.FromHex();
00828         this->fToolTipBg.r = (CATUInt8)((rawColor & 0xff0000) >>16);
00829         this->fToolTipBg.g = (CATUInt8)((rawColor & 0xff00) >> 8);
00830         this->fToolTipBg.b = (CATUInt8)(rawColor & 0xff);
00831         this->fToolTipBg.a = 255;
00832     }
00833 
00834 
00835     fIsOverlapped = GetAttribute(L"Overlapped",fIsOverlapped);   
00836     fTitle = GetAttribute(L"Title");    
00837 
00838     return result;
00839 }
00840 
00841 bool CATWindow::IsPrimary()
00842 {
00843     return fPrimary;
00844 }
00845 
00846 //---------------------------------------------------------------------------
00847 CATControl* CATWindow::HitTest(const CATPOINT& point)
00848 {
00849     CATControl* finalHit = 0;
00850     CATUInt32 numControls = this->GetNumChildren();
00851     for (CATUInt32 i = 0; i < numControls; i++)
00852     {
00853         CATXMLObject* curChild = 0;
00854         if (0 != (curChild = GetChild(i)))
00855         {
00856             CATWidget* curControl = (CATWidget*)curChild;
00857             if (curControl->IsEnabled())
00858             {
00859                 CATControl* hitControl = curControl->HitTest(point);
00860                 if (hitControl)
00861                 {
00862                     finalHit = hitControl;
00863                 }
00864             }         
00865         }
00866     }
00867     return finalHit;
00868 }
00869 
00870 void CATWindow::OnMouseMove(const CATPOINT& point, bool leftButton, CATMODKEY modKey)
00871 {
00872     fLastMouseUpdate = clock();
00873     fMouseInWindow = true; 
00874 
00875     OSUpdateToolTip();
00876 
00877     if (fDragging)
00878     {
00879         if (!leftButton)
00880         {
00881             fDragging = false;         
00882             this->SetCursorType(CATCURSOR_ARROW);         
00883             this->OSEndMouseTrack();
00884             return;
00885         }
00886 
00887         CATPOINT screenPoint = point;
00888         this->OSWndToScreen(screenPoint.x, screenPoint.y);
00889 
00890         if (this->fIsOverlapped == false)
00891         {
00892             CATRect newRect = this->OSGetWndRect();
00893             newRect.Offset(screenPoint.x - fDragLastPoint.x, screenPoint.y - fDragLastPoint.y);
00894             this->OSMoveWnd(newRect);
00895         }
00896         else
00897         {           
00898 #ifdef _WIN32
00899             HWND curWnd = this->OSGetWnd();
00900             HWND parWnd = this->GetBaseWindow();
00901             RECT parRect;
00902 
00903             ::GetWindowRect(parWnd,&parRect);
00904 
00905             POINT tl;
00906             tl.x = parRect.left;
00907             tl.y = parRect.top;
00908 
00909             if (::GetWindowLong(parWnd, GWL_STYLE) & WS_CHILD)
00910             {
00911                 HWND rootWnd = ::GetParent(parWnd);
00912                 if ((rootWnd != 0) && (rootWnd != parWnd))
00913                 {                   
00914                     ::ScreenToClient(rootWnd, &tl);
00915                 }
00916             }
00917 
00918             ::SetWindowPos(
00919                 parWnd,
00920                 0,
00921                 tl.x + (screenPoint.x - fDragLastPoint.x), 
00922                 tl.y + (screenPoint.y - fDragLastPoint.y),
00923                 0,
00924                 0,
00925                 SWP_NOSIZE | SWP_NOZORDER);
00926 #endif
00927         }
00928         fDragLastPoint = screenPoint;      
00929 
00930         // No need to mark dirty - size isn't changing, just position here.
00931         // this->MarkDirty();
00932 
00933         // Force update - removes the 'dragging behind' effect.
00934         this->Update();
00935 
00936         return;
00937     }
00938 
00939     // Retrieve control under mouse, if any
00940     CATControl* curControl = this->HitTest(point);
00941 
00942     if (this->fMouseTrackTarget == 0)
00943     {      
00944         // No current mouse tracking - just do the control activation and 
00945         // status bar code.
00946         if ((curControl) && (curControl->IsFocusable()))
00947         {
00948             // Unset previous control if any
00949             if ((this->fActiveControl) && (fActiveControl != curControl))
00950             {
00951                 OSHideToolTip();            
00952                 if (fActiveControl)
00953                 {
00954                     fActiveControl->SetActive(false);
00955                     fActiveControl = 0;
00956                 }
00957             }
00958 
00959             // Set the active control
00960             if (fActiveControl == 0)
00961             {
00962                 OSHideToolTip();
00963                 fActiveControl = curControl;
00964                 fActiveControl->SetActive(true);
00965                 this->fCursor = *curControl->GetCursor();
00966                 this->SetStatusBarHint(fActiveControl->GetHint());
00967             }
00968         }
00969         else
00970         {
00971             // Unset any controls         
00972             OSHideToolTip();
00973             if (this->fActiveControl)
00974             {
00975                 if (fActiveControl)
00976                 {
00977                     fActiveControl->SetActive(false);
00978                     fActiveControl = 0;
00979                 }
00980                 this->SetStatusBarHint(this->fHintText);
00981             }
00982             else
00983             {
00984                 if (this->fStatusBarHint.Compare(fHintText) != 0)
00985                 {
00986                     this->SetStatusBarHint(this->fHintText);
00987                 }
00988             }
00989             this->SetCursorType(CATCURSOR_ARROW);
00990         }
00991     }
00992     else
00993     {
00994         // We're tracking for a control....
00995         CATPOINT objPoint = point;
00996         WindowToWidget(fMouseTrackTarget, objPoint);
00997         this->fMouseTrackTarget->TrackMouseMove(objPoint,leftButton, modKey);
00998         this->SetStatusBarHint(fMouseTrackTarget->GetHint());
00999 
01000     }
01001 
01002 }
01003 
01004 void CATWindow::OnMouseLeave()
01005 {
01006     fMouseInWindow = false;
01007     if (fActiveControl)
01008     {
01009         fActiveControl->SetActive(false);
01010         fActiveControl = 0;
01011     }
01012 }
01013 
01014 void CATWindow::OnMouseWheel(  const CATPOINT& point,
01015                              CATFloat32        wheelMove,
01016                              CATMODKEY          modKey)
01017 {
01018     if (this->fMouseTrackTarget)
01019     {
01020         CATPOINT objPoint = point;
01021         WindowToWidget(fMouseTrackTarget, objPoint);
01022         this->fMouseTrackTarget->TrackMouseWheel( objPoint, 
01023             wheelMove, 
01024             modKey);
01025         OSShowToolTip(fMouseTrackTarget,point);
01026         OSUpdateToolTip();
01027         this->SetStatusBarHint(fMouseTrackTarget->GetHint());
01028     }
01029     else
01030     {
01031         CATControl* hit = 0;
01032         if (hit = this->HitTest(point))
01033         {
01034             CATPOINT objPoint = point;
01035             WindowToWidget(hit, objPoint);
01036 
01037             hit->OnMouseWheel(objPoint, wheelMove,modKey);
01038 
01039             OSShowToolTip(hit,point);
01040             OSUpdateToolTip();
01041 
01042             this->SetStatusBarHint(hit->GetHint());
01043         }
01044     }
01045 }
01046 
01047 void CATWindow::OnMouseDown(const CATPOINT& point, CATMODKEY modKey)
01048 {
01049     CATControl* hitControl = this->HitTest(point);
01050     if (hitControl)
01051     {
01052         this->SetFocus(hitControl);
01053         OSBeginMouseTrack();      
01054         this->fMouseTrackTarget = hitControl;
01055         if (this->fCurTool == 0)
01056         {
01057             this->OSShowToolTip(hitControl,point);
01058         }
01059 
01060         CATPOINT objPoint = point;
01061         WindowToWidget(hitControl, objPoint);
01062 
01063         hitControl->TrackMouseDown(objPoint, modKey);
01064 
01065         OSUpdateToolTip();
01066         this->SetStatusBarHint(fMouseTrackTarget->GetHint());
01067 
01068     }
01069     else
01070     {
01071 //      KillFocus();
01072 
01073         // Left button down not on a control - begin move if we don't have a caption bar
01074         if (fDragAnywhere)
01075         {         
01076             fDragLastPoint = point;
01077             this->OSWndToScreen(fDragLastPoint.x, fDragLastPoint.y);
01078             this->OSBeginMouseTrack();
01079             this->SetCursorType(CATCURSOR_MOVE);         
01080             fDragging = true;     
01081         }
01082     }
01083 }
01084 
01085 
01086 void CATWindow::OnRightMouseDown(const CATPOINT& point, CATMODKEY modKey)
01087 {
01088     CATControl* hitControl = this->HitTest(point);
01089     if (hitControl)
01090     {
01091         fRightTrack = hitControl;
01092     }
01093     else
01094     {
01095         fRightTrack = 0;
01096     }
01097 }
01098 
01099 void CATWindow::OnRightMouseUp(const CATPOINT& point, CATMODKEY modKey)
01100 {
01101     if (fRightTrack != 0)
01102     {
01103         CATControl* hitControl = this->HitTest(point);
01104         if (hitControl == fRightTrack)
01105         {
01106             // Right-click
01107             hitControl->OnRightMouseClick();
01108         }
01109     }
01110 
01111     fRightTrack = 0;
01112 }
01113 
01114 // OnMouseDoubleClick() is called the mouse is double clicked.
01115 //
01116 // \param point - location mouse was released
01117 // \param modKey - Key state modifiers for ctrl/shift/alt/etc.
01118 void CATWindow::OnMouseDoubleClick( const CATPOINT& point, 
01119                                    CATMODKEY            modKey)
01120 {
01121     CATControl* hitControl = this->HitTest(point);
01122     if (hitControl)
01123     {
01124         this->SetFocus(hitControl);
01125         hitControl->OnMouseDoubleClick(modKey);
01126 
01127     }
01128     else
01129     {
01130         KillFocus();
01131     }
01132 }
01133 
01134 
01135 void CATWindow::OnMouseHover(const CATPOINT& point, bool left, CATMODKEY modKey)
01136 {
01137     CATControl* hitControl = this->HitTest(point);
01138     if (hitControl)
01139     {
01140         OSShowToolTip(hitControl, point);
01141     }
01142     else
01143     {
01144         OSHideToolTip();
01145     }
01146 }
01147 
01148 void CATWindow::OnMouseUp(const CATPOINT& point, CATMODKEY modKey)
01149 {
01150     if (fMouseTrackTarget)
01151     {
01152         OSEndMouseTrack();
01153 
01154         CATPOINT objPoint = point;
01155         WindowToWidget(fMouseTrackTarget, objPoint);
01156         fMouseTrackTarget->TrackMouseRelease(objPoint, modKey);
01157 
01158         // Mouse release engages a click, which could kill mouse target in some controls.
01159         if (fMouseTrackTarget)
01160         {
01161             OSUpdateToolTip();
01162             this->SetStatusBarHint(fMouseTrackTarget->GetHint());
01163 
01164             fMouseTrackTarget = 0;
01165         }
01166     }
01167 
01168     // End moving
01169     if (fDragging)
01170     {
01171         fDragging = false;
01172         this->SetCursorType(CATCURSOR_ARROW);
01173         this->OSEndMouseTrack();
01174     }
01175 }
01176 
01177 void CATWindow::SetStatusBarHint(const CATString& hintText)
01178 {
01179     if (hintText != fStatusBarHint)
01180     {
01181         fStatusBarHint = hintText;
01182 
01183         if (fStatusLabel)
01184         {
01185             fStatusLabel->SetString(fStatusBarHint);
01186         }
01187     }
01188 }
01189 
01190 CATString CATWindow::GetStatusBarHint()
01191 {
01192     return fStatusBarHint;
01193 }
01194 
01195 
01196 void CATWindow::KillFocus()
01197 {    
01198     if (fFocusControl != 0)
01199     {
01200         CATString focusInfo = fFocusControl->GetName() << L" losing focus.";
01201         CATTRACE(focusInfo);
01202         fFocusControl->SetFocused(false);
01203         fFocusControl = 0;      
01204     }
01205 }
01206 
01207 void CATWindow::SetFocus(CATControl* control)
01208 {
01209     if (control == 0)
01210         CATTRACE("Focus set to 0.");
01211     else    
01212     {
01213         CATString focusInfo = control->GetName() << L" receiving focus.";
01214         CATTRACE(focusInfo);
01215     
01216     }
01217 
01218     if (control != fFocusControl)
01219     {
01220         KillFocus();
01221         fFocusControl = control;
01222         if (fFocusControl)
01223         {      
01224             if (fFocusControl == 0)
01225             {
01226                 CATTRACE("Control reset focus to 0.");
01227             }
01228         }
01229     }
01230 
01231     if (fFocusControl)
01232     {
01233         fFocusControl->SetFocused(true);
01234         SetStatusBarHint(fFocusControl->GetHint());
01235     }
01236 }
01237 
01238 
01239 CATResult CATWindow::EnableObject(const CATString& controlName, bool enabled)
01240 {
01241     CATGuiObj* curObj = Find(controlName);
01242 
01243     if (curObj == 0)
01244     {
01245         return CATRESULT(CAT_ERR_CONTROL_NOT_FOUND);
01246     }
01247 
01248     curObj->SetEnabled(enabled);
01249     return CAT_SUCCESS;
01250 }
01251 
01252 bool CATWindow::FindControlCallback(CATControl* curControl, void* userParam)
01253 {
01254     CATFINDCONTROLSTRUCT* ctrlStruct = (CATFINDCONTROLSTRUCT*)userParam;
01255     ctrlStruct->CurControl = curControl;
01256 
01257     if (curControl->GetName().Compare(ctrlStruct->Name) == 0)
01258     {
01259         if (0 == wcscmp(curControl->GetType(),ctrlStruct->TypeName))
01260         {
01261             ctrlStruct->FoundControl = curControl;
01262             return false;
01263         }
01264     }
01265     return true;
01266 }
01267 
01268 CATControl* CATWindow::FindControlAndVerify(const CATString& controlName, 
01269                                             const CATString& typeName,
01270                                             CATUInt32* index)
01271 {   
01272     CATFINDCONTROLSTRUCT ctrlStruct;
01273     ctrlStruct.Name         = controlName;
01274     ctrlStruct.TypeName     = typeName;
01275     ctrlStruct.FoundControl = 0;
01276     ctrlStruct.PrevControl  = 0;
01277     ctrlStruct.FirstControl = 0;
01278     ctrlStruct.NextControl  = 0;
01279     ctrlStruct.CurControl   = 0;
01280     ctrlStruct.TargetControl= 0;
01281 
01282     ForEachControl(FindControlCallback, &ctrlStruct);
01283 
01284     // MAEDEBUG - set index here!
01285 
01286     return ctrlStruct.FoundControl;
01287 }
01288 
01289 bool CATWindow::GetControlSiblingsCallback(CATControl* curControl, void* userParam)
01290 {
01291     CATFINDCONTROLSTRUCT* ctrlStruct = (CATFINDCONTROLSTRUCT*)userParam;
01292 
01293     // Ignore stuff that's not available.
01294     if ((curControl->IsEnabled() == false) || (curControl->IsFocusable() == false) || (curControl->IsVisible() == false))
01295     {
01296         return true;
01297     }
01298 
01299     // Set first control if unset.
01300     if (ctrlStruct->FirstControl == 0)
01301     {
01302         ctrlStruct->FirstControl = curControl;
01303     }
01304 
01305     // If target control is 0, then first is our target.
01306     if (ctrlStruct->TargetControl == 0)
01307     {
01308         if (ctrlStruct->NextControl == 0)
01309         {         
01310             ctrlStruct->NextControl = curControl;
01311         }
01312 
01313         // Prev control is the last one we visit.
01314         ctrlStruct->PrevControl = curControl;
01315         ctrlStruct->CurControl = curControl;
01316         return true;
01317     }
01318     else if (curControl == ctrlStruct->TargetControl)
01319     {
01320         ctrlStruct->PrevControl = ctrlStruct->CurControl;
01321         ctrlStruct->FoundControl = curControl;
01322         ctrlStruct->CurControl = curControl;
01323         return true;
01324     }
01325     else if ((ctrlStruct->FoundControl != 0) && (ctrlStruct->NextControl == 0))
01326     {
01327         ctrlStruct->NextControl = curControl;
01328     }
01329 
01330     ctrlStruct->CurControl = curControl;
01331 
01332     return true;
01333 }
01334 
01335 void CATWindow::GetControlStruct(CATFINDCONTROLSTRUCT& ctrlStruct, CATControl* control)
01336 {
01337     ctrlStruct.FoundControl    = 0;
01338     ctrlStruct.PrevControl     = 0;
01339     ctrlStruct.FirstControl    = 0;
01340     ctrlStruct.NextControl     = 0;
01341     ctrlStruct.CurControl      = 0;
01342     ctrlStruct.TargetControl   = control;   
01343     ForEachControl(GetControlSiblingsCallback, &ctrlStruct);
01344 }
01345 
01346 void CATWindow::SetFocusNext()
01347 {
01348     CATFINDCONTROLSTRUCT ctrlStruct;
01349 
01350     GetControlStruct(ctrlStruct,this->fFocusControl);
01351 
01352     if (ctrlStruct.NextControl)
01353     {
01354         CATTRACE((CATString)"SetFocusNext from: " << (CATString)(fFocusControl?fFocusControl->GetName():"Null") << " to " << ctrlStruct.NextControl->GetName());
01355 
01356         this->SetFocus(ctrlStruct.NextControl);
01357     }
01358     else if (ctrlStruct.FirstControl)
01359     {
01360         this->SetFocus(ctrlStruct.FirstControl);
01361     }
01362     else
01363     {
01364         KillFocus();
01365     }
01366 
01367     // MAEDEBUG - 
01368     // Gah. Rework for layers...
01369 }
01370 
01371 void CATWindow::SetFocusPrev()
01372 {
01373     CATFINDCONTROLSTRUCT ctrlStruct;
01374     ctrlStruct.FoundControl    = 0;
01375     ctrlStruct.PrevControl     = 0;
01376     ctrlStruct.FirstControl    = 0;
01377     ctrlStruct.NextControl     = 0;
01378     ctrlStruct.CurControl      = 0;
01379     ctrlStruct.TargetControl   = this->fFocusControl;   
01380 
01381     ForEachControl(GetControlSiblingsCallback, &ctrlStruct);
01382 
01383     if (ctrlStruct.PrevControl)
01384     {
01385         CATTRACE((CATString)"SetFocusPrev from: " << (CATString)(fFocusControl?fFocusControl->GetName():"Null")  << " to " << ctrlStruct.PrevControl->GetName());
01386         this->SetFocus(ctrlStruct.PrevControl);
01387     }
01388     else if (ctrlStruct.CurControl)
01389     {
01390         this->SetFocus(ctrlStruct.CurControl);
01391     }
01392     else
01393     {
01394         KillFocus();
01395     }
01396     // MAEDEBUG - 
01397     // Gah. Rework for layers...
01398 }
01399 
01400 
01401 CATControl* CATWindow::GetFocusControl()
01402 {
01403     return this->fFocusControl;
01404 }
01405 
01406 void CATWindow::OnKeyDown(const CATKeystroke& keystroke)
01407 {
01408     if (this->fFocusControl != 0)
01409     {
01410         fFocusControl->OnKeyDown(keystroke);
01411         this->SetStatusBarHint(fFocusControl->GetHint());
01412 
01413     }
01414 }
01415 
01416 void CATWindow::OnKeyUp(const CATKeystroke& keystroke)
01417 {
01418     if (this->fFocusControl != 0)
01419     {
01420         fFocusControl->OnKeyUp(keystroke);
01421     }
01422 }
01423 
01424 void CATWindow::OnKeyPress(const CATKeystroke& keystroke)
01425 {
01426     if (this->fFocusControl != 0)
01427     {
01428         fFocusControl->OnKeyPress(keystroke);      
01429     }
01430 }
01431 
01432 void CATWindow::OnHelp()
01433 {
01434     gApp->OnHelp();
01435 }
01436 
01437 
01438 void CATWindow::OnClose(CATCommand& command, CATControl* ctrl)
01439 {
01440     this->Hide(true);
01441 }
01442 
01443 void CATWindow::OnMinimize(CATCommand& command, CATControl* ctrl)
01444 {
01445     this->OSMinimize();
01446 }
01447 
01448 void CATWindow::OnMaximize(CATCommand& command, CATControl* ctrl)
01449 {
01450     this->OSMaximize();
01451 }
01452 
01453 const CATWindow::GGWINDOWCMDFUNC BaseCmdTable[3] =
01454 {
01455     "Close",    &CATWindow::OnClose,        false,  false,
01456     "Minimize", &CATWindow::OnMinimize, false,  false,
01457     "Maximize", &CATWindow::OnMaximize, false,  false
01458 };
01459 
01460 void CATWindow::OnCommand(CATCommand& command, CATControl* ctrl)
01461 {   
01462     CATResult result = ProcessCommandTable(command,ctrl,BaseCmdTable,3,false);
01463 
01464 
01465     if (CATFAILED(result))
01466     {
01467         // If we have a parent skin (not a template) then
01468         // pass command up to it if we're unaware of how to
01469         // handle it.
01470         CATSkin* skin = (CATSkin*)this->fParent;
01471         if (skin != 0)
01472         {
01473             skin->OnCommand(command, ctrl, this);   
01474         }
01475     }
01476 
01477     OSUpdateToolTip();
01478 
01479     if (ctrl)
01480     {      
01481         SetStatusBarHint(ctrl->GetHint());
01482     }
01483 }
01484 
01485 
01486 void CATWindow::OnThreadedCommand(CATCommand& command)
01487 {   
01488     CATResult result = ProcessCommandTable(command,0,BaseCmdTable,3,true);
01489 }
01490 
01491 
01492 void CATWindow::OnMouseTimer(CATMODKEY modKey)
01493 {
01494     CATFloat32 timeSinceLast = ((CATFloat32)(clock() - fLastMouseUpdate)) / (CATFloat32)(CLOCKS_PER_SEC);
01495     if ( timeSinceLast  < 0.01f )
01496     {
01497         return;
01498     }
01499 
01500     fLastMouseUpdate = clock();
01501 
01502     if (fMouseTrackTarget)
01503     {
01504         this->fMouseTrackTarget->TrackMouseTimer(modKey);
01505         OSUpdateToolTip();
01506     }
01507 }
01508 
01509 CATWND CATWindow::OSGetWnd()
01510 {
01511     return fWindow;
01512 }
01513 
01514 // RegCtlWnd() registers a window handle from a CATControlWnd.
01515 // This allows us to send messages w/o doing full scans for the
01516 // control through the skin's tree.
01517 //
01518 // \param wndCtl - window control
01519 // \param wndHandle - window handle of the control
01520 // \return CATResult - CAT_SUCCESS on success
01521 // \sa UnRegCtlWnd()
01522 CATResult CATWindow::RegCtlWnd(CATControlWnd* wndCtl, CATWND wndHandle)
01523 {
01524     this->fCWT.insert(std::make_pair(wndHandle,wndCtl));
01525     return CAT_SUCCESS;
01526 }
01527 
01528 /// UnRegCtlWnd() unregisters a window handle from a CATControlWnd.
01529 /// This should be called when the control destroys its handle to
01530 /// prevent mis-sends.
01531 /// \param wndHandle - old window handle of the control
01532 /// \return CATResult - CAT_SUCCESS on success
01533 /// \sa RegCtlWnd()
01534 CATResult CATWindow::UnRegCtlWnd(CATWND wndHandle)
01535 {
01536     CATControlWnd* wndCtl = 0;
01537     std::map<CATWND, CATControlWnd*>::iterator iter = fCWT.find(wndHandle);
01538     if (iter != fCWT.end())
01539     {
01540         fCWT.erase(iter);    
01541         return CAT_SUCCESS;
01542     }   
01543     return CAT_ERR_INVALID_PARAM;
01544 }
01545 
01546 // GetCtlWnd() retrieves a CATControlWnd for a given
01547 // handle, or 0 if none is registered.
01548 CATControlWnd* CATWindow::GetCtlWnd(CATWND wndHandle)
01549 {
01550     CATControlWnd* wndCtl = 0;
01551     std::map<CATWND, CATControlWnd*>::iterator iter = fCWT.find(wndHandle);
01552     if (iter != fCWT.end())
01553     {
01554         wndCtl = iter->second;
01555     }   
01556     return wndCtl;
01557 }
01558 
01559 void CATWindow::SetCursorType(CATCURSORTYPE type)
01560 {
01561     this->fCursor.SetType(type);
01562     OSSetCursor();
01563 }
01564 
01565 void CATWindow::SetEnabled(bool enabled)
01566 {
01567     CATGuiObj::SetEnabled(enabled);
01568 #ifdef _WIN32
01569     if (this->fWindow != 0)
01570     {
01571         ::EnableWindow(this->OSGetWnd(), enabled);
01572     }       
01573 #endif
01574 
01575     if (enabled == false)
01576     {
01577         this->SetCursorType(CATCURSOR_WAIT);
01578     }
01579     else
01580     {
01581         this->SetCursorType(CATCURSOR_ARROW);
01582     }
01583 
01584     CATInt32 dummy = 0;
01585     this->OnEvent(CATEvent(CATEVENT_ENABLE_CHANGE), dummy);
01586     this->MarkDirty();
01587 }  
01588 
01589 
01590 bool  CATWindow::IsTemplate()
01591 {
01592     return fIsTemplate;
01593 }
01594 
01595 void  CATWindow::SetIsTemplate(bool isTemplate)
01596 {
01597     fIsTemplate = isTemplate;
01598 }
01599 
01600 CATResult CATWindow::PostEvent(CATEvent* event)
01601 {
01602 
01603     CATResult result = CAT_SUCCESS;
01604     if (CATFAILED(result = fEventLock.Wait()))
01605     {
01606         return result;
01607     }
01608 
01609     if (fExiting)
01610     {
01611         delete event;
01612         fEventLock.Release();
01613         return CAT_SUCCESS;
01614     }
01615 
01616     result = fEventQueue.Queue(event);
01617 
01618     fEventLock.Release();
01619     PostEventNotification();
01620     return result;
01621 }
01622 
01623 void CATWindow::ProcessPostedEvent()
01624 {
01625     CATResult result = CAT_SUCCESS;
01626     if (CATFAILED(result = fEventLock.Wait()))
01627     {
01628         return;
01629     }
01630 
01631     CATEvent* event = 0;
01632     while (CATSUCCEEDED(result = fEventQueue.Next(event)))
01633     {
01634         if ((CATSUCCEEDED(result)) && (event != 0))
01635         {
01636             CATInt32 retVal = 0;
01637             this->OnEvent( *event,retVal);
01638             delete event;
01639         }
01640     }
01641     fEventLock.Release();
01642 }
01643 
01644 bool CATWindow::IsOverlapped()
01645 {
01646     return fIsOverlapped;
01647 }
01648 
01649 
01650 
01651 // CAllback for SEtKnobOverride
01652 bool CATWindow::SetKnobCallback(CATControl* curControl, void* userParam)
01653 {
01654     CATKNOB_STYLE knobStyle = (CATKNOB_STYLE)(int)userParam;
01655     if (wcscmp(curControl->GetType(),L"Knob") == 0)
01656     {
01657         ((CATKnob*)curControl)->SetKnobStyle(knobStyle);
01658     }
01659     return true;
01660 }
01661 
01662 
01663 void CATWindow::SetKnobOverride(CATKNOB_STYLE knobStyle)
01664 {
01665     this->ForEachControl(SetKnobCallback, (void *)knobStyle);
01666 }
01667 
01668 /// GetWindow() retrieves the parent window.
01669 CATWindow* CATWindow::GetWindow() const
01670 {
01671     return (CATWindow*)this;
01672 }      
01673 
01674 CATRect CATWindow::GetRectAbs(bool screenCoordinates)
01675 {
01676     CATRect rect = fRect;
01677 
01678     if (screenCoordinates)
01679     {
01680         CATPOINT screenPoint;
01681         screenPoint.x = 0;
01682         screenPoint.y = 0;
01683 
01684         OSWndToScreen(screenPoint.x, screenPoint.y);
01685         rect.Offset(screenPoint.x, screenPoint.y);
01686     }
01687 
01688     return rect;
01689 }
01690 
01691 
01692 void CATWindow::WindowToWidget( CATGuiObj* widget, CATPOINT& pt)
01693 {
01694     if (widget == 0)
01695         return;
01696 
01697     CATGuiObj* parObj = (CATGuiObj*)widget->GetParent();
01698 
01699     if (parObj)
01700     {
01701         CATRect offsetRect = parObj->GetRectAbs();
01702         pt.x -= offsetRect.left;
01703         pt.y -= offsetRect.top;
01704     }
01705 }
01706 
01707 void CATWindow::WindowToWidget( CATGuiObj* widget, CATRect& rect)
01708 {
01709     if (widget == 0)
01710         return;
01711 
01712     CATGuiObj* parObj = (CATGuiObj*)widget->GetParent();
01713 
01714     if (parObj)
01715     {
01716         CATRect offsetRect = parObj->GetRectAbs();
01717         rect.Offset( -offsetRect.left, -offsetRect.top);
01718     }
01719 }
01720 
01721 void CATWindow::WidgetToWindow( CATGuiObj* widget, CATPOINT& pt)
01722 {
01723     if (widget == 0)
01724         return;
01725 
01726     CATGuiObj* parObj = (CATGuiObj*)widget->GetParent();
01727 
01728     if (parObj)
01729     {
01730         CATRect offsetRect = parObj->GetRectAbs();
01731         pt.x += offsetRect.left;
01732         pt.y += offsetRect.top;
01733     }
01734 }
01735 
01736 void CATWindow::WidgetToWindow( CATGuiObj* widget, CATRect& rect)
01737 {
01738     if (widget == 0)
01739         return;
01740 
01741     CATGuiObj* parObj = (CATGuiObj*)widget->GetParent();
01742 
01743     if (parObj)
01744     {
01745         CATRect offsetRect = parObj->GetRectAbs();
01746         rect.Offset( offsetRect.left, offsetRect.top);
01747     }
01748 }
01749 
01750 CATResult CATWindow::OnDropFile(const CATString& filePath)
01751 {
01752     return CAT_SUCCESS;
01753 }
01754 
01755 CATResult CATWindow::ProcessCommandTable(   CATCommand&              cmd,
01756                                          CATControl*              control,
01757                                          const GGWINDOWCMDFUNC*  cmdTable,
01758                                          CATUInt32                 cmdTableLen,
01759                                          bool                           inThread)
01760 
01761 {   
01762     this->SetFocus(control);
01763 
01764     for (CATUInt32 i = 0; i < cmdTableLen; i++)
01765     {
01766         CATString cmdString = cmd.GetCmdString();
01767         if (cmdString.Compare( cmdTable[i].CommandName) == 0)
01768         {
01769             if ((cmdTable[i].Threaded) && (!inThread))
01770             {
01771                 if (cmdTable[i].DisableWindow)
01772                     this->SetEnabled(false);
01773 
01774 
01775                 this->PostThreadedCommand(cmd);
01776             }
01777             else
01778             {               
01779                 if (cmdTable[i].DisableWindow)
01780                 {
01781                     this->SetEnabled(false);
01782                     this->Update();
01783                 }
01784 
01785                 (this->*cmdTable[i].CommandFunc)(cmd,control);
01786 
01787 
01788                 if (cmdTable[i].DisableWindow)
01789                     this->SetEnabled(true);
01790             }
01791 
01792             return CAT_SUCCESS;
01793         }
01794     }
01795 
01796     return CATRESULT(CAT_ERR_CMD_NOT_FOUND);
01797 }
01798 
01799 void CATWindow::OnNoop(CATCommand& command, CATControl* ctrl)
01800 {
01801     CATTRACE("NOOP command - not implemented.");
01802 }
01803 
01804 
01805 /// GetPref() retrieves the value of the requested preference.
01806 /// 
01807 /// \param prefName    - name of preference
01808 /// \param prefValue   - ref to value of preference (several overloaded types)
01809 /// \return bool - true if the preference existed, false otherwise.
01810 ///         If not found, prefValue remains unchanged.
01811 /// \sa SetPref()
01812 bool CATWindow::GetPref(const CATString& prefName, CATString& prefValue)
01813 {
01814     return gApp->GetPrefs()->GetPref( fName, prefName, prefValue);
01815 }
01816 
01817 bool CATWindow::GetPref(const CATString& prefName, CATInt32& prefValue)
01818 {
01819     return gApp->GetPrefs()->GetPref( fName, prefName, prefValue);
01820 }
01821 
01822 bool CATWindow::GetPref(const CATString& prefName, CATUInt32& prefValue)
01823 {
01824     return gApp->GetPrefs()->GetPref( fName, prefName, prefValue);
01825 }
01826 
01827 bool CATWindow::GetPref(const CATString& prefName, CATFloat32& prefValue)
01828 {
01829     return gApp->GetPrefs()->GetPref( fName, prefName, prefValue);
01830 }
01831 
01832 bool CATWindow::GetPref(const CATString& prefName, bool& prefValue)
01833 {
01834     return gApp->GetPrefs()->GetPref( fName, prefName, prefValue);
01835 }
01836 
01837 
01838 /// SetPref() sets the value of the specified preference.
01839 /// 
01840 /// \param prefSection - section name of preference (window name, etc.)
01841 /// \param prefName    - name of preference
01842 /// \param prefValue   - value of preference (several overloaded types)
01843 /// \return bool - true on success.
01844 /// \sa SetPref()
01845 bool CATWindow::SetPref(const CATString& prefName, const CATString& prefValue)
01846 {
01847     bool result = gApp->GetPrefs()->SetPref( fName, prefName, prefValue);
01848 
01849     CATInt32 lRes = 0;
01850     this->SendEvent(CATEvent(CATEVENT_PREF_CHANGED,0,0,0,0,0,prefName),lRes);
01851 
01852     return result;
01853 }
01854 bool CATWindow::SetPref(const CATString& prefName, CATInt32 prefValue)
01855 {
01856     bool result = gApp->GetPrefs()->SetPref( fName, prefName, prefValue);
01857 
01858     CATInt32 lRes = 0;
01859     this->SendEvent(CATEvent(CATEVENT_PREF_CHANGED,0,0,0,0,0,prefName),lRes);
01860 
01861     return result;
01862 }
01863 bool CATWindow::SetPref(const CATString& prefName, CATUInt32 prefValue)
01864 {
01865     bool result = gApp->GetPrefs()->SetPref( fName, prefName, prefValue);
01866 
01867     CATInt32 lRes = 0;
01868     this->SendEvent(CATEvent(CATEVENT_PREF_CHANGED,0,0,0,0,0,prefName),lRes);
01869 
01870     return result;
01871 }
01872 bool CATWindow::SetPref(const CATString& prefName, CATFloat32 prefValue)
01873 {
01874     bool result = gApp->GetPrefs()->SetPref( fName, prefName, prefValue);
01875 
01876     CATInt32 lRes = 0;
01877     this->SendEvent(CATEvent(CATEVENT_PREF_CHANGED,0,0,0,0,0,prefName),lRes);
01878 
01879     return result;
01880 }
01881 bool CATWindow::SetPref(const CATString& prefName, bool prefValue)
01882 {
01883     bool result = gApp->GetPrefs()->SetPref( fName, prefName, prefValue);
01884 
01885     CATInt32 lRes = 0;
01886     this->SendEvent(CATEvent(CATEVENT_PREF_CHANGED,0,0,0,0,0,prefName),lRes);
01887 
01888     return result;
01889 }
01890 
01891 
01892 CATResult CATWindow::SendEvent( const CATEvent& event, CATInt32& lRes)
01893 {
01894 
01895     CATResult result = gApp->OnEvent(event, lRes);
01896     if (this->IsTemplate())
01897     {
01898         result = this->OnEvent(event,lRes);
01899     }
01900 
01901     return result;
01902 }
01903 
01904 
01905 void CATWindow::DisplayMessage( const CATString& msg)
01906 {
01907     if (gApp != 0)
01908     {
01909         gApp->DisplayMessage(msg,this);
01910     }
01911 }
01912 
01913 void CATWindow::DisplayError( const CATResult& result)
01914 {
01915     if (gApp != 0)
01916     {
01917         gApp->DisplayError(result,this);
01918     }
01919 }
01920 
01921 CATResult CATWindow::DisplayPrompt( const CATString& msg, CATApp::CATPROMPTTYPE prompt)
01922 {
01923     CATResult result = CAT_SUCCESS;
01924     if (gApp != 0)
01925     {
01926         result = gApp->DisplayPrompt(msg,prompt,this);
01927     }
01928     return result;
01929 }
01930 
01931 CATResult CATWindow::GetScale(CATFloat32& xScale, CATFloat32& yScale)
01932 {
01933     xScale = 1.0f;
01934     yScale = 1.0f;
01935     return CAT_ERR_NOT_IMPLEMENTED;
01936 }

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