@breakside/jskit 2026.6.0 → 2026.9.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.
- package/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSContext.js +23 -1
- package/Frameworks/Foundation.jsframework/JS/JSGradient.js +25 -0
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +80 -0
- package/Frameworks/Foundation.jsframework/JS/JSRect.js +12 -0
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/io.breakside.jskit-bundle.js +4 -4
- package/Resources/doc-default.css +8 -0
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSContext.js +23 -1
- package/Root/Frameworks/Foundation/JSGradient.js +25 -0
- package/Root/Frameworks/Foundation/JSPath.js +80 -0
- package/Root/Frameworks/Foundation/JSRect.js +12 -0
- package/Root/Frameworks/ImageKit/IKHTMLCanvasBitmapContext.js +91 -13
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIApplication.js +5 -1
- package/Root/Frameworks/UIKit/UIHTMLApplication.js +24 -0
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +87 -13
- package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +17 -3
- package/Root/Frameworks/UIKit/UIKit.js +2 -0
- package/Root/Frameworks/UIKit/UILayer.js +6 -0
- package/Root/Frameworks/UIKit/UIPopupWindow.js +15 -5
- package/Root/Frameworks/UIKit/UITextAction.js +16 -0
- package/Root/Frameworks/UIKit/UITextActionsMenu.js +95 -0
- package/Root/Frameworks/UIKit/UITextEditor.js +57 -7
- package/Root/Frameworks/UIKit/UITextField.js +102 -0
- package/Root/Frameworks/UIKit/en.lproj/Localizable.strings.yaml +4 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -77,6 +77,18 @@ JSRect.prototype = {
|
|
|
77
77
|
return JSRect(origin, size);
|
|
78
78
|
},
|
|
79
79
|
|
|
80
|
+
unioningRect: function(other){
|
|
81
|
+
var origin = JSPoint(
|
|
82
|
+
Math.min(this.origin.x, other.origin.x),
|
|
83
|
+
Math.min(this.origin.y, other.origin.y)
|
|
84
|
+
);
|
|
85
|
+
var size = JSSize(
|
|
86
|
+
Math.max(0, Math.max(this.origin.x + this.size.width, other.origin.x + other.size.width) - origin.x),
|
|
87
|
+
Math.max(0, Math.max(this.origin.y + this.size.height, other.origin.y + other.size.height) - origin.y)
|
|
88
|
+
);
|
|
89
|
+
return JSRect(origin, size);
|
|
90
|
+
},
|
|
91
|
+
|
|
80
92
|
isEqual: function(other){
|
|
81
93
|
return this.origin.isEqual(other.origin) && this.size.isEqual(other.size);
|
|
82
94
|
},
|
|
@@ -248,38 +248,116 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
248
248
|
|
|
249
249
|
drawLinearGradient: function(gradient, rect){
|
|
250
250
|
this.enqueueOperation(function(state, completion, target){
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
this.canvasContext.save();
|
|
252
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
253
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
254
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
255
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
256
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
257
|
+
);
|
|
256
258
|
var stop;
|
|
257
259
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
258
260
|
stop = gradient.stops[i];
|
|
259
261
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
260
262
|
}
|
|
261
263
|
this.canvasContext.fillStyle = canvasGradient;
|
|
262
|
-
this.canvasContext.fillRect(
|
|
264
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
265
|
+
this.canvasContext.restore();
|
|
263
266
|
completion.call(target);
|
|
264
267
|
});
|
|
265
268
|
},
|
|
266
269
|
|
|
267
|
-
drawRadialGradient: function(gradient, rect
|
|
270
|
+
drawRadialGradient: function(gradient, rect){
|
|
268
271
|
this.enqueueOperation(function(state, completion, target){
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
var r0 = 0;
|
|
273
|
+
var start = JSPoint(
|
|
274
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
275
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
276
|
+
);
|
|
277
|
+
var end = JSPoint(
|
|
278
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
279
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
280
|
+
);
|
|
281
|
+
var r1 = start.distanceToPoint(end);
|
|
282
|
+
this.canvasContext.save();
|
|
283
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
284
|
+
start.x,
|
|
285
|
+
start.y,
|
|
286
|
+
r0,
|
|
287
|
+
start.x,
|
|
288
|
+
start.y,
|
|
289
|
+
r1
|
|
290
|
+
);
|
|
274
291
|
var stop;
|
|
275
292
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
276
293
|
stop = gradient.stops[i];
|
|
277
294
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
278
295
|
}
|
|
279
296
|
this.canvasContext.fillStyle = canvasGradient;
|
|
280
|
-
this.canvasContext.fillRect(
|
|
297
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
298
|
+
this.canvasContext.restore();
|
|
299
|
+
completion.call(target);
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
304
|
+
this.enqueueOperation(function(state, completion, target){
|
|
305
|
+
var rect = path.boundingRect;
|
|
306
|
+
this.canvasContext.save();
|
|
307
|
+
this.addPath(path);
|
|
308
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
309
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
310
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
311
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
312
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
313
|
+
);
|
|
314
|
+
var stop;
|
|
315
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
316
|
+
stop = gradient.stops[i];
|
|
317
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
318
|
+
}
|
|
319
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
320
|
+
this.canvasContext.stroke();
|
|
321
|
+
this.canvasContext.restore();
|
|
281
322
|
completion.call(target);
|
|
282
323
|
});
|
|
324
|
+
this.beginPath();
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
328
|
+
this.enqueueOperation(function(state, completion, target){
|
|
329
|
+
var rect = path.boundingRect;
|
|
330
|
+
var r0 = 0;
|
|
331
|
+
var start = JSPoint(
|
|
332
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
333
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
334
|
+
);
|
|
335
|
+
var end = JSPoint(
|
|
336
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
337
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
338
|
+
);
|
|
339
|
+
var r1 = start.distanceToPoint(end);
|
|
340
|
+
this.canvasContext.save();
|
|
341
|
+
this.addPath(path);
|
|
342
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
343
|
+
start.x,
|
|
344
|
+
start.y,
|
|
345
|
+
r0,
|
|
346
|
+
start.x,
|
|
347
|
+
start.y,
|
|
348
|
+
r1
|
|
349
|
+
);
|
|
350
|
+
var stop;
|
|
351
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
352
|
+
stop = gradient.stops[i];
|
|
353
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
354
|
+
}
|
|
355
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
356
|
+
this.canvasContext.stroke();
|
|
357
|
+
this.canvasContext.restore();
|
|
358
|
+
completion.call(target);
|
|
359
|
+
});
|
|
360
|
+
this.beginPath();
|
|
283
361
|
},
|
|
284
362
|
|
|
285
363
|
// ----------------------------------------------------------------------
|
|
@@ -438,11 +438,15 @@ JSClass('UIApplication', UIResponder, {
|
|
|
438
438
|
target = this.firstTargetForAction(action, target, sender);
|
|
439
439
|
if (target !== null){
|
|
440
440
|
actionLogger.debug("sendAction " + action + " to %{public}#%d from %{public}#%d", target.$class.className, target.objectID, sender.$class.className, sender.objectID);
|
|
441
|
-
target
|
|
441
|
+
this._sendAction(action, target, sender, event);
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
444
|
},
|
|
445
445
|
|
|
446
|
+
_sendAction: function(action, target, sender, event){
|
|
447
|
+
target[action](sender, event);
|
|
448
|
+
},
|
|
449
|
+
|
|
446
450
|
targetForAction: function(action, sender){
|
|
447
451
|
var target = UIApplication.$super.targetForAction.call(this, action, sender);
|
|
448
452
|
if (target !== null){
|
|
@@ -140,6 +140,30 @@ JSClass("UIHTMLApplication", UIApplication, {
|
|
|
140
140
|
return url;
|
|
141
141
|
},
|
|
142
142
|
|
|
143
|
+
_sendAction: function(action, target, sender, event){
|
|
144
|
+
var application = this;
|
|
145
|
+
var window = this.domWindow;
|
|
146
|
+
if (action === "paste" && sender !== this.windowServer){
|
|
147
|
+
if (this.domWindow.navigator.clipboard){
|
|
148
|
+
logger.info("sending paste action with clipboard.readText");
|
|
149
|
+
window.navigator.clipboard.readText().then(function(text){
|
|
150
|
+
var strings = {};
|
|
151
|
+
strings[UIPasteboard.ContentType.plainText] = text;
|
|
152
|
+
UIPasteboard.general.withStrings(strings, function(){
|
|
153
|
+
UIHTMLApplication.$super._sendAction.call(application, action, target, sender, event);
|
|
154
|
+
});
|
|
155
|
+
}, function(e){
|
|
156
|
+
logger.warn("could not readText() from clipboard: %{error}", e);
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
logger.info("sending paste action with document.execCommand");
|
|
161
|
+
this.domWindow.document.execCommand("paste");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
UIHTMLApplication.$super._sendAction.call(this, action, target, sender, event);
|
|
165
|
+
},
|
|
166
|
+
|
|
143
167
|
addEventListeners: function(){
|
|
144
168
|
this.domWindow.addEventListener("error", this);
|
|
145
169
|
this.domWindow.addEventListener("unhandledrejection", this);
|
|
@@ -169,6 +169,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
169
169
|
this[methodName](layer);
|
|
170
170
|
}
|
|
171
171
|
this.propertiesNeedingUpdate = {};
|
|
172
|
+
this.renderScale = layer._renderScale;
|
|
172
173
|
|
|
173
174
|
if (this.needsCustomDisplay){
|
|
174
175
|
layer._drawInContext(this);
|
|
@@ -412,13 +413,14 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
412
413
|
return this.element.ownerDocument.defaultView.devicePixelRatio || 1;
|
|
413
414
|
},
|
|
414
415
|
|
|
416
|
+
renderScale: 1,
|
|
417
|
+
|
|
415
418
|
getCanvasContext: function(){
|
|
416
419
|
if (!this._canvasContext){
|
|
417
|
-
var scale = this.deviceScale;
|
|
418
|
-
// FIXME: scale should account for any transform ancestor layers
|
|
420
|
+
var scale = this.deviceScale * this.renderScale;
|
|
419
421
|
var canvas = this._dequeueReusableCanvasElement();
|
|
420
|
-
canvas.width = this.bounds.size.width * scale;
|
|
421
|
-
canvas.height = this.bounds.size.height * scale;
|
|
422
|
+
canvas.width = Math.ceil(this.bounds.size.width * scale);
|
|
423
|
+
canvas.height = Math.ceil(this.bounds.size.height * scale);
|
|
422
424
|
this._insertChildElement(canvas);
|
|
423
425
|
this._canvasContext = canvas.getContext('2d');
|
|
424
426
|
this._canvasContext.save();
|
|
@@ -685,32 +687,104 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
685
687
|
|
|
686
688
|
drawLinearGradient: function(gradient, rect){
|
|
687
689
|
this.canvasContext.save();
|
|
688
|
-
this.canvasContext.
|
|
689
|
-
|
|
690
|
-
|
|
690
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
691
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
692
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
693
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
694
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
695
|
+
);
|
|
691
696
|
var stop;
|
|
692
697
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
693
698
|
stop = gradient.stops[i];
|
|
694
699
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
695
700
|
}
|
|
696
701
|
this.canvasContext.fillStyle = canvasGradient;
|
|
697
|
-
this.canvasContext.fillRect(
|
|
702
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
698
703
|
this.canvasContext.restore();
|
|
699
704
|
},
|
|
700
705
|
|
|
701
|
-
drawRadialGradient: function(gradient, rect
|
|
706
|
+
drawRadialGradient: function(gradient, rect){
|
|
707
|
+
var r0 = 0;
|
|
708
|
+
var start = JSPoint(
|
|
709
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
710
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
711
|
+
);
|
|
712
|
+
var end = JSPoint(
|
|
713
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
714
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
715
|
+
);
|
|
716
|
+
var r1 = start.distanceToPoint(end);
|
|
702
717
|
this.canvasContext.save();
|
|
703
|
-
this.canvasContext.
|
|
704
|
-
|
|
705
|
-
|
|
718
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
719
|
+
start.x,
|
|
720
|
+
start.y,
|
|
721
|
+
r0,
|
|
722
|
+
start.x,
|
|
723
|
+
start.y,
|
|
724
|
+
r1
|
|
725
|
+
);
|
|
706
726
|
var stop;
|
|
707
727
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
708
728
|
stop = gradient.stops[i];
|
|
709
729
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
710
730
|
}
|
|
711
731
|
this.canvasContext.fillStyle = canvasGradient;
|
|
712
|
-
this.canvasContext.fillRect(
|
|
732
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
733
|
+
this.canvasContext.restore();
|
|
734
|
+
},
|
|
735
|
+
|
|
736
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
737
|
+
var rect = path.boundingRect;
|
|
738
|
+
this.canvasContext.save();
|
|
739
|
+
this.addPath(path);
|
|
740
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
741
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
742
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
743
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
744
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
745
|
+
);
|
|
746
|
+
var stop;
|
|
747
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
748
|
+
stop = gradient.stops[i];
|
|
749
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
750
|
+
}
|
|
751
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
752
|
+
this.canvasContext.stroke();
|
|
713
753
|
this.canvasContext.restore();
|
|
754
|
+
this.beginPath();
|
|
755
|
+
},
|
|
756
|
+
|
|
757
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
758
|
+
var rect = path.boundingRect;
|
|
759
|
+
var r0 = 0;
|
|
760
|
+
var start = JSPoint(
|
|
761
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
762
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
763
|
+
);
|
|
764
|
+
var end = JSPoint(
|
|
765
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
766
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
767
|
+
);
|
|
768
|
+
var r1 = start.distanceToPoint(end);
|
|
769
|
+
this.canvasContext.save();
|
|
770
|
+
this.addPath(path);
|
|
771
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
772
|
+
start.x,
|
|
773
|
+
start.y,
|
|
774
|
+
r0,
|
|
775
|
+
start.x,
|
|
776
|
+
start.y,
|
|
777
|
+
r1
|
|
778
|
+
);
|
|
779
|
+
var stop;
|
|
780
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
781
|
+
stop = gradient.stops[i];
|
|
782
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
783
|
+
}
|
|
784
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
785
|
+
this.canvasContext.stroke();
|
|
786
|
+
this.canvasContext.restore();
|
|
787
|
+
this.beginPath();
|
|
714
788
|
},
|
|
715
789
|
|
|
716
790
|
// ----------------------------------------------------------------------
|
|
@@ -690,7 +690,7 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
|
|
|
690
690
|
return;
|
|
691
691
|
}
|
|
692
692
|
UIPasteboard.general.withDataTransfer(e.clipboardData, function(){
|
|
693
|
-
this.keyWindow.application.sendAction('cut');
|
|
693
|
+
this.keyWindow.application.sendAction('cut', null, this);
|
|
694
694
|
}, this);
|
|
695
695
|
},
|
|
696
696
|
|
|
@@ -702,7 +702,7 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
|
|
|
702
702
|
return;
|
|
703
703
|
}
|
|
704
704
|
UIPasteboard.general.withDataTransfer(e.clipboardData, function(){
|
|
705
|
-
this.keyWindow.application.sendAction('copy');
|
|
705
|
+
this.keyWindow.application.sendAction('copy', null, this);
|
|
706
706
|
}, this);
|
|
707
707
|
},
|
|
708
708
|
|
|
@@ -714,7 +714,7 @@ JSClass("UIHTMLWindowServer", UIWindowServer, {
|
|
|
714
714
|
return;
|
|
715
715
|
}
|
|
716
716
|
UIPasteboard.general.withDataTransfer(e.clipboardData, function(){
|
|
717
|
-
this.keyWindow.application.sendAction('paste');
|
|
717
|
+
this.keyWindow.application.sendAction('paste', null, this);
|
|
718
718
|
}, this);
|
|
719
719
|
},
|
|
720
720
|
|
|
@@ -1513,6 +1513,20 @@ JSClass("UIHTMLDataTransferPasteboard", UIPasteboard, {
|
|
|
1513
1513
|
}
|
|
1514
1514
|
return UIHTMLDataTransferPasteboard.$super.containsType.call(this, type);
|
|
1515
1515
|
},
|
|
1516
|
+
|
|
1517
|
+
withStrings: function(strings, action, target){
|
|
1518
|
+
var locallySetTypes = JSCopy(this._locallySetTypes);
|
|
1519
|
+
try{
|
|
1520
|
+
for (var type in strings){
|
|
1521
|
+
this.setStringForType(strings[type], type);
|
|
1522
|
+
}
|
|
1523
|
+
action.call(target);
|
|
1524
|
+
}finally{
|
|
1525
|
+
this._locallySetTypes = locallySetTypes;
|
|
1526
|
+
this.dataTransfer = null;
|
|
1527
|
+
}
|
|
1528
|
+
},
|
|
1529
|
+
|
|
1516
1530
|
});
|
|
1517
1531
|
|
|
1518
1532
|
|
|
@@ -769,6 +769,12 @@ JSClass("UILayer", JSObject, {
|
|
|
769
769
|
// MARK: - Display
|
|
770
770
|
|
|
771
771
|
_needsDisplay: false,
|
|
772
|
+
renderScale: JSDynamicProperty("_renderScale", 1),
|
|
773
|
+
|
|
774
|
+
setRenderScale: function(renderScale){
|
|
775
|
+
this._renderScale = renderScale;
|
|
776
|
+
this.setNeedsDisplay();
|
|
777
|
+
},
|
|
772
778
|
|
|
773
779
|
setNeedsDisplay: function(){
|
|
774
780
|
if (this._displayServer !== null){
|
|
@@ -116,17 +116,27 @@ JSClass("UIPopupWindow", UIWindow, {
|
|
|
116
116
|
},
|
|
117
117
|
|
|
118
118
|
openAdjacentToView: function(view, preferredPlacement, animated){
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
var rect = view.bounds;
|
|
120
|
+
if (view.sourceRectForPopupWindow){
|
|
121
|
+
rect = view.sourceRectForPopupWindow(this);
|
|
121
122
|
}
|
|
123
|
+
this.openAdjacentToRectInView(rect, view, preferredPlacement, animated);
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
openAtLocationInView: function(location, view, preferredPlacement, animated){
|
|
127
|
+
var rect = JSRect(location, JSSize.Zero);
|
|
128
|
+
this.openAdjacentToRectInView(rect, view, preferredPlacement, animated);
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
openAdjacentToRectInView: function(rect, view, preferredPlacement, animated){
|
|
122
132
|
if (view.window === null || view.window.screen === null){
|
|
123
133
|
JSNotificationCenter.shared.post("UIWindowWillClose", this);
|
|
124
134
|
return;
|
|
125
135
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
sourceBounds = view.sourceRectForPopupWindow(this);
|
|
136
|
+
if (animated === undefined){
|
|
137
|
+
animated = true;
|
|
129
138
|
}
|
|
139
|
+
var sourceBounds = rect;
|
|
130
140
|
var sourceFrame = view.convertRectToScreen(sourceBounds).rectWithInsets(-this._sourceSpacing);
|
|
131
141
|
var safeFrame = view.window.screen.availableFrame.rectWithInsets(20);
|
|
132
142
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// #import Foundation
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
JSClass("UITextAction", JSObject, {
|
|
5
|
+
|
|
6
|
+
title: null,
|
|
7
|
+
action: null,
|
|
8
|
+
target: null,
|
|
9
|
+
|
|
10
|
+
initWithTitle: function(title, action, target){
|
|
11
|
+
this.title = title;
|
|
12
|
+
this.action = action;
|
|
13
|
+
this.target = target || null;
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// #import "UIPopupWindow.js"
|
|
2
|
+
// #import "UIButton.js"
|
|
3
|
+
// #import "UIStackView.js"
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
JSClass("UITextActionsMenu", JSObject, {
|
|
7
|
+
|
|
8
|
+
delegate: null,
|
|
9
|
+
|
|
10
|
+
initWithActions: function(actions){
|
|
11
|
+
this.actions = actions;
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
openAtLocationInView: function(location, sourceView){
|
|
15
|
+
if (this._window !== null){
|
|
16
|
+
this._window.orderFront();
|
|
17
|
+
}else{
|
|
18
|
+
var window = UITextActionsMenuWindow.init(UITextActionsMenu.Styler.default);
|
|
19
|
+
window.contentInsets = JSInsets.Zero;
|
|
20
|
+
var buttons = [];
|
|
21
|
+
var button;
|
|
22
|
+
var action;
|
|
23
|
+
for (var i = 0, l = this.actions.length; i < l; ++i){
|
|
24
|
+
action = this.actions[i];
|
|
25
|
+
button = UIButton.initWithStyler(UITextActionsMenu.ButtonStyler.default);
|
|
26
|
+
button.titleLabel.text = action.title;
|
|
27
|
+
button.addAction(action.action, action.target);
|
|
28
|
+
button.addAction("close", this);
|
|
29
|
+
buttons.push(button);
|
|
30
|
+
}
|
|
31
|
+
var stackView = UIStackView.initWithArrangedSubviews(buttons);
|
|
32
|
+
stackView.cornerRadius = window.cornerRadius;
|
|
33
|
+
stackView.clipsToBounds = true;
|
|
34
|
+
stackView.backgroundColor = JSColor.separator;
|
|
35
|
+
stackView.viewSpacing = 1;
|
|
36
|
+
stackView.axis = UIStackView.Axis.horizontal;
|
|
37
|
+
window.contentView = stackView;
|
|
38
|
+
window.openAtLocationInView(location, sourceView, UIPopupWindow.Placement.above, false);
|
|
39
|
+
this._window = window;
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
close: function(){
|
|
44
|
+
if (this._window !== null){
|
|
45
|
+
this._window.close();
|
|
46
|
+
this._window = null;
|
|
47
|
+
if (this.delegate && this.delegate.textActionsMenuDidClose){
|
|
48
|
+
this.delegate.textActionsMenuDidClose(this);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
_window: null,
|
|
54
|
+
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
UITextActionsMenu.Styler = Object.create({}, {
|
|
58
|
+
|
|
59
|
+
default: {
|
|
60
|
+
configurable: true,
|
|
61
|
+
get: function(){
|
|
62
|
+
var styler = UIPopupWindowStyler.init();
|
|
63
|
+
styler.cornerRadius = 7;
|
|
64
|
+
Object.defineProperty(this, "default", {value: styler, writable: true});
|
|
65
|
+
return styler;
|
|
66
|
+
},
|
|
67
|
+
set: function(value){
|
|
68
|
+
Object.defineProperty(this, "default", {value: value, writable: true});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
UITextActionsMenu.ButtonStyler = Object.create({}, {
|
|
75
|
+
|
|
76
|
+
default: {
|
|
77
|
+
configurable: true,
|
|
78
|
+
get: function(){
|
|
79
|
+
var styler = UIButtonCustomStyler.initWithBackgroundColor(JSColor.background, JSColor.highlight);
|
|
80
|
+
styler.titleInsets = JSInsets(10, 10, 10, 10);
|
|
81
|
+
Object.defineProperty(this, "default", {value: styler, writable: true});
|
|
82
|
+
return styler;
|
|
83
|
+
},
|
|
84
|
+
set: function(value){
|
|
85
|
+
Object.defineProperty(this, "default", {value: value, writable: true});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
JSClass("UITextActionsMenuWindow", UIPopupWindow, {
|
|
92
|
+
|
|
93
|
+
canBecomeKey: false,
|
|
94
|
+
|
|
95
|
+
});
|