@breakside/jskit 2021.52.0 → 2022.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSColorSpace.js +106 -20
  7. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  8. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  9. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  10. package/Info.json +2 -2
  11. package/Node/io.breakside.jskit-bundle.js +2 -2
  12. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  13. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  14. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  15. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  16. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  17. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  18. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  19. package/Root/Frameworks/DOM/Info.yaml +1 -1
  20. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  21. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  22. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  23. package/Root/Frameworks/Foundation/JSColorSpace.js +106 -20
  24. package/Root/Frameworks/ImageKit/IKColorProfile.js +979 -0
  25. package/Root/Frameworks/ImageKit/IKColorSpace.js +49 -198
  26. package/Root/Frameworks/ImageKit/IKMatrix.js +124 -0
  27. package/Root/Frameworks/ImageKit/ImageKit.js +2 -0
  28. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  29. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  30. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  31. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  32. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  33. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  34. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  35. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  36. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  37. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  38. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  39. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  40. package/Root/Frameworks/UIKit/UICollectionReusableView.js +91 -0
  41. package/Root/Frameworks/UIKit/UICollectionView.js +1254 -0
  42. package/Root/Frameworks/UIKit/UICollectionViewCell.js +121 -0
  43. package/Root/Frameworks/UIKit/UICollectionViewGridLayout.js +425 -0
  44. package/Root/Frameworks/UIKit/UICollectionViewLayout.js +82 -0
  45. package/Root/Frameworks/UIKit/UIColorWell.js +12 -1
  46. package/Root/Frameworks/UIKit/UIDisplayServer.js +5 -1
  47. package/Root/Frameworks/UIKit/UIKit.js +7 -0
  48. package/Root/Frameworks/UIKit/UILayer.js +3 -0
  49. package/Root/Frameworks/UIKit/UIListView.js +8 -9
  50. package/Root/Frameworks/UIKit/UIMenu.js +1 -1
  51. package/Root/Frameworks/UIKit/UIMenuView.js +5 -1
  52. package/Root/Frameworks/UIKit/UINavigationBar.js +2 -2
  53. package/Root/Frameworks/UIKit/UIPopupButton.js +31 -3
  54. package/Root/Frameworks/UIKit/UIScrollView.js +2 -0
  55. package/Root/Frameworks/UIKit/UISplitViewController.js +43 -9
  56. package/Root/Frameworks/UIKit/UITextField.js +3 -0
  57. package/Root/Frameworks/UIKit/UIView.js +3 -0
  58. package/Root/Frameworks/UIKit/UIViewController.js +8 -0
  59. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,121 @@
1
+ // Copyright 2022 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import "UICollectionReusableView.js"
17
+ // #import "UILabel.js"
18
+ // #import "UIImageView.js"
19
+ 'use strict';
20
+
21
+ JSClass("UICollectionViewCell", UICollectionReusableView, {
22
+
23
+ layoutSubviews: function(){
24
+ UICollectionViewCell.$super.layoutSubviews.call(this);
25
+ var styler = (this._styler || (this.collectionView && this.collectionView._styler));
26
+ if (!styler){
27
+ return;
28
+ }
29
+ styler.layoutCell(this);
30
+ },
31
+
32
+ // --------------------------------------------------------------------
33
+ // MARK: - State
34
+
35
+ state: JSReadOnlyProperty('_state', null),
36
+ active: JSDynamicProperty(null, null, 'isActive'),
37
+ selected: JSDynamicProperty(null, null, 'isSelected'),
38
+ contextSelected: JSDynamicProperty(null, null, 'isContextSelected'),
39
+
40
+ _updateState: function(newState){
41
+ if (newState != this._state){
42
+ this._state = newState;
43
+ if (this._didChangeState){
44
+ this._didChangeState();
45
+ }else{
46
+ this.update();
47
+ }
48
+ }
49
+ },
50
+
51
+ update: function(){
52
+ var styler = (this._styler || (this.collectionView && this.collectionView._styler));
53
+ if (!styler){
54
+ return;
55
+ }
56
+ styler.updateCell(this, this.indexPath);
57
+ },
58
+
59
+ _toggleState: function(flag, on){
60
+ var newState = this._state;
61
+ if (on){
62
+ newState |= flag;
63
+ }else{
64
+ newState &= ~flag;
65
+ }
66
+ this._updateState(newState);
67
+ },
68
+
69
+ toggleStates: function(flag, on){
70
+ this._toggleState(flag, on);
71
+ },
72
+
73
+ isActive: function(){
74
+ return (this._state & UICollectionViewCell.State.active) === UICollectionViewCell.State.active;
75
+ },
76
+
77
+ setActive: function(isActive){
78
+ this._toggleState(UICollectionViewCell.State.active, isActive);
79
+ },
80
+
81
+ isSelected: function(){
82
+ return (this._state & UICollectionViewCell.State.selected) === UICollectionViewCell.State.selected;
83
+ },
84
+
85
+ setSelected: function(isSelected){
86
+ this._toggleState(UICollectionViewCell.State.selected, isSelected);
87
+ },
88
+
89
+ isContextSelected: function(){
90
+ return (this._state & UICollectionViewCell.State.contextSelected) === UICollectionViewCell.State.contextSelected;
91
+ },
92
+
93
+ setContextSelected: function(isContextSelected){
94
+ this._toggleState(UICollectionViewCell.State.contextSelected, isContextSelected);
95
+ },
96
+
97
+ // --------------------------------------------------------------------
98
+ // MARK: - Accessibility
99
+
100
+ isAccessibilityElement: true,
101
+ accessibilityRole: UIAccessibility.Role.cell,
102
+
103
+ getAccessibilityElements: function(){
104
+ return this._contentView.accessibilityElements;
105
+ },
106
+
107
+ accessibilitySelected: JSReadOnlyProperty(),
108
+
109
+ getAccessibilitySelected: function(){
110
+ return this.selected;
111
+ },
112
+
113
+ });
114
+
115
+ UICollectionViewCell.State = {
116
+ normal: 0,
117
+ active: 1 << 1,
118
+ selected: 1 << 2,
119
+ contextSelected: 1 << 3,
120
+ firstUserState: 1 << 4
121
+ };
@@ -0,0 +1,425 @@
1
+ // Copyright 2022 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import "UICollectionViewLayout.js"
17
+ /* global UICollectionView */
18
+ "use strict";
19
+
20
+ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
21
+
22
+ init: function(){
23
+ this._collectionInsets = JSInsets.Zero;
24
+ this._sectionInsets = JSInsets.Zero;
25
+ this._cellSize = JSSize(50, 50);
26
+ },
27
+
28
+ initWithSpec: function(spec){
29
+ UICollectionViewGridLayout.$super.initWithSpec.call(this, spec);
30
+ if (spec.containsKey("collectionInsets")){
31
+ this._collectionInsets = spec.valueForKey("collectionInsets", JSInsets);
32
+ }else{
33
+ this._collectionInsets = JSInsets.Zero;
34
+ }
35
+ if (spec.containsKey("collectionHeaderHeight")){
36
+ this._collectionHeaderHeight = spec.valueForKey("collectionHeaderHeight", Number);
37
+ }
38
+ if (spec.containsKey("collectionFooterHeight")){
39
+ this._collectionFooterHeight = spec.valueForKey("collectionFooterHeight", Number);
40
+ }
41
+ if (spec.containsKey("collectionHeaderSpacing")){
42
+ this._collectionHeaderSpacing = spec.valueForKey("collectionHeaderSpacing", Number);
43
+ }
44
+ if (spec.containsKey("collectionFooterSpacing")){
45
+ this._collectionFooterSpacing = spec.valueForKey("collectionFooterSpacing", Number);
46
+ }
47
+ if (spec.containsKey("sectionInsets")){
48
+ this._sectionInsets = spec.valueForKey("sectionInsets", JSInsets);
49
+ }else{
50
+ this._sectionInsets = JSInsets.Zero;
51
+ }
52
+ if (spec.containsKey("showsSectionBackgroundViews")){
53
+ this._showsSectionBackgroundViews = spec.valueForKey("showsSectionBackgroundViews");
54
+ }
55
+ if (spec.containsKey("sectionSpacing")){
56
+ this._sectionSpacing = spec.valueForKey("sectionSpacing", Number);
57
+ }
58
+ if (spec.containsKey("sectionHeaderHeight")){
59
+ this._sectionHeaderHeight = spec.valueForKey("sectionHeaderHeight", Number);
60
+ }
61
+ if (spec.containsKey("sectionFooterHeight")){
62
+ this._sectionFooterHeight = spec.valueForKey("sectionFooterHeight", Number);
63
+ }
64
+ if (spec.containsKey("sectionHeaderSpacing")){
65
+ this._sectionHeaderSpacing = spec.valueForKey("sectionHeaderSpacing", Number);
66
+ }
67
+ if (spec.containsKey("sectionFooterSpacing")){
68
+ this._sectionFooterSpacing = spec.valueForKey("sectionFooterSpacing", Number);
69
+ }
70
+ if (spec.containsKey("columnSpacing")){
71
+ this._columnSpacing = spec.valueForKey("columnSpacing", Number);
72
+ }
73
+ if (spec.containsKey("rowSpacing")){
74
+ this._rowSpacing = spec.valueForKey("rowSpacing", Number);
75
+ }
76
+ if (spec.containsKey("cellSize")){
77
+ this._cellSize = spec.valueForKey("cellSize", JSSize);
78
+ }else{
79
+ this._cellSize = JSSize(50, 50);
80
+ }
81
+ if (spec.containsKey("headersStickToTop")){
82
+ this._headersStickToTop = spec.valueForKey("headersStickToTop");
83
+ }
84
+ },
85
+
86
+ collectionInsets: JSDynamicProperty("_collectionInsets", null),
87
+ collectionHeaderHeight: JSDynamicProperty("_collectionHeaderHeight", 0),
88
+ collectionFooterHeight: JSDynamicProperty("_collectionFooterHeight", 0),
89
+ collectionHeaderSpacing: JSDynamicProperty("_collectionHeaderSpacing", 0),
90
+ collectionFooterSpacing: JSDynamicProperty("_collectionFooterSpacing", 0),
91
+ showsSectionBackgroundViews: JSDynamicProperty("_showsSectionBackgroundViews", false),
92
+ sectionInsets: JSDynamicProperty("_sectionInsets", null),
93
+ sectionSpacing: JSDynamicProperty("_sectionSpacing", 0),
94
+ sectionHeaderHeight: JSDynamicProperty("_sectionHeaderHeight", 0),
95
+ sectionFooterHeight: JSDynamicProperty("_sectionFooterHeight", 0),
96
+ sectionHeaderSpacing: JSDynamicProperty("_sectionHeaderSpacing", 0),
97
+ sectionFooterSpacing: JSDynamicProperty("_sectionFooterSpacing", 0),
98
+ columnSpacing: JSDynamicProperty("_columnSpacing", 1),
99
+ rowSpacing: JSDynamicProperty("_rowSpacing", 1),
100
+ cellSize: JSDynamicProperty("_cellSize", null),
101
+ headersStickToTop: JSDynamicProperty("_headersStickToTop", false),
102
+
103
+ setCollectionInsets: function(collectionInsets){
104
+ this._collectionInsets = JSInsets(collectionInsets);
105
+ this.invalidateLayout();
106
+ },
107
+
108
+ setCollectionHeaderHeight: function(collectionHeaderHeight){
109
+ this._collectionHeaderHeight = collectionHeaderHeight;
110
+ this.invalidateLayout();
111
+ },
112
+
113
+ setCollectionFooterHeight: function(collectionFooterHeight){
114
+ this._collectionFooterHeight = collectionFooterHeight;
115
+ this.invalidateLayout();
116
+ },
117
+
118
+ setCollectionHeaderSpacing: function(collectionHeaderSpacing){
119
+ this._collectionHeaderSpacing = collectionHeaderSpacing;
120
+ this.invalidateLayout();
121
+ },
122
+
123
+ setCollectionFooterSpacing: function(collectionFooterSpacing){
124
+ this._collectionFooterSpacing = collectionFooterSpacing;
125
+ this.invalidateLayout();
126
+ },
127
+
128
+ setShowsSectionBackgroundViews: function(showsSectionBackgroundViews){
129
+ this._showsSectionBackgroundViews = showsSectionBackgroundViews;
130
+ this.invalidateLayout();
131
+ },
132
+
133
+ setSectionInsets: function(sectionInsets){
134
+ this._sectionInsets = JSInsets(sectionInsets);
135
+ this.invalidateLayout();
136
+ },
137
+
138
+ setSectionSpacing: function(sectionSpacing){
139
+ this._sectionSpacing = sectionSpacing;
140
+ this.invalidateLayout();
141
+ },
142
+
143
+ setSectionHeaderHeight: function(sectionHeaderHeight){
144
+ this._sectionHeaderHeight = sectionHeaderHeight;
145
+ this.invalidateLayout();
146
+ },
147
+
148
+ setSectionFooterHeight: function(sectionFooterHeight){
149
+ this._sectionFooterHeight = sectionFooterHeight;
150
+ this.invalidateLayout();
151
+ },
152
+
153
+ setSectionHeaderSpacing: function(sectionHeaderSpacing){
154
+ this._sectionHeaderSpacing = sectionHeaderSpacing;
155
+ this.invalidateLayout();
156
+ },
157
+
158
+ setSectionFooterSpacing: function(sectionFooterSpacing){
159
+ this._sectionFooterSpacing = sectionFooterSpacing;
160
+ this.invalidateLayout();
161
+ },
162
+
163
+ setColumnSpacing: function(columnSpacing){
164
+ this._columnSpacing = columnSpacing;
165
+ this.invalidateLayout();
166
+ },
167
+
168
+ setRowSpacing: function(rowSpacing){
169
+ this._rowSpacing = rowSpacing;
170
+ this.invalidateLayout();
171
+ },
172
+
173
+ setCellSize: function(cellSize){
174
+ this._cellSize = JSSize(cellSize);
175
+ this.invalidateLayout();
176
+ },
177
+
178
+ fillingCellSizeClosestToSize: function(preferredCellSize){
179
+ var bounds = this.collectionView.contentView.bounds;
180
+ var availableWidth = bounds.size.width - this._collectionInsets.width - this._sectionInsets.width;
181
+ var columnCount = Math.max(1, Math.round((availableWidth + this._columnSpacing) / (preferredCellSize.width + this._columnSpacing)));
182
+ var cellWidth = Math.floor((availableWidth - (columnCount - 1) * this._columnSpacing) / columnCount);
183
+ return JSSize(cellWidth, Math.floor(preferredCellSize.height * cellWidth / preferredCellSize.width));
184
+ },
185
+
186
+ setHeadersStickToTop: function(headersStickToTop){
187
+ this._headersStickToTop = headersStickToTop;
188
+ this.invalidateLayout();
189
+ },
190
+
191
+ _cachedLayout: null,
192
+
193
+ prepare: function(){
194
+ this._cachedLayout = {
195
+ sections: [],
196
+ columns: [],
197
+ headerFrame: JSRect.Zero,
198
+ footerFrame: JSRect.Zero,
199
+ contentSize: JSSize.Zero
200
+ };
201
+ if (this.collectionView === null){
202
+ return;
203
+ }
204
+ var origin = JSPoint(this._collectionInsets.left, this._collectionInsets.top);
205
+ this._cachedLayout.contentSize.width = this.collectionView.contentView.bounds.size.width;
206
+ this._cachedLayout.contentSize.height += this._collectionInsets.height;
207
+ if (this._collectionHeaderHeight > 0){
208
+ this._cachedLayout.contentSize.height += this._collectionHeaderHeight + this._collectionHeaderSpacing;
209
+ origin.y += this._collectionHeaderHeight + this._collectionHeaderSpacing;
210
+ }
211
+ if (this._collectionFooterHeight > 0){
212
+ this._cachedLayout.contentSize.height += this._collectionFooterHeight + this._collectionFooterSpacing;
213
+ }
214
+ var availableWidth = this._cachedLayout.contentSize.width - this._collectionInsets.width - this._sectionInsets.width;
215
+ var columnCount = Math.max(1, Math.floor((availableWidth + this._columnSpacing) / (this._cellSize.width + this._columnSpacing)));
216
+ var columnIndex;
217
+ var x = this._collectionInsets.left + this._sectionInsets.left;
218
+ for (columnIndex = 0; columnIndex < columnCount; ++columnIndex){
219
+ this._cachedLayout.columns.push({x: x});
220
+ x += this._cellSize.width + this._columnSpacing;
221
+ }
222
+ var sectionCount = this.collectionView.dataSource.numberOfSectionsInCollectionView(this.collectionView);
223
+ var cellCount;
224
+ var sectionIndex;
225
+ var sectionLayout;
226
+ var size = JSSize(this._cachedLayout.contentSize.width - this._collectionInsets.width, 0);
227
+ var rowCount;
228
+ var rowOffset = 0;
229
+ var sectionHeaderAndSpacingHeight = 0;
230
+ var sectionFooterAndSpacingHeight = 0;
231
+ if (this._sectionHeaderHeight > 0){
232
+ sectionHeaderAndSpacingHeight = this._sectionHeaderHeight + this._sectionHeaderSpacing;
233
+ }
234
+ if (this._sectionFooterHeight > 0){
235
+ sectionFooterAndSpacingHeight= this._sectionFooterHeight + this._sectionFooterSpacing;
236
+ }
237
+ for (sectionIndex = 0; sectionIndex < sectionCount; ++sectionIndex){
238
+ cellCount = this.collectionView.dataSource.numberOfCellsInCollectionViewSection(this.collectionView, sectionIndex);
239
+ rowCount = Math.ceil(cellCount / columnCount);
240
+ size.height = this._sectionInsets.height + sectionHeaderAndSpacingHeight + sectionFooterAndSpacingHeight;
241
+ size.height += rowCount * this._cellSize.height + (rowCount - 1) * this._rowSpacing;
242
+ this._cachedLayout.sections.push({
243
+ rowOffset: rowOffset,
244
+ cellCount: cellCount,
245
+ rowCount: rowCount,
246
+ frame: JSRect(origin, size),
247
+ headerFrame: JSRect(
248
+ origin.x + this._sectionInsets.left,
249
+ origin.y + this._sectionInsets.top,
250
+ availableWidth,
251
+ this._sectionHeaderHeight
252
+ ),
253
+ footerFrame: JSRect(
254
+ origin.x + this._sectionInsets.left,
255
+ origin.y + size.height - this._sectionInsets.bottom - this._sectionFooterHeight,
256
+ availableWidth,
257
+ this._sectionFooterHeight
258
+ ),
259
+ cellsFrame: JSRect(
260
+ origin.x + this._sectionInsets.left,
261
+ origin.y + this._sectionInsets.top + sectionHeaderAndSpacingHeight,
262
+ availableWidth,
263
+ size.height - this._sectionInsets.height - sectionHeaderAndSpacingHeight - sectionFooterAndSpacingHeight
264
+ )
265
+ });
266
+ this._cachedLayout.contentSize.height += size.height;
267
+ if (sectionIndex < sectionCount - 1){
268
+ this._cachedLayout.contentSize.height += this._sectionSpacing;
269
+ }
270
+ origin.y += size.height + this._sectionSpacing;
271
+ rowOffset += rowCount;
272
+ }
273
+ this._cachedLayout.headerFrame = JSRect(
274
+ this._collectionInsets.left,
275
+ this._collectionInsets.top,
276
+ this._cachedLayout.contentSize.width - this._collectionInsets.width,
277
+ this._collectionHeaderHeight
278
+ );
279
+ this._cachedLayout.footerFrame = JSRect(
280
+ this._collectionInsets.left,
281
+ this._cachedLayout.contentSize.height - this._collectionInsets.bottom - this._collectionFooterHeight,
282
+ this._cachedLayout.contentSize.width - this._collectionInsets.width,
283
+ this._collectionFooterHeight
284
+ );
285
+ this.collectionView.accessibilityRowCount = rowOffset;
286
+ this.collectionView.accessibilityColumnCount = this._cachedLayout.columns.length;
287
+ },
288
+
289
+ getCollectionViewContentSize: function(){
290
+ return this._cachedLayout.contentSize;
291
+ },
292
+
293
+ layoutAttributesForElementsInRect: function(rect){
294
+ var attributes = [];
295
+ if (this._cachedLayout.headerFrame.size.height > 0 && (this._headersStickToTop || rect.intersectsRect(this._cachedLayout.headerFrame))){
296
+ attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([]), UICollectionViewGridLayout.SupplimentaryKind.header));
297
+ }
298
+ var columnCount = this._cachedLayout.columns.length;
299
+ var columnIndex;
300
+ var sectionIndex;
301
+ var sectionCount = this._cachedLayout.sections.length;
302
+ var sectionLayout;
303
+ var indexPath;
304
+ var y;
305
+ var y0 = rect.origin.y;
306
+ var y1 = rect.origin.y + rect.size.height;
307
+ var rowHeight = this._cellSize.height + this._rowSpacing;
308
+ var rowIndex;
309
+ var attrs;
310
+ // FIXME: can do a more efficient search of sections
311
+ for (sectionIndex = 0; sectionIndex < sectionCount; ++sectionIndex){
312
+ sectionLayout = this._cachedLayout.sections[sectionIndex];
313
+ if (sectionLayout.frame.size.height > 0 && rect.intersectsRect(sectionLayout.frame)){
314
+ if (this._showsSectionBackgroundViews){
315
+ attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([sectionIndex]), UICollectionViewGridLayout.SupplimentaryKind.background));
316
+ }
317
+ if (sectionLayout.headerFrame.size.height > 0 && (this._headersStickToTop || rect.intersectsRect(sectionLayout.headerFrame))){
318
+ attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([sectionIndex]), UICollectionViewGridLayout.SupplimentaryKind.header));
319
+ }
320
+ if (sectionLayout.cellsFrame.size.height > 0 && rect.intersectsRect(sectionLayout.cellsFrame)){
321
+ indexPath = JSIndexPath(sectionIndex, 0);
322
+ y = sectionLayout.cellsFrame.origin.y;
323
+ rowIndex = Math.max(0, Math.floor((y0 - y) / rowHeight));
324
+ y += rowIndex * rowHeight;
325
+ indexPath.row = rowIndex * columnCount;
326
+ for (; rowIndex < sectionLayout.rowCount && y < y1; ++rowIndex, y += rowHeight){
327
+ for (columnIndex = 0; columnIndex < columnCount && indexPath.row < sectionLayout.cellCount; ++columnIndex, ++indexPath.row){
328
+ attrs = UICollectionViewLayoutAttributes.initCellAtIndexPath(indexPath, JSRect(
329
+ this._cachedLayout.columns[columnIndex].x,
330
+ y,
331
+ this._cellSize.width,
332
+ this._cellSize.height
333
+ ));
334
+ attrs.rowIndex = sectionLayout.rowOffset + rowIndex;
335
+ attrs.columnIndex = columnIndex;
336
+ attributes.push(attrs);
337
+ }
338
+ }
339
+ }
340
+ if (sectionLayout.footerFrame.size.height > 0 && rect.intersectsRect(sectionLayout.footerFrame)){
341
+ attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([sectionIndex]), UICollectionViewGridLayout.SupplimentaryKind.footer));
342
+ }
343
+ }
344
+ }
345
+ if (this._cachedLayout.footerFrame.size.height > 0 && rect.intersectsRect(this._cachedLayout.footerFrame)){
346
+ attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([]), UICollectionViewGridLayout.SupplimentaryKind.footer));
347
+ }
348
+ if (this._headersStickToTop){
349
+ var i = attributes.length - 1;
350
+ var j = i;
351
+ for (; i >= 0; --i){
352
+ attrs = attributes[i];
353
+ if (attrs.elementCategory === UICollectionView.ElementCategory.supplimentary && attrs.kind === UICollectionViewGridLayout.SupplimentaryKind.header){
354
+ attributes.splice(i, 1);
355
+ attributes.splice(j, 0, attrs);
356
+ }
357
+ }
358
+ }
359
+ return attributes;
360
+ },
361
+
362
+ layoutAttributesForCellAtIndexPath: function(indexPath){
363
+ var sectionLayout = this._cachedLayout.sections[indexPath.section];
364
+ var columnCount = this._cachedLayout.columns.length;
365
+ var rowIndex = Math.floor(indexPath.row / columnCount);
366
+ var columnIndex = indexPath.row % columnCount;
367
+ var origin = JSPoint(
368
+ this._cachedLayout.columns[columnIndex].x,
369
+ sectionLayout.cellsFrame.origin.y + rowIndex * (this._cellSize.height + this._rowSpacing)
370
+ );
371
+ var frame = JSRect(
372
+ origin,
373
+ this._cellSize
374
+ );
375
+ var attributes = UICollectionViewLayoutAttributes.initCellAtIndexPath(indexPath, frame);
376
+ attributes.rowIndex = sectionLayout.rowOffset + rowIndex;
377
+ attributes.columnIndex = columnIndex;
378
+ return attributes;
379
+ },
380
+
381
+ layoutAttributesForSupplimentaryViewAtIndexPath: function(indexPath, kind){
382
+ var attributes;
383
+ var ty;
384
+ if (indexPath.length === 0){
385
+ if (kind === UICollectionViewGridLayout.SupplimentaryKind.header){
386
+ attributes = UICollectionViewLayoutAttributes.initSupplimentaryAtIndexPath(indexPath, kind, this._cachedLayout.headerFrame);
387
+ if (this._headersStickToTop){
388
+ ty = Math.max(0, this.collectionView.contentView.bounds.origin.y - attributes.frame.origin.y);
389
+ attributes.transform = JSAffineTransform.Translated(0, ty);
390
+ }
391
+ return attributes;
392
+ }
393
+ if (kind === UICollectionViewGridLayout.SupplimentaryKind.footer){
394
+ return UICollectionViewLayoutAttributes.initSupplimentaryAtIndexPath(indexPath, kind, this._cachedLayout.footerFrame);
395
+ }
396
+ return null;
397
+ }
398
+ if (indexPath.length === 1){
399
+ var sectionLayout = this._cachedLayout.sections[indexPath.section];
400
+ if (kind === UICollectionViewGridLayout.SupplimentaryKind.background){
401
+ return UICollectionViewLayoutAttributes.initSupplimentaryAtIndexPath(indexPath, kind, sectionLayout.frame);
402
+ }
403
+ if (kind === UICollectionViewGridLayout.SupplimentaryKind.header){
404
+ attributes = UICollectionViewLayoutAttributes.initSupplimentaryAtIndexPath(indexPath, kind, sectionLayout.headerFrame);
405
+ if (this._headersStickToTop){
406
+ ty = Math.min(Math.max(0, this.collectionView.contentView.bounds.origin.y - attributes.frame.origin.y + this._cachedLayout.headerFrame.size.height), (sectionLayout.frame.origin.y + sectionLayout.frame.size.height) - (sectionLayout.headerFrame.origin.y + sectionLayout.headerFrame.size.height));
407
+ attributes.transform = JSAffineTransform.Translated(0, ty);
408
+ }
409
+ return attributes;
410
+ }
411
+ if (kind === UICollectionViewGridLayout.SupplimentaryKind.footer){
412
+ return UICollectionViewLayoutAttributes.initSupplimentaryAtIndexPath(indexPath, kind, sectionLayout.footerFrame);
413
+ }
414
+ return null;
415
+ }
416
+ return null;
417
+ }
418
+
419
+ });
420
+
421
+ UICollectionViewGridLayout.SupplimentaryKind = {
422
+ background: "background",
423
+ header: "header",
424
+ footer: "footer"
425
+ };
@@ -0,0 +1,82 @@
1
+ // Copyright 2022 Breakside Inc.
2
+ //
3
+ // Licensed under the Breakside Public License, Version 1.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // If a copy of the License was not distributed with this file, you may
6
+ // obtain a copy at
7
+ //
8
+ // http://breakside.io/licenses/LICENSE-1.0.txt
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // #import Foundation
17
+ /* global UICollectionView */
18
+ "use strict";
19
+
20
+ JSClass("UICollectionViewLayout", JSObject, {
21
+
22
+ collectionView: null,
23
+ collectionViewContentSize: JSReadOnlyProperty(),
24
+
25
+ prepare: function(){
26
+ },
27
+
28
+ getCollectionViewContentSize: function(){
29
+ return JSSize.Zero;
30
+ },
31
+
32
+ layoutAttributesForElementsInRect: function(rect){
33
+ },
34
+
35
+ layoutAttributesForCellAtIndexPath: function(indexPath){
36
+ },
37
+
38
+ layoutAttributesForSupplimentaryViewAtIndexPath: function(indexPath){
39
+ },
40
+
41
+ shouldInvalidateLayoutForBounds: function(bounds){
42
+ return true;
43
+ },
44
+
45
+ invalidateLayout: function(){
46
+ if (this.collectionView === null){
47
+ return;
48
+ }
49
+ this.collectionView.setNeedsLayout();
50
+ },
51
+
52
+ });
53
+
54
+ JSClass("UICollectionViewLayoutAttributes", JSObject, {
55
+
56
+ initCellAtIndexPath: function(indexPath, frame){
57
+ this.elementCategory = UICollectionView.ElementCategory.cell;
58
+ this.indexPath = JSIndexPath(indexPath);
59
+ this.frame = JSRect(frame);
60
+ this.elementIdentifier = indexPath.toString();
61
+ this.transform = JSAffineTransform.Identity;
62
+ },
63
+
64
+ initSupplimentaryAtIndexPath: function(indexPath, kind, frame){
65
+ this.elementCategory = UICollectionView.ElementCategory.supplimentary;
66
+ this.kind = kind;
67
+ this.indexPath = JSIndexPath(indexPath);
68
+ this.frame = JSRect(frame);
69
+ this.elementIdentifier = "%s/%s".sprintf(indexPath.toString(), kind);
70
+ this.transform = JSAffineTransform.Identity;
71
+ },
72
+
73
+ elementCategory: 0,
74
+ kind: null,
75
+ indexPath: null,
76
+ frame: null,
77
+ rowIndex: 0,
78
+ columnIndex: 0,
79
+ elementIdentifier: null,
80
+ transform: null,
81
+
82
+ });
@@ -401,6 +401,17 @@ JSClass("UIColorWellDefaultStyler", UIColorWellStyler, {
401
401
  return JSSize(this.size);
402
402
  },
403
403
 
404
+ sizeControlToFitSize: function(colorWell, maxSize){
405
+ var size = JSSize(this.size);
406
+ if (maxSize.width < size.width){
407
+ size.width = maxSize.width;
408
+ }
409
+ if (maxSize.height < size.height){
410
+ size.height = maxSize.height;
411
+ }
412
+ colorWell.bounds = JSRect(JSPoint.Zero, size);
413
+ },
414
+
404
415
  layoutControl: function(colorWell){
405
416
  var wellLayer = colorWell.stylerProperties.wellLayer;
406
417
  wellLayer.frame = colorWell.bounds.rectWithInsets(this.wellInsets);
@@ -423,7 +434,7 @@ JSClass("UIColorWellDefaultStyler", UIColorWellStyler, {
423
434
  context.fillPath();
424
435
  context.restore();
425
436
  }
426
- if (this.wellInnerShadowOffset){
437
+ if (this.wellInnerShadowColor !== null){
427
438
  context.save();
428
439
  context.addRect(layer.bounds.rectWithInsets(-100));
429
440
  context.addPath(layer.backgroundPath());
@@ -213,7 +213,11 @@ JSClass("UIDisplayServer", JSObject, {
213
213
  _flushLayerLayoutQueue: function(){
214
214
  var layer;
215
215
  while ((layer = this.layerLayoutQueue.dequeue()) !== null){
216
- layer.layout();
216
+ if (layer.superlayer !== null && this.layerLayoutQueue.contains(layer.superlayer)){
217
+ this.layerLayoutQueue.enqueue(layer);
218
+ }else{
219
+ layer.layout();
220
+ }
217
221
  }
218
222
  },
219
223
 
@@ -97,6 +97,13 @@
97
97
  // #import "UIOutlineView.js"
98
98
  // #import "UIOutlineViewCell.js"
99
99
 
100
+ // Collections
101
+ // #import "UICollectionView.js"
102
+ // #import "UICollectionViewCell.js"
103
+ // #import "UICollectionReusableView.js"
104
+ // #import "UICollectionViewLayout.js"
105
+ // #import "UICollectionViewGridLayout.js"
106
+
100
107
  // Specialized View Controllers
101
108
  // #import "UISplitViewController.js"
102
109
  // #import "UITabViewController.js"