ControlHelper Class Reference

Provide a system for subclassing controls on Camelot bars which offers various facilities such as bubble help/status bar text and commit handling. To use this system you use the Notifyxxx() functions to keep the class up to date with which bars/controls exist. This module will subclass these controls and do some preprocessing of Windows messages in order to do bubble help/commit handling etc. You can 'fake' bubble help on a window that doesn't really have controls in it, by using the 'ad-hoc' bubble help function, DoBubbleHelpOn(). More...

#include <ctrlhelp.h>

Inheritance diagram for ControlHelper:

SimpleCCObject List of all members.

Public Types

typedef TCHAR *(* BubbleHelpCallback )(wxWindow *, UINT32, void *)

Static Public Member Functions

static BOOL Init ()
 Called to initialise the control helper system.
static void DeInit ()
 Deinitialise the control helper system.
static BOOL NotifyBarCreated (wxWindow *)
 Inform the ControlHelper class that a bar has been created with the specified window handle.
static BOOL NotifyBarDeleted (wxWindow *)
 Notify the ControlHelper class that a bar has been deleted.
static BOOL NotifyBarChanged (wxWindow *Old, wxWindow *New)
 Notify the ControlHelper class that a bar's window handle has been changed.
static BOOL NotifyControlCreated (wxWindow *, ControlHelpInfo *)
 Inform the Control helper system that a control has just been created.
static BOOL NotifyControlCreated (wxWindow *, OpDescriptor *)
static BOOL NotifyControlDeleted (wxWindow *)
 Notify the control helper system that a control has just been deleted.
static BOOL NotifyControlChanged (wxWindow *, ControlHelpInfo *)
 Allows the Bubble and Status ID's of a control to be changed.
static void DoBubbleHelpOn (wxWindow *, UINT32, BubbleHelpCallback, void *)
 Provide bubble-help on an ad-hoc basis, i.e. this allows bubble help to be provided for GUI elements which are not necessarily 'controls' as such on a Camelot bar. For example the colour bar uses this to pretend that each colour swatch is a control, and provides the bubble help to be shown on it. This function should be called on mouse move messages over such GUI elements. (It cannot be done automatically by the bubble help system because we do not subclass such elements - because they're not really individual windows!).
static void ServiceBubbleHelp ()
 Updates the bubble help for our controls. Should be called on idle or timer events.
static void BubbleHelpDisable ()
 Cause the bubble help to go into its 'disabled' state, so that even if it is over a control that supports bubble help, bubble help will not be displayed. If bubble help is currently displayed, it is removed. This function should be called on events that ought to kill off bubble help, e.g. key presses, focus switches etc.
static void InformModalDialogOpened ()
 Informs the ControlHelper class that a modal dialog which is NOT managed by the kernel Dialog Manager (i.e. NOT a DialogOp) has been opened. This allows us to disable bubble help whiole modal dialogs are open. Examples of the use of this are the error box, or use of the Windows Common Dialog functions.
static void InformModalDialogClosed ()
 Informs the ControlHelper class that a modal dialog which is NOT managed by the kernel Dialog Manager (i.e. NOT a DialogOp) has been closed. This allows us to disable bubble help whiole modal dialogs are open. Examples of the use of this are the error box, or use of the Windows Common Dialog functions.
static BOOL GetStatusLineText (String_256 *ptext, wxWindow *window)
 Get status-line text for a control with given WHND.
static BOOL IsUserInterfaceCaptured ()
 Determine if the user interface is 'captured' in any way, e.g. if a bar is being dragged or a menu is up, and so on. This is used to determine whether or not to do certain background/idle operations, e.g. background rendering and the like. This does NOT include drag operations such as any tool drags etc., as this would mean that the push tool would not work properly etc.

Private Types

enum  BubbleState {
  STATE_DEAD, STATE_ACTIVE, STATE_INITIAL_PENDING, STATE_UPDATE_PENDING,
  STATE_INITIAL_DISABLED, STATE_DISABLED
}

Static Private Member Functions

static void BubbleHelpKill ()
 Low level function to kill off the bubble help window and delete it, and set various variables for ad-hoc bubble help to sensible 'null' values.
static BOOL AddControl (wxWindow *, ControlHelpInfo *)
 Add entries for a window and all its descendant windows to our list of subclassed controls. This is a 'helper' function for ControlHelper::NotifyControlCreated.
static LRESULT CALLBACK MyWndProc (wxWindow *, UINT32, WPARAM, LPARAM)
 Callback function for special handling of controls on Camelot bars. At present it does nothing - just chains to the controls usual WndProc.
static void SetState (BubbleState NewState, wxWindow *Window=NULL)
 Change the state of the bubble help state machine to the specified state. Calls the appropriate state change handler to process the event.
static void DeadHandler ()
 Kill off the bubble help by setting the bubble help state machine to the STATE_DEAD state.
static void ActiveHandler (wxWindow *Window)
 Activate the bubble help system by moving to the STATE_ACTIVE state. This causes a bubble help window to appear under the cursor, but not is there are any keys down, or if there is a drag going on, or if our app is not active. At some time in the future we should also refuse to put up bubble help if the user has the menu up.
static void InitialPendingHandler ()
 Sets the state to STATE_INITIAL_PENDING, which means that the bubble help window is about to come up, when a timer has elapsed, providing the user doesn't move the cursor away or press a key etc.
static void InitialDisabledHandler ()
 Sets the bubble help state to STATE_INITIAL_DISABLED, which means that the cursor is over a Camelot bar but not over a control, or that for some reason (key press, focus change etc) bubble help should not be displayed, even though the cursor is over a control that supports bubble help.
static void UpdatePendingHandler ()
 Set the bubble help state to STATE_UPDATE_PENDING, which means that the bubble help will appear very quickly if moved over a control. This is used when the user moves from a control to another control, so it enables the user to move along the controls and browse the bubble text for them quite quickly.
static void DisabledHandler ()
 Set the bubble help state to STATE_DISABLED, which means that the bubble help will appear very quickly if moved over a control. This is used when the user moves from a control to a Camelot bar, so it enables the user to move between bars (or even controls which are separated on a bar) and browse the bubble text for them quite quickly.

Static Private Attributes

static ControlTableControls = NULL
static BarTableBars = NULL
static BubbleHelpWndBubbleWnd = NULL
static MonotonicTime PendingTimer
static POINT LastPos = {-1, -1}
static wxWindow * LastControl = NULL
static BOOL ControlHasFocus = FALSE
static wxWindow * AdHocWindow = NULL
static UINT32 AdHocControl = 0
static BOOL AdHocControlIsDifferent = TRUE
static void * AdHocReference = NULL
static BubbleHelpCallback AdHocCallback = NULL
static BubbleState BubbleHelpState = STATE_DEAD
static INT32 ModalDialogs = 0

Detailed Description

Provide a system for subclassing controls on Camelot bars which offers various facilities such as bubble help/status bar text and commit handling. To use this system you use the Notifyxxx() functions to keep the class up to date with which bars/controls exist. This module will subclass these controls and do some preprocessing of Windows messages in order to do bubble help/commit handling etc. You can 'fake' bubble help on a window that doesn't really have controls in it, by using the 'ad-hoc' bubble help function, DoBubbleHelpOn().

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
01/07/94
See also:
ControlHelpInfo; ControlHelper::NotifyBarCreated; ControlHelper::NotifyBarDeleted; ControlHelper::NotifyBarChanged; ControlHelper::NotifyControlCreated; ControlHelper::NotifyControlDeleted ControlHelper::DoBubbleHelpOn

Definition at line 205 of file ctrlhelp.h.


Member Typedef Documentation

typedef TCHAR*(* ControlHelper::BubbleHelpCallback)(wxWindow *, UINT32, void *)
 

Definition at line 222 of file ctrlhelp.h.


Member Enumeration Documentation

enum ControlHelper::BubbleState [private]
 

Enumerator:
STATE_DEAD 
STATE_ACTIVE 
STATE_INITIAL_PENDING 
STATE_UPDATE_PENDING 
STATE_INITIAL_DISABLED 
STATE_DISABLED 

Definition at line 255 of file ctrlhelp.h.

00256     {
00257 
00258         STATE_DEAD,             // No bubble help is displayed - cursor is not over a
00259                                 // a bar or a control.
00260 
00261         STATE_ACTIVE,           // Bubble help is displayed - cursor is over a control.
00262 
00263         STATE_INITIAL_PENDING,  // Waiting to show bubble help for the first time - the 
00264                                 // cursor is over a control.
00265 
00266         STATE_UPDATE_PENDING,   // Waiting to display help for a different control - i.e.
00267                                 // the user has moved from one control to another,
00268                                 // possible via a bar (STATE_DISABLED).
00269 
00270         STATE_INITIAL_DISABLED, // Pointer is over bar, but no help has yet been displayed 
00271                                 // during this session.
00272 
00273         STATE_DISABLED          // Pointer over bar, and bubble help has been displayed
00274                                 // during this session.
00275 
00276     } BubbleState;


Member Function Documentation

void ControlHelper::ActiveHandler wxWindow *  Window  )  [static, private]
 

Activate the bubble help system by moving to the STATE_ACTIVE state. This causes a bubble help window to appear under the cursor, but not is there are any keys down, or if there is a drag going on, or if our app is not active. At some time in the future we should also refuse to put up bubble help if the user has the menu up.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
Parameters:
Window - handle of the control the cursor is currently over. [INPUTS]
See also:
ControlHelper::DeadHandler; ControlHelper::InitialPendingHandler; ControlHelper::InitialDisabledHandler; ControlHelper::DisabledHandler; ControlHelper::UpdatePendingHandler

Definition at line 1791 of file ctrlhelp.cpp.

01792 {
01793     // Sanity checks
01794     ENSURE(Window != NULL, "Bad handle in control helper ActiveHandler()");
01795     ENSURE(BubbleWnd == NULL, "Bubble window already exists in BubbleHelpStart()");
01796 
01797     // No bubble help during drags, or if any mouse buttons are down.
01798 
01799     // Get mouse keys - top bit is set if the button is down.
01800     INT8 MouseStatus = (::GetKeyState(CAMKEY(LBUTTON)) | 
01801                          ::GetKeyState(CAMKEY(MBUTTON)) | 
01802                          ::GetKeyState(CAMKEY(RBUTTON)));
01803 
01804     if ((MouseStatus & 0x8000) ||
01805         (Operation::GetCurrentDragOp() != NULL))
01806     {
01807         // Revert to pending
01808         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01809         SetState(STATE_INITIAL_PENDING);
01810         return;
01811     }
01812 
01813     // Don't do bubble help if we're iconised.
01814     CWnd *pMainWnd = AfxGetApp()->m_pMainWnd;
01815     if (pMainWnd->IsIconic())
01816     {
01817         // Revert to pending
01818         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01819         SetState(STATE_INITIAL_PENDING);
01820         return;
01821     }
01822 
01823     // Only do bubble help if our application is active.
01824     wxWindow* Active  = ::GetActiveWindow();
01825     wxWindow* MainWnd = pMainWnd->m_wxWindow*;
01826 
01827     if ((Active != MainWnd) && (::GetParent(Active) != MainWnd))
01828     {
01829         // Revert to pending
01830         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01831         SetState(STATE_INITIAL_PENDING);
01832         return;
01833     }
01834 
01835     // Don't do bubble help if modal dialog is open.
01836     if (DialogManager::ModalDialogOpen() || (ModalDialogs > 0))
01837     {
01838         // Revert to pending
01839         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01840         SetState(STATE_INITIAL_PENDING);
01841         return;
01842     }
01843 
01844     // Don't do bubble help if a menu is up - Windows captures the mouse during a menu
01845     // processing loop.
01846     if (::GetCapture() != NULL)
01847     {
01848         // Revert to pending
01849         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01850         SetState(STATE_INITIAL_PENDING);
01851         return;
01852     }
01853 
01854     // also only do bubble help if the control were over is actually visible
01855     if (::IsWindowVisible (Window) == FALSE)
01856     {
01857         // Revert to pending
01858         BubbleHelpState = STATE_ACTIVE; // Very important else state machine gets upset!
01859         SetState(STATE_INITIAL_PENDING);
01860         return;
01861     }
01862 
01863     // Ok - we're allowed to display bubble help - work out what to do:
01864 
01865 #if STATE_TRACE
01866     if (IsUserName("Tim"))
01867         TRACE( _T("STATE_ACTIVE\n"));
01868 #endif
01869 
01870     switch (BubbleHelpState)
01871     {
01872         case STATE_INITIAL_PENDING:
01873         case STATE_UPDATE_PENDING:
01874             BubbleHelpState = STATE_ACTIVE;
01875 
01876             // Create and show a bubble help window
01877             ENSURE(BubbleWnd == NULL, "Bubble window already exists!");
01878     
01879             // Make a new bubble help window
01880             TRY
01881             {
01882                 BubbleWnd = new BubbleHelpWnd;
01883             }
01884             CATCH(CMemoryException, e)
01885             {
01886                 TRACEALL( _T("Unable to create bubble help window!\n"));
01887                 return;
01888             }
01889             END_CATCH
01890 
01891             // Create the actual window
01892             if (!BubbleWnd->Create())
01893             {
01894                 TRACEALL( _T("Could not Init bubble help window\n"));
01895                 return;
01896             }
01897 
01898             // If ad-hoc bubble help, call provider to get required text, otherwise
01899             // get resource IDs out of the OpDescriptor in our table of controls.
01900             if ((AdHocCallback != NULL) && (Window == AdHocWindow))
01901             {
01902                 char *BubbleText = AdHocCallback(AdHocWindow, AdHocControl, AdHocReference);
01903                 if (BubbleWnd->SetText(BubbleText))
01904                     BubbleWnd->Show();
01905             }
01906             else
01907             {
01908                 // Find the record for this control.
01909                 ControlEntry *pEntry;
01910                 pEntry = Controls->FindControl(Window);
01911 
01912                 ENSURE(pEntry != NULL, "Bad Entry in ActiveHandler");
01913 
01914                 // If we have an OpDescriptor, then get the bubble help/module IDs from that,
01915                 // otherwise get them directly out of the ControlEntry.
01916                 UINT32 BubbleID;
01917                 UINT32 ModuleID;
01918 
01919                 if (pEntry->pOpDesc != NULL)
01920                 {
01921                     BubbleID = pEntry->pOpDesc->GetBubbleId();
01922                     ModuleID = Tool::GetModuleID(pEntry->pOpDesc->GetToolID());
01923                 }
01924                 else
01925                 {
01926                     BubbleID = pEntry->BubbleID;
01927                     ModuleID = pEntry->ModuleID;
01928                 }
01929 
01930                 // Load the bubble help text.
01931                 // Ugly hack, but who cares?
01932                 String_256 strCaption;
01933                 GetWindowText(Window, strCaption, 255);
01934                 if (strCaption == String_256("Download"))
01935                 {
01936                     if (BubbleWnd->SetText("Download this resource"))
01937                     // If the string loaded ok, put the window in the correct place and show it.
01938                     BubbleWnd->Show();
01939                 }
01940                 else
01941                 {
01942                     if (BubbleWnd->SetText(BubbleID, ModuleID))
01943                     // If the string loaded ok, put the window in the correct place and show it.
01944                     BubbleWnd->Show();
01945                 }
01946             }
01947 
01948             break;
01949 
01950         default:
01951             ENSURE(FALSE, "Wrong state in bubble help");
01952             break;
01953     }
01954 }

BOOL ControlHelper::AddControl wxWindow *  Window,
ControlHelpInfo pInfo
[static, private]
 

Add entries for a window and all its descendant windows to our list of subclassed controls. This is a 'helper' function for ControlHelper::NotifyControlCreated.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
10/05/94
Parameters:
Window - The window to add an entries for. [INPUTS] pInfo - information about the control being added.
Returns:
TRUE if the window and its descendants were processed ok; FALSE if not.
See also:
ControlTable::AddControl; ControlHelper::NotifyControlCreated

Definition at line 947 of file ctrlhelp.cpp.

00948 {
00949     // Firstly, try to add this control
00950     WNDPROC WndProc = (WNDPROC) ::GetWindowLong(Window, GWL_WNDPROC);
00951     ENSURE(WndProc != 0, "NULL WndProc in ControlHelper::AddControl");
00952 
00953     if (!(Controls->AddControl(Window, pInfo, WndProc)))
00954         goto Failure;
00955 
00956     // Subclass the control.
00957     ::SetWindowLong(Window, GWL_WNDPROC, (INT32) MyWndProc);
00958 
00959     // Now try to add/subclass all the children...
00960     wxWindow* Child;
00961     Child = ::GetWindow(Window, GW_CHILD);
00962 
00963     while (Child != NULL)
00964     {
00965         // Recurse for this child window
00966         if (!(AddControl(Child, pInfo)))
00967             goto Failure;
00968 
00969         // Get the next child window, if any.
00970         Child = ::GetWindow(Child, GW_wxWindow*NEXT);
00971     }
00972 
00973     // Success!
00974     return TRUE;
00975 
00976 Failure:
00977     // Could not add all the controls for some reason - remove any we might have added
00978     // so far, but only if this call is for the parent control (cos we recurse in this
00979     // function, and we only want to do this once).
00980     if (Window == pInfo->Parent)
00981     {
00982         wxWindow* RealWindow;
00983 
00984         while ((WndProc = Controls->DeleteControl(Window, &RealWindow)) != NULL)
00985         {
00986             // De-subclass the control.
00987             WNDPROC TheWndProc = (WNDPROC) ::GetWindowLong(Window, GWL_WNDPROC);
00988             if (TheWndProc = MyWndProc)
00989                 // It really is one we've subclassed, so 'de-subclass' it!
00990                 ::SetWindowLong(Window, GWL_WNDPROC, (INT32) WndProc);
00991         }
00992     }
00993 
00994     // Failed
00995     return FALSE;
00996 }

void ControlHelper::BubbleHelpDisable  )  [static]
 

Cause the bubble help to go into its 'disabled' state, so that even if it is over a control that supports bubble help, bubble help will not be displayed. If bubble help is currently displayed, it is removed. This function should be called on events that ought to kill off bubble help, e.g. key presses, focus switches etc.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::BubbleHelpKill

Definition at line 2149 of file ctrlhelp.cpp.

02150 {
02151     // If bubble help is around, disable it.
02152     switch (BubbleHelpState)
02153     {
02154         case STATE_ACTIVE:
02155         case STATE_UPDATE_PENDING:
02156             // Bubble help is on screen or will be RSN so slide into the disabled
02157             // state in order to get rid of/avoid it.
02158             SetState(STATE_DISABLED);
02159             break;
02160 
02161         case STATE_INITIAL_PENDING:
02162             // Bubble help will be on screen RSN so slide into the initial disabled
02163             // state in order to get rid of/avoid it.
02164             SetState(STATE_INITIAL_DISABLED);
02165             break;
02166     }
02167 }

void ControlHelper::BubbleHelpKill  )  [static, private]
 

Low level function to kill off the bubble help window and delete it, and set various variables for ad-hoc bubble help to sensible 'null' values.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::BubbleHelpDisable Scope: Private

Definition at line 2182 of file ctrlhelp.cpp.

02183 {
02184     // Destroy the bubble help window.
02185     if (BubbleWnd != NULL)
02186     {
02187         BubbleWnd->Hide();
02188         delete BubbleWnd;
02189         BubbleWnd = NULL;
02190     }
02191 
02192     // Disable ad-hoc bubble help.
02193     // NB we don't change the AdHocControl, because then we know that we're over the same
02194     // control and should remain disabled (e.g. if user clicks on button and bubble help
02195     // goes away, it shouldn't come back until they move to another control).
02196     AdHocWindow = NULL;
02197     AdHocCallback = NULL;
02198     AdHocReference = NULL;
02199 }

void ControlHelper::DeadHandler  )  [static, private]
 

Kill off the bubble help by setting the bubble help state machine to the STATE_DEAD state.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::ActiveHandler; ControlHelper::InitialPendingHandler; ControlHelper::InitialDisabledHandler; ControlHelper::DisabledHandler; ControlHelper::UpdatePendingHandler

Definition at line 1746 of file ctrlhelp.cpp.

01747 {
01748 #if STATE_TRACE
01749     if (IsUserName("Tim"))
01750         TRACE( _T("STATE_DEAD\n"));
01751 #endif
01752 
01753     switch (BubbleHelpState)
01754     {
01755         case STATE_ACTIVE:
01756             // Kill the bubble help window and fall through.
01757             ENSURE(BubbleWnd != NULL, "No bubble help window!");
01758             BubbleHelpKill();
01759 
01760         case STATE_INITIAL_PENDING:
01761         case STATE_INITIAL_DISABLED:
01762         case STATE_DISABLED:
01763         case STATE_UPDATE_PENDING:
01764             BubbleHelpState = STATE_DEAD;
01765             break;
01766 
01767         default:
01768             ENSURE(FALSE, "Wrong state in bubble help");
01769             break;
01770     }
01771 }

void ControlHelper::DeInit void   )  [static]
 

Deinitialise the control helper system.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/04/94

Definition at line 842 of file ctrlhelp.cpp.

00843 {
00844     // Deallocate our control table and bar table objects.
00845     delete Bars;
00846     Bars = NULL;
00847     delete Controls;
00848     Controls = NULL;
00849     BubbleHelpWnd::DeInit();
00850 }

void ControlHelper::DisabledHandler  )  [static, private]
 

Set the bubble help state to STATE_DISABLED, which means that the bubble help will appear very quickly if moved over a control. This is used when the user moves from a control to a Camelot bar, so it enables the user to move between bars (or even controls which are separated on a bar) and browse the bubble text for them quite quickly.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::DeadHandler; ControlHelper::ActiveHandler; ControlHelper::InitialPendingHandler; ControlHelper::InitialDisabledHandler; ControlHelper::UpdatePendingHandler

Definition at line 2103 of file ctrlhelp.cpp.

02104 {
02105 #if STATE_TRACE
02106     if (IsUserName("Tim"))
02107         TRACE( _T("STATE_DISABLED\n"));
02108 #endif
02109 
02110     // If a control has focus, then don't change state unless it's in order to die.
02111     if (ControlHasFocus)
02112     {
02113         if (BubbleHelpState != STATE_DEAD)
02114             return;
02115     }
02116 
02117     switch (BubbleHelpState)
02118     {
02119         case STATE_ACTIVE:
02120             // Kill the bubble help window and fall through.
02121             ENSURE(BubbleWnd != NULL, "No bubble help window!");
02122             BubbleHelpKill();
02123 
02124         case STATE_UPDATE_PENDING:
02125             BubbleHelpState = STATE_DISABLED;
02126             break;
02127 
02128         default:
02129             ENSURE(FALSE, "Wrong state in bubble help");
02130             break;
02131     }
02132 }

void ControlHelper::DoBubbleHelpOn wxWindow *  Window,
UINT32  NewControl,
BubbleHelpCallback  Callback,
void *  Reference
[static]
 

Provide bubble-help on an ad-hoc basis, i.e. this allows bubble help to be provided for GUI elements which are not necessarily 'controls' as such on a Camelot bar. For example the colour bar uses this to pretend that each colour swatch is a control, and provides the bubble help to be shown on it. This function should be called on mouse move messages over such GUI elements. (It cannot be done automatically by the bubble help system because we do not subclass such elements - because they're not really individual windows!).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
Parameters:
Window - the window to provide bubble help on. [INPUTS] NewControl - pseudo-ID of the imaginary control - this is so the bubble knows when a different control has been moved onto, and hence that it should update the bubble help window. Callback - the callback routine for ad-hoc bubble help - this is called to get the bubble help text when the bubble window needs to be shown. Reference - arbritrary data that the Callback may make use of to provide it with context information for the callback event.

Definition at line 2227 of file ctrlhelp.cpp.

02229 {
02230     // Caller is telling us that they have detected a mouse move over one of their
02231     // controls - therefore take a record of their window handle, and fake an event
02232     // to the state machine.
02233     AdHocWindow = Window;
02234     AdHocCallback = Callback;
02235     AdHocReference = Reference;
02236 
02237     // Work out if this is a different control we're being told about.
02238     AdHocControlIsDifferent = (AdHocControl != NewControl);
02239 
02240     // Remember control ID for next time (we do this before calling BubbleHelpStateMachine()
02241     // because it uses AdHocControl to display the bubble help when it flips into the
02242     // Active state).
02243     AdHocControl = NewControl;
02244 
02245     // We give our WndProc to the state machine so that it thinks that NewControl is one of
02246     // our 'proper' controls.
02247     POINT Pos;
02248     ::GetCursorPos(&Pos);
02249     BubbleHelpStateMachine(Pos, Window, ControlHelper::MyWndProc);
02250 }

BOOL ControlHelper::GetStatusLineText String_256 ptext,
wxWindow *  window
[static]
 

Get status-line text for a control with given WHND.

Author:
Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/11/94
Returns:
TRUE if returning valid text

Definition at line 1128 of file ctrlhelp.cpp.

01129 {
01130     if (window==NULL)
01131         return FALSE;
01132 
01133     ControlEntry* pEntry=Controls->FindControl(window);
01134     if (pEntry==NULL)
01135         return FALSE;
01136     String_256 strCaption;
01137     GetWindowText(window, strCaption, 255);
01138     if (strCaption == String_256("Download"))
01139     {
01140         *ptext = "Download selected resource to the local hard disk";
01141         return TRUE;
01142     }
01143     else return pEntry->ControlStatusLineText(ptext);
01144 }

void ControlHelper::InformModalDialogClosed  )  [static]
 

Informs the ControlHelper class that a modal dialog which is NOT managed by the kernel Dialog Manager (i.e. NOT a DialogOp) has been closed. This allows us to disable bubble help whiole modal dialogs are open. Examples of the use of this are the error box, or use of the Windows Common Dialog functions.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/09/94
See also:
ControlHelper::IncModalDialogCount

Definition at line 2293 of file ctrlhelp.cpp.

02294 {
02295     ModalDialogs--;
02296 
02297     // Restore the active window
02298     DialogManager::RestoreActiveDialogState();
02299 
02300     // Sanity check
02301     ENSURE(ModalDialogs >= 0, 
02302            "Unbalanced call to ControlHelper::InformModalDialogClosed()!");
02303 
02304 }

void ControlHelper::InformModalDialogOpened  )  [static]
 

Informs the ControlHelper class that a modal dialog which is NOT managed by the kernel Dialog Manager (i.e. NOT a DialogOp) has been opened. This allows us to disable bubble help whiole modal dialogs are open. Examples of the use of this are the error box, or use of the Windows Common Dialog functions.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/09/94
See also:
ControlHelper::DecModalDialogCount

Definition at line 2268 of file ctrlhelp.cpp.

02269 {
02270     ModalDialogs++;
02271     // Record the currently active window
02272     DialogManager::RecordActiveDialogState();
02273     // This is the ideal place to disable all modeless dialogs
02274     DialogManager::EnableAllDialogs(FALSE);
02275 }

BOOL ControlHelper::Init void   )  [static]
 

Called to initialise the control helper system.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/04/94
Returns:
TRUE if initialised ok; FALSE if not.

Reimplemented from SimpleCCObject.

Definition at line 816 of file ctrlhelp.cpp.

00817 {
00818     // Allocate and initialise a BarTable object.
00819     Bars = new BarTable;
00820     if ((Bars == NULL) || !Bars->Init())
00821         return FALSE;
00822 
00823     // Allocate and intialise ourselves a ControlTable object
00824     Controls = new ControlTable;
00825     if ((Controls == NULL) || !Controls->Init())
00826         return FALSE;
00827 
00828     // Initialise the bubble help window system
00829     return BubbleHelpWnd::Init();
00830 }

void ControlHelper::InitialDisabledHandler  )  [static, private]
 

Sets the bubble help state to STATE_INITIAL_DISABLED, which means that the cursor is over a Camelot bar but not over a control, or that for some reason (key press, focus change etc) bubble help should not be displayed, even though the cursor is over a control that supports bubble help.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::DeadHandler; ControlHelper::ActiveHandler; ControlHelper::InitialPendingHandler; ControlHelper::DisabledHandler; ControlHelper::UpdatePendingHandler

Definition at line 2013 of file ctrlhelp.cpp.

02014 {
02015 #if STATE_TRACE
02016     if (IsUserName("Tim"))
02017         TRACE( _T("STATE_INITIAL_DISABLED\n"));
02018 #endif
02019 
02020     // If a control has focus, then don't change state unless it's in order to die.
02021     if (ControlHasFocus)
02022     {
02023         if (BubbleHelpState != STATE_DEAD)
02024             return;
02025     }
02026 
02027     switch (BubbleHelpState)
02028     {
02029         case STATE_DEAD:
02030         case STATE_INITIAL_PENDING:
02031             // Don't do anything.
02032             BubbleHelpState = STATE_INITIAL_DISABLED;
02033             break;
02034 
02035         default:
02036             ENSURE(FALSE, "Wrong state in bubble help");
02037             break;
02038     }
02039 }

void ControlHelper::InitialPendingHandler  )  [static, private]
 

Sets the state to STATE_INITIAL_PENDING, which means that the bubble help window is about to come up, when a timer has elapsed, providing the user doesn't move the cursor away or press a key etc.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/06/94
See also:
ControlHelper::DeadHandler; ControlHelper::ActiveHandler; ControlHelper::InitialDisabledHandler; ControlHelper::DisabledHandler; ControlHelper::UpdatePendingHandler

Definition at line 1971 of file ctrlhelp.cpp.

01972 {
01973 #if STATE_TRACE
01974     if (IsUserName("Tim"))
01975         TRACE( _T("STATE_INITIAL_PENDING\n"));
01976 #endif
01977 
01978     switch (BubbleHelpState)
01979     {
01980         case STATE_ACTIVE:
01981             // Kill off bubble help (if it exists) and fall through
01982             BubbleHelpKill();
01983 
01984         case STATE_DEAD:
01985         case STATE_INITIAL_DISABLED:
01986             // Sample timer (i.e. reset delay)
01987             PendingTimer.Sample();
01988             BubbleHelpState = STATE_INITIAL_PENDING;
01989             break;
01990 
01991         default:
01992             ENSURE(FALSE, "Wrong state in bubble help");
01993             break;
01994     }
01995 }

BOOL ControlHelper::IsUserInterfaceCaptured  )  [static]
 

Determine if the user interface is 'captured' in any way, e.g. if a bar is being dragged or a menu is up, and so on. This is used to determine whether or not to do certain background/idle operations, e.g. background rendering and the like. This does NOT include drag operations such as any tool drags etc., as this would mean that the push tool would not work properly etc.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/01/95
Returns:
TRUE => User interface is captured in some way (e.g. a menu is up) FALSE => User interface is not captured.

Definition at line 2324 of file ctrlhelp.cpp.

02325 {
02326     // Bodge for delta - don't ever disable background rendering.
02327     return FALSE;
02328 
02329     if (Operation::GetCurrentDragOp() != NULL)
02330         // Camelot drag in progress - this does not count as capture.
02331         return FALSE;
02332 
02333     // Find out the handle of our main window
02334     CWnd *pMainCWnd = AfxGetMainWnd();
02335 
02336     wxWindow* MainwxWindow* = NULL;
02337 
02338     if (pMainCWnd != NULL)
02339         MainwxWindow* = pMainCWnd->GetSafewxWindow*();
02340 
02341     // Find out which window, if any, is captured.
02342     wxWindow* CapturedwxWindow* = ::GetCapture();
02343 
02344     // Return TRUE if mouse is captured, and it is not our window.
02345     return ((CapturedwxWindow* != NULL) && (CapturedwxWindow* != MainwxWindow*));
02346 }

LRESULT ControlHelper::MyWndProc wxWindow *  Window,
UINT32  Msg,
WPARAM  wParam,
LPARAM  lParam
[static, private]
 

Callback function for special handling of controls on Camelot bars. At present it does nothing - just chains to the controls usual WndProc.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/04/94
Parameters:
The usual - see SDK documentation for "WindowProc". [INPUTS]
Returns:
As for SDK WindowProc.

Errors:

See also:
ControlHelper

Definition at line 1162 of file ctrlhelp.cpp.

01163 {
01164     ENSURE(Window != 0, "NULL Window handle in ControlHelper::MyWndProc");
01165 
01166     // Find the WindowProc for this control.
01167 
01168     ControlEntry *pEntry = Controls->FindControl(Window);
01169 
01170     ENSURE(pEntry != NULL, "Could not find subclassed control in ControlHelper::MyWndProc");
01171 
01172     if (pEntry != NULL)
01173     {
01174         switch (Msg)
01175         {
01176             case WM_MOUSEMOVE:
01177             {
01178         
01179                 // start control drag
01180                 if(KeyPress::IsAlternativePressed())
01181                 {
01182                     return TRUE;
01183                 }
01184                 // Update the status bar on MouseMove messages
01185                 String_256 Desc;
01186                 if (pEntry->ControlStatusLineText(&Desc))
01187                 {
01188                     StatusLine* pStatusLine=GetApplication()->GetpStatusLine();
01189                     if (pStatusLine->AllowControlHelp ())
01190                     {
01191                         if (pStatusLine)
01192                             pStatusLine->UpdateText(&Desc,STATUSLINE_SELDESC_BUTTONS);
01193                     }
01194                 }
01195             }
01196             break;
01197   
01198             case WM_SETFOCUS:
01199                 // This control has focus - disable the bubble help.
01200                 //ControlHasFocus = TRUE;
01201                 if (pEntry->AddCommitHandling)
01202                 {
01203                     SendMessage(GetParent(GetParent(Window)),WM_CTL_SETFOCUS,TRUE,(LPARAM)Window);  
01204                     SendMessage(GetParent(Window),WM_CTL_SETFOCUS,TRUE,(LPARAM)Window);
01205                     
01206                     // Send the control an EM_SETSEL message so the text within it is highlighted.
01207                     ::SendMessage(Window, EM_SETSEL, 0, (LPARAM) (INT32) -1);
01208                 }
01209 
01210                 // Fall through...
01211             
01212             case WM_LBUTTONDOWN:
01213                 if(KeyPress::IsAlternativePressed())
01214                 {
01215                     String_256 ClassNameStr;  // The control type
01216                     GetClassName(GetParent(Window), (TCHAR*)ClassNameStr, 255);
01217                     if (ClassNameStr == String_8(TEXT("ComboBox")))
01218                     {
01219                         SendMessage(GetParent(GetParent(Window)),WM_START_CTLDRAG,
01220                                         KeyPress::IsConstrainPressed(),(LPARAM)GetParent(Window));  
01221                     }
01222                     else
01223                     {
01224                         SendMessage(GetParent(Window),WM_START_CTLDRAG,
01225                                         KeyPress::IsConstrainPressed(),(LPARAM)Window);
01226                     }
01227                     return TRUE;
01228                 }
01229             case WM_MBUTTONDOWN:
01230             case WM_RBUTTONDOWN:
01231             case WM_LBUTTONUP:
01232             case WM_MBUTTONUP:
01233             case WM_RBUTTONUP:
01234             case WM_LBUTTONDBLCLK:
01235             case WM_MBUTTONDBLCLK:
01236             case WM_RBUTTONDBLCLK:
01237         
01238                 // start control drag
01239             
01240                 // Mouse activity - disable bubble help.
01241                 BubbleHelpDisable();
01242                 break;
01243 
01244             case WM_KILLFOCUS:
01245                 // This control has lost focus - allow the bubble help to start working again.
01246                 ControlHasFocus = FALSE;
01247                 if (pEntry->AddCommitHandling)
01248                 {
01249                     SendMessage(GetParent(GetParent(Window)),WM_CTL_SETFOCUS,FALSE,(LPARAM)Window); 
01250                     SendMessage(GetParent(Window),WM_CTL_SETFOCUS,FALSE,(LPARAM)Window);    
01251                 }
01252                 break;
01253             default:
01254 
01255                 if (pEntry->AddCommitHandling)
01256                 {
01257                     // Is commit processing required, this should be the case if the control 
01258                     // is an edit or ComboBox 
01259 
01260                     // Determine the control type
01261                     switch (Msg)
01262                     {
01263                         case WM_CHAR:
01264                             // Process this message to avoid message beeps.
01265                             if ((wParam == CAMKEY(RETURN)) || (wParam == CAMKEY(TAB)))
01266                             {
01267                                 ControlHasFocus = FALSE;
01268                                 return FALSE;
01269                             }
01270                             break;
01271 
01272                         case WM_GETDLGCODE:
01273                             return DLGC_WANTALLKEYS;
01274 
01275                         case WM_KEYDOWN:
01276                             // escape should return the focus back to the main frame
01277                             if (wParam == CAMKEY(ESCAPE))
01278                             {
01279                                 ControlHasFocus = FALSE;
01280                                 DialogManager::DefaultKeyboardFocus();
01281                                 return FALSE;
01282                             }
01283                             else if (wParam == CAMKEY(RETURN) || wParam == CAMKEY(TAB))
01284                             {
01285                                 wxWindow* BarWnd;
01286                                 wxWindow* CtlWnd; 
01287                     
01288                                 String_256 ClassNameStr;  // The control type
01289 
01290                                 BOOL camelotCustomComboBox = FALSE;
01291 
01293                                 
01294                                 // need to do things slightly differently if the control is a 
01295                                 // cc_1dBitmapComboBoxEdit or cc_2dBitmapComboBoxEdit
01296 
01297                                 GetClassName (Window, (TCHAR*)ClassNameStr, 255);
01298 
01299                                 if ((ClassNameStr == String_64(TEXT("cc_1dBitmapComboBoxEdit"))) ||
01300                                     (ClassNameStr == String_64(TEXT("cc_2dBitmapComboBoxEdit"))))
01301                                 {
01302                                     camelotCustomComboBox = TRUE;
01303                                 }
01304 
01306 
01307                                 if (camelotCustomComboBox == FALSE)
01308                                 {
01309                                     GetClassName(GetParent(Window), (TCHAR*)ClassNameStr, 255);
01310 
01311                                     if (ClassNameStr == String_8(TEXT("ComboBox")) || ClassNameStr == String_16(TEXT("cc_CustomEdit")))
01312                                     {
01313                                         // edit controls of these classes are children of the controls.
01314                                         BarWnd = GetParent(GetParent(Window));  // Because combo edit control
01315                                                                             // is a child of the combo 
01316                                                                             // control itself
01317                                         CtlWnd = GetParent(Window);
01318                                     }
01319                                     else
01320                                     {
01321                                         // It's an Edit control
01322                                         BarWnd = GetParent(Window);  // Bar is the edit's parent
01323                                         CtlWnd = Window;
01324                                     }
01325                                 }
01326                                 else
01327                                 {
01328                                     BarWnd = GetParent (Window);
01329                                     CtlWnd = Window;
01330 
01331                                     // the following sendmessage is actually so that when CAMKEY(RETURN) is hit,
01332                                     // (which actually goes through the WM_KEYDOWN in ctrlhelp.cpp); that we can actually
01333                                     // set the selected item BEFORE dialog manager continues !
01334 
01335                                     if (wParam == CAMKEY(RETURN))
01336                                     {
01337                                         SendMessage (CtlWnd, CB_SETTOPINDEX, 1, 0);
01338                                     }
01339                                     else
01340                                     {
01341                                         SendMessage (CtlWnd, CB_SETTOPINDEX, 0, 0);
01342                                     }
01343                                 }
01344 
01345                                 if (wParam == CAMKEY(RETURN) )
01346                                 {
01347                                     ControlHasFocus = FALSE;
01348                                     SendMessage(BarWnd, WM_CTL_SETFOCUS, COMMIT, (LPARAM) Window);  
01349                                 }                                               
01350 
01351                                 // Send commit message to parent, passing the key code (TAB or ENTER) which
01352                                 // it might be useful to know.
01353                                 SendMessage(BarWnd, WM_CTL_COMMIT, GetWindowID(CtlWnd), (LPARAM) wParam);
01354                                 
01355                                 // To fix various bugs this code is a little bodged.  The problems
01356                                 // that this code tries to address are:
01357                                 //  1)  Clicking in one of the size edit controls in the selector info bar,
01358                                 //      entering some text, pressing enter and then clicking in the same edit
01359                                 //      control a second time (this was refusing to take the focus a second
01360                                 //      time)
01361                                 //  2)  Typing a font name in the font drop down box box and then pressing
01362                                 //      enter (this was returning to the font the user had selected before
01363                                 //      they started typeing)
01364                                 if (::GetDlgCtrlID(Window) != _R(IDC_FONT_COMBO))
01365                                 {
01366                                     if (wParam == CAMKEY(RETURN))
01367                                     {
01368                                         GetMainFrame()->SetFocus();
01369                                     }
01370                                     else
01371                                     {
01372                                         // Move focus to the next (previous) control, just like Windows.
01373                                         wxWindow* wxWindow*NewFocus = ::GetNextDlgTabItem(BarWnd, Window, ::GetKeyState(CAMKEY(SHIFT)) < 0);
01374                                         if (wxWindow*NewFocus != NULL) ::SetFocus(wxWindow*NewFocus);
01375                                     }
01376                                     return FALSE;
01377                                 }
01378                             }
01379                             // added by Karim 30/9/99, to allow a more intelligent font-combo
01380                             else if (wParam >= 'A' && wParam <= 'Z' && ::GetDlgCtrlID(Window) == _R(IDC_FONT_COMBO))
01381                             {
01382                                 // pass the message on to the combo-box's parent, to be
01383                                 // processed in DialogManager::SendDialogMessage.
01384                                 ::SendMessage(GetParent(Window), WM_KEYDOWN, wParam, lParam);
01385                             }
01386                             break;
01387                     }
01388 
01389                 }
01390         }
01391     }
01392 
01393     // For any other messages, kill bubble help before passing them on.
01394 //  if (BubbleHel