-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathframe.r
1283 lines (1024 loc) · 35.7 KB
/
frame.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
REBOL [
; -- Core Header attributes --
title: "Glass frame"
file: %frame.r
version: 1.0.2
date: 2013-12-17
author: "Maxim Olivier-Adlhoch"
purpose: {The core marble type which acts as a container for other marbles.}
web: http://www.revault.org/modules/frame.rmrk
source-encoding: "Windows-1252"
note: {slim Library Manager is Required to use this module.}
; -- slim - Library Manager --
slim-name: 'frame
slim-version: 1.2.2
slim-prefix: none
slim-update: http://www.revault.org/downloads/modules/frame.r
; -- Licensing details --
copyright: "Copyright © 2013 Maxim Olivier-Adlhoch"
license-type: "Apache License v2.0"
license: {Copyright © 2013 Maxim Olivier-Adlhoch
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.}
;- / history
history: {
v1.0.0 - 2013-09-17
-License change to Apache v2
v1.0.1 - 2013-11-20
- frames can now be activated (aspects/active?) so they end up receiving mouse events, just like normal marbles.
this allows us to generate control zones which receive inputs (like drag and drop).
v1.0.2 - 2013-12-17
-Added fill weight scaling allow you to manipulate the relative weight
of one frame wrt another within their parent frame. (scaling to 0 effectively
cancels resizing for the frame!)
-added frame stiffness control in dialect (using fill weight scaling)
-added manual frame size adjustment
-replaced frame-color to border-color as to follow the new attribute in the core marble
}
;- \ history
;- / documentation
documentation: {
The Frame serves as the root marble for all layout. Any marble providing layout capabilities
MUST derive from this one. you may implement the gl-fasten how-ever you wish, but
every method and parameter in this object is required by GLASS.
Also, deriving will future-proof your custom layout styles.
This module is EXTENSIVELY commented, so refer to the code when in doubt.
}
;- \ documentation
]
slim/register [
;- .
;-----------------------------------------------------------------------------------------------------------
;
;- LIBS
;
;-----------------------------------------------------------------------------------------------------------
glob-lib: slim/open/expose 'glob none [!glob to-color]
liquid-lib: slim/open/expose 'liquid none [
!plug
[liquify* liquify ]
[content* content]
[fill* fill]
[link* link]
[unlink* unlink]
[detach* detach]
]
sillica-lib: slim/open/expose 'sillica none [
master-stylesheet
alloc-marble
regroup-specification
list-stylesheet
collect-style
relative-marble?
prim-bevel
prim-x
prim-label
]
epoxy-lib: slim/open/expose 'epoxy none [!box-intersection !pair-mult]
marble-lib: slim/open 'marble none
;- .
;-----------------------------------------------------------------------------------------------------------
;
;- !FRAME[ ]
;
;-----------------------------------------------------------------------------------------------------------
!frame: make marble-lib/!marble [
;- aspects[ ]
aspects: context [
; managed positioning
;- offset:
;
; the offset is manipulated by the default fasten code.
offset: -1x-1
;- color
color: none ;theme-bg-color
;- border-color
border-color: theme-border-color
;- enabled?:
; when false or none, this will dim the gui and add an input blocker OVER our frame
; so child collection mouse handling is deactivated.
;
; this used to be named 'DISABLE? but it proved ineffective to use a negative value
; when linking with other controls and data.
enabled?: #[true]
;- corner:
corner: 3
;--------------------------
;- active?:
;
; when hot, we will receive mouse events
;
; by default, frames do not attempt to interact with the event system
;--------------------------
active?: false
;--------------------------
;- fill-scale:
;
; this multiplies the values of fill-weight and fill-accumulation, allowing you to allocate more
; space to the frame, or completely disable its resizing (by setting 0 in X AND/OR Y).
;--------------------------
fill-scale: 1x1
;--------------------------
;- dimension-adjust:
;
; allows us to adjust the min size manually. this forces us to receive more space
; which is evenly spread out to children.
;
; it may also cause our children to shrink if a negative adjustment is required.
;
; this is a manual hack which may cause strange side-effects in some layouts, use with caution.
;--------------------------
dimension-adjust: 0x0
]
;- material[ ]
material: make material [
;- position:
; the global coordinates your marble is at
; (automatically linked to gui by parent frame).
position: 0x0
;- border-size:
;
; border-size is used as a containter for now, but eventually, it will be a calculated value,
; based on margins, padding and edge-size
border-size: 5x5
;- content-size:
; depending on marble type, the content-size will mutate into different sizing plugs
; the most prevalent is the !text-sizing type which expects a !theme plug
;content-size: none
;--------------------------
;- content-fill-weight:
;
; fill weight of content inside of frame
;
; is used to rescale content.
;
; frames inherit & accumulate these values, marbles supply them.
;--------------------------
content-fill-weight: none
;- fill-weight:
; fill up / compress extra space in either direction (independent), but don't initiate resising
;
; this is our own adjusted fill-weight, used for our parents to allocate extra-space
; to us and our children.
;
; this value is basically our content fill-weight multiplied by fill-scale.
;
; it allows us to get more extra space than our brethren, or none, if set to 0x0.
fill-weight: 0x0
;- fill-accumulation:
; stores the accumulated fill-weight of this and previous marbles.
;
; allows you to identify the fill regions
;
; regions 0 2 3 6 6 8
; fill 2 1 3 0 2
; gui |--|-|---|..|--|
;
; using regions fills all gaps and any decimal rounding errors are alleviated.
fill-accumulation: 0x0
;- stretch:
; marble benefits from extra space, initiates resizing ... preempts fill
;
;
; frames inherit & accumulate these values, marbles supply them.
stretch: 0x0
;- dimension:
; computed size, setup by parent frame, includes at least min-dimension, but can be larger, depending
; on the layout method of your parent.
;
; dimension is a special plug in that it is allocated arbitrarily by the marble as a !plug,
; but its valve, will be mutated into what is required by the frame.
;
; the observer connections will remain intact, but its subordinates are controled
; by the frame on collect.
dimension: 200x300
;- min-dimension:
;
; minimal space required by this frame including any layout properties like margins,
; borders, padding, frame banner, required size and accumulated minimum sizes of collection.
;
; used by dimension
min-dimension: 30x30
;- content-dimension:
; same as dimension with our own added size requirements removed (borders, margins, etc)
content-dimension: none
;- content-min-dimension:
; same as min-dimension without our own added size requirements removed (borders, margins, etc)
content-min-dimension: none
;- content-spacing:
; accumulates all the offsets in our collection
content-spacing: none
;- origin:
; this is the origin we supply to our children
; a clip-region might also use this value or the position.
;
; normally, the origin is connected to border-size and offset
origin: 5x5
;- clip-region
; our own calculated global cliping rectangle, is affected by parent frame clip regions once collected.
; until a marble is collected, its clipping region makes it invisible (from -1x-1 to -1x-1)
clip-region: none
;- parent-clip-region:
parent-clip-region: none
]
;- collection:
; stores any marbles we contain (link to?)
; ATTENTION: ONLY use the collect() & to manipulate this list.
collection: none
;- frame-bg-glob:
; a glob used to render any frame visuals behind marbles.
; intersects our clip region with that of our frame.
;
; this allows glass to simulate view's hierarchical nested face clipping using draw !!!
frame-bg-glob: none
;- frame-fg-glob:
; a glob used to render any frame visuals Over its marbles.
; the default frame uses this to restore its frame's clip region.
frame-fg-glob: none
;- spacing-on-collect:
; when collecting marbles, automatically set their offset to this value
spacing-on-collect: 5x5
;- layout-method:
; this changes the frame into various types of grouped layout methods.
;
; values are: [row, column, absolute, relative, column-grid, row-grid, explode]
;
; changing this value at run-time should only be performed by expert programmers
; since it requires rebuilding outer panes to adjust to new inner values.
;
; if the method changes and is incompatible with the previous method, some layout
; breakage will result in outer panes, since the various calculated sizing parameters
; will not be updated for them.
;
; usually, this means calling refresh on the most outer frame which can be affected by
; the change to this frame.
;
layout-method: 'column
;- valve []
valve: make valve [
type: '!marble
;- style-name:
style-name: 'frame
;- is-frame?:
is-frame?: true
;- glob-class:
; defines the glob which will be built by each marble instance.
glob-class: none
;- bg-glob-class:
; class used to allocate and link a glob drawn BEHIND the marble collection
bg-glob-class: make !glob [
valve: make valve [
;- glob/input-spec:
input-spec: [
; list of inputs to generate automatically on setup these will be stored within the instance under input
position !pair (random 200x200)
dimension !pair (300x300)
color !color
border-color !color (random white)
corner !integer
; uncomment to debug
; clip-region !block ([0x0 1000x1000])
; min-dimension !pair
; content-dimension !pair
; content-min-dimension !pair
active? !bool
]
;- glob/gel-spec:
gel-spec: [
; event backplane
position dimension active?
[
(
either data/active?= [
compose/deep [
line-width 1
pen none
fill-pen (to-color gel/glob/marble/sid)
box (data/position=) (data/position= + data/dimension= - 1x1)
]
][
[]
]
)
]
; bg layer (ex: shadows, textures)
; keep in mind... this can be switched off for greater performance
;[]
; FG LAYER
position dimension color border-color corner
;------
; uncomment following for debugging
;
; min-dimension content-dimension content-min-dimension
;------
[
; here we restore our parent's clip region :-)
fill-pen (data/color=)
pen (data/border-color=)
line-width 1
box (data/position=) (data/position= + data/dimension= - 1x1) (data/corner=)
;------
; uncomment for debugging purposes.
; line-width 1
; pen blue
; fill-pen (0.0.0.129 + data/color=)
; box (data/position=) (data/position= + data/content-dimension=)
; pen red
; fill-pen (0.0.0.129 + data/color=)
; box (data/position=) (data/position= + data/dimension=)
; pen black
; fill-pen (0.0.0.129 + data/color=)
; box (data/position=) (data/position= + data/min-dimension=)
; pen white
; fill-pen (0.0.0.129 + data/color=)
; box (data/position=) (data/position= + data/content-min-dimension=)
;------
]
; controls layer
;[]
; overlay
;[]
]
]
]
;- fg-glob-class:
; class used to allocate and link a glob drawn IN FRONT OF the marble collection
;
; windows use this to create an input blocker, for example.
fg-glob-class: make !glob [
valve: make valve [
;- glob/input-spec:
input-spec: [
; list of inputs to generate automatically on setup these will be stored within the instance under input
position !pair ( random 200x200 )
dimension !pair ( 300x300 )
enabled? !bool
;color !color
;border-color !color (random white)
;clip-region !block ([0x0 1000x1000])
;parent-clip-region !block ([0x0 1000x1000])
]
;- glob/gel-spec:
gel-spec: [
;---
; event backplane
enabled? position dimension
[
(
either not data/enabled?= [
compose [
pen none
fill-pen (white) ; erases backplane.
box (data/position=) (data/position= + data/dimension= - 1x1)
]
][ [] ]
)
]
; bg layer (ex: shadows, textures)
; keep in mind... this can be switched off for greater performance
;[]
; fg layer
; position dimension color border-color clip-region parent-clip-region
enabled? position dimension
[
; here we restore our parent's clip region :-)
;clip (data/parent-clip-region=)
(
either not data/enabled?= [
compose [
pen none
fill-pen (theme-bg-color + 0.0.0.100)
box (data/position=) (data/position= + data/dimension= )
]
][
[]
]
)
]
; controls layer
;[]
; overlay
;[]
]
]
]
;-----------------
;- gl-materialize()
;
; see !marble for details
;-----------------
gl-materialize: func [
frame [object!]
][
vin [{frame/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/gl-materialize()}]
; manage relative positioning
;if relative-marble? frame [
frame/material/position: liquify*/fill epoxy-lib/!junction frame/material/position
;link* frame/material/position frame/aspects/offset
;]
frame/material/origin: liquify*/fill !plug frame/material/origin
frame/material/dimension: liquify*/fill !plug frame/material/dimension
frame/material/content-dimension: liquify*/fill !plug frame/material/content-dimension
frame/material/min-dimension: liquify*/fill !plug frame/material/min-dimension
frame/material/content-min-dimension: liquify*/fill !plug frame/material/content-min-dimension
; manage resizing
frame/material/content-fill-weight: liquify*/fill !plug frame/material/content-fill-weight
frame/material/fill-weight: liquify*/fill !pair-mult frame/material/fill-weight
frame/material/fill-accumulation: liquify*/fill !plug frame/material/fill-accumulation
frame/material/stretch: liquify*/fill !plug frame/material/stretch
frame/material/content-spacing: liquify*/fill !plug 0x0
frame/material/border-size: liquify*/fill !plug frame/material/border-size
; this controls where our PARENT can draw we link to it, cause we restore it after our marbles
; have done their stuff. We also need it to resolve our own clip-region
;
; clip regions are stored as a block containing two pairs
;marble/parent-clip-region: liquify* !plug
; this controls where WE can draw
frame/material/clip-region: liquify* epoxy-lib/!box-intersection
;link* frame/material/clip-region frame/material/position
;link* frame/material/clip-region frame/material/dimension
frame/material/parent-clip-region: liquify* !plug
; our link itself after.
;marble/material/origin: liquify*/link epoxy/!fast-add marble/material/position
; this is meant for styles to setup their specific materials.
;marble/valve/setup-materials marble
vout
]
;-----------------
;- accumulate()
;
; add one or more marble(s) in our collection
;
; this is just a wrapper which accepts several input types.
;
; it is optimised for collecting several marbles at once.
;
; when actively controling marbles, use GL-COLLECT() directly.
;
;-----------------
accumulate: func [
frame [object!]
marbles [object! block!]
/local marble fg-glob
][
vin [{frame/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/accumulate()}]
; normalize the input type,
; if marbles is a block, it must only contain a series of marble OBJECTS.
marbles: compose [(marbles)]
vprint [length? marbles " Marble(s) to collect"]
if object? frame/frame-fg-glob [
vprint "must unlink FG GLOB"
fg-glob: frame/frame-fg-glob
frame/frame-fg-glob: none
frame/glob/valve/unlink/only frame/glob fg-glob
]
; collect every marble
foreach marble marbles [
frame/valve/gl-collect frame marble
]
;ask ""
if object? fg-glob [
vprint "Relinking FG GLOB"
frame/frame-fg-glob: fg-glob
fg-glob: none
frame/glob/valve/link frame/glob frame/frame-fg-glob
]
;----
; cleanup GC
marble: marbles: frame: fb-glob: none
vout
]
;-----------------
;- link-glob()
; callback used to perform the link of a collected marble.
;
; in some styles, collected marbles aren't directly linked to the frame's
; glob, but to an intermediate.
;-----------------
link-glob: func [
frame
marble
][
vin [{frame/link-glob()}]
frame/glob/valve/link frame/glob marble/glob
vprobe content frame/glob
vout
]
;-----------------
;- unlink-glob()
; callback used to perform the unlink of a discarded marble.
;
; in some styles, collected marbles aren't directly linked to the frame's
; glob, but to an intermediate.
;-----------------
unlink-glob: func [
frame
marble
][
vin [{frame/unlink-glob()}]
frame/glob/valve/unlink/only frame/glob marble/glob
;vprobe content frame/glob/reflection
vout
]
;-----------------
;- gl-collect()
;
; add a marble to a frame.
;
; use accumulate() when collecting several marbles at a time
;
; it is THE ONLY LEGAL WAY to assign marbles to a frame.
;
; ATTENTION: collecting a marble which is already in a frame, automatically
; removes it from that frame.
;
; <TO DO> refinements:
; /at index [integer! object!] ; same as /before when used with object!
; /before marble [object!]
; /after marble [object!]
;-----------------
gl-collect: func [
frame [object!]
marble [object!]
/top "collects at the top rather tahn the end"
/local frm
][
vin [{frame/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/gl-collect()}]
;vprint ["collecting one marble of type: " to-string marble/valve/style-name ]
either frm: get in frame 'collect-in-frame [
marble/frame: frm
frm/valve/gl-collect frm marble
][
; make sure we add marbles UNDER frame's fg-glob
if object? frame/frame-fg-glob [
;print "must unlink FG GLOB"
frame/glob/valve/unlink/only frame/glob frame/frame-fg-glob
]
; make sure the marble isn't shared in several frames
if any [
; marble is framed, but its from another collection
all [
not same? marble/frame frame
marble/frame
]
all [
; on init, the frame is set, but its not yet collected, ignore the discard in this case.
same? frame marble/frame
find frame/collection marble
]
][
; note: gl-discard() calls discard() on its own
marble/frame/valve/gl-discard marble/frame marble
]
; assign this frame to the marble
marble/frame: frame
; hoard it in our collection
either top [
insert frame/collection marble
][
append frame/collection marble
]
; tell our glob to add the marble's graphics to our graphics.
link-glob frame marble
; make sure fg-glob is ALWAYS in front of marbles
if object? frame/frame-fg-glob [
;print "Relinking FG GLOB"
frame/glob/valve/link frame/glob frame/frame-fg-glob
]
; rarely, if ever, used... but may be usefull for specialized layout styles
; this is advanced stuff, use with caution.
frame/valve/collect frame marble
]
vout
]
;-----------------
;- collect()
;
; this is a style-specific collection method for custom styles.
;
; it is evaluated WITHIN the low-level internal gl-collect() call, AFTER gl-collect has completed.
;
; this is not intended for casual users, there are many things to know when collecting a marble,
; and full understanding of the framework is required.
;
; nonetheless, advanced users will enjoy the fact that they can actually change how marbles
; are stacked visually, so there is virtually no limit beyond what Draw can accomplish.
;-----------------
collect: func [
frame
marble
][
;vin [{glass/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/collect()}]
;vout
]
;-----------------
;- gl-discard()
;
; remove one or more marble(s) from OUR collection
;
; the only valid word marble value is 'all ('last , 'first are obvious enhancements)
;
; note that this doesn't destroy the marbles, it just removes it/them from our collection.
;
; ATTENTION: care must be taken to supply only marbles which actually are part of the frame's collection
; otherwise an error WILL BE RAISED!
;-----------------
gl-discard: func [
frame [object!]
marble [object! block! word!]
/local marbles blk frm
][
vin [{glass/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/gl-discard()}]
either frm: get in frame 'collect-in-frame [
frm/valve/gl-discard frm marble
][
; normalize the input type
switch type?/word marble [
word! [
if marble = 'all [
vprint "Discarding ALL marbles"
marbles: copy frame/collection
]
]
object! [
marbles: reduce [marble]
]
block! [
marbles: marble
]
]
vprint ["number of marbles: " length? marbles]
foreach marble marbles [
vprint "-"
vprobe type? :marble
]
foreach marble marbles [
vprint "--------------------"
vprint ["type? marble: " type? marble]
vprint ["marble: " marble/sid]
vprint ["marble/frame: " all [marble/frame marble/frame/sid]]
either blk: find frame/collection marble [
; first discard a style's collection customisation
frame/valve/discard frame marble
; remove marble from collection
remove blk
; disconnect the marble position from its frame
if relative-marble? marble [
if object? get in marble/material 'position [
if 2 = length? marble/material/position/subordinates [
marble/material/position/valve/unlink/tail marble/material/position
]
]
]
; disconnect the marble's glob from its frame
unlink-glob frame marble
; detach marble from frame
marble/frame: none
][
to-error "Trying to discard marble from wrong frame"
]
]
]
vout
]
;-----------------
;- discard()
;
; a style should undo any special stuff it might do when it collect collected
;-----------------
discard: func [
frame
marble
][
vin [{glass/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/discard-hook()}]
vout
]
;-----------------
;- gl-fasten()
;
; low-level default GLASS fastening.
;
; perform all linkeage required for this frame to effectively layout its collection.
;
; this is usually only called once, when our collection has changed. since we must update
; how each marble is related to its siblings and how we compare to the whole collection's new
; content.
;
; the frame is responsable for allocation and linking marbles so the layout will
; correspond to the frame's intended layout look and feel.
;
; Fasten is where MUTATIONS will take place on materials, so do not expect any specific
; marble to retain its previous marble/valve after gl-fasten is called.
;
; the frame will always call fasten on its marble collection members BEFORE it performs its own
; fastening on the marbles.
;
; note, fasten() on a marble is ONLY called from frames ... control-type
; marbles never call gl-fasten() directly !!
;
;
; Note, right now, gl-fasten isn't optimised for speed but raw robustness... so for this reason,
; each fasten call, unlinks the whole collection and refastens it from scratch. this way we are
; sure that strange collect() calls do not corrupt the display by adding a new marble somewhere
; in the middle of the collection.
;
; Once glass will mature and usage patterns become obvious, we will improve gl-fasten().
;
; at least, gl-fasten is called when the whole collection is accumulated, not everytime a single
; marble is collected
;-----------------
gl-fasten: func [
frame
/local marble previous-marble mtrl mmtrl
][
vin [{frame/!} uppercase to-string frame/valve/style-name {[} frame/sid {]/gl-fasten()}]
mtrl: frame/material
;- -wrapper
if find frame/options 'wrapper [
;vprint "SPECIFYING WRAPPER!"
;vprint content* frame/aspects/offset
link*/reset mtrl/position frame/aspects/offset
]
; setup our own materials
link*/reset mtrl/origin reduce [
mtrl/position
mtrl/border-size
]
link*/reset mtrl/content-dimension reduce [
mtrl/dimension
mtrl/border-size
mtrl/border-size
]
link*/reset mtrl/min-dimension reduce [
mtrl/content-min-dimension
mtrl/border-size
mtrl/border-size
frame/aspects/dimension-adjust
]
;- -mutate
; mutate our materials
mtrl/origin/valve: epoxy-lib/!pair-add/valve
mtrl/content-dimension/valve: epoxy-lib/!pair-subtract/valve
mtrl/min-dimension/valve: epoxy-lib/!pair-add/valve
switch frame/layout-method [
column [
;vprint "COLUMN!"
; position
mtrl/content-min-dimension/valve: epoxy-lib/!vertical-accumulate/valve
mtrl/content-fill-weight/valve: epoxy-lib/!vertical-accumulate/valve
mtrl/content-spacing/valve: epoxy-lib/!vertical-accumulate/valve
]
;
row [
;vprint "ROW!"
; position
mtrl/content-min-dimension/valve: epoxy-lib/!horizontal-accumulate/valve
mtrl/content-fill-weight/valve: epoxy-lib/!horizontal-accumulate/valve
mtrl/content-spacing/valve: epoxy-lib/!horizontal-accumulate/valve
]
]
; setup my clip-region
; link to my parent's clip-region
;- -reset frame
; reset our marble-dependent material properties
unlink*/detach mtrl/content-fill-weight
unlink*/detach mtrl/stretch
unlink*/detach mtrl/content-spacing