Sign in Join
Wiki copytemporary

Cocoa Internals/Extensions: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Extensions are used to add additional lcl-friendly methods to all Cocoa classes. The default implementation of each method should:
22
33- either indicate that a class is not a LCL-specific class (it's Cocoa native) thus should be handled with care
44- provide a basic functionality for LCL types (for example setting a control bounds using TRect type. Where cocoa is using float-point NSRect)
55
66## Extensions
77
88### LCLObjectExtension
99
1010The extensions adds additional methods to **NSObject** class of cocoa. (This is TObject counterpart, where (almost) all classes in Cocoa inherit from).
1111
1212A lot of the methods below are control specific methods, thus it might be a good idea to elevate the extension from NSObject to NSView or NSControl. However, this might impact other control-like objects (i.w. NSWindow?)
1313
1414#### Methods
1515
16-<table>
17-<thead>
18-<tr>
19-<th><p>Method</p></th>
20-<th><p>Description</p></th>
21-<th colspan="2"><p>Default behavior</p></th>
22-</tr>
23-</thead>
24-<tbody>
25-<tr>
26-<td><p>LCLObjectExtension</p></td>
27-<td><p>LCLViewExtensions</p></td>
28-<td></td>
29-<td></td>
30-</tr>
31-<tr>
32-<td><p>lclIsEnabled</p></td>
33-<td><p>Returns true/false if control is enabled</p></td>
34-<td><p>false</p></td>
35-<td><p>true</p></td>
36-</tr>
37-<tr>
38-<td><p>lclSetEnable</p></td>
39-<td><p>Enables or disables the control</p></td>
40-<td><p>does nothing</p></td>
41-<td><p>traverses child views and passes new enabled status to them</p></td>
42-</tr>
43-<tr>
44-<td><p>lclisVisible</p></td>
45-<td><p>Returns true/false if control is visible</p></td>
46-<td><p>false</p></td>
47-<td><p>not <a href="https://developer.apple.com/documentation/appkit/nsview/1483369-hidden">hidden()</a></p></td>
48-</tr>
49-<tr>
50-<td><p>lclSetVisible</p></td>
51-<td><p>shows or hides a control</p></td>
52-<td><p>does nothing</p></td>
53-<td><p>setHidden() (where is the method in the documentation? deprecated?)</p></td>
54-</tr>
55-<tr>
56-<td><p>lclisHandle</p></td>
57-<td><p>Returns true if the instance of the class can be considered a LCL handle</p></td>
58-<td><p>false</p></td>
59-<td></td>
60-</tr>
61-<tr>
62-<td><p>lclClientFrame</p></td>
63-<td><p>Returns client rectangle (content of the control) in the control's coordinate system</p></td>
64-<td><p>does nothing</p></td>
65-<td></td>
66-</tr>
67-<tr>
68-<td><p>lclFrame</p></td>
69-<td><p>Returns controls position rectangle in the parent's coordinate system</p></td>
70-<td><p>does nothing</p></td>
71-<td><p>frame()</p></td>
72-</tr>
73-<tr>
74-<td><p>lclContentView</p></td>
75-<td><p>Returns NSView that represents the (drawn) contents. In many NSViews or combination of NSViews the content might be different. For example for NSButton (TButton), the content view is NSButton itself. For NSBox (TGroupBox), the content view is contentView. For a NSTextView sunken in NSScrollView (TMemo) the contentView would be documentView of NSScrollView.</p>
76-<p><strong>Important</strong>: lclContentView is also a view where all children controls should be added-to.</p>
77-<p><strong>Important</strong>: lclContentView is also a view that should receive focus (become a firstReponder)</p>
78-<p>The problem is that all WidgetAPI calls are made through a control Handle. Handle doesn't always map to a NSView directly (TMemo, TGroupbox) where additional NSViews are in placed. lclContentView is intent to return the view, where the <strong>draw</strong> methods are called. The method is used by lclInvalidate and lclInvaldateRect.</p>
79-<p>It should be overridden in every composite component to return the actual drawn contents.</p>
80-<p><strong>The alternative</strong> to not having this method is to override lclInvalidateRect for each composition control (which is also doable)</p></td>
81-<td><p>nil</p></td>
82-<td><p>returns self</p></td>
83-</tr>
84-<tr>
85-<td><p>lclGetCallback</p></td>
86-<td><p>The method would only be implemented by LCL controls that inherited from Cocoa controls and are used as LCL widgets. (i.e. TCocoaButton)</p>
87-<p>The method returns the callback interface that was allocated during LCL Handle creation. ObjC control is responsible for storing the interfaces in some manner. (typically a field is added to a subclass).</p>
88-<p>Note that the returned callback can be nil, in two cases:</p>
89-<p>1) the ObjC object queried is NOT an LCL created object</p>
90-<p>2) the ObjC object is being destroyed (by LCL DestroyHandel call), and thus the callback has already been cleared</p></td>
91-<td><p>nil</p></td>
92-<td><p>nil</p></td>
93-</tr>
94-<tr>
95-<td><p>lclClearCallback</p></td>
96-<td><p>The method should be implemented by LCL controls used as widgets.</p>
97-<p>The method clears out the callback interface. Meaning that a subsequent call of lclGetCallback should return nil. The object should also clear out the internal reference. Any methods that are using callback interface (to report events) must always check, if the callback has not been cleared yet.</p>
98-<p>It's not uncommon to destroy the object, that started an event. (i.e. freeing control, during MouseUp or MouseDown).</p>
99-<p>Thus LCL provides it's own kind of protection. The widgetset is expecting itself NOT to cause a conflict (i.e. should not return any event from a handle, that has already been destroyed)</p></td>
100-<td><p>does nothing</p></td>
101-<td><p>does nothing.</p></td>
102-</tr>
103-</tbody>
104-</table>
16+**Method**
17+
18+**Description**
19+
20+**Default behavior**
21+
22+LCLObjectExtension
23+
24+LCLViewExtensions
25+
26+lclIsEnabled
27+
28+Returns true/false if control is enabled
29+
30+false
31+
32+true
33+
34+lclSetEnable
35+
36+Enables or disables the control
37+
38+does nothing
39+
40+traverses child views and passes new enabled status to them
41+
42+lclisVisible
43+
44+Returns true/false if control is visible
45+
46+false
47+
48+not [hidden()](https://developer.apple.com/documentation/appkit/nsview/1483369-hidden)
49+
50+lclSetVisible
51+
52+shows or hides a control
53+
54+does nothing
55+
56+setHidden() (where is the method in the documentation? deprecated?)
57+
58+lclisHandle
59+
60+Returns true if the instance of the class can be considered a LCL handle
61+
62+false
63+
64+lclClientFrame
65+
66+Returns client rectangle (content of the control) in the control's coordinate system
67+
68+does nothing
69+
70+lclFrame
71+
72+Returns controls position rectangle in the parent's coordinate system
73+
74+does nothing
75+
76+frame()
77+
78+lclContentView
79+
80+Returns NSView that represents the (drawn) contents. In many NSViews or combination of NSViews the content might be different. For example for NSButton (TButton), the content view is NSButton itself. For NSBox (TGroupBox), the content view is contentView. For a NSTextView sunken in NSScrollView (TMemo) the contentView would be documentView of NSScrollView.
81+
82+**Important**: lclContentView is also a view where all children controls should be added-to.
83+
84+**Important**: lclContentView is also a view that should receive focus (become a firstReponder)
85+
86+The problem is that all WidgetAPI calls are made through a control Handle. Handle doesn't always map to a NSView directly (TMemo, TGroupbox) where additional NSViews are in placed. lclContentView is intent to return the view, where the **draw** methods are called. The method is used by lclInvalidate and lclInvaldateRect.
87+
88+It should be overridden in every composite component to return the actual drawn contents.
89+
90+**The alternative** to not having this method is to override lclInvalidateRect for each composition control (which is also doable)
91+
92+nil
93+
94+returns self
95+
96+lclGetCallback
97+
98+The method would only be implemented by LCL controls that inherited from Cocoa controls and are used as LCL widgets. (i.e. TCocoaButton)
99+
100+The method returns the callback interface that was allocated during LCL Handle creation. ObjC control is responsible for storing the interfaces in some manner. (typically a field is added to a subclass).
101+
102+Note that the returned callback can be nil, in two cases:
103+
104+1\) the ObjC object queried is NOT an LCL created object
105+
106+2\) the ObjC object is being destroyed (by LCL DestroyHandel call), and thus the callback has already been cleared
107+
108+nil
109+
110+nil
111+
112+lclClearCallback
113+
114+The method should be implemented by LCL controls used as widgets.
115+
116+The method clears out the callback interface. Meaning that a subsequent call of lclGetCallback should return nil. The object should also clear out the internal reference. Any methods that are using callback interface (to report events) must always check, if the callback has not been cleared yet.
117+
118+It's not uncommon to destroy the object, that started an event. (i.e. freeing control, during MouseUp or MouseDown).
119+
120+Thus LCL provides it's own kind of protection. The widgetset is expecting itself NOT to cause a conflict (i.e. should not return any event from a handle, that has already been destroyed)
121+
122+does nothing
123+
124+does nothing.
105125
106126**Consideration**: if everything is bound to lclContentView. - why is it not used as a Handle anyway? Because Handle needs to match the hierarchy of Cocoa objects. I.e. an actual content residers within a ScrollView. And ScrollView is am immediate child of Form. Not the its contents.
107127
108128### Convention
109129
110130- All lcl extension methods should start with "lcl" to distinguish them Cocoa native methods.
111131
112132## Enabled State
113133
114134Enabled state is a basic attribute of all Controls in LCL.
115135
116136In Cocoa Enabled state is only part of NSControl class (derived). Not every LCL-control is mapped to Cocoa NSControl. For example TGroupBox is mapped to NSBox in Cocoa. NSBox is a subclass of NSView (and not NSControl). Thus NSBox doesn't have methods to control if it's enabled or not. (NSBox cannot be "disabled")
117137
118138In order to treat all Cocoa classes the same, LCLExtension introduced 2 methods lclIsEnabled and lclSetEnabled.
119139
120140- for subclasses of NSControl these methods are almost direct mapping to **setEnabled** and **enabled** methods.
121141- for NSView, NSWindow the implementation may vary
122142
123143### Switching Enabled State for Children
124144
125145In LCL design, once a parent control has been disabled, all it's children are disabled automatically. (Yet, they keep their "Enabled" property)
126146
127147If a parent control has been enabled, then all its children are changing to the state of their "Enabled" property.
128148
129149Traversing children must be done implicitly within Widgetset itself. (There's no LCL code to pass through children and change the state).
130150
131151Cocoa implements the loop of state change in LCLViewExtension for **lclSetEnabled** method.
132152
133153**ICommonCallBack** provides a method GetShouldBeEnabled, that returns **Enabled** property of a mapped LCL control. Used whenever a lclSetEnabled is requested to enable controls.
134154
135155## See Also
136156
137157- [[Cocoa Internals]]
138158
139159---
140160*From the Free Pascal wiki, page "Cocoa Internals/Extensions", as it stood on 2019-12-29 after a change by Skalogryz, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
141161Category: Cocoa
142162Category: macOS

Back to history