CursorStack Class Reference

A stack of Cursor objects, which is part of the kernel (NB Cursor objects are part of the OIL). More...

#include <csrstack.h>

List of all members.

Public Member Functions

 CursorStack (INT32 maxdepth=10)
 Constructs an empty stack of Cursor objects, with a maximum depth (by default this is 10 deep).
virtual ~CursorStack ()
 Destroys a CursorStack object.
void BeginBusy ()
 Tells the cursor stack to show the busy cursor. Multiple calls will increment a usage count, and the cursor won't disappear until the usage count drops to zero.
void EndBusy ()
 Turns off the busy cursor (if there has only been one call to BeginBusy) for this cursor stack. Waits until BusyCount reaches zero before turning off the busy cursor.
void SmashBusy ()
 Turns off the busy cursor (without exceptions) for this cursor stack. Resets the Busy count to zero. Called by Progress.cpp's SmashBusyJob to ensure the cursor is off.

Static Public Member Functions

static BOOL Init ()
 Initialises the cursor system, loading the standard OS-provided cursors, such as the arrow and the hour-glass, creating the application's cursor stack etc.
static void DeInit ()
 Shuts down the cursor system, releasing resources allocated by the Init() member function.
static BOOL GIsValid ()
static INT32 GPush (Cursor *pCursor, BOOL ActivateNow=TRUE)
static CursorGPop (INT32 cursorID)
static CursorGSetTop (Cursor *pCursor, INT32 cursorID)
static void GSetActive ()
static BOOL GIsActive (const Cursor *pCursor)
static CursorGetActive ()

Private Member Functions

 CC_DECLARE_MEMDUMP (CursorStack)
BOOL IsValid () const
 Tests if the object was successfully constructed, and is coherent.
INT32 Push (Cursor *pCursor, BOOL ActivateNow=TRUE)
 Pushes the parameter onto the stack, making it top-most and hence the Cursor which will become active when SetActive() is called (this is done automatically by default, or if you pass in ActivateNow == TRUE) The Unique ID returned will be required by calls to SetTop and Pop so that we don't have any problems with the wrong cursors being popped and deleted.
CursorPop (INT32 cursorID=0)
 Removes a cursor from the stack. Because of the strange, asynchronous nature of Camelot, and the way cursors are seemingly added and removed from the stack at random, when popping a cursor from the stack, a unique ID is used to identify which cursor you actually want to remove. That one is removed, whether it's at the top of the stack or not.
CursorSetTop (Cursor *pCursor, INT32 cursorID=0)
 Replaces a cursor on the stack with a new Cursor object. Combines a pop and a push. Note that the function detects if the stack is empty and will skip the initial pop if it is. The unique ID is used to find which cursor is actually to be replaced. If the cursor passed to this function is the same as the one already occupying the slot, no switching is done, otherwise the top cursor on the stack will be switched on (not necessarily the one passed to this function).
void SetActive (bool fOnlyRendWnd=true) const
 Makes the Cursor object on the top of the stack the active cursor.
BOOL IsActive (const Cursor *pCursor) const
 Tests if a particular cursor is on the top of the stack, ie. is currently visible and active.

Private Attributes

CursorIdentpcStack
INT32 nNextFreeSlot
INT32 nSentinel
INT32 BusyCount

Static Private Attributes

static CursorStackGlobal

Friends

void BeginBusyCursor ()
 Tells the global cursor stack to display a busy cursor.
void EndBusyCursor ()
 Tells the global cursor stack to stop displaying the busy cursor. If more than one call has been previously made to beginBusyCursor, the busy cursor isn't removed - a usage count is decremented.
void SmashBusyCursor ()
 Tells the global cursor stack to stop displaying the busy cursor, regardless of how many calls have been previously made to beginBusyCursor.


Detailed Description

A stack of Cursor objects, which is part of the kernel (NB Cursor objects are part of the OIL).

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
15th November, 1993

Definition at line 145 of file csrstack.h.


Constructor & Destructor Documentation

CursorStack::CursorStack INT32  maxdepth = 10  ) 
 

Constructs an empty stack of Cursor objects, with a maximum depth (by default this is 10 deep).

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: The allocation of the stack may fail, if so all subsequent calls to Push and Pop will be ignored.

See also:
CursorStack::CursorStack

Definition at line 201 of file csrstack.cpp.

00202 {
00203     nSentinel = maxdepth;
00204     nNextFreeSlot = 0;
00205     BusyCount = 0;
00206     
00207     pcStack = new CursorIdent[maxdepth];        // array of CursorIdent objects
00208 
00209 #ifdef  _DEBUG
00210     if( !pcStack )
00211         TRACEUSER( "JustinF", _T("Failed to allocate stack in CursorStack::CursorStack!\n"));
00212 #endif  // _DEBUG
00213 }

CursorStack::~CursorStack  )  [virtual]
 

Destroys a CursorStack object.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
CursorStack::CursorStack

Definition at line 231 of file csrstack.cpp.

00232 {
00233     #ifdef  _DEBUG
00234         if (nNextFreeSlot != 0)
00235             TRACE( _T("WARNING: Cursor Stack at 0x%p not empty (%d deep) upon destruction!\n"),
00236                   this, nNextFreeSlot);
00237     #endif  // _DEBUG
00238 
00239     delete[] pcStack;
00240 }


Member Function Documentation

void CursorStack::BeginBusy  ) 
 

Tells the cursor stack to show the busy cursor. Multiple calls will increment a usage count, and the cursor won't disappear until the usage count drops to zero.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/1/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
CursorStack::EndBusy; CursorStack::SmashBusy

Definition at line 553 of file csrstack.cpp.

00554 {
00555     BusyCount++;
00556     SetActive();
00557 }

CursorStack::CC_DECLARE_MEMDUMP CursorStack   )  [private]
 

void CursorStack::DeInit  )  [static]
 

Shuts down the cursor system, releasing resources allocated by the Init() member function.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
CursorStack::Init; Cursor::DeInit

Definition at line 174 of file csrstack.cpp.

00175 {
00176     if (!Global) return;
00177     Global->Pop();              // undo the push done in Init()
00178     delete Global;
00179     Global = 0;
00180     Cursor::DeInit();
00181 }

void CursorStack::EndBusy  ) 
 

Turns off the busy cursor (if there has only been one call to BeginBusy) for this cursor stack. Waits until BusyCount reaches zero before turning off the busy cursor.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/1/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: ERROR3 if busy count drops below zero.

See also:
CursorStack::BeginBusy; CursorStack::SmashBusy

Definition at line 576 of file csrstack.cpp.

00577 {
00578     if ((--BusyCount) < 0)
00579     {
00580         BusyCount=0;
00581         ERROR3("Too many calls to CursorStack::EndBusy\n");
00582     }
00583     SetActive();
00584 }

Cursor * CursorStack::GetActive  )  [static]
 

Definition at line 482 of file csrstack.cpp.

00483 {
00484     if( Global->nNextFreeSlot <= 0 )
00485     {
00486         ERROR3("Stack empty in CursorStack::SetActive!\n");
00487         return NULL;
00488     }
00489     
00490     // If BusyCount > 0 show the busy cursor instead of the topmost one
00491     if( Global->BusyCount > 0 )
00492     {
00493         return Cursor::Busy;
00494     }
00495     else
00496     {
00497         return Global->pcStack[Global->nNextFreeSlot - 1].pCursor;
00498     }
00499 }

BOOL CursorStack::GIsActive const Cursor pCursor  )  [static]
 

Definition at line 716 of file csrstack.cpp.

00717 {
00718     return Global->IsActive(pCursor);
00719 }

BOOL CursorStack::GIsValid  )  [static]
 

Definition at line 691 of file csrstack.cpp.

00692 {
00693     return Global->IsValid();
00694 }

Cursor * CursorStack::GPop INT32  cursorID  )  [static]
 

Definition at line 701 of file csrstack.cpp.

00702 {
00703     return Global->Pop(cursorID);
00704 }

INT32 CursorStack::GPush Cursor pCursor,
BOOL  ActivateNow = TRUE
[static]
 

Definition at line 696 of file csrstack.cpp.

00697 {
00698     return Global->Push( pCursor, ActivateNow );
00699 }

void CursorStack::GSetActive  )  [static]
 

Definition at line 711 of file csrstack.cpp.

00712 {
00713     Global->SetActive();
00714 }

Cursor * CursorStack::GSetTop Cursor pCursor,
INT32  cursorID
[static]
 

Definition at line 706 of file csrstack.cpp.

00707 {
00708     return Global->SetTop(pCursor, cursorID);
00709 }

BOOL CursorStack::Init void   )  [static]
 

Initialises the cursor system, loading the standard OS-provided cursors, such as the arrow and the hour-glass, creating the application's cursor stack etc.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if initialisation was successful.

Errors: -

See also:
CursorStack::DeInit; Cursor::Init

Definition at line 141 of file csrstack.cpp.

00142 {
00143     Global = new CursorStack;
00144     if (!Global || !Global->IsValid() || !Cursor::Init())
00145     {
00146         delete Global;
00147         Global = 0;
00148         return FALSE;
00149     }
00150     Global->Push(Cursor::Arrow);    // This is about the only occurrence of Push
00151                                     // that can legitimately ignore the return value, since
00152                                     // this cursor should always be on the stack.
00153     Global->SetActive();
00154     return TRUE;
00155 }

BOOL CursorStack::IsActive const Cursor pCursor  )  const [private]
 

Tests if a particular cursor is on the top of the stack, ie. is currently visible and active.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/11/93
Parameters:
A pointer to a (constant) Cursor object. [INPUTS]
- [OUTPUTS]
Returns:
TRUE if the top of the stack is the same as the parameter, FALSE if it isn't or if the stack is empty.

Errors: -

See also:
-

Definition at line 516 of file csrstack.cpp.

00517 {
00518 //  return (nNextFreeSlot > 0) ? (pcStack[nNextFreeSlot - 1] == pCursor) : FALSE;
00519 
00520     // if BusyCount>0 that means the busy cursor is active, so check for that situation
00521 
00522     if (BusyCount > 0)
00523     {
00524         return (pCursor == Cursor::Busy);
00525     }
00526     else
00527     {
00528         if (nNextFreeSlot>0 && (pcStack[nNextFreeSlot - 1].pCursor == pCursor))
00529 
00530             return TRUE;
00531 
00532         return FALSE;
00533     }
00534 }

BOOL CursorStack::IsValid  )  const [private]
 

Tests if the object was successfully constructed, and is coherent.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if the stack was allocated OK.

Errors: -

See also:
-

Definition at line 258 of file csrstack.cpp.

00259 {
00260     return pcStack != 0 && (nNextFreeSlot >= 0 && nNextFreeSlot <= nSentinel);
00261 }

Cursor * CursorStack::Pop INT32  cursorID = 0  )  [private]
 

Removes a cursor from the stack. Because of the strange, asynchronous nature of Camelot, and the way cursors are seemingly added and removed from the stack at random, when popping a cursor from the stack, a unique ID is used to identify which cursor you actually want to remove. That one is removed, whether it's at the top of the stack or not.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>/Jim
Date:
11/11/93 Modified: 27/1/95
Parameters:
Unique ID of the cursor you want to pop from the stack [INPUTS]
- [OUTPUTS]
Returns:
A pointer to the Cursor object that was previously at the top of the stack. Returns NULL if the stack is empty or a cursor of that ID is not found

Errors: Checks for stack underflow. Also, it now handles stack underflow, as well. Will ERROR in debug builds if the ID is not found in the stack.

See also:
CursorStack::Push; CursorStack::SetActive

Definition at line 323 of file csrstack.cpp.

00324 {
00325     ERROR2IF(nNextFreeSlot <= 0,NULL, "Underflow in CursorStack::Pop!\n");
00326     
00327     // For old code which doesn't pass the ID, we'll pop the top one off and hope
00328     if (cursorID == 0)
00329     {   
00330         Cursor* pc = pcStack[--nNextFreeSlot].pCursor;
00331         return pc;
00332     }
00333     else
00334     {
00335         INT32 n=0;      // Counter to go through the stack
00336         
00337         // Yes, I know this while loop could be more cleverly implemented, but I'm
00338         // sticking with easier to understand code, and letting the optimiser do
00339         // the hard work.
00340 
00341         // Find the ID on the stack and remove it, sealing the hole up
00342         while(n<nNextFreeSlot)
00343         {
00344             if (pcStack[n].UniqueID == cursorID)
00345             {
00346                 Cursor* pc = pcStack[n].pCursor;    // for return
00347 
00348                 // Now, what's the best way of closing up the gap?
00349                 INT32 m = n+1;                      // Point at the next item on stack
00350                 while (m<nNextFreeSlot)             // Don't copy anything if n is the last one
00351                 {
00352                     pcStack[n].pCursor = pcStack[m].pCursor;
00353                     pcStack[n].UniqueID = pcStack[m].UniqueID;
00354                     n++;
00355                     m++;
00356                 }
00357 
00358                 // Now the gap has been closed, let's decrement the nextfree counter
00359                 nNextFreeSlot--;
00360                 if (nNextFreeSlot > 0)
00361                     SetActive();
00362 
00363                 // Finally, return the pointer to the cursor we've just removed from the stack
00364                 return pc;
00365 
00366             }
00367             n++;
00368         }
00369 
00370         // If we arrive here, there wasn't a valid cursor on the stack, so complain
00371         ERROR2(NULL,"Unique ID not found in cursor stack\n");
00372     
00373     }
00374 
00375 }

INT32 CursorStack::Push Cursor pCursor,
BOOL  ActivateNow = TRUE
[private]
 

Pushes the parameter onto the stack, making it top-most and hence the Cursor which will become active when SetActive() is called (this is done automatically by default, or if you pass in ActivateNow == TRUE) The Unique ID returned will be required by calls to SetTop and Pop so that we don't have any problems with the wrong cursors being popped and deleted.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93 Modified: 27/1/95 by Jim
Parameters:
pCursor - A pointer to a Cursor object. [INPUTS] ActivateNow - if TRUE (the default), the cursor will be immediately activated (will become visible immediately). If FALSE, the cursor will not be displayed until the mouse pointer is moved over the appropriate window/area. (The latter form is used by tools so that there is no cursor-flicker when a tool is selected)
- [OUTPUTS]
Returns:
Unique ID which should be used to reference this cursor while it's in the stack

Errors: Tests for stack overflow.

See also:
CursorStack::Pop; CursorStack::SetActive

Definition at line 289 of file csrstack.cpp.

00290 {
00291     ENSURE(nNextFreeSlot < nSentinel, "Overflow in CursorStack::Push!\n");
00292 
00293     INT32 retID = pcStack[nNextFreeSlot++].StoreNewCursor(pCursor);
00294     if (ActivateNow)
00295         SetActive();
00296 
00297     return retID;
00298 }

void CursorStack::SetActive bool  fOnlyRendWnd = true  )  const [private]
 

Makes the Cursor object on the top of the stack the active cursor.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: Checks that the stack isn't empty. Returns if it is

See also:
Cursor::SetActive

Definition at line 467 of file csrstack.cpp.

00468 {
00469     if (nNextFreeSlot <= 0)
00470     {
00471         ERROR3("Stack empty in CursorStack::SetActive!\n");
00472         return;
00473     }
00474     
00475     // If BusyCount > 0 show the busy cursor instead of the topmost one
00476     if (BusyCount > 0)
00477         Cursor::Busy->SetActive();
00478     else
00479         pcStack[nNextFreeSlot - 1].pCursor->SetActive( fOnlyRendWnd );
00480 }

Cursor * CursorStack::SetTop Cursor pCursor,
INT32  cursorID = 0
[private]
 

Replaces a cursor on the stack with a new Cursor object. Combines a pop and a push. Note that the function detects if the stack is empty and will skip the initial pop if it is. The unique ID is used to find which cursor is actually to be replaced. If the cursor passed to this function is the same as the one already occupying the slot, no switching is done, otherwise the top cursor on the stack will be switched on (not necessarily the one passed to this function).

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/93 Modified: 28/1/95 by Jim
Parameters:
pCursor points to a Cursor object. [INPUTS] cursorID is the unique ID of the cursor that wants to be changed
- [OUTPUTS]
Returns:
A pointer to the Cursor object that was previously occupied by the cursor replaced or NULL if there wasn't one.

Errors: -

See also:
CursorStack::Push; CursorStack::Pop

Definition at line 401 of file csrstack.cpp.

00402 {
00403     // cursorID will be zero if unmodified code is used.
00404     if (cursorID == 0)
00405     {
00406         ERROR3("CursorStack::SetTop called without a valid cursorID. Please change the offending code.\n");
00407         Cursor* pc;
00408         if (nNextFreeSlot > 0)
00409         {
00410             pc = pcStack[nNextFreeSlot - 1].pCursor;
00411             pcStack[nNextFreeSlot - 1].pCursor = pCursor;
00412         }
00413         else
00414         {
00415             pc = NULL;
00416             Push(pCursor);
00417         }
00418         SetActive();
00419         return pc;
00420     }
00421     else
00422     {
00423         // This is the new case
00424         INT32 n=0;      // Counter to go through the stack
00425         
00426         // Find the ID on the stack and replace it with the new cursor
00427         while(n<nNextFreeSlot)
00428         {
00429             if (pcStack[n].UniqueID == cursorID)
00430             {
00431                 Cursor* pc = pcStack[n].pCursor;    // for return
00432                 if (pc == pCursor)
00433                     return pc;                      // Don't try and set the cursor if it's the same
00434 
00435                 // Replace this cursor with the new one
00436                 pcStack[n].pCursor = pCursor;
00437 
00438                 if (nNextFreeSlot > 0) SetActive();
00439 
00440                 // Finally, return the pointer to the cursor we've just removed from the stack
00441                 return pc;
00442 
00443             }
00444             n++;
00445         }
00446         // Oh dear, we seem not to have found this cursorID on the stack. 
00447         ERROR2(NULL,"cursorID not found on stack in SetTop.\n");
00448     }
00449 }

void CursorStack::SmashBusy  ) 
 

Turns off the busy cursor (without exceptions) for this cursor stack. Resets the Busy count to zero. Called by Progress.cpp's SmashBusyJob to ensure the cursor is off.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/8/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-
See also:
CursorStack::BeginBusy; CursorStack::EndBusy

Definition at line 605 of file csrstack.cpp.

00606 {
00607     if (BusyCount == 0)     // Not showing a busy cursor, so return ASAP
00608         return;
00609 
00610     // Turn off the busy cursor
00611     BusyCount = 0;
00612     SetActive();
00613 }


Friends And Related Function Documentation

void BeginBusyCursor  )  [friend]
 

Tells the global cursor stack to display a busy cursor.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/93 Modified: 28/1/95 by Jim
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
CursorStack::Push; CursorStack::SetActive; EndBusyCursor; SmashBusyCursor

Definition at line 632 of file csrstack.cpp.

00633 {
00634     //CursorStack::Global->Push(Cursor::Busy);
00635     if (CursorStack::Global)
00636         CursorStack::Global->BeginBusy();
00637 }

void EndBusyCursor  )  [friend]
 

Tells the global cursor stack to stop displaying the busy cursor. If more than one call has been previously made to beginBusyCursor, the busy cursor isn't removed - a usage count is decremented.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/93 Modified: 28/1/95 by Jim
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: ERROR3 failure if the cursor stack isn't displaying a busy cursor at all

See also:
CursorStack::Pop; CursorStack::SetActive; BeginBusyCursor; SmashBusyCursor

Definition at line 658 of file csrstack.cpp.

00659 {
00660     if (CursorStack::Global)
00661         CursorStack::Global->EndBusy();
00662 }

void SmashBusyCursor  )  [friend]
 

Tells the global cursor stack to stop displaying the busy cursor, regardless of how many calls have been previously made to beginBusyCursor.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/8/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-
See also:
BeginBusyCursor; EndBusyCursor

Definition at line 681 of file csrstack.cpp.

00682 {
00683     if (CursorStack::Global)
00684         CursorStack::Global->SmashBusy();
00685 }


Member Data Documentation

INT32 CursorStack::BusyCount [private]
 

Definition at line 193 of file csrstack.h.

CursorStack * CursorStack::Global [static, private]
 

Definition at line 187 of file csrstack.h.

INT32 CursorStack::nNextFreeSlot [private]
 

Definition at line 190 of file csrstack.h.

INT32 CursorStack::nSentinel [private]
 

Definition at line 191 of file csrstack.h.

CursorIdent* CursorStack::pcStack [private]
 

Definition at line 189 of file csrstack.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:53:19 2007 for Camelot by  doxygen 1.4.4