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