Module Modal_mx.pkg

     1// Modal_mx.pkg - Modal mixin pacakge support
     2//
     3// John Tuohy
     4// Data Access Corporation
     5//
     6// 02/01/96 - Created
     7// 11/14/97 JJT - Fixed problem where modal objects improperly inherit acc.
     8//                keys from parents. This no longer happens. Popup_state blocks
     9//                all parent inheritance. To override and get the old behavior
    10//                do following: Set Key_Path to (parent(self))
    11//
    12// Primary Interface:
    13//
    14// Get msg_Popup_Modal to Rval  - starts a modal popup, Returns UI stop
    15// Send popup_Modal               value. Can be used on any object (modal
    16//                                or modeless)
    17//
    18// Set Modal_State to T|F       - When true, an object becomes a modal
    19//                                popup object. This sets  TRUE  False
    20//                                    Block_mouse_State   = t      f
    21//                                    Attach_Parent_state = f      t
    22//                                    Ring_State          = t    nochange
    23//                                    Scope_State         = t    nochange
    24//                                    Popup_State         = t    nochange
    25//                                    Key_Pathe           = desktop 0  * (see msg)
    26//
    27// Send Stop_modal_UI           - Stops Current Level of Modal UI.
    28//                                Note: You should NOT use Stop_UI or
    29//                                      set stop_ui_state any more
    30//
    31// Private Augmentations and Changes
    32// ---------------------------------
    33// Global integer Current_modal_object - tracks current modal UI object
    34//
    35// Procedure remove_object - Augmented to stop UI if current modal object
    36//
    37// Procedure Create_Dialog - Augmented to track current_modal object and
    38//                           restore previous modal_object when done.
    39// Property Private_Stop_UI_State - internal, tracks if the current
    40//                           modal ui has been stopped
    41//
    42//
    43
    44// Global integer. Keeps track of current modal object if one
    45// exists. We made this global so that all objects may check this.
    46// It is possible to next modal objects but only one has the active
    47// focus at any one time.
    48Use VDFBase.pkg
    49
    50
    51Global_Variable Integer Current_modal_Object
    52Move 0 to Current_modal_Object  // 0 = no object current modal object
    53
    54// needed by the cCJGridColumnEdit control in grids. Very Private.
    55// all other objects do nothing with this.
    56{ MethodType=Event Visibility=Private }
    57Procedure OnPreCreate_Dialog for cObject
    58End_Procedure
    59
    60Class Modal_Mixin is a Mixin
    61
    62  { MethodType=Event Visibility=Private }
    63  Procedure Define_Modal_Mixin
    64     { Visibility=Private }
    65     property integer private.stop_ui_state false
    66     // This can only be used with the CD_Popup_Object command. If true
    67     // the command will destroy the object it created.
    68     { Visibility=Private }
    69     Property Integer Destroy_Object_State   false
    70     { Visibility=Private }
    71     Property Integer Exit_Application_Local_State False
    72     
    73  End_Procedure // Define_Modal_Mixin
    74
    75  // Public Message: Get Msg_Popup_Modal to rval
    76  //                 Send Popup_Modal
    77  //
    78  //  Allows any object to be used as a modal popup object.
    79  //  This messages creates a modal object (Setting all properties as
    80  //  required), activates via ui_accept, restores all properties, and
    81  //  then returns the exit value.
    82  //
    83  Procedure Popup_Modal Returns Integer // force object to be modal and then pop it up!
    84     Integer OldBMS OldAPS OldPS OldRS OldSS OldEALS
    85     Integer rVal
    86     // If object is active we can't do anything. -1 means already active
    87     If (Active_State(self)) procedure_Return -1
    88
    89     // Remember all important modal property settings.
    90     Get Block_mouse_State            to OldBMS
    91     Get Attach_parent_State          to OldAPS
    92     Get Popup_State                  to OldPS
    93     Get Ring_State                   to OldRS
    94     Get Scope_State                  to OldSS
    95     Get Exit_Application_Local_State to OldEALS
    96
    97     Set Modal_State to True  // Set modal properties (can be augmented)
    98     Get Msg_Popup to rVal
    99     If rval Move -2 to rVal      // did not activate
   100     Else    Move StrMark to rVal // StrMark keeps track of UI value
   101                                  // if 0- a stop_ui, if >0, ret value
   102     Set Modal_State to False // Unset (in case of augmentation)
   103     // restore all expected properties
   104     Set Block_mouse_State   to OldBMS
   105     Set Attach_parent_State to OldAPS
   106     Set Popup_State         to OldPS
   107     Set Ring_State          to OldRS
   108     Set Scope_State         to OldSS
   109     Set Exit_Application_Local_State to OldEALS
   110     Procedure_Return rVal
   111  End_Procedure
   112
   113  // Public Message: Set Modal_State - T = Makes object Modal
   114  //                                   F = Make object nonModal
   115  //
   116  { MethodType=Property }
   117  { Category=Behavior }
   118  { PropertyType=Boolean }
   119  Procedure Set Modal_State Integer Fg
   120     Set Block_mouse_state to fg
   121     Set Attach_parent_state to (not(fg))
   122     Set Exit_Application_Local_State to fg
   123     if fg begin
   124        set popup_state to true
   125        set ring_state to true
   126        set scope_state to true
   127     end
   128     // this will block parent accelorator keys in modal objects
   129     // by assigning the inheritance path directly to the desktop
   130     // thereby skipping all inherited keys. Only do this if Key_path
   131     // has not been tampered with (i.e. set by developer). If changed,
   132     // its up to developer to make this right
   133     // Note that 0 = no special path - use parent
   134     // To override and get the old behavior do the following in your object:
   135     //     Set Key_Path to (parent(self))
   136
   137     if (Fg and key_path(self)=0) ;  // if set to modal, and no special inheritance path
   138        set Key_path to Desktop                // set to desktop (skipping all objects)
   139     Else if (not(Fg) and key_path(self)=desktop) ;  // if non modal and on desktop
   140        set Key_path to 0                      // change to no special path
   141  End_Procedure
   142
   143  //  Public Message: Get Modal_State
   144  //
   145  { MethodType=Property }
   146  Function Modal_State Returns Integer
   147     function_return (block_mouse_state(self))
   148  End_Function // Modal_state
   149
   150  //  Public Message: This will stop the current modal UI if a modal UI level
   151  //  exists and it has not already been stopped.
   152  //  This is smarter than Stop_ui (which should dnot be used) because it can
   153  //  be sent multiple times and only the current UI is stopped.
   154  //
   155  Procedure Stop_Modal_UI
   156      If ( Current_Modal_Object AND ; // only if modal object exists
   157           Private.stop_ui_state(Current_Modal_Object) ) Begin // and it needs stopping
   158             Send stop_ui
   159             set private.stop_ui_state of Current_Modal_Object to false
   160      End
   161  End_Procedure
   162
   163
   164
   165  // Private
   166  //
   167  { Visibility=Private }
   168  Procedure Create_Dialog integer i1 integer i2
   169      Integer OldModalObj
   170      Handle hoFocus
   171      
   172      // this is required by cCJGrids to make sure that the cell's edit control is removed before 
   173      // the modal object takes the focus. For all other objects, this does nothing. 
   174      Get Focus to hoFocus
   175      If (hoFocus>Desktop) Begin
   176          Send OnPreCreate_Dialog of hoFocus
   177      End
   178      
   179      // by keeping track of the old modal object we can properly nest
   180      // modal popups
   181      Move Current_Modal_Object to OldModalObj
   182      Move self to Current_Modal_Object
   183      Set private.stop_ui_state to True
   184      Send OnPreApplySkin False
   185      forward send create_dialog i1 i2 // will activate and start a new UI
   186
   187      // at this point the object may or may not be active. To handle
   188      // this, DF will send deactivate_group to get rid of it if it is
   189      // still active. It will send this after the procedure is complete.
   190      // We know that the UI is stopped!
   191
   192      set private.stop_ui_state to false // since UI is stopped. Shut this off
   193      Move OldModalObj to Current_Modal_Object // the prior modal level if any
   194  End_procedure
   195
   196  // Private
   197  //
   198  { Visibility=Private }
   199  procedure Remove_Object
   200      forward send remove_object
   201      // If we are removing the current modal object we might need
   202      // to stop the UI as well.
   203      if Current_Modal_Object eq self ;
   204         Send Stop_Modal_UI
   205  end_procedure
   206
   207End_Class
   208