atome 0.5.7.5.4 → 0.5.7.5.9
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.
- checksums.yaml +4 -4
- data/documentation/deep learning/basic_infos.txt +5 -0
- data/lib/atome/genesis/atomes.rb +12 -0
- data/lib/atome/genesis/particles/event.rb +141 -97
- data/lib/atome/genesis/particles/identity.rb +2 -1
- data/lib/atome/genesis/particles/spatial.rb +25 -0
- data/lib/atome/genesis/particles/utility.rb +13 -5
- data/lib/atome/utilities/essentials.rb +5 -2
- data/lib/atome/version.rb +1 -1
- data/lib/molecules/intuition/tools.rb +1 -1
- data/lib/molecules/intuition/utilities.rb +3 -0
- data/lib/platform_specific/opal/extensions/object.rb +3 -1
- data/lib/platform_specific/wasm/atome_wasm_extensions.rb +2 -1
- data/lib/renderers/html/event.rb +20 -6
- data/lib/renderers/html/html.rb +753 -446
- data/lib/renderers/html/identity.rb +33 -6
- data/lib/renderers/html/spatial.rb +27 -0
- data/lib/renderers/html/utility.rb +4 -0
- data/vendor/assets/application/examples/audio.rb +25 -9
- data/vendor/assets/application/examples/calendar.rb +186 -0
- data/vendor/assets/application/examples/drop.rb +1 -0
- data/vendor/assets/application/examples/editor.rb +139 -0
- data/vendor/assets/application/examples/inspector.rb +129 -0
- data/vendor/assets/application/examples/keyboard.rb +20 -10
- data/vendor/assets/application/examples/map.rb +42 -0
- data/vendor/assets/application/examples/meteo.rb +8 -0
- data/vendor/assets/application/examples/midi.rb +4 -0
- data/vendor/assets/application/examples/on_resize.rb +14 -0
- data/vendor/assets/application/examples/over.rb +0 -1
- data/vendor/assets/application/examples/overflow.rb +20 -5
- data/vendor/assets/application/examples/particles.rb +1 -1
- data/vendor/assets/application/examples/preset.rb +1 -1
- data/vendor/assets/application/examples/resize.rb +11 -0
- data/vendor/assets/application/examples/tick.rb +10 -0
- data/vendor/assets/application/examples/tools.rb +6 -1
- data/vendor/assets/application/examples/touch.rb +2 -14
- data/vendor/assets/application/examples/trigger_abstraction.rb +165 -0
- data/vendor/assets/application/examples/vr.rb +3 -0
- data/vendor/assets/src/css/codemirror.min.css +472 -0
- data/vendor/assets/src/css/fonts/tui/icon.eot +0 -0
- data/vendor/assets/src/css/fonts/tui/icon.svg +17 -0
- data/vendor/assets/src/css/fonts/tui/icon.ttf +0 -0
- data/vendor/assets/src/css/fonts/tui/icon.woff +0 -0
- data/vendor/assets/src/css/fonts/tui/noto.woff +72 -0
- data/vendor/assets/src/css/images/leaflet/layers-2x.png +0 -0
- data/vendor/assets/src/css/images/leaflet/layers.png +0 -0
- data/vendor/assets/src/css/images/leaflet/marker-icon-2x.png +0 -0
- data/vendor/assets/src/css/images/leaflet/marker-icon.png +0 -0
- data/vendor/assets/src/css/images/leaflet/marker-shadow.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-left.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-left@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-left@3x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-right.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-right@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-arrow-line-right@3x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-traveltime-w.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-day.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-day@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-day@3x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-month.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-month@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-month@3x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-week.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-week@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/ic-view-week@3x.png +0 -0
- data/vendor/assets/src/css/images/tui/icon.png +0 -0
- data/vendor/assets/src/css/images/tui/img-bi.png +0 -0
- data/vendor/assets/src/css/images/tui/img-bi@2x.png +0 -0
- data/vendor/assets/src/css/images/tui/img-bi@3x.png +0 -0
- data/vendor/assets/src/css/leaflet.css +664 -0
- data/vendor/assets/src/css/monokai.min.css +127 -0
- data/vendor/assets/src/css/style.css +1 -1
- data/vendor/assets/src/css/toastui-calendar.min.css +6 -0
- data/vendor/assets/src/index.html +12 -1
- data/vendor/assets/src/index_opal.html +16 -1
- data/vendor/assets/src/index_server.html +11 -1
- data/vendor/assets/src/index_server_wasm.html +10 -1
- data/vendor/assets/src/index_wasm.html +12 -1
- data/vendor/assets/src/js/atome/specific/tauri.js +32 -0
- data/vendor/assets/src/js/atome/utilities/importmap.js +9 -0
- data/vendor/assets/src/js/atome/utilities/three_module.js +88 -0
- data/vendor/assets/src/js/test.js +42 -0
- data/vendor/assets/src/js/third_parties/Three/build/three.cjs +54216 -0
- data/vendor/assets/src/js/third_parties/Three/build/three.module.min.js +6 -0
- data/vendor/assets/src/js/third_parties/Three/build/three.webgpu.min.js +6 -0
- data/vendor/assets/src/js/third_parties/Three/jsm/controls/OrbitControls.js +1532 -0
- data/vendor/assets/src/js/third_parties/codemirror.min.js +1 -0
- data/vendor/assets/src/js/third_parties/leaflet.js +6 -0
- data/vendor/assets/src/js/third_parties/leaflet.js.map +1 -0
- data/vendor/assets/src/js/third_parties/ruby.min.js +1 -0
- data/vendor/assets/src/js/third_parties/toastui-calendar.min.js +9 -0
- data/vendor/assets/src/medias/images/puydesancy.jpg +0 -0
- data/vendor/assets/src-tauri/Cargo.toml +6 -5
- data/vendor/assets/src-tauri/Info.plist +12 -0
- data/vendor/assets/src-tauri/src/main.rs +32 -3
- data/vendor/assets/src-tauri/src/midi.rs +25 -0
- data/vendor/assets/src-tauri/tauri.conf.json +4 -4
- metadata +60 -3
- data/vendor/assets/src/js/third_parties/three.min.js +0 -6
data/lib/renderers/html/html.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
|
5
5
|
class HTML
|
6
6
|
|
7
|
-
|
8
|
-
|
9
7
|
def self.locate(selector, base_element = JS.global[:document][:body])
|
10
8
|
return base_element if selector.empty?
|
11
9
|
|
@@ -41,8 +39,6 @@ class HTML
|
|
41
39
|
@element
|
42
40
|
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
42
|
def hypertext(params)
|
47
43
|
current_div = JS.global[:document].getElementById(@id.to_s)
|
48
44
|
current_div[:innerHTML] = params
|
@@ -200,6 +196,26 @@ class HTML
|
|
200
196
|
hash_result
|
201
197
|
end
|
202
198
|
|
199
|
+
def markup(new_tag, _usr_bloc)
|
200
|
+
element_id = @id.to_s
|
201
|
+
js_code = <<~JAVASCRIPT
|
202
|
+
let element = document.getElementById('#{element_id}');
|
203
|
+
if (!element) {
|
204
|
+
console.error(`Element with id "${'#{element_id}'}" not found.`);
|
205
|
+
return;
|
206
|
+
}
|
207
|
+
let newElement = document.createElement('#{new_tag}');
|
208
|
+
|
209
|
+
newElement.style.cssText = element.style.cssText;
|
210
|
+
Array.from(element.attributes).forEach(attr => {
|
211
|
+
newElement.setAttribute(attr.name, attr.value);
|
212
|
+
});
|
213
|
+
newElement.innerHTML = element.innerHTML;
|
214
|
+
element.parentNode.replaceChild(newElement, element);
|
215
|
+
JAVASCRIPT
|
216
|
+
JS.eval(js_code)
|
217
|
+
end
|
218
|
+
|
203
219
|
def hyperedit(params, usr_bloc)
|
204
220
|
html_object = JS.global[:document].getElementById(params.to_s)
|
205
221
|
particles_from_style = {}
|
@@ -264,6 +280,163 @@ class HTML
|
|
264
280
|
@websocket.close
|
265
281
|
end
|
266
282
|
|
283
|
+
# map
|
284
|
+
def location(loc_found)
|
285
|
+
if loc_found[:longitude] && loc_found[:latitude]
|
286
|
+
long_f = loc_found[:longitude]
|
287
|
+
lat_f = loc_found[:latitude]
|
288
|
+
js_code = <<~JAVASCRIPT
|
289
|
+
const locatorElement = document.getElementById('#{@id}');
|
290
|
+
if (!locatorElement._leaflet_map) {
|
291
|
+
const map = L.map('#{@id}').setView([51.505, -0.09], 2); // Centrer initialement sur une position par défaut
|
292
|
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
293
|
+
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
294
|
+
}).addTo(map);
|
295
|
+
locatorElement._leaflet_map = map;
|
296
|
+
|
297
|
+
if ('#{long_f}' === 'auto' || '#{lat_f}' === 'auto') {
|
298
|
+
function onLocationFound(e) {
|
299
|
+
const radius = e.accuracy / 2;
|
300
|
+
const locationMarker = L.marker(e.latlng).addTo(map)
|
301
|
+
.bindPopup(`You are within ${radius} meters from this point`).openPopup();
|
302
|
+
|
303
|
+
// Ajouter un ID au marqueur
|
304
|
+
locationMarker._icon.id = '#{@id}_locator';
|
305
|
+
|
306
|
+
locationMarker.on('click', function() {
|
307
|
+
alert(`You clicked the location marker at ${e.latlng.toString()}`);
|
308
|
+
});
|
309
|
+
|
310
|
+
const locationCircle = L.circle(e.latlng, radius).addTo(map);
|
311
|
+
map.setView(e.latlng, map.getZoom()); // Centrer la carte sur la position trouvée en conservant le zoom actuel
|
312
|
+
}
|
313
|
+
|
314
|
+
function onLocationError(e) {
|
315
|
+
console.log(e.message);
|
316
|
+
}
|
317
|
+
|
318
|
+
map.on('locationfound', onLocationFound);
|
319
|
+
map.on('locationerror', onLocationError);
|
320
|
+
|
321
|
+
map.locate({ setView: true }); // Tenter de localiser l'utilisateur sans modifier le zoom
|
322
|
+
} else {
|
323
|
+
const lat = parseFloat('#{lat_f}');
|
324
|
+
const long = parseFloat('#{long_f}');
|
325
|
+
map.setView([lat, long], map.getZoom()); // Centrer la carte sur les coordonnées fournies en conservant le zoom actuel
|
326
|
+
|
327
|
+
const locationMarker = L.marker([lat, long]).addTo(map)
|
328
|
+
.bindPopup('This is your point').openPopup();
|
329
|
+
|
330
|
+
// Ajouter un ID au marqueur
|
331
|
+
locationMarker._icon.id = '#{@id}_locator';
|
332
|
+
|
333
|
+
locationMarker.on('click', function() {
|
334
|
+
alert(`You clicked the location marker at [${lat}, ${long}]`);
|
335
|
+
});
|
336
|
+
}
|
337
|
+
|
338
|
+
// Ecouter l'événement 'load' de la carte pour rafraîchir l'écran et afficher une alerte
|
339
|
+
map.whenReady(function() {
|
340
|
+
map.invalidateSize();
|
341
|
+
// important setimout re-center the view else the view is incorrect (map.invalidateSize() refresh the view)
|
342
|
+
setTimeout(function() {
|
343
|
+
map.invalidateSize();
|
344
|
+
}, 0001);
|
345
|
+
});
|
346
|
+
} else {
|
347
|
+
const map = locatorElement._leaflet_map;
|
348
|
+
if ('#{long_f}' !== 'auto' && '#{lat_f}' !== 'auto') {
|
349
|
+
const lat = parseFloat('#{lat_f}');
|
350
|
+
const long = parseFloat('#{long_f}');
|
351
|
+
map.setView([lat, long], map.getZoom()); // Centrer la carte sur les coordonnées fournies en conservant le zoom actuel
|
352
|
+
|
353
|
+
const locationMarker = L.marker([lat, long]).addTo(map)
|
354
|
+
.bindPopup('This is your point').openPopup();
|
355
|
+
|
356
|
+
// Ajouter un ID au marqueur
|
357
|
+
locationMarker._icon.id = '#{@id}_locator';
|
358
|
+
|
359
|
+
locationMarker.on('click', function() {
|
360
|
+
alert(`You clicked the location marker at [${lat}, ${long}]`);
|
361
|
+
});
|
362
|
+
}
|
363
|
+
|
364
|
+
// Ecouter l'événement 'load' de la carte pour rafraîchir l'écran et afficher une alerte
|
365
|
+
map.whenReady(function() {
|
366
|
+
|
367
|
+
setTimeout(function() {
|
368
|
+
map.invalidateSize();
|
369
|
+
}, 0001);
|
370
|
+
});
|
371
|
+
}
|
372
|
+
|
373
|
+
// Ecouter l'événement de redimensionnement de la fenêtre pour réinitialiser la taille de la carte et la vue
|
374
|
+
window.addEventListener('resize', () => {
|
375
|
+
const map = locatorElement._leaflet_map;
|
376
|
+
setTimeout(function() {
|
377
|
+
map.invalidateSize();
|
378
|
+
}, 0001);
|
379
|
+
});
|
380
|
+
|
381
|
+
|
382
|
+
|
383
|
+
JAVASCRIPT
|
384
|
+
JS.eval(js_code)
|
385
|
+
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def map_zoom(params)
|
390
|
+
js_code = <<~JAVASCRIPT
|
391
|
+
const locatorElement = document.getElementById('#{@id}');
|
392
|
+
const map = locatorElement._leaflet_map;
|
393
|
+
map.setZoom(#{params});
|
394
|
+
JAVASCRIPT
|
395
|
+
JS.eval(js_code)
|
396
|
+
end
|
397
|
+
|
398
|
+
def map_pan(params)
|
399
|
+
left_found = params[:left] || 0
|
400
|
+
top_found = params[:top] || 0
|
401
|
+
js_code = <<~JAVASCRIPT
|
402
|
+
const locatorElement = document.getElementById('#{@id}');
|
403
|
+
const map = locatorElement._leaflet_map;
|
404
|
+
map.panBy([#{left_found}, #{top_found}], { animate: true });
|
405
|
+
JAVASCRIPT
|
406
|
+
JS.eval(js_code)
|
407
|
+
end
|
408
|
+
|
409
|
+
# meteo
|
410
|
+
def meteo_helper(data)
|
411
|
+
grab(@id).instance_variable_get('@meteo_code')[:meteo].call(data)
|
412
|
+
end
|
413
|
+
|
414
|
+
def meteo(location)
|
415
|
+
js_code = <<~JAVASCRIPT
|
416
|
+
const url = 'https://api.openweathermap.org/data/2.5/weather?q=#{location},fr&appid=c21a75b667d6f7abb81f118dcf8d4611&units=metric';
|
417
|
+
async function fetchWeather() {
|
418
|
+
try {
|
419
|
+
let response = await fetch(url);
|
420
|
+
|
421
|
+
if (!response.ok) {
|
422
|
+
throw new Error('Erreur HTTP ! statut : ' + response.status);
|
423
|
+
}
|
424
|
+
|
425
|
+
let data = await response.json();
|
426
|
+
|
427
|
+
|
428
|
+
let jsonString = JSON.stringify(data);
|
429
|
+
atomeJsToRuby("grab('#{@id}').html.meteo_helper("+jsonString+")");
|
430
|
+
} catch (error) {
|
431
|
+
console.log('Error getting meteo : ' + error.message);
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
fetchWeather();
|
436
|
+
JAVASCRIPT
|
437
|
+
JS.eval(js_code)
|
438
|
+
end
|
439
|
+
|
267
440
|
def attr(attribute, value)
|
268
441
|
@element.setAttribute(attribute.to_s, value.to_s)
|
269
442
|
self
|
@@ -290,6 +463,39 @@ class HTML
|
|
290
463
|
delete(id) unless element_to_delete.inspect == 'null'
|
291
464
|
end
|
292
465
|
|
466
|
+
def editor(id)
|
467
|
+
check_double(id)
|
468
|
+
editor_id = "#{id}_editor"
|
469
|
+
check_double(editor_id)
|
470
|
+
markup_found = @original_atome.markup || :textarea
|
471
|
+
@element_type = markup_found.to_s
|
472
|
+
@element = JS.global[:document].createElement(@element_type)
|
473
|
+
JS.global[:document][:body].appendChild(@element)
|
474
|
+
add_class('atome')
|
475
|
+
id(id)
|
476
|
+
self
|
477
|
+
end
|
478
|
+
|
479
|
+
# def editor(id)
|
480
|
+
# check_double(id)
|
481
|
+
# editor_id = "#{id}_editor"
|
482
|
+
# check_double(editor_id)
|
483
|
+
# markup_found = @original_atome.markup || :div
|
484
|
+
# @element_type = markup_found.to_s
|
485
|
+
# @element = JS.global[:document].createElement(@element_type)
|
486
|
+
# @element.setAttribute('style', 'font-size: 12px;')
|
487
|
+
#
|
488
|
+
# JS.global[:document][:body].appendChild(@element)
|
489
|
+
# add_class('atome')
|
490
|
+
# id(id)
|
491
|
+
# textarea = JS.global[:document].createElement('textarea')
|
492
|
+
# textarea.setAttribute('id', editor_id)
|
493
|
+
# wait 0.1 do
|
494
|
+
# @element.appendChild(textarea)
|
495
|
+
# end
|
496
|
+
# self
|
497
|
+
# end
|
498
|
+
|
293
499
|
def shape(id)
|
294
500
|
# we remove any element if the id already exist
|
295
501
|
check_double(id)
|
@@ -373,6 +579,49 @@ class HTML
|
|
373
579
|
self
|
374
580
|
end
|
375
581
|
|
582
|
+
def vr(id)
|
583
|
+
# we remove any element if the id already exist
|
584
|
+
check_double(id)
|
585
|
+
markup_found = @original_atome.markup || :div
|
586
|
+
@element_type = markup_found.to_s
|
587
|
+
@element = JS.global[:document].createElement(@element_type)
|
588
|
+
JS.global[:document][:body].appendChild(@element)
|
589
|
+
add_class('atome')
|
590
|
+
self.id(id)
|
591
|
+
|
592
|
+
self
|
593
|
+
end
|
594
|
+
|
595
|
+
def vr_path(objet_path)
|
596
|
+
js_code = <<~JAVASCRIPT
|
597
|
+
initWithParam('#{objet_path}', '#{@id}', 'method', 'params');
|
598
|
+
JAVASCRIPT
|
599
|
+
|
600
|
+
JS.eval(js_code)
|
601
|
+
# tags = <<~HTML
|
602
|
+
# <a-scene embedded>
|
603
|
+
# <a-sky src="#{objet_path}" rotation="0 -130 0"></a-sky>
|
604
|
+
# <a-text font="kelsonsans" value="Puy de Sancy, France" width="6" position="-2.5 0.25 -1.5" rotation="0 15 0"></a-text>
|
605
|
+
# <!-- Hotspot -->
|
606
|
+
# <a-sphere id="clickable" color="#FF0000" radius="0.1" position="0 1 -2"
|
607
|
+
# event-set__mouseenter="_event: mouseenter; color: green"
|
608
|
+
# event-set__mouseleave="_event: mouseleave; color: red"></a-sphere>
|
609
|
+
# <!-- Camera with cursor to detect clicks -->
|
610
|
+
# </a-scene>
|
611
|
+
# HTML
|
612
|
+
# @element[:innerHTML] = tags
|
613
|
+
#
|
614
|
+
# # Ajouter un écouteur d'événement pour le hotspot
|
615
|
+
# cursor = JS.global[:document].getElementById('cursor')
|
616
|
+
# cursor.addEventListener('click', -> {
|
617
|
+
# target = cursor.components.cursor.intersectedEl
|
618
|
+
# if target && target.id == 'clickable'
|
619
|
+
# alert :yes
|
620
|
+
# end
|
621
|
+
# })
|
622
|
+
|
623
|
+
end
|
624
|
+
|
376
625
|
def www(id)
|
377
626
|
# we remove any element if the id already exist
|
378
627
|
check_double(id)
|
@@ -607,7 +856,9 @@ class HTML
|
|
607
856
|
|
608
857
|
def delete(id_to_delete)
|
609
858
|
element_to_delete = JS.global[:document].getElementById(id_to_delete.to_s)
|
610
|
-
element_to_delete.
|
859
|
+
return unless element_to_delete.to_s != 'null'
|
860
|
+
return unless element_to_delete
|
861
|
+
element_to_delete.remove
|
611
862
|
end
|
612
863
|
|
613
864
|
def append(child_id_found)
|
@@ -618,7 +869,6 @@ class HTML
|
|
618
869
|
|
619
870
|
# events handlers
|
620
871
|
def on(property, _option)
|
621
|
-
bloc = @original_atome.instance_variable_get('@on_code')[:view_resize]
|
622
872
|
property = property.to_s
|
623
873
|
|
624
874
|
if property.start_with?('media:')
|
@@ -628,6 +878,7 @@ class HTML
|
|
628
878
|
mql = JS.global[:window].matchMedia(media_query)
|
629
879
|
|
630
880
|
event_handler = ->(event) do
|
881
|
+
bloc = @original_atome.instance_variable_get('@on_code')[:view_resize]
|
631
882
|
proc_content = bloc.call({ matches: event[:matches] }) if event_validation(bloc)
|
632
883
|
if proc_content.instance_of? Hash
|
633
884
|
proc_content.each do |k, v|
|
@@ -640,18 +891,27 @@ class HTML
|
|
640
891
|
mql.addListener(event_handler)
|
641
892
|
|
642
893
|
elsif property == 'resize'
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
894
|
+
unless @on_resize_already_set
|
895
|
+
event_handler = ->(event) do
|
896
|
+
width = JS.global[:window][:innerWidth]
|
897
|
+
height = JS.global[:window][:innerHeight]
|
898
|
+
blocs = @original_atome.instance_variable_get('@on_code')[:view_resize]
|
899
|
+
blocs.each do |bloc|
|
900
|
+
proc_content = bloc.call({ width: width, height: height }) if event_validation(bloc)
|
901
|
+
if proc_content.instance_of? Hash
|
902
|
+
proc_content.each do |k, v|
|
903
|
+
@original_atome.send(k, v)
|
904
|
+
end
|
905
|
+
end
|
650
906
|
end
|
651
907
|
end
|
652
|
-
end
|
653
908
|
|
654
|
-
|
909
|
+
JS.global[:window].addEventListener('resize', event_handler)
|
910
|
+
end
|
911
|
+
@on_resize_already_set = true
|
912
|
+
elsif property == 'remove'
|
913
|
+
alert 'ok'
|
914
|
+
@original_atome.instance_variable_get('@on_code')[:view_resize] = []
|
655
915
|
else
|
656
916
|
event_handler = ->(event) do
|
657
917
|
proc_content = bloc.call(event) if event_validation(bloc)
|
@@ -733,14 +993,13 @@ class HTML
|
|
733
993
|
end
|
734
994
|
end
|
735
995
|
|
736
|
-
def drag_code(params=nil)
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
end
|
996
|
+
# def drag_code(params = nil)
|
997
|
+
# # FIXME : this method is an ugly patch when refreshing an atome twice, else it crash
|
998
|
+
# # and lose it's drag
|
999
|
+
# drag_move(params)
|
1000
|
+
# end
|
741
1001
|
|
742
1002
|
def event(action, variance, option = nil)
|
743
|
-
# puts " remove 'if option', if unable ti unbind# : #{action} _ #{variance}"
|
744
1003
|
send("#{action}_#{variance}", option)
|
745
1004
|
end
|
746
1005
|
|
@@ -749,210 +1008,260 @@ class HTML
|
|
749
1008
|
@original_atome.top(restricted_y)
|
750
1009
|
end
|
751
1010
|
|
752
|
-
def
|
1011
|
+
def drag_move(_option)
|
753
1012
|
|
754
|
-
@
|
755
|
-
|
1013
|
+
unless @drag_move_already_set
|
1014
|
+
# the condition below prevent drag accumulation
|
1015
|
+
interact = JS.eval("return interact('##{@id}')")
|
1016
|
+
|
1017
|
+
unless @draggable
|
1018
|
+
interact.draggable({
|
1019
|
+
drag: true,
|
1020
|
+
inertia: { resistance: 12,
|
1021
|
+
minSpeed: 200,
|
1022
|
+
endSpeed: 100 },
|
1023
|
+
})
|
1024
|
+
unless @first_drag
|
1025
|
+
interact.on('dragmove') do |native_event|
|
1026
|
+
drag_moves = @original_atome.instance_variable_get('@drag_code')[:move]
|
1027
|
+
|
1028
|
+
# the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
|
1029
|
+
event = Native(native_event)
|
1030
|
+
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1031
|
+
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1032
|
+
# group etc..
|
1033
|
+
drag_moves.each do |drag_move|
|
1034
|
+
proc_content = drag_move.call(event) if event_validation(drag_move)
|
1035
|
+
if proc_content.instance_of? Hash
|
1036
|
+
proc_content.each do |k, v|
|
1037
|
+
@original_atome.send(k, v)
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
end
|
756
1041
|
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
@
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
interact.
|
779
|
-
|
1042
|
+
Universe.allow_tool_operations = false
|
1043
|
+
dx = event[:dx]
|
1044
|
+
dy = event[:dy]
|
1045
|
+
x = (@original_atome.left || 0) + dx.to_f
|
1046
|
+
y = (@original_atome.top || 0) + dy.to_f
|
1047
|
+
@original_atome.left(x)
|
1048
|
+
@original_atome.top(y)
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
end
|
1052
|
+
end
|
1053
|
+
@first_drag = true
|
1054
|
+
@draggable = true
|
1055
|
+
end
|
1056
|
+
@drag_move_already_set = true
|
1057
|
+
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
def drag_restrict(option)
|
1061
|
+
|
1062
|
+
unless @drag_restrict_already_set
|
1063
|
+
interact = JS.eval("return interact('##{@id}')")
|
1064
|
+
interact.draggable({
|
1065
|
+
drag: true,
|
1066
|
+
inertia: { resistance: 12,
|
1067
|
+
minSpeed: 200,
|
1068
|
+
endSpeed: 100 },
|
1069
|
+
})
|
1070
|
+
|
1071
|
+
if option.instance_of? Hash
|
1072
|
+
max_left = grab(:view).to_px(:width)
|
1073
|
+
max_top = grab(:view).to_px(:height)
|
1074
|
+
min_left = 0
|
1075
|
+
min_top = 0
|
1076
|
+
|
1077
|
+
if option[:max]
|
1078
|
+
max_left = option[:max][:left] || max_left
|
1079
|
+
max_top = option[:max][:top] || max_top
|
1080
|
+
else
|
1081
|
+
max_left
|
1082
|
+
max_top
|
1083
|
+
end
|
1084
|
+
if option[:min]
|
1085
|
+
min_left = option[:min][:left] || min_left
|
1086
|
+
min_top = option[:min][:top] || min_top
|
1087
|
+
else
|
1088
|
+
min_left
|
1089
|
+
min_top
|
1090
|
+
end
|
1091
|
+
else
|
1092
|
+
parent_found = grab(option)
|
1093
|
+
min_left = parent_found.left
|
1094
|
+
min_top = parent_found.top
|
1095
|
+
parent_width = parent_found.compute({ particle: :width })[:value]
|
1096
|
+
parent_height = parent_found.compute({ particle: :height })[:value]
|
1097
|
+
original_width = @original_atome.width
|
1098
|
+
original_height = @original_atome.height
|
1099
|
+
max_left = min_left + parent_width - original_width
|
1100
|
+
max_top = min_top + parent_height - original_height
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
interact.on('dragmove') do |native_event|
|
1104
|
+
drag_moves = @original_atome.instance_variable_get('@drag_code')[:restrict]
|
1105
|
+
|
1106
|
+
# the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
|
1107
|
+
event = Native(native_event)
|
1108
|
+
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1109
|
+
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1110
|
+
# group etc..
|
1111
|
+
drag_moves.each do |drag_move|
|
1112
|
+
proc_content = drag_move.call(event) if event_validation(drag_move)
|
1113
|
+
if proc_content.instance_of? Hash
|
1114
|
+
proc_content.each do |k, v|
|
1115
|
+
@original_atome.send(k, v)
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
dx = event[:dx]
|
1121
|
+
dy = event[:dy]
|
1122
|
+
x = (@original_atome.left || 0) + dx.to_f
|
1123
|
+
y = (@original_atome.top || 0) + dy.to_f
|
1124
|
+
restricted_x = [[x, min_left].max, max_left].min
|
1125
|
+
restricted_y = [[y, min_top].max, max_top].min
|
1126
|
+
restrict_movement(restricted_x, restricted_y)
|
1127
|
+
end
|
780
1128
|
end
|
1129
|
+
@drag_restrict_already_set = true
|
781
1130
|
|
782
1131
|
end
|
783
1132
|
|
784
1133
|
def drag_start(_option)
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
1134
|
+
unless @drag_start_already_set
|
1135
|
+
interact = JS.eval("return interact('##{@id}')")
|
1136
|
+
interact.on('dragstart') do |native_event|
|
1137
|
+
drag_starts = @original_atome.instance_variable_get('@drag_code')[:start]
|
1138
|
+
event = Native(native_event)
|
1139
|
+
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1140
|
+
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1141
|
+
# group etc..
|
1142
|
+
drag_starts.each do |drag_start|
|
1143
|
+
proc_content = drag_start.call(event) if event_validation(drag_start)
|
1144
|
+
if proc_content.instance_of? Hash
|
1145
|
+
proc_content.each do |k, v|
|
1146
|
+
@original_atome.send(k, v)
|
1147
|
+
end
|
1148
|
+
end
|
796
1149
|
end
|
797
1150
|
end
|
798
1151
|
end
|
1152
|
+
@drag_start_already_set = true
|
799
1153
|
end
|
800
1154
|
|
801
1155
|
def drag_end(_option)
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
1156
|
+
|
1157
|
+
unless @drag_end_already_set
|
1158
|
+
interact = JS.eval("return interact('##{@id}')")
|
1159
|
+
interact.on('dragend') do |native_event|
|
1160
|
+
drag_ends = @original_atome.instance_variable_get('@drag_code')[:end]
|
1161
|
+
event = Native(native_event)
|
1162
|
+
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1163
|
+
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1164
|
+
# group etc..
|
1165
|
+
drag_ends.each do |drag_end|
|
1166
|
+
proc_content = drag_end.call(event) if event_validation(drag_end)
|
1167
|
+
if proc_content.instance_of? Hash
|
1168
|
+
proc_content.each do |k, v|
|
1169
|
+
@original_atome.send(k, v)
|
1170
|
+
end
|
1171
|
+
end
|
813
1172
|
end
|
1173
|
+
|
814
1174
|
end
|
815
1175
|
end
|
816
|
-
|
1176
|
+
@drag_end_already_set = true
|
817
1177
|
|
818
|
-
|
819
|
-
# the condition below prevent drag accumulation
|
820
|
-
interact = JS.eval("return interact('##{@id}')")
|
1178
|
+
end
|
821
1179
|
|
822
|
-
|
1180
|
+
def drag_locked(_option)
|
1181
|
+
unless @drag_locked_already_set
|
1182
|
+
interact = JS.eval("return interact('##{@id}')")
|
823
1183
|
interact.draggable({
|
824
1184
|
drag: true,
|
825
1185
|
inertia: { resistance: 12,
|
826
1186
|
minSpeed: 200,
|
827
|
-
endSpeed: 100 }
|
1187
|
+
endSpeed: 100 }
|
828
1188
|
})
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
1189
|
+
|
1190
|
+
interact.on('dragmove') do |native_event|
|
1191
|
+
drag_locks = @original_atome.instance_variable_get('@drag_code')[:locked]
|
1192
|
+
# the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
|
1193
|
+
event = Native(native_event)
|
1194
|
+
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1195
|
+
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1196
|
+
# group etc..
|
1197
|
+
drag_locks.each do |drag_lock|
|
1198
|
+
proc_content = drag_lock.call(event) if event_validation(drag_lock)
|
838
1199
|
if proc_content.instance_of? Hash
|
839
1200
|
proc_content.each do |k, v|
|
840
1201
|
@original_atome.send(k, v)
|
841
1202
|
end
|
842
1203
|
end
|
843
|
-
Universe.allow_tool_operations = false
|
844
|
-
dx = event[:dx]
|
845
|
-
dy = event[:dy]
|
846
|
-
x = (@original_atome.left || 0) + dx.to_f
|
847
|
-
y = (@original_atome.top || 0) + dy.to_f
|
848
|
-
@original_atome.left(x)
|
849
|
-
@original_atome.top(y)
|
850
1204
|
end
|
851
|
-
|
852
1205
|
end
|
853
1206
|
end
|
854
|
-
@
|
855
|
-
|
1207
|
+
@drag_locked_already_set = true
|
1208
|
+
|
856
1209
|
end
|
857
1210
|
|
858
|
-
def
|
1211
|
+
def remove_this_drag(option)
|
1212
|
+
@original_atome.instance_variable_get('@drag_code')[option] = [] if @original_atome.instance_variable_get('@drag_code')
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
def drag_remove(_opt)
|
1216
|
+
|
859
1217
|
interact = JS.eval("return interact('##{@id}')")
|
860
|
-
|
861
|
-
|
862
|
-
inertia: { resistance: 12,
|
863
|
-
minSpeed: 200,
|
864
|
-
endSpeed: 100 },
|
865
|
-
})
|
866
|
-
|
867
|
-
@drag_move = @original_atome.instance_variable_get('@drag_code')[:restrict]
|
868
|
-
if option.instance_of? Hash
|
869
|
-
max_left = grab(:view).to_px(:width)
|
870
|
-
max_top = grab(:view).to_px(:height)
|
871
|
-
min_left = 0
|
872
|
-
min_top = 0
|
873
|
-
|
874
|
-
if option[:max]
|
875
|
-
max_left = option[:max][:left] || max_left
|
876
|
-
max_top = option[:max][:top] || max_top
|
877
|
-
else
|
878
|
-
max_left
|
879
|
-
max_top
|
880
|
-
end
|
881
|
-
if option[:min]
|
882
|
-
min_left = option[:min][:left] || min_left
|
883
|
-
min_top = option[:min][:top] || min_top
|
884
|
-
else
|
885
|
-
min_left
|
886
|
-
min_top
|
887
|
-
end
|
1218
|
+
if @original_atome.instance_variable_get('@drag_code')
|
1219
|
+
options = @original_atome.instance_variable_get('@drag_code')[:remove]
|
888
1220
|
else
|
889
|
-
|
890
|
-
min_left = parent_found.left
|
891
|
-
min_top = parent_found.top
|
892
|
-
parent_width = parent_found.compute({ particle: :width })[:value]
|
893
|
-
parent_height = parent_found.compute({ particle: :height })[:value]
|
894
|
-
original_width = @original_atome.width
|
895
|
-
original_height = @original_atome.height
|
896
|
-
max_left = min_left + parent_width - original_width
|
897
|
-
max_top = min_top + parent_height - original_height
|
898
|
-
end
|
899
|
-
|
900
|
-
interact.on('dragmove') do |native_event|
|
901
|
-
# the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
|
902
|
-
event = Native(native_event)
|
903
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
904
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
905
|
-
# group etc..
|
906
|
-
proc_content = @drag_move.call(event) if event_validation(@drag_move)
|
907
|
-
if proc_content.instance_of? Hash
|
908
|
-
proc_content.each do |k, v|
|
909
|
-
@original_atome.send(k, v)
|
910
|
-
end
|
911
|
-
end
|
912
|
-
dx = event[:dx]
|
913
|
-
dy = event[:dy]
|
914
|
-
x = (@original_atome.left || 0) + dx.to_f
|
915
|
-
y = (@original_atome.top || 0) + dy.to_f
|
916
|
-
restricted_x = [[x, min_left].max, max_left].min
|
917
|
-
restricted_y = [[y, min_top].max, max_top].min
|
918
|
-
restrict_movement(restricted_x, restricted_y)
|
1221
|
+
options = false
|
919
1222
|
end
|
920
|
-
end
|
921
1223
|
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
inertia: { resistance: 12,
|
927
|
-
minSpeed: 200,
|
928
|
-
endSpeed: 100 }
|
929
|
-
})
|
930
|
-
|
931
|
-
@drag_lock = @original_atome.instance_variable_get('@drag_code')[:locked]
|
932
|
-
interact.on('dragmove') do |native_event|
|
933
|
-
# the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
|
934
|
-
event = Native(native_event)
|
935
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
936
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
937
|
-
# group etc..
|
938
|
-
proc_content = @drag_lock.call(event) if event_validation(@drag_lock)
|
939
|
-
if proc_content.instance_of? Hash
|
940
|
-
proc_content.each do |k, v|
|
941
|
-
@original_atome.send(k, v)
|
1224
|
+
options.each do |option|
|
1225
|
+
if option.instance_of? Array
|
1226
|
+
option.each do |opt|
|
1227
|
+
remove_this_drag(opt)
|
942
1228
|
end
|
1229
|
+
return false
|
1230
|
+
end
|
1231
|
+
@element[:style][:cursor] = 'default'
|
1232
|
+
|
1233
|
+
@draggable = nil
|
1234
|
+
case option
|
1235
|
+
when :start
|
1236
|
+
remove_this_drag(:start)
|
1237
|
+
when :end, :stop
|
1238
|
+
remove_this_drag(:end)
|
1239
|
+
remove_this_drag(:stop)
|
1240
|
+
when :move
|
1241
|
+
remove_this_drag(:move)
|
1242
|
+
when :locked
|
1243
|
+
remove_this_drag(:locked)
|
1244
|
+
when :restrict
|
1245
|
+
remove_this_drag(:restrict)
|
1246
|
+
else
|
1247
|
+
interact.draggable(false)
|
1248
|
+
|
943
1249
|
end
|
944
1250
|
end
|
1251
|
+
|
945
1252
|
end
|
946
1253
|
|
947
|
-
def
|
1254
|
+
def drop_common(method, native_event)
|
948
1255
|
event = Native(native_event)
|
949
1256
|
draggable_element = event[:relatedTarget][:id].to_s
|
950
1257
|
dropzone_element = event[:target][:id].to_s
|
951
1258
|
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
952
1259
|
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
953
1260
|
# group etc..
|
954
|
-
|
955
|
-
|
1261
|
+
proc_contents = @original_atome.instance_variable_get('@drop_code')[method]
|
1262
|
+
proc_contents.each do |proc_content|
|
1263
|
+
proc_content = proc_content.call({ source: draggable_element, destination: dropzone_element }) if event_validation(proc_content)
|
1264
|
+
return unless proc_content.instance_of? Hash
|
956
1265
|
proc_content.each do |k, v|
|
957
1266
|
@original_atome.send(k, v)
|
958
1267
|
end
|
@@ -960,97 +1269,108 @@ class HTML
|
|
960
1269
|
end
|
961
1270
|
|
962
1271
|
def drop_activate(_option)
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
end
|
1272
|
+
unless @drop_activate_already_set
|
1273
|
+
interact = JS.eval("return interact('##{@id}')")
|
1274
|
+
interact.dropzone({
|
1275
|
+
accept: nil, # Accept any element
|
1276
|
+
overlap: 0.75,
|
1277
|
+
ondropactivate: lambda do |native_event|
|
1278
|
+
drop_common(:activate, native_event)
|
1279
|
+
end
|
1280
|
+
})
|
1281
|
+
end
|
974
1282
|
|
975
|
-
|
976
|
-
interact = JS.eval("return interact('##{@id}')")
|
977
|
-
@drop_deactivate = @original_atome.instance_variable_get('@drop_code')[:deactivate]
|
978
|
-
interact.dropzone({
|
979
|
-
# accept: nil, # Accept any element
|
980
|
-
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
981
|
-
ondropdeactivate: lambda do |native_event|
|
982
|
-
drop_action(native_event, @drop_deactivate) if event_validation(@drop_deactivate)
|
983
|
-
end
|
984
|
-
})
|
1283
|
+
@drop_activate_already_set = true
|
985
1284
|
end
|
986
1285
|
|
987
1286
|
def drop_dropped(_option)
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
1287
|
+
unless @drop_dropped_already_set
|
1288
|
+
interact = JS.eval("return interact('##{@id}')")
|
1289
|
+
interact.dropzone({
|
1290
|
+
overlap: 0.75,
|
1291
|
+
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
1292
|
+
ondrop: lambda do |native_event|
|
1293
|
+
drop_common(:dropped, native_event)
|
1294
|
+
end
|
1295
|
+
})
|
1296
|
+
|
1297
|
+
end
|
1298
|
+
@drop_dropped_already_set = true
|
998
1299
|
end
|
999
1300
|
|
1000
1301
|
def drop_enter(_option)
|
1001
|
-
|
1302
|
+
unless @drop_enter_already_set
|
1303
|
+
interact = JS.eval("return interact('##{@id}')")
|
1304
|
+
interact.dropzone({
|
1305
|
+
overlap: 0.001,
|
1306
|
+
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
1307
|
+
ondragenter: lambda do |native_event|
|
1308
|
+
drop_common(:enter, native_event)
|
1309
|
+
end
|
1310
|
+
})
|
1311
|
+
end
|
1312
|
+
@drop_enter_already_set = true
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
def drop_leave(_option)
|
1316
|
+
unless @drop_leave_already_set
|
1317
|
+
interact = JS.eval("return interact('##{@id}')")
|
1318
|
+
interact.dropzone({
|
1319
|
+
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
1320
|
+
ondragleave: lambda do |native_event|
|
1321
|
+
drop_common(:leave, native_event)
|
1322
|
+
end
|
1323
|
+
})
|
1324
|
+
end
|
1002
1325
|
|
1003
|
-
@
|
1326
|
+
@drop_leave_already_set = true
|
1004
1327
|
|
1005
|
-
interact.dropzone({
|
1006
|
-
overlap: 0.001,
|
1007
|
-
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
1008
|
-
ondragenter: lambda do |native_event|
|
1009
|
-
drop_action(native_event, @drop_enter) if event_validation(@drop_enter)
|
1010
|
-
end
|
1011
|
-
})
|
1012
1328
|
end
|
1013
1329
|
|
1014
|
-
def
|
1015
|
-
|
1016
|
-
@drop_leave = @original_atome.instance_variable_get('@drop_code')[:leave]
|
1330
|
+
def drop_deactivate(_option)
|
1331
|
+
unless @drop_remove_already_set
|
1017
1332
|
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1333
|
+
interact = JS.eval("return interact('##{@id}')")
|
1334
|
+
interact.dropzone({
|
1335
|
+
# accept: nil, # Accept any element
|
1336
|
+
# FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
|
1337
|
+
ondropdeactivate: lambda do |native_event|
|
1338
|
+
drop_common(:deactivate, native_event)
|
1339
|
+
end
|
1340
|
+
})
|
1024
1341
|
|
1342
|
+
end
|
1343
|
+
@drop_remove_already_set = true
|
1025
1344
|
end
|
1026
1345
|
|
1027
1346
|
def drop_remove(option)
|
1028
1347
|
case option
|
1029
1348
|
when :activate
|
1030
|
-
@
|
1349
|
+
@original_atome.instance_variable_get('@drop_code')[:activate] = []
|
1031
1350
|
when :deactivate
|
1032
|
-
@
|
1351
|
+
@original_atome.instance_variable_get('@drop_code')[:deactivate] = []
|
1033
1352
|
when :dropped
|
1034
|
-
@
|
1353
|
+
@original_atome.instance_variable_get('@drop_code')[:dropped] = []
|
1035
1354
|
when :enter
|
1036
|
-
@
|
1355
|
+
@original_atome.instance_variable_get('@drop_code')[:enter] = []
|
1037
1356
|
when :leave
|
1038
|
-
@
|
1357
|
+
@original_atome.instance_variable_get('@drop_code')[:leave] = []
|
1039
1358
|
else
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
@drop_enter = ''
|
1046
|
-
@drop_leave = ''
|
1047
|
-
|
1359
|
+
drop_remove(:activate)
|
1360
|
+
drop_remove(:deactivate)
|
1361
|
+
drop_remove(:dropped)
|
1362
|
+
drop_remove(:enter)
|
1363
|
+
drop_remove(:leave)
|
1048
1364
|
end
|
1049
1365
|
|
1050
1366
|
end
|
1051
1367
|
|
1052
1368
|
def resize(params, options)
|
1053
1369
|
interact = JS.eval("return interact('##{@id}')")
|
1370
|
+
|
1371
|
+
# Désactiver explicitement le déplacement
|
1372
|
+
# interact.draggable(false)
|
1373
|
+
|
1054
1374
|
if params == :remove
|
1055
1375
|
@resize = ''
|
1056
1376
|
interact.resizable(false)
|
@@ -1060,6 +1380,7 @@ class HTML
|
|
1060
1380
|
max_width = options[:max][:width] || 3000
|
1061
1381
|
max_height = options[:max][:height] || 3000
|
1062
1382
|
@resize = @original_atome.instance_variable_get('@resize_code')[:resize]
|
1383
|
+
|
1063
1384
|
interact.resizable({
|
1064
1385
|
edges: { left: true, right: true, top: true, bottom: true },
|
1065
1386
|
inertia: true,
|
@@ -1067,12 +1388,8 @@ class HTML
|
|
1067
1388
|
listeners: {
|
1068
1389
|
move: lambda do |native_event|
|
1069
1390
|
Universe.allow_tool_operations = false
|
1070
|
-
|
1391
|
+
|
1071
1392
|
event = Native(native_event)
|
1072
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1073
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1074
|
-
# group etc..
|
1075
|
-
# @resize.call(event) if event_validation(@resize)
|
1076
1393
|
proc_content = @resize.call(event) if event_validation(@resize)
|
1077
1394
|
if proc_content.instance_of? Hash
|
1078
1395
|
proc_content.each do |k, v|
|
@@ -1084,18 +1401,19 @@ class HTML
|
|
1084
1401
|
y = (@element[:offsetTop].to_i || 0)
|
1085
1402
|
width = event[:rect][:width]
|
1086
1403
|
height = event[:rect][:height]
|
1404
|
+
|
1087
1405
|
# Translate when resizing from any corner
|
1088
1406
|
x += event[:deltaRect][:left].to_f
|
1089
1407
|
y += event[:deltaRect][:top].to_f
|
1408
|
+
|
1090
1409
|
@original_atome.width width.to_i if width.to_i.between?(min_width, max_width)
|
1091
1410
|
@original_atome.height height.to_i if height.to_i.between?(min_height, max_height)
|
1092
1411
|
@original_atome.left(x)
|
1093
1412
|
@original_atome.top(y)
|
1094
|
-
end
|
1095
|
-
# end
|
1413
|
+
end,
|
1096
1414
|
},
|
1097
|
-
|
1098
1415
|
})
|
1416
|
+
|
1099
1417
|
end
|
1100
1418
|
|
1101
1419
|
end
|
@@ -1121,87 +1439,112 @@ class HTML
|
|
1121
1439
|
end
|
1122
1440
|
|
1123
1441
|
def over_over(_option)
|
1124
|
-
|
1125
|
-
@
|
1126
|
-
|
1127
|
-
JS.global[:myRubyMouseOverCallback] = Proc.new { @original_atome.over_code[:over].call }
|
1442
|
+
return if @over_over_already_set
|
1443
|
+
@element.addEventListener('mouseover') do |native_event|
|
1444
|
+
over_options = @original_atome.instance_variable_get('@over_code')[:flyover]
|
1128
1445
|
event = Native(native_event)
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
proc_content.each do |k, v|
|
1136
|
-
@original_atome.send(k, v)
|
1446
|
+
over_options.each do |over_option|
|
1447
|
+
proc_content = over_option.call(event) if event_validation(over_option)
|
1448
|
+
if proc_content.instance_of? Hash
|
1449
|
+
proc_content.each do |k, v|
|
1450
|
+
@original_atome.send(k, v)
|
1451
|
+
end
|
1137
1452
|
end
|
1138
1453
|
end
|
1139
1454
|
end
|
1455
|
+
@over_over_already_set = true
|
1456
|
+
# unless @over_over_already_set
|
1457
|
+
# interact = JS.eval("return interact('##{@id}')")
|
1458
|
+
# over_overs = @original_atome.instance_variable_get('@over_code')[:flyover]
|
1459
|
+
# # return unless over_overs
|
1460
|
+
# over_overs.each do |over_over|
|
1461
|
+
# interact.on('mouseover') do |native_event|
|
1462
|
+
# over_over_event = Native(native_event)
|
1463
|
+
# # we use .call instead of instance_eval because instance_eval bring the current object as context
|
1464
|
+
# # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1465
|
+
# # group etc..
|
1466
|
+
#
|
1467
|
+
# proc_content = over_over.call(over_over_event) if event_validation(over_over)
|
1468
|
+
# if proc_content.instance_of? Hash
|
1469
|
+
# proc_content.each do |k, v|
|
1470
|
+
# @original_atome.send(k, v)
|
1471
|
+
# end
|
1472
|
+
# end
|
1473
|
+
# end
|
1474
|
+
# end
|
1475
|
+
# end
|
1476
|
+
# @over_over_already_set = true
|
1140
1477
|
end
|
1141
1478
|
|
1142
1479
|
def over_enter(_option)
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
@original_atome.send(k, v)
|
1480
|
+
return if @over_enter_already_set
|
1481
|
+
@element.addEventListener('mouseenter') do |native_event|
|
1482
|
+
over_options = @original_atome.instance_variable_get('@over_code')[:enter]
|
1483
|
+
event = Native(native_event)
|
1484
|
+
over_options.each do |over_option|
|
1485
|
+
proc_content = over_option.call(event) if event_validation(over_option)
|
1486
|
+
if proc_content.instance_of? Hash
|
1487
|
+
proc_content.each do |k, v|
|
1488
|
+
@original_atome.send(k, v)
|
1489
|
+
end
|
1154
1490
|
end
|
1155
1491
|
end
|
1156
1492
|
end
|
1157
|
-
@
|
1493
|
+
@over_enter_already_set = true
|
1494
|
+
# unless @over_enter_already_set
|
1495
|
+
# over_enters = @original_atome.instance_variable_get('@over_code')[:enter]
|
1496
|
+
# # return unless over_enters
|
1497
|
+
#
|
1498
|
+
# over_enters.each do |over_enter|
|
1499
|
+
# @over_enter_callback = lambda do |event|
|
1500
|
+
# # we use .call instead of instance_eval because instance_eval bring the current object as context
|
1501
|
+
# # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1502
|
+
# # group etc..
|
1503
|
+
# proc_content = over_enter.call(event) if event_validation(over_enter)
|
1504
|
+
# if proc_content.instance_of? Hash
|
1505
|
+
# proc_content.each do |k, v|
|
1506
|
+
# @original_atome.send(k, v)
|
1507
|
+
# end
|
1508
|
+
# end
|
1509
|
+
# end
|
1510
|
+
# @element.addEventListener('mouseenter', @over_enter_callback)
|
1511
|
+
#
|
1512
|
+
# end
|
1513
|
+
#
|
1514
|
+
# end
|
1515
|
+
# @over_enter_already_set = true
|
1158
1516
|
|
1159
1517
|
end
|
1160
1518
|
|
1161
1519
|
def over_leave(_option)
|
1162
|
-
|
1163
|
-
@
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
if proc_content.instance_of? Hash
|
1173
|
-
proc_content.each do |k, v|
|
1174
|
-
@original_atome.send(k, v)
|
1520
|
+
return if @over_leave_already_set
|
1521
|
+
@element.addEventListener('mouseleave') do |native_event|
|
1522
|
+
over_leaves = @original_atome.instance_variable_get('@over_code')[:leave]
|
1523
|
+
event = Native(native_event)
|
1524
|
+
over_leaves.each do |over_leave|
|
1525
|
+
proc_content = over_leave.call(event) if event_validation(over_leave)
|
1526
|
+
if proc_content.instance_of? Hash
|
1527
|
+
proc_content.each do |k, v|
|
1528
|
+
@original_atome.send(k, v)
|
1529
|
+
end
|
1175
1530
|
end
|
1176
1531
|
end
|
1177
1532
|
end
|
1178
|
-
@
|
1179
|
-
|
1533
|
+
@over_leave_already_set = true
|
1180
1534
|
end
|
1181
1535
|
|
1182
1536
|
def over_remove(option)
|
1183
1537
|
case option
|
1184
1538
|
when :enter
|
1185
|
-
|
1186
|
-
# Remove the event listener using the same lambda
|
1187
|
-
@element.removeEventListener('mouseenter', @over_enter_callback)
|
1188
|
-
@over_enter_callback = nil
|
1189
|
-
@over_enter = nil
|
1190
|
-
end
|
1539
|
+
@original_atome.instance_variable_get('@over_code')[:enter] = []
|
1191
1540
|
when :leave
|
1192
|
-
@
|
1193
|
-
@over_leave_callback = nil
|
1194
|
-
@over_leave = nil
|
1541
|
+
@original_atome.instance_variable_get('@over_code')[:leave] = []
|
1195
1542
|
when :over
|
1196
|
-
@
|
1543
|
+
@original_atome.instance_variable_get('@over_code')[:flyover] = []
|
1197
1544
|
else
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
@element.removeEventListener('mouseleave', @over_leave_callback)
|
1202
|
-
@over_leave_callback = nil
|
1203
|
-
@over_leave = nil
|
1204
|
-
@over_over = ''
|
1545
|
+
over_remove(:enter)
|
1546
|
+
over_remove(:leave)
|
1547
|
+
over_remove(:over)
|
1205
1548
|
end
|
1206
1549
|
end
|
1207
1550
|
|
@@ -1209,155 +1552,119 @@ class HTML
|
|
1209
1552
|
action_proc.is_a?(Proc) && (!Universe.edit_mode || @original_atome.tag[:system])
|
1210
1553
|
end
|
1211
1554
|
|
1212
|
-
def
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1221
|
-
# group etc..
|
1222
|
-
proc_content = @touch_down.call(@touch_down_event) if event_validation(@touch_down)
|
1223
|
-
if proc_content.instance_of? Hash
|
1224
|
-
proc_content.each do |k, v|
|
1225
|
-
@original_atome.send(k, v)
|
1226
|
-
end
|
1227
|
-
end
|
1228
|
-
# end
|
1229
|
-
# end
|
1230
|
-
end
|
1231
|
-
end
|
1232
|
-
|
1233
|
-
def touch_tap(_option)
|
1234
|
-
@element[:style][:cursor] = 'pointer'
|
1235
|
-
interact = JS.eval("return interact('##{@id}')")
|
1236
|
-
@touch_tap = @original_atome.instance_variable_get('@touch_code')[:tap]
|
1237
|
-
# unless @touch_removed[:tap]
|
1238
|
-
interact.on('tap') do |native_event|
|
1239
|
-
|
1240
|
-
@touch_tap_event = Native(native_event)
|
1241
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1242
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1243
|
-
# group etc..
|
1244
|
-
proc_content = @touch_tap.call(@touch_tap_event) if event_validation(@touch_tap)
|
1245
|
-
if proc_content.instance_of? Hash
|
1246
|
-
proc_content.each do |k, v|
|
1247
|
-
# alert "(#{@original_atome.id}, #{k}, #{v}, #{_option})"
|
1248
|
-
@original_atome.send(k, v)
|
1249
|
-
end
|
1250
|
-
end
|
1251
|
-
end
|
1252
|
-
# end
|
1253
|
-
end
|
1555
|
+
def setup_touch_event(event_type, _option)
|
1556
|
+
instance_variable = "@touch_#{event_type}_already_set"
|
1557
|
+
unless instance_variable_get(instance_variable)
|
1558
|
+
@element[:style][:cursor] = 'pointer'
|
1559
|
+
interact = JS.eval("return interact('##{@id}')")
|
1560
|
+
interact.on(event_type) do |native_event|
|
1561
|
+
touch_event = Native(native_event)
|
1562
|
+
touch_needed = @original_atome.instance_variable_get('@touch_code')[event_type.to_sym]
|
1254
1563
|
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1263
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1264
|
-
# group etc..
|
1265
|
-
proc_content = @touch_up.call(@touch_up_event) if event_validation(@touch_up)
|
1266
|
-
if proc_content.instance_of? Hash
|
1267
|
-
proc_content.each do |k, v|
|
1268
|
-
@original_atome.send(k, v)
|
1269
|
-
end
|
1270
|
-
end
|
1271
|
-
end
|
1272
|
-
end
|
1273
|
-
|
1274
|
-
def touch_double(_option)
|
1275
|
-
@element[:style][:cursor] = 'pointer'
|
1276
|
-
interact = JS.eval("return interact('##{@id}')")
|
1277
|
-
@touch_double = @original_atome.instance_variable_get('@touch_code')[:double]
|
1278
|
-
# unless @touch_removed[:double]
|
1279
|
-
interact.on('doubletap') do |native_event|
|
1280
|
-
@touch_double_event = Native(native_event)
|
1281
|
-
# we use .call instead of instance_eval because instance_eval bring the current object as context
|
1282
|
-
# and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1283
|
-
# group etc..
|
1284
|
-
proc_content = @touch_double.call(@touch_double_event) if event_validation(@touch_double)
|
1285
|
-
if proc_content.instance_of? Hash
|
1286
|
-
proc_content.each do |k, v|
|
1287
|
-
@original_atome.send(k, v)
|
1564
|
+
touch_needed.each do |proc_found|
|
1565
|
+
proc_content = proc_found.call(touch_event) if event_validation(proc_found)
|
1566
|
+
if proc_content.instance_of? Hash
|
1567
|
+
proc_content.each do |k, v|
|
1568
|
+
@original_atome.send(k, v)
|
1569
|
+
end
|
1570
|
+
end
|
1288
1571
|
end
|
1289
1572
|
end
|
1290
1573
|
end
|
1291
|
-
|
1292
|
-
end
|
1293
|
-
|
1294
|
-
def
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1574
|
+
instance_variable_set(instance_variable, true)
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
def touch_down(option)
|
1578
|
+
setup_touch_event('down', option)
|
1579
|
+
end
|
1580
|
+
|
1581
|
+
def touch_up(option)
|
1582
|
+
setup_touch_event('up', option)
|
1583
|
+
end
|
1584
|
+
|
1585
|
+
def touch_tap(option)
|
1586
|
+
setup_touch_event('tap', option)
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
def touch_double(option)
|
1590
|
+
setup_touch_event('doubletap', option)
|
1591
|
+
end
|
1592
|
+
|
1593
|
+
def touch_long(option)
|
1594
|
+
setup_touch_event('hold', option)
|
1595
|
+
end
|
1596
|
+
|
1597
|
+
# def touch_double(_option)
|
1598
|
+
# @element[:style][:cursor] = 'pointer'
|
1599
|
+
# interact = JS.eval("return interact('##{@id}')")
|
1600
|
+
# @touch_double = @original_atome.instance_variable_get('@touch_code')[:double]
|
1601
|
+
# # unless @touch_removed[:double]
|
1602
|
+
# interact.on('doubletap') do |native_event|
|
1603
|
+
# # we use an instance variable below instead of a local variable to be able to kill the event
|
1604
|
+
# @touch_double_event = Native(native_event)
|
1605
|
+
# # we use .call instead of instance_eval because instance_eval bring the current object as context
|
1606
|
+
# # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1607
|
+
# # group etc..
|
1608
|
+
# proc_content = @touch_double.call(@touch_double_event) if event_validation(@touch_double)
|
1609
|
+
# if proc_content.instance_of? Hash
|
1610
|
+
# proc_content.each do |k, v|
|
1611
|
+
# @original_atome.send(k, v)
|
1612
|
+
# end
|
1613
|
+
# end
|
1614
|
+
# end
|
1615
|
+
#
|
1616
|
+
# end
|
1617
|
+
|
1618
|
+
# def touch_long(_option)
|
1619
|
+
# @element[:style][:cursor] = 'pointer'
|
1620
|
+
# @touch_long = @original_atome.instance_variable_get('@touch_code')[:long]
|
1621
|
+
# interact = JS.eval("return interact('##{@id}')")
|
1622
|
+
# # unless @touch_removed[:long]
|
1623
|
+
# interact.on('hold') do |native_event|
|
1624
|
+
# @touch_long_event = Native(native_event)
|
1625
|
+
# # we use .call instead of instance_eval because instance_eval bring the current object as context
|
1626
|
+
# # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
|
1627
|
+
# # group etc..
|
1628
|
+
# proc_content = @touch_long.call(@touch_long_event) if event_validation(@touch_long)
|
1629
|
+
# if proc_content.instance_of? Hash
|
1630
|
+
# proc_content.each do |k, v|
|
1631
|
+
# @original_atome.send(k, v)
|
1632
|
+
# end
|
1633
|
+
# end
|
1634
|
+
# end
|
1635
|
+
# end
|
1636
|
+
def remove_this_touch(option)
|
1637
|
+
@original_atome.instance_variable_get('@touch_code')[option] = [] if @original_atome.instance_variable_get('@touch_code')
|
1638
|
+
end
|
1639
|
+
|
1640
|
+
def touch_remove(_opt)
|
1641
|
+
if @original_atome.instance_variable_get('@touch_code')
|
1642
|
+
option = @original_atome.instance_variable_get('@touch_code')[:remove]
|
1643
|
+
else
|
1644
|
+
option = false
|
1310
1645
|
end
|
1311
|
-
end
|
1312
1646
|
|
1313
|
-
def touch_remove(option)
|
1314
1647
|
@element[:style][:cursor] = 'default'
|
1315
1648
|
case option
|
1316
1649
|
when :double
|
1317
|
-
|
1318
|
-
@touch_removed[:double] = true
|
1319
|
-
@touch_double_event= nil
|
1650
|
+
remove_this_touch(:double)
|
1320
1651
|
when :down
|
1321
|
-
|
1322
|
-
@touch_removed[:down] = true
|
1323
|
-
@touch_down_event= nil
|
1652
|
+
remove_this_touch(:down)
|
1324
1653
|
when :long
|
1325
|
-
|
1326
|
-
@touch_long = ''
|
1327
|
-
@touch_long_event= nil
|
1654
|
+
remove_this_touch(:long)
|
1328
1655
|
when :tap
|
1329
|
-
|
1330
|
-
@touch_tap = ''
|
1331
|
-
@touch_removed[:touch] = true
|
1332
|
-
@touch_touch = ''
|
1333
|
-
@touch_tap_event= nil
|
1334
|
-
|
1656
|
+
remove_this_touch(:tap)
|
1335
1657
|
when :touch
|
1336
|
-
|
1337
|
-
@touch_tap = ''
|
1338
|
-
@touch_removed[:touch] = true
|
1339
|
-
@touch_touch = ''
|
1340
|
-
@touch_tap_event= nil
|
1341
|
-
|
1658
|
+
remove_this_touch(:touch)
|
1342
1659
|
when :up
|
1343
|
-
|
1344
|
-
@touch_up = ''
|
1345
|
-
@touch_up_event= nil
|
1660
|
+
remove_this_touch(:up)
|
1346
1661
|
else
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
touch_remove(:long)
|
1354
|
-
@touch_long_event= nil
|
1355
|
-
|
1356
|
-
touch_remove(:tap)
|
1357
|
-
touch_remove(:touch)
|
1358
|
-
@touch_tap_event= nil
|
1359
|
-
touch_remove(:up)
|
1360
|
-
@touch_up_event= nil
|
1662
|
+
remove_this_touch(:double)
|
1663
|
+
remove_this_touch(:down)
|
1664
|
+
remove_this_touch(:long)
|
1665
|
+
remove_this_touch(:touch)
|
1666
|
+
remove_this_touch(:double)
|
1667
|
+
remove_this_touch(:up)
|
1361
1668
|
end
|
1362
1669
|
|
1363
1670
|
end
|
@@ -1740,12 +2047,12 @@ class HTML
|
|
1740
2047
|
|
1741
2048
|
apply_centering(@center_options, @parent)
|
1742
2049
|
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
end
|
1747
|
-
JS.global[:window].addEventListener('resize', event_handler)
|
2050
|
+
return unless @center_options[:dynamic]
|
2051
|
+
event_handler = ->(event) do
|
2052
|
+
apply_centering(@center_options, @parent)
|
1748
2053
|
end
|
2054
|
+
JS.global[:window].addEventListener('resize', event_handler)
|
2055
|
+
|
1749
2056
|
end
|
1750
2057
|
|
1751
2058
|
def record_audio(params)
|
@@ -1780,10 +2087,10 @@ class HTML
|
|
1780
2087
|
@original_atome.left(x_position)
|
1781
2088
|
end
|
1782
2089
|
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
2090
|
+
return unless options[:y]
|
2091
|
+
y_position = calculate_position(options[:y], parent.to_px(:height), @original_atome.to_px(:height))
|
2092
|
+
@original_atome.top(y_position)
|
2093
|
+
|
1787
2094
|
end
|
1788
2095
|
|
1789
2096
|
def calculate_position(option, parent_dimension, self_dimension)
|