changeset 58 | 668eb9eae2ac |
parent 55 | 19e021c8f1ef |
child 59 | 0a2b2ff030a0 |
57:5af567f52811 | 58:668eb9eae2ac |
---|---|
131 |
131 |
132 ! ! |
132 ! ! |
133 |
133 |
134 !UIObjectView methodsFor:'event handling'! |
134 !UIObjectView methodsFor:'event handling'! |
135 |
135 |
136 doKeyInput:key |
|
137 ^ self |
|
138 |
|
139 |
|
140 ! |
|
141 |
|
142 elementChanged:aView |
136 elementChanged:aView |
143 "some element has been changed - kludge to force a resizing |
137 "some element has been changed - kludge to force a resizing |
144 operation (for child layout recomputation) in its superView" |
138 operation (for child layout recomputation) in its superView" |
145 |
139 |
146 aView superView sizeChanged:nil. |
140 aView superView sizeChanged:nil. |
161 |
155 |
162 exposeX:x y:y width:w height:h |
156 exposeX:x y:y width:w height:h |
163 "handle an expose event from device; redraw selection |
157 "handle an expose event from device; redraw selection |
164 " |
158 " |
165 super exposeX:x y:y width:w height:h. |
159 super exposeX:x y:y width:w height:h. |
166 |
160 self selectionDo:[:v | self showSelected:v] |
167 selection notNil ifTrue:[ |
|
168 self selectionDo:[:v | self showSelected:v] |
|
169 ] |
|
170 |
161 |
171 |
162 |
172 ! |
163 ! |
173 |
164 |
174 keyPress:key x:x y:y |
165 keyPress:key x:x y:y |
166 <resource: #keyboard ( #InspectIt #Delete #BackSpace #Cut) > |
|
175 |
167 |
176 key == #InspectIt ifTrue:[ |
168 key == #InspectIt ifTrue:[ |
177 ^ self inspectSelection |
169 ^ self inspectSelection |
178 ]. |
170 ]. |
179 |
171 |
180 (key == #Delete or:[key == #BackSpace]) ifTrue: [ |
172 (key == #Cut or:[key == #Delete or:[key == #BackSpace]]) ifTrue: [ |
181 selection notNil ifTrue:[ |
173 ^ self deleteSelection |
182 self deleteSelection |
174 ]. |
183 ] |
175 |
184 ] ifFalse:[ |
176 super keyPress:key x:x y:y |
185 keyPressAction notNil ifTrue:[ |
|
186 keyPressAction value:key |
|
187 ] |
|
188 ] |
|
189 |
177 |
190 |
178 |
191 ! |
179 ! |
192 |
180 |
193 processEvent:anEvent |
181 processEvent:anEvent |
289 |
277 |
290 pressAction := [:pressPoint | self startSelectOrMove:pressPoint]. |
278 pressAction := [:pressPoint | self startSelectOrMove:pressPoint]. |
291 shiftPressAction := [:pressPoint | self startSelectMoreOrMove:pressPoint]. |
279 shiftPressAction := [:pressPoint | self startSelectMoreOrMove:pressPoint]. |
292 motionAction := [:movePoint | nil]. |
280 motionAction := [:movePoint | nil]. |
293 releaseAction := [nil]. |
281 releaseAction := [nil]. |
294 keyPressAction := [:key | self doKeyInput:key]. |
282 keyPressAction := nil. |
295 |
283 |
296 self cursor:Cursor normal. |
284 self cursor:Cursor normal. |
297 |
285 |
298 ! |
286 ! |
299 |
287 |
412 startCreate:aPoint |
400 startCreate:aPoint |
413 "start a widget create |
401 "start a widget create |
414 " |
402 " |
415 |widget object start frame delta| |
403 |widget object start frame delta| |
416 |
404 |
417 createClass isNil ifTrue:[ |
405 (createClass isNil or:[self numberOfSelections > 1]) ifTrue:[ |
418 ^ self setDefaultActions |
|
419 ]. |
|
420 (selection isKindOf:Collection) ifTrue:[ |
|
421 self unselect. |
406 self unselect. |
422 ^ self setDefaultActions. |
407 ^ self setDefaultActions. |
423 ]. |
408 ]. |
424 |
409 |
425 motionAction := [:movePoint| self doDragCreate:movePoint]. |
410 motionAction := [:movePoint| self doDragCreate:movePoint]. |
426 releaseAction := [ self endCreate]. |
411 releaseAction := [ self endCreate]. |
427 |
412 |
428 selection notNil ifTrue:[ |
413 widget := self singleSelection. |
429 ( (self isPoint:aPoint containedIn:selection) |
414 |
430 and:[self supportsSubComponents:selection] |
415 ( widget notNil |
431 ) ifFalse:[ |
416 and:[(self isPoint:aPoint containedIn:widget) |
432 self unselect |
417 and:[self supportsSubComponents:widget]] |
433 ] |
418 ) ifFalse:[ |
434 ]. |
419 self unselect. |
435 |
420 widget := self. |
436 widget := selection ? self. |
421 ]. |
422 |
|
437 object := createClass new. |
423 object := createClass new. |
438 widget addSubView:object. |
424 widget addSubView:object. |
439 |
425 |
440 start := self alignToGrid:aPoint. |
426 start := self alignToGrid:aPoint. |
441 delta := widget originRelativeTo:self. |
427 delta := widget originRelativeTo:self. |
501 delta := (self alignToGrid:aPoint) - org. |
487 delta := (self alignToGrid:aPoint) - org. |
502 dX := delta x. |
488 dX := delta x. |
503 dY := delta y. |
489 dY := delta y. |
504 |
490 |
505 undoHistory disabledTransitionDo:[ |
491 undoHistory disabledTransitionDo:[ |
506 self shifLayout:anObject top:dY bottom:dY left:dX right:dX |
492 self shiftLayout:anObject top:dY bottom:dY left:dX right:dX |
507 ] |
493 ] |
508 ] |
494 ] |
509 |
495 |
510 ! |
496 ! |
511 |
497 |
512 startObjectMoveAt:aPoint |
498 startObjectMoveAt:aPoint |
513 |
499 |
514 self startObjectMove:selection at:aPoint. |
500 self startObjectMove:selection at:aPoint. |
515 |
501 |
516 selection size == 0 ifTrue:[ |
502 selection isCollection ifTrue:[ |
503 movedObject := selection |
|
504 ] ifFalse:[ |
|
517 movedObject := Array with:selection |
505 movedObject := Array with:selection |
518 ] ifFalse:[ |
|
519 movedObject := selection |
|
520 ]. |
506 ]. |
521 super unselect. |
507 super unselect. |
522 |
508 |
523 moveDelta := movedObject collect:[:aView| |
509 moveDelta := movedObject collect:[:aView| |
524 aPoint - aView computeOrigin |
510 aPoint - aView computeOrigin |
525 ]. |
511 ]. |
526 |
512 |
527 selection := movedObject. |
513 self transaction:#move objects:movedObject do:[:aView| |
528 self transaction:#move selectionDo:[:aView| |
|
529 self invertOutlineOf:aView. |
514 self invertOutlineOf:aView. |
530 self undoBlockPositionChanged:aView |
515 self undoBlockPositionChanged:aView |
531 ]. |
516 ]. |
532 selection := nil |
|
533 |
517 |
534 ! |
518 ! |
535 |
519 |
536 startSelectMoreOrMove:aPoint |
520 startSelectMoreOrMove:aPoint |
537 "add/remove to/from selection" |
521 "add/remove to/from selection" |
555 " |
539 " |
556 |anObject b| |
540 |anObject b| |
557 |
541 |
558 testMode ifTrue:[^ self]. |
542 testMode ifTrue:[^ self]. |
559 |
543 |
560 "if there is one selection and point hits handle, start a resize |
544 "if there is one object selected and point hits a handle, start a resize |
561 " |
545 " |
562 self singleSelection notNil ifTrue:[ |
546 anObject := self singleSelection. |
563 b := self whichHandleOf:selection isHitBy:aPoint. |
547 |
548 anObject notNil ifTrue:[ |
|
549 b := self whichHandleOf:anObject isHitBy:aPoint. |
|
564 |
550 |
565 (b notNil and:[b ~~ #view]) ifTrue:[ |
551 (b notNil and:[b ~~ #view]) ifTrue:[ |
566 ^ self startResizeBorder:b of:selection. |
552 ^ self startResizeBorder:b of:anObject. |
567 ] |
553 ] |
568 ]. |
554 ]. |
569 |
555 |
570 anObject := self findObjectAt:aPoint. |
556 anObject := self findObjectAt:aPoint. |
571 |
557 |
578 (self isSelected:anObject) ifFalse:[ |
564 (self isSelected:anObject) ifFalse:[ |
579 super unselect. |
565 super unselect. |
580 self select:anObject. |
566 self select:anObject. |
581 ]. |
567 ]. |
582 |
568 |
583 selection isCollection ifTrue:[ |
569 (self numberOfSelections ~~ 1) ifTrue:[ |
584 releaseAction := [ |
570 releaseAction := [ |
585 self setDefaultActions. |
571 self setDefaultActions. |
586 self select:anObject |
572 self select:anObject |
587 ] |
573 ] |
588 ] ifFalse:[ |
574 ] ifFalse:[ |
652 "resize selected view |
638 "resize selected view |
653 " |
639 " |
654 |object| |
640 |object| |
655 |
641 |
656 object := self singleSelection. |
642 object := self singleSelection. |
643 |
|
644 (object geometryLayout) isNil ifTrue:[ |
|
645 ^ self setDefaultActions. |
|
646 ]. |
|
647 |
|
657 self actionResize:object selector:b. |
648 self actionResize:object selector:b. |
658 |
649 |
659 self transaction:#extent selectionDo:[:aView| |
650 self transaction:#extent selectionDo:[:aView| |
660 self undoBlockDimensionChanged:aView |
651 self undoBlockDimensionChanged:aView |
661 ]. |
652 ]. |
783 !UIObjectView methodsFor:'private resizing-subviews'! |
774 !UIObjectView methodsFor:'private resizing-subviews'! |
784 |
775 |
785 resize:aView bottom:aPoint |
776 resize:aView bottom:aPoint |
786 |
777 |
787 undoHistory disabledTransitionDo:[ |
778 undoHistory disabledTransitionDo:[ |
788 self shifLayout:aView top:0 bottom:((aPoint y) - (aView computeCorner y)) |
779 self shiftLayout:aView top:0 bottom:((aPoint y) - (aView computeCorner y)) |
789 ] |
780 ] |
790 ! |
781 ! |
791 |
782 |
792 resize:aView bottomLeft:aPoint |
783 resize:aView bottomLeft:aPoint |
793 |
784 |
794 undoHistory disabledTransitionDo:[ |
785 undoHistory disabledTransitionDo:[ |
795 self shifLayout:aView top:0 |
786 self shiftLayout:aView top:0 |
796 bottom:((aPoint y) - (aView computeCorner y)) |
787 bottom:((aPoint y) - (aView computeCorner y)) |
797 left:((aPoint x) - (aView computeOrigin x)) |
788 left:((aPoint x) - (aView computeOrigin x)) |
798 right:0 |
789 right:0 |
799 |
790 |
800 ] |
791 ] |
801 |
792 |
802 |
793 |
803 ! |
794 ! |
806 |delta| |
797 |delta| |
807 |
798 |
808 delta := aPoint - aView computeCorner. |
799 delta := aPoint - aView computeCorner. |
809 |
800 |
810 undoHistory disabledTransitionDo:[ |
801 undoHistory disabledTransitionDo:[ |
811 self shifLayout:aView top:0 bottom:(delta y) left:0 right:(delta x) |
802 self shiftLayout:aView top:0 bottom:(delta y) left:0 right:(delta x) |
812 ] |
803 ] |
813 ! |
804 ! |
814 |
805 |
815 resize:aView left:aPoint |
806 resize:aView left:aPoint |
816 |
807 |
817 undoHistory disabledTransitionDo:[ |
808 undoHistory disabledTransitionDo:[ |
818 self shifLayout:aView left:((aPoint x) - (aView computeOrigin x)) right:0 |
809 self shiftLayout:aView left:((aPoint x) - (aView computeOrigin x)) right:0 |
819 ] |
810 ] |
820 |
811 |
821 ! |
812 ! |
822 |
813 |
823 resize:aView origin:aPoint |
814 resize:aView origin:aPoint |
824 |delta| |
815 |delta| |
825 |
816 |
826 delta := aPoint - aView computeOrigin. |
817 delta := aPoint - aView computeOrigin. |
827 |
818 |
828 undoHistory disabledTransitionDo:[ |
819 undoHistory disabledTransitionDo:[ |
829 self shifLayout:aView top:(delta y) bottom:0 left:(delta x) right:0 |
820 self shiftLayout:aView top:(delta y) bottom:0 left:(delta x) right:0 |
830 ] |
821 ] |
831 |
822 |
832 ! |
823 ! |
833 |
824 |
834 resize:aView right:aPoint |
825 resize:aView right:aPoint |
835 |
826 |
836 undoHistory disabledTransitionDo:[ |
827 undoHistory disabledTransitionDo:[ |
837 self shifLayout:aView left:0 right:((aPoint x) - (aView computeCorner x)) |
828 self shiftLayout:aView left:0 right:((aPoint x) - (aView computeCorner x)) |
838 ] |
829 ] |
839 ! |
830 ! |
840 |
831 |
841 resize:aView top:aPoint |
832 resize:aView top:aPoint |
842 |
833 |
843 undoHistory disabledTransitionDo:[ |
834 undoHistory disabledTransitionDo:[ |
844 self shifLayout:aView top:((aPoint y) - (aView computeOrigin y)) bottom:0 |
835 self shiftLayout:aView top:((aPoint y) - (aView computeOrigin y)) bottom:0 |
845 ] |
836 ] |
846 ! |
837 ! |
847 |
838 |
848 resize:aView topRight:aPoint |
839 resize:aView topRight:aPoint |
849 |
840 |
850 undoHistory disabledTransitionDo:[ |
841 undoHistory disabledTransitionDo:[ |
851 self shifLayout:aView top:((aPoint y) - (aView computeOrigin y)) |
842 self shiftLayout:aView top:((aPoint y) - (aView computeOrigin y)) |
852 bottom:0 |
843 bottom:0 |
853 left:0 |
844 left:0 |
854 right:((aPoint x) - (aView computeCorner x)) |
845 right:((aPoint x) - (aView computeCorner x)) |
855 |
846 |
856 ] |
847 ] |
857 |
848 |
858 ! ! |
849 ! ! |
859 |
850 |
860 !UIObjectView methodsFor:'private shift-layout'! |
851 !UIObjectView methodsFor:'private shift-layout'! |
861 |
852 |
862 shifLayout:aView left:l right:r |
853 shiftLayout:aView left:l right:r |
863 "shift layout for a view; in case of an open transaction, the undo |
854 "shift layout for a view; in case of an open transaction, the undo |
864 action is registered |
855 action is registered |
865 " |
856 " |
866 self shifLayout:aView top:0 bottom:0 left:l right:r |
857 self shiftLayout:aView top:0 bottom:0 left:l right:r |
867 |
858 |
868 ! |
859 ! |
869 |
860 |
870 shifLayout:aView top:t bottom:b |
861 shiftLayout:aView top:t bottom:b |
871 "shift layout for a view; in case of an open transaction, the undo |
862 "shift layout for a view; in case of an open transaction, the undo |
872 action is registered |
863 action is registered |
873 " |
864 " |
874 self shifLayout:aView top:t bottom:b left:0 right:0 |
865 self shiftLayout:aView top:t bottom:b left:0 right:0 |
875 |
866 |
876 |
867 |
877 ! |
868 ! |
878 |
869 |
879 shifLayout:aView top:t bottom:b left:l right:r |
870 shiftLayout:aView top:t bottom:b left:l right:r |
880 "shift layout for a view; in case of an open transaction, the undo |
871 "shift layout for a view; in case of an open transaction, the undo |
881 action is registered |
872 action is registered |
882 " |
873 " |
883 |layout| |
874 |layout| |
884 |
875 |
885 self undoBlockPositionChanged:aView. |
|
886 |
|
887 layout := aView geometryLayout. |
876 layout := aView geometryLayout. |
888 |
877 |
889 layout leftOffset:(layout leftOffset + l) |
878 layout isLayout ifTrue:[ |
890 topOffset:(layout topOffset + t). |
879 self undoBlockPositionChanged:aView. |
891 |
880 |
892 layout isLayoutFrame ifTrue:[ |
881 layout leftOffset:(layout leftOffset + l) |
893 layout bottomOffset:(layout bottomOffset + b). |
882 topOffset:(layout topOffset + t). |
894 layout rightOffset:(layout rightOffset + r). |
883 |
895 ]. |
884 layout isLayoutFrame ifTrue:[ |
896 |
885 layout bottomOffset:(layout bottomOffset + b). |
897 aView geometryLayout:layout. |
886 layout rightOffset:(layout rightOffset + r). |
898 |
887 ]. |
888 aView geometryLayout:layout. |
|
889 ] ifFalse:[ |
|
890 |pixelOrigin| |
|
891 |
|
892 self undoBlockPositionChanged:aView. |
|
893 |
|
894 pixelOrigin := aView pixelOrigin. |
|
895 pixelOrigin := pixelOrigin + (l@t). |
|
896 aView pixelOrigin:pixelOrigin |
|
897 ] |
|
899 |
898 |
900 |
899 |
901 ! ! |
900 ! ! |
902 |
901 |
903 !UIObjectView methodsFor:'searching'! |
902 !UIObjectView methodsFor:'searching'! |
928 ! |
927 ! |
929 |
928 |
930 isPoint:aPoint containedIn:aView |
929 isPoint:aPoint containedIn:aView |
931 "checks whether a point is covered by a view. |
930 "checks whether a point is covered by a view. |
932 " |
931 " |
933 |org ext| |
932 |p| |
934 |
933 |
935 org := aView computeOrigin. |
934 p := device translatePoint:aPoint from:inputView id to:aView id. |
936 ext := aView computeExtent. |
935 |
937 |
936 (p x >= 0 and:[p y >= 0]) ifTrue:[ |
938 ^ ((org extent:ext) containsPoint:aPoint) |
937 p := aView extent - p. |
938 |
|
939 (p x >= 0 and:[p y >= 0]) ifTrue:[ |
|
940 ^ true |
|
941 ] |
|
942 ]. |
|
943 ^ false |
|
939 ! |
944 ! |
940 |
945 |
941 whichBorderOf:aView isHitBy:aPoint |
946 whichBorderOf:aView isHitBy:aPoint |
942 |p r bw org| |
947 |p r bw org| |
943 |
948 |
964 ! ! |
969 ! ! |
965 |
970 |
966 !UIObjectView methodsFor:'selections'! |
971 !UIObjectView methodsFor:'selections'! |
967 |
972 |
968 addToSelection:something |
973 addToSelection:something |
969 (testMode or:[something == selection]) ifFalse:[ |
974 (self canSelect:something) ifTrue:[ |
970 super addToSelection:something. |
975 super addToSelection:something. |
971 self changed:#selection. |
976 self changed:#selection. |
972 ] |
977 ] |
973 ! |
978 ! |
974 |
979 |
976 self singleSelectionDo:[:aView | |
981 self singleSelectionDo:[:aView | |
977 aView inspect |
982 aView inspect |
978 ] |
983 ] |
979 ! |
984 ! |
980 |
985 |
986 numberOfSelections |
|
987 "return the number of selected entries" |
|
988 |
|
989 |sz| |
|
990 |
|
991 selection isNil ifTrue:[^ 0]. |
|
992 |
|
993 selection isCollection ifTrue:[^ selection size] |
|
994 ifFalse:[^ 1 ] |
|
995 ! |
|
996 |
|
981 removeFromSelection:something |
997 removeFromSelection:something |
982 super removeFromSelection:something. |
998 super removeFromSelection:something. |
983 self changed:#selection |
999 self changed:#selection |
984 |
1000 |
985 ! |
1001 ! |
986 |
1002 |
987 select:something |
1003 select:something |
988 (testMode or:[something == selection]) ifFalse:[ |
1004 (self canSelect:something) ifTrue:[ |
989 super select:something. |
1005 super select:something. |
990 self changed:#selection |
1006 self changed:#selection |
991 ] |
1007 ] |
992 |
1008 |
993 ! |
1009 ! |
994 |
1010 |
995 selection |
1011 selection |
996 ^ selection |
1012 ^ selection |
997 |
1013 |
998 |
1014 |
999 ! |
|
1000 |
|
1001 selectionFindMinimum:aOneArgBlock |
|
1002 "returns the minimum value from the block evaluated on each view |
|
1003 in the selection |
|
1004 " |
|
1005 |min val| |
|
1006 |
|
1007 self selectionDo:[:aView| |
|
1008 val := aOneArgBlock value:aView. |
|
1009 |
|
1010 min isNil ifTrue:[min := val] |
|
1011 ifFalse:[min := min min:val] |
|
1012 ]. |
|
1013 ^ min |
|
1014 ! |
1015 ! |
1015 |
1016 |
1016 selectionHiddenDo:aBlock |
1017 selectionHiddenDo:aBlock |
1017 "apply block to every object in selection" |
1018 "apply block to every object in selection" |
1018 |
1019 |
1029 ! |
1030 ! |
1030 |
1031 |
1031 singleSelection |
1032 singleSelection |
1032 "returns single selection or nil |
1033 "returns single selection or nil |
1033 " |
1034 " |
1034 (selection isKindOf:SimpleView) ifTrue:[^ selection] |
1035 selection isCollection ifFalse:[ |
1035 ifFalse:[^ nil] |
1036 ^ selection |
1037 ]. |
|
1038 selection size == 1 ifTrue:[ ^ selection at:1] |
|
1039 ifFalse:[ ^ nil]. |
|
1036 ! |
1040 ! |
1037 |
1041 |
1038 singleSelectionDo:aBlock |
1042 singleSelectionDo:aBlock |
1039 |
1043 |view| |
1040 self singleSelection notNil ifTrue:[ |
1044 |
1041 aBlock value:selection |
1045 (view := self singleSelection) notNil ifTrue:[ |
1046 aBlock value:view |
|
1042 ] |
1047 ] |
1043 ! |
1048 ! |
1044 |
1049 |
1045 unselect |
1050 unselect |
1046 selection notNil ifTrue:[ |
1051 selection notNil ifTrue:[ |
1075 ^ true |
1080 ^ true |
1076 |
1081 |
1077 |
1082 |
1078 ! |
1083 ! |
1079 |
1084 |
1085 canPaste:something |
|
1086 "returns true if something could be paste |
|
1087 " |
|
1088 something notNil ifTrue:[ |
|
1089 something isCollection ifTrue:[ |
|
1090 something notEmpty ifTrue:[ |
|
1091 ^ (something at:1) isKindOf:UISpecification |
|
1092 ] |
|
1093 ] ifFalse:[ |
|
1094 ^ something isKindOf:UISpecification |
|
1095 ] |
|
1096 ]. |
|
1097 ^ false |
|
1098 |
|
1099 ! |
|
1100 |
|
1101 canSelect:something |
|
1102 ^ (testMode not and:[something ~~ selection]) |
|
1103 |
|
1104 ! |
|
1105 |
|
1106 hasUndos |
|
1107 "returns true if undoHistory not empty |
|
1108 " |
|
1109 ^ undoHistory notEmpty |
|
1110 ! |
|
1111 |
|
1080 isHorizontalResizable:aComponent |
1112 isHorizontalResizable:aComponent |
1081 ^ self subclassResponsibility |
1113 ^ self subclassResponsibility |
1082 |
1114 |
1083 |
1115 |
1084 ! |
1116 ! |
1148 |
1180 |
1149 undoHistory isTransactionOpen ifTrue:[ |
1181 undoHistory isTransactionOpen ifTrue:[ |
1150 |layout| |
1182 |layout| |
1151 |
1183 |
1152 layout := aView geometryLayout copy. |
1184 layout := aView geometryLayout copy. |
1153 undoHistory addUndoBlock:[aView geometryLayout:layout] |
1185 layout isNil ifFalse:[ |
1154 ] |
1186 undoHistory addUndoBlock:[aView geometryLayout:layout] |
1155 |
1187 ] ifTrue:[ |
1188 layout := aView pixelOrigin. |
|
1189 undoHistory addUndoBlock:[aView pixelOrigin:layout] |
|
1190 ] |
|
1191 ] |
|
1192 |
|
1193 ! |
|
1194 |
|
1195 undoDeleteAll |
|
1196 "delete total undo history |
|
1197 " |
|
1198 undoHistory reinitialize |
|
1156 ! |
1199 ! |
1157 |
1200 |
1158 undoLast |
1201 undoLast |
1159 self undoLast:1 |
1202 self undoLast:1 |
1160 ! |
1203 ! |
1169 ! ! |
1212 ! ! |
1170 |
1213 |
1171 !UIObjectView methodsFor:'user actions - dimension'! |
1214 !UIObjectView methodsFor:'user actions - dimension'! |
1172 |
1215 |
1173 copyExtent |
1216 copyExtent |
1174 (selection isNil or:[selection isKindOf:Collection]) ifTrue:[ |
1217 |object| |
1175 ^ self warn:'exactly one element must be selected'. |
1218 |
1176 ]. |
1219 object := self singleSelection. |
1177 copiedExtent := selection computeExtent |
1220 |
1221 object notNil ifTrue:[ |
|
1222 copiedExtent := object computeExtent |
|
1223 ] ifFalse:[ |
|
1224 self warn:'exactly one element must be selected'. |
|
1225 ] |
|
1178 |
1226 |
1179 |
1227 |
1180 |
1228 |
1181 ! |
1229 ! |
1182 |
1230 |
1262 ] |
1310 ] |
1263 ! ! |
1311 ! ! |
1264 |
1312 |
1265 !UIObjectView methodsFor:'user actions - move'! |
1313 !UIObjectView methodsFor:'user actions - move'! |
1266 |
1314 |
1267 basicMoveSelectionHorizontal:n |
1315 moveSelectionDown:aNumber |
1268 "move left: n < 0 |
1316 |gridY| |
1269 move right: n > 0 |
1317 |
1270 " |
1318 gridAlign notNil ifTrue:[ |
1319 gridY := gridAlign y. |
|
1320 ]. |
|
1321 |
|
1271 self selectionHiddenDo:[ |
1322 self selectionHiddenDo:[ |
1272 self transaction:#move selectionDo:[:v| self shifLayout:v left:n right:n]. |
1323 self transaction:#move selectionDo:[:aView| |
1324 |n d| |
|
1325 |
|
1326 n := aNumber. |
|
1327 |
|
1328 aligning ifTrue:[ |
|
1329 d := ((aView computeCorner y) \\ gridY). |
|
1330 n := n * gridY. |
|
1331 |
|
1332 d ~~ 0 ifTrue:[ |
|
1333 n := n - d + 1. |
|
1334 ] |
|
1335 ]. |
|
1336 self shiftLayout:aView top:n bottom:n |
|
1337 ]. |
|
1273 self changed:#layout |
1338 self changed:#layout |
1274 ] |
1339 ] |
1275 |
1340 |
1276 |
1341 |
1277 ! |
1342 ! |
1278 |
1343 |
1279 basicMoveSelectionVertical:n |
1344 moveSelectionLeft:aNumber |
1280 "move up: n < 0 |
1345 "move selection left |
1281 move down: n > 0 |
1346 " |
1282 " |
1347 |gridX| |
1348 |
|
1349 gridAlign notNil ifTrue:[ |
|
1350 gridX := gridAlign x. |
|
1351 ]. |
|
1352 |
|
1283 self selectionHiddenDo:[ |
1353 self selectionHiddenDo:[ |
1284 self transaction:#move selectionDo:[:v| self shifLayout:v top:n bottom:n ]. |
1354 self transaction:#move selectionDo:[:aView| |
1355 |n d| |
|
1356 |
|
1357 n := aNumber. |
|
1358 |
|
1359 aligning ifTrue:[ |
|
1360 d := ((aView computeOrigin x) \\ gridX). |
|
1361 d ~~ 0 ifTrue:[ |
|
1362 n := n-1. |
|
1363 ]. |
|
1364 n := (n * gridX) + d. |
|
1365 ]. |
|
1366 n := n negated. |
|
1367 self shiftLayout:aView left:n right:n |
|
1368 |
|
1369 ]. |
|
1285 self changed:#layout |
1370 self changed:#layout |
1286 ] |
1371 ] |
1287 |
1372 ! |
1288 |
1373 |
1289 |
1374 moveSelectionRight:aNumber |
1290 ! |
1375 "move selection right |
1291 |
1376 " |
1292 moveSelectionDown:n |
1377 |gridX| |
1293 self basicMoveSelectionVertical:n |
1378 |
1294 |
1379 gridAlign notNil ifTrue:[ |
1295 |
1380 gridX := gridAlign x. |
1296 ! |
1381 ]. |
1297 |
1382 |
1298 moveSelectionLeft:n |
1383 self selectionHiddenDo:[ |
1299 self basicMoveSelectionHorizontal:(n negated) |
1384 self transaction:#move selectionDo:[:aView| |
1300 |
1385 |n d| |
1301 |
1386 |
1302 ! |
1387 n := aNumber. |
1303 |
1388 |
1304 moveSelectionRight:n |
1389 aligning ifTrue:[ |
1305 self basicMoveSelectionHorizontal:n |
1390 d := ((aView computeCorner x) \\ gridX). |
1306 |
1391 n := n * gridX. |
1307 |
1392 |
1308 ! |
1393 d ~~ 0 ifTrue:[ |
1309 |
1394 n := n - d + 1. |
1310 moveSelectionUp:n |
1395 ] |
1311 self basicMoveSelectionVertical:(n negated) |
1396 ]. |
1397 self shiftLayout:aView left:n right:n |
|
1398 |
|
1399 ]. |
|
1400 self changed:#layout |
|
1401 ] |
|
1402 ! |
|
1403 |
|
1404 moveSelectionUp:aNumber |
|
1405 "move selection up |
|
1406 " |
|
1407 |gridY| |
|
1408 |
|
1409 gridAlign notNil ifTrue:[ |
|
1410 gridY := gridAlign y. |
|
1411 ]. |
|
1412 |
|
1413 self selectionHiddenDo:[ |
|
1414 self transaction:#move selectionDo:[:aView| |
|
1415 |n d| |
|
1416 |
|
1417 n := aNumber. |
|
1418 |
|
1419 aligning ifTrue:[ |
|
1420 d := ((aView computeOrigin x) \\ gridY). |
|
1421 d ~~ 0 ifTrue:[ |
|
1422 n := n-1. |
|
1423 ]. |
|
1424 n := (n * gridY) + d. |
|
1425 ]. |
|
1426 n := n negated. |
|
1427 self shiftLayout:aView top:n bottom:n |
|
1428 ]. |
|
1429 self changed:#layout |
|
1430 ] |
|
1312 |
1431 |
1313 |
1432 |
1314 ! ! |
1433 ! ! |
1315 |
1434 |
1316 !UIObjectView methodsFor:'user actions - position'! |
1435 !UIObjectView methodsFor:'user actions - position'! |
1317 |
1436 |
1318 alignSelectionBottom |
1437 alignSelectionBottom |
1319 |bmost delta| |
1438 |bmost delta layout| |
1320 |
1439 |
1321 self selectionHiddenDo:[ |
1440 selection notNil ifTrue:[ |
1322 bmost := 0. |
1441 self selectionHiddenDo:[ |
1323 self selectionDo:[:v| bmost := bmost max:(v computeCorner y)]. |
1442 self numberOfSelections > 1 ifTrue:[ |
1324 |
1443 bmost := (selection at:1) computeCorner y. |
1325 self transaction:#align selectionDo:[:v| |
1444 |
1326 (delta := bmost - (v computeCorner y)) ~~ 0 ifTrue:[ |
1445 self transaction:#align selectionDo:[:v| |
1327 self shifLayout:v top:delta bottom:delta. |
1446 (delta := bmost - (v computeCorner y)) ~~ 0 ifTrue:[ |
1447 self shiftLayout:v top:delta bottom:delta. |
|
1448 ] |
|
1449 ] |
|
1450 ] ifFalse:[ |
|
1451 layout := selection geometryLayout. |
|
1452 |
|
1453 (layout isLayout and:[layout isLayoutFrame]) ifFalse:[ |
|
1454 ^ self |
|
1455 ]. |
|
1456 |
|
1457 self transaction:#layout selectionDo:[:aView| |
|
1458 self undoBlockDimensionChanged:aView. |
|
1459 layout := aView geometryLayout. |
|
1460 layout bottomOffset:0. |
|
1461 layout bottomFraction:1.0. |
|
1462 aView geometryLayout:layout. |
|
1463 ] |
|
1328 ] |
1464 ] |
1329 ]. |
1465 ]. |
1330 self changed:#layout |
1466 self changed:#layout |
1331 ] |
1467 ] |
1332 |
1468 |
1333 |
1469 |
1334 |
1470 |
1335 ! |
1471 ! |
1336 |
1472 |
1337 alignSelectionCenterHor |
1473 alignSelectionCenterHor |
1338 |counter centerX| |
1474 |view center| |
1339 |
1475 |
1340 self selectionHiddenDo:[ |
1476 selection notNil ifTrue:[ |
1341 counter := 0. |
1477 self selectionHiddenDo:[ |
1342 centerX := 0. |
1478 view := self singleSelection. |
1343 |
1479 |
1344 self selectionDo:[:v | |
1480 view notNil ifTrue:[ |
1345 centerX := centerX + (v computeCorner x + v computeOrigin x). |
1481 view := view superView. |
1346 counter := counter + 1. |
1482 center := view computeExtent |
1347 ]. |
1483 ] ifFalse:[ |
1348 centerX := centerX // (counter * 2). |
1484 view := selection at:1. |
1349 |
1485 center := view computeCorner + view computeOrigin. |
1350 self transaction:#align selectionDo:[:v| |
1486 ]. |
1351 |newX oldX delta| |
1487 center := center x // 2. |
1352 |
1488 |
1353 oldX := v computeOrigin x. |
1489 self transaction:#align selectionDo:[:v| |
1354 newX := centerX - ((v computeCorner x - oldX) // 2). |
1490 |newX oldX delta| |
1355 delta := newX - oldX. |
1491 |
1356 |
1492 oldX := v computeOrigin x. |
1357 self shifLayout:v left:delta right:delta |
1493 newX := center - ((v computeCorner x - oldX) // 2). |
1494 delta := newX - oldX. |
|
1495 |
|
1496 self shiftLayout:v left:delta right:delta |
|
1497 ]. |
|
1498 self changed:#layout |
|
1499 ] |
|
1500 ] |
|
1501 |
|
1502 |
|
1503 |
|
1504 ! |
|
1505 |
|
1506 alignSelectionCenterVer |
|
1507 |view center| |
|
1508 |
|
1509 selection notNil ifTrue:[ |
|
1510 self selectionHiddenDo:[ |
|
1511 view := self singleSelection. |
|
1512 |
|
1513 view notNil ifTrue:[ |
|
1514 view := view superView. |
|
1515 center := view computeExtent |
|
1516 ] ifFalse:[ |
|
1517 view := selection at:1. |
|
1518 center := view computeCorner + view computeOrigin. |
|
1519 ]. |
|
1520 center := center y // 2. |
|
1521 |
|
1522 self transaction:#align selectionDo:[:v| |
|
1523 |newY oldY delta| |
|
1524 |
|
1525 oldY := v computeOrigin y. |
|
1526 newY := center - ((v computeCorner y - oldY) // 2). |
|
1527 delta := newY - oldY. |
|
1528 |
|
1529 self shiftLayout:v top:delta bottom:delta |
|
1530 ]. |
|
1531 self changed:#layout |
|
1532 ] |
|
1533 ] |
|
1534 ! |
|
1535 |
|
1536 alignSelectionLeft |
|
1537 |lmost delta layout| |
|
1538 |
|
1539 selection notNil ifTrue:[ |
|
1540 self selectionHiddenDo:[ |
|
1541 self numberOfSelections > 1 ifTrue:[ |
|
1542 lmost := (selection at:1) computeOrigin x. |
|
1543 |
|
1544 self transaction:#align selectionDo:[:v| |
|
1545 (delta := lmost - (v computeOrigin x)) ~~ 0 ifTrue:[ |
|
1546 self shiftLayout:v left:delta right:delta |
|
1547 ] |
|
1548 ] |
|
1549 ] ifFalse:[ |
|
1550 self transaction:#layout selectionDo:[:aView| |
|
1551 layout := aView geometryLayout. |
|
1552 |
|
1553 layout isLayout ifTrue:[ |
|
1554 self undoBlockDimensionChanged:aView. |
|
1555 layout leftOffset:0. |
|
1556 layout leftFraction:0.0. |
|
1557 aView geometryLayout:layout. |
|
1558 ] |
|
1559 ] |
|
1560 ] |
|
1358 ]. |
1561 ]. |
1359 self changed:#layout |
1562 self changed:#layout |
1360 ] |
1563 ] |
1361 |
1564 ! |
1362 |
1565 |
1363 |
1566 alignSelectionLeftAndRight |
1364 ! |
1567 |lmost rmost layout| |
1365 |
1568 |
1366 alignSelectionCenterVer |
1569 selection notNil ifTrue:[ |
1367 |counter centerY| |
1570 self selectionHiddenDo:[ |
1368 |
1571 self numberOfSelections > 1 ifTrue:[ |
1369 self selectionHiddenDo:[ |
1572 lmost := (selection at:1) computeOrigin x. |
1370 counter := 0. |
1573 rmost := (selection at:1) computeCorner x. |
1371 centerY := 0. |
1574 |
1372 |
1575 self transaction:#align selectionDo:[:v| |
1373 self selectionDo:[:v | |
1576 self shiftLayout:v left:(lmost - (v computeOrigin x)) |
1374 centerY := centerY + (v computeCorner y + v computeOrigin y). |
1577 right:(rmost - (v computeCorner x)) |
1375 counter := counter + 1. |
1578 ] |
1376 ]. |
1579 ] ifFalse:[ |
1377 centerY := centerY // (counter * 2). |
1580 self transaction:#layout selectionDo:[:aView| |
1378 |
1581 layout := aView geometryLayout. |
1379 self transaction:#align selectionDo:[:v| |
1582 |
1380 |newY oldY delta| |
1583 layout isLayout ifTrue:[ |
1381 |
1584 self undoBlockDimensionChanged:aView. |
1382 oldY := v computeOrigin y. |
1585 layout leftOffset:0. |
1383 newY := centerY - ((v computeCorner y - oldY) // 2). |
1586 layout leftFraction:0.0. |
1384 delta := newY - oldY. |
1587 |
1385 |
1588 (layout isLayout and:[layout isLayoutFrame]) ifTrue:[ |
1386 self shifLayout:v top:delta bottom:delta |
1589 layout rightOffset:0. |
1590 layout rightFraction:1.0. |
|
1591 ]. |
|
1592 aView geometryLayout:layout. |
|
1593 ] |
|
1594 ] |
|
1595 ] |
|
1387 ]. |
1596 ]. |
1388 self changed:#layout |
1597 self changed:#layout |
1389 ] |
1598 ] |
1390 ! |
1599 ! |
1391 |
1600 |
1392 alignSelectionLeft |
1601 alignSelectionRight |
1393 |lmost delta| |
1602 |rmost delta layout| |
1394 |
1603 |
1395 self selectionHiddenDo:[ |
1604 selection notNil ifTrue:[ |
1396 lmost := self selectionFindMinimum:[:v| v computeOrigin x]. |
1605 self selectionHiddenDo:[ |
1397 |
1606 self numberOfSelections > 1 ifTrue:[ |
1398 self transaction:#align selectionDo:[:v| |
1607 rmost := (selection at:1) computeCorner x. |
1399 (delta := lmost - (v computeOrigin x)) ~~ 0 ifTrue:[ |
1608 |
1400 self shifLayout:v left:delta right:delta |
1609 self transaction:#align selectionDo:[:v| |
1610 (delta := rmost - (v computeCorner x)) ~~ 0 ifTrue:[ |
|
1611 self shiftLayout:v left:delta right:delta |
|
1612 ] |
|
1613 ] |
|
1614 ] ifFalse:[ |
|
1615 layout := selection geometryLayout. |
|
1616 |
|
1617 (layout isLayout and:[layout isLayoutFrame]) ifFalse:[ |
|
1618 ^ self |
|
1619 ]. |
|
1620 |
|
1621 self transaction:#layout selectionDo:[:aView| |
|
1622 self undoBlockDimensionChanged:aView. |
|
1623 layout := aView geometryLayout. |
|
1624 layout rightOffset:0. |
|
1625 layout rightFraction:1.0. |
|
1626 aView geometryLayout:layout. |
|
1627 ] |
|
1401 ] |
1628 ] |
1402 ]. |
1629 ]. |
1403 self changed:#layout |
1630 self changed:#layout |
1404 ] |
1631 ] |
1405 |
1632 ! |
1406 ! |
1633 |
1407 |
1634 alignSelectionTop |
1408 alignSelectionLeftAndRight |
1635 |tmost delta layout| |
1409 |lmost rmost| |
1636 |
1410 |
1637 selection notNil ifTrue:[ |
1411 self selectionHiddenDo:[ |
1638 self selectionHiddenDo:[ |
1412 lmost := self selectionFindMinimum:[:v| v computeOrigin x]. |
1639 self numberOfSelections > 1 ifTrue:[ |
1413 rmost := 0. |
1640 tmost := (selection at:1) computeOrigin y. |
1414 self selectionDo:[:v | rmost := rmost max:(v computeCorner x)]. |
1641 |
1415 |
1642 self transaction:#align selectionDo:[:v| |
1416 self transaction:#align selectionDo:[:v| |
1643 (delta := tmost - (v computeOrigin y)) ~~ 0 ifTrue:[ |
1417 self shifLayout:v left:(lmost - (v computeOrigin x)) |
1644 self shiftLayout:v top:delta bottom:delta |
1418 right:(rmost - (v computeCorner x)) |
1645 ] |
1646 ] |
|
1647 ] ifFalse:[ |
|
1648 self transaction:#layout selectionDo:[:aView| |
|
1649 layout := aView geometryLayout. |
|
1650 |
|
1651 layout isLayout ifTrue:[ |
|
1652 self undoBlockDimensionChanged:aView. |
|
1653 layout topOffset:0. |
|
1654 layout topFraction:0.0. |
|
1655 aView geometryLayout:layout. |
|
1656 ] |
|
1657 ] |
|
1658 ] |
|
1419 ]. |
1659 ]. |
1420 self changed:#layout |
1660 self changed:#layout |
1421 ] |
1661 ] |
1422 ! |
1662 |
1423 |
1663 ! |
1424 alignSelectionRight |
1664 |
1425 |rmost delta| |
1665 alignSelectionTopAndBottom |
1426 |
1666 |tmost bmost layout| |
1427 self selectionHiddenDo:[ |
1667 |
1428 rmost := 0. |
1668 selection notNil ifTrue:[ |
1429 self selectionDo:[:v| rmost := rmost max:(v computeCorner x)]. |
1669 self selectionHiddenDo:[ |
1430 |
1670 self numberOfSelections > 1 ifTrue:[ |
1431 self transaction:#align selectionDo:[:v| |
1671 tmost := (selection at:1) computeOrigin y. |
1432 (delta := rmost - (v computeCorner x)) ~~ 0 ifTrue:[ |
1672 bmost := (selection at:1) computeCorner y. |
1433 self shifLayout:v left:delta right:delta |
1673 |
1674 self transaction:#align selectionDo:[:v| |
|
1675 self shiftLayout:v top:(tmost - (v computeOrigin y)) |
|
1676 bottom:(bmost - (v computeCorner y)) |
|
1677 ] |
|
1678 ] ifFalse:[ |
|
1679 self transaction:#layout selectionDo:[:aView| |
|
1680 layout := aView geometryLayout. |
|
1681 |
|
1682 layout isLayout ifTrue:[ |
|
1683 self undoBlockDimensionChanged:aView. |
|
1684 layout topOffset:0. |
|
1685 layout topFraction:0.0. |
|
1686 |
|
1687 (layout isLayout and:[layout isLayoutFrame]) ifTrue:[ |
|
1688 layout bottomOffset:0. |
|
1689 layout bottomFraction:1.0. |
|
1690 ]. |
|
1691 aView geometryLayout:layout. |
|
1692 ] |
|
1693 ] |
|
1434 ] |
1694 ] |
1435 ]. |
|
1436 self changed:#layout |
|
1437 ] |
|
1438 |
|
1439 ! |
|
1440 |
|
1441 alignSelectionTop |
|
1442 |tmost delta| |
|
1443 |
|
1444 self selectionHiddenDo:[ |
|
1445 tmost := self selectionFindMinimum:[:v| v computeOrigin y]. |
|
1446 |
|
1447 self transaction:#align selectionDo:[:v| |
|
1448 (delta := tmost - (v computeOrigin y)) ~~ 0 ifTrue:[ |
|
1449 self shifLayout:v top:delta bottom:delta |
|
1450 ] |
|
1451 ]. |
|
1452 self changed:#layout |
|
1453 ] |
|
1454 |
|
1455 ! |
|
1456 |
|
1457 alignSelectionTopAndBottom |
|
1458 |tmost bmost| |
|
1459 |
|
1460 self selectionHiddenDo:[ |
|
1461 tmost := self selectionFindMinimum:[:v| v computeOrigin y]. |
|
1462 bmost := 0. |
|
1463 self selectionDo:[:v| bmost := bmost max:(v computeCorner y)]. |
|
1464 |
|
1465 self transaction:#align selectionDo:[:v| |
|
1466 self shifLayout:v top:(tmost - (v computeOrigin y)) |
|
1467 bottom:(bmost - (v computeCorner y)) |
|
1468 ]. |
1695 ]. |
1469 self changed:#layout |
1696 self changed:#layout |
1470 ] |
1697 ] |
1471 ! |
1698 ! |
1472 |
1699 |
1502 max == min ifFalse:[ |
1729 max == min ifFalse:[ |
1503 delta := max - min. |
1730 delta := max - min. |
1504 |
1731 |
1505 self transaction:#center selectionDo:[:v| |
1732 self transaction:#center selectionDo:[:v| |
1506 orientation == #y ifTrue:[ |
1733 orientation == #y ifTrue:[ |
1507 self shifLayout:v top:delta bottom:delta |
1734 self shiftLayout:v top:delta bottom:delta |
1508 ] ifFalse:[ |
1735 ] ifFalse:[ |
1509 self shifLayout:v left:delta right:delta |
1736 self shiftLayout:v left:delta right:delta |
1510 ] |
1737 ] |
1511 ]. |
1738 ]. |
1512 self changed:#layout |
1739 self changed:#layout |
1513 ] |
1740 ] |
1514 ] |
1741 ] |
1531 ! |
1758 ! |
1532 |
1759 |
1533 spreadSelectionHor |
1760 spreadSelectionHor |
1534 |sumWidths min max viewsInOrder topsInOrder count space| |
1761 |sumWidths min max viewsInOrder topsInOrder count space| |
1535 |
1762 |
1536 (selection isKindOf:Collection) ifFalse:[^ self]. |
1763 (self numberOfSelections > 1) ifFalse:[ |
1764 ^ self |
|
1765 ]. |
|
1537 |
1766 |
1538 self selectionHiddenDo:[ |
1767 self selectionHiddenDo:[ |
1539 count := 0. |
1768 count := 0. |
1540 sumWidths := 0. |
1769 sumWidths := 0. |
1541 max := 0. |
1770 max := 0. |
1557 |
1786 |
1558 self transaction:#spread objects:viewsInOrder do:[:aView| |
1787 self transaction:#spread objects:viewsInOrder do:[:aView| |
1559 |delta| |
1788 |delta| |
1560 |
1789 |
1561 delta := min - aView computeOrigin x. |
1790 delta := min - aView computeOrigin x. |
1562 self shifLayout:aView left:delta right:delta. |
1791 self shiftLayout:aView left:delta right:delta. |
1563 min := min + aView computeExtent x + space |
1792 min := min + aView computeExtent x + space |
1564 ]. |
1793 ]. |
1565 self changed:#layout |
1794 self changed:#layout |
1566 ] |
1795 ] |
1567 |
1796 |
1568 ! |
1797 ! |
1569 |
1798 |
1570 spreadSelectionVer |
1799 spreadSelectionVer |
1571 |sumHeights min max viewsInOrder topsInOrder count space| |
1800 |sumHeights min max viewsInOrder topsInOrder count space| |
1572 |
1801 |
1573 (selection isKindOf:Collection) ifFalse:[^ self]. |
1802 (self numberOfSelections > 1) ifFalse:[ |
1803 ^ self |
|
1804 ]. |
|
1574 |
1805 |
1575 self selectionHiddenDo:[ |
1806 self selectionHiddenDo:[ |
1576 count := 0. |
1807 count := 0. |
1577 sumHeights := 0. |
1808 sumHeights := 0. |
1578 max := 0. |
1809 max := 0. |
1594 |
1825 |
1595 self transaction:#spread objects:viewsInOrder do:[:aView| |
1826 self transaction:#spread objects:viewsInOrder do:[:aView| |
1596 |delta| |
1827 |delta| |
1597 |
1828 |
1598 delta := min - aView computeOrigin y. |
1829 delta := min - aView computeOrigin y. |
1599 self shifLayout:aView top:delta bottom:delta. |
1830 self shiftLayout:aView top:delta bottom:delta. |
1600 min := min + aView height + space |
1831 min := min + aView height + space |
1601 ]. |
1832 ]. |
1602 self changed:#layout |
1833 self changed:#layout |
1603 ] |
1834 ] |
1604 ! ! |
1835 ! ! |