72 subclasses (where it belongs) and give a better encapsulation and |
72 subclasses (where it belongs) and give a better encapsulation and |
73 overall structure. Do not take this as an example for good style ;-) |
73 overall structure. Do not take this as an example for good style ;-) |
74 " |
74 " |
75 ! ! |
75 ! ! |
76 |
76 |
|
77 !ChangesBrowser class methodsFor:'instance creation'! |
|
78 |
|
79 new |
|
80 "create a new changes browser" |
|
81 |
|
82 ^ super label:'Changes Browser' |
|
83 icon:(Form fromFile:'CBrowser.xbm' resolution:100) |
|
84 ! |
|
85 |
|
86 openOn:aFileName |
|
87 "create c changes browser on a change file" |
|
88 |
|
89 ^ ((self new label:'Changes Browser: ', aFileName) changeFileName:aFileName) open |
|
90 ! ! |
|
91 |
|
92 !ChangesBrowser class methodsFor:'behavior'! |
|
93 |
|
94 autoSelectNext |
|
95 "returning true here, makes a Delete operation automatically |
|
96 select the next change" |
|
97 |
|
98 ^ true |
|
99 ! ! |
|
100 |
77 !ChangesBrowser class methodsFor:'defaults'! |
101 !ChangesBrowser class methodsFor:'defaults'! |
78 |
102 |
79 defaultLabel |
103 defaultLabel |
80 ^ 'Changes Browser' |
104 ^ 'Changes Browser' |
81 ! ! |
105 ! ! |
82 |
106 |
83 !ChangesBrowser class methodsFor:'instance creation'! |
|
84 |
|
85 new |
|
86 "create a new changes browser" |
|
87 |
|
88 ^ super label:'Changes Browser' |
|
89 icon:(Form fromFile:'CBrowser.xbm' resolution:100) |
|
90 ! |
|
91 |
|
92 openOn:aFileName |
|
93 "create c changes browser on a change file" |
|
94 |
|
95 ^ ((self new label:'Changes Browser: ', aFileName) changeFileName:aFileName) open |
|
96 ! ! |
|
97 |
|
98 !ChangesBrowser class methodsFor:'behavior'! |
|
99 |
|
100 autoSelectNext |
|
101 "returning true here, makes a Delete operation automatically |
|
102 select the next change" |
|
103 |
|
104 ^ true |
|
105 ! ! |
|
106 |
|
107 !ChangesBrowser methodsFor:'menu stuff'! |
|
108 |
|
109 disableMenuEntries |
|
110 "enable all entries refering to a selected change" |
|
111 |
|
112 #(doApply doApplyClassRest doApplyRest doDelete doDeleteRest doDeleteClassRest |
|
113 doDeleteClassAll doCompare doMakePatch doSaveChangeInFile doMakePermanent |
|
114 doSave doSaveRest doSaveClassAll doSaveClassRest doBrowse) |
|
115 do:[:sel | |
|
116 changeListView middleButtonMenu disable:sel |
|
117 ]. |
|
118 ! |
|
119 |
|
120 enableMenuEntries |
|
121 "enable all entries refering to a selected change" |
|
122 |
|
123 #(doApply doApplyClassRest doApplyRest |
|
124 doDelete doDeleteRest doDeleteClassRest |
|
125 doDeleteClassAll |
|
126 doCompare doMakePatch doSaveChangeInFile doMakePermanent |
|
127 doSave doSaveRest doSaveClassAll doSaveClassRest doBrowse) |
|
128 do:[:sel | |
|
129 changeListView middleButtonMenu enable:sel |
|
130 ]. |
|
131 ! ! |
|
132 |
|
133 !ChangesBrowser methodsFor:'private'! |
107 !ChangesBrowser methodsFor:'private'! |
134 |
|
135 clearCodeView |
|
136 self unselect "changeListView deselect". |
|
137 codeView contents:nil. |
|
138 changeNrShown := nil |
|
139 ! |
|
140 |
|
141 unselect |
|
142 "common unselect" |
|
143 |
|
144 changeListView deselect. |
|
145 self disableMenuEntries |
|
146 ! |
|
147 |
108 |
148 streamForChange:changeNr |
109 streamForChange:changeNr |
149 "answer a stream for change" |
110 "answer a stream for change" |
150 |
111 |
151 |aStream| |
112 |aStream| |
482 ] |
474 ] |
483 ]. |
475 ]. |
484 ^ s |
476 ^ s |
485 ! |
477 ! |
486 |
478 |
487 autoSelect:changeNr |
479 silentDeleteChange:changeNr |
488 "select a change" |
480 "delete a change do not update changeListView" |
489 |
481 |
490 self class autoSelectNext ifTrue:[ |
482 anyChanges := true. |
491 (changeNr <= changePositions size) ifTrue:[ |
483 changeChunks removeIndex:changeNr. |
492 changeListView selection:changeNr. |
484 changePositions removeIndex:changeNr. |
493 self changeSelection:changeNr. |
485 changeClassNames removeIndex:changeNr. |
494 ^ self |
486 changeHeaderLines removeIndex:changeNr |
495 ] |
|
496 ]. |
|
497 self clearCodeView. |
|
498 changeListView selection:nil. |
|
499 self disableMenuEntries |
|
500 ! |
|
501 |
|
502 autoSelectOrEnd:changeNr |
|
503 "select the next change or the last" |
|
504 |
|
505 |last| |
|
506 |
|
507 last := changePositions size. |
|
508 changeNr < last ifTrue:[ |
|
509 self autoSelect:changeNr |
|
510 ] ifFalse:[ |
|
511 changeListView selection:last . |
|
512 self changeSelection:last. |
|
513 ] |
|
514 ! |
|
515 |
|
516 autoSelectLast |
|
517 "select the last change" |
|
518 |
|
519 self autoSelect:(changePositions size) |
|
520 ! |
487 ! |
521 |
488 |
522 classNameOfChange:changeNr |
489 classNameOfChange:changeNr |
523 "return the classname of a change (for xxx class - changes xxx is returned) |
490 "return the classname of a change (for xxx class - changes xxx is returned) |
524 - since parsing ascii methods is slow, keep result cached in |
491 - since parsing ascii methods is slow, keep result cached in |
639 ^ name |
607 ^ name |
640 ] |
608 ] |
641 ] |
609 ] |
642 ]. |
610 ]. |
643 ^ nil |
611 ^ nil |
|
612 ! |
|
613 |
|
614 autoSelectOrEnd:changeNr |
|
615 "select the next change or the last" |
|
616 |
|
617 |last| |
|
618 |
|
619 last := changePositions size. |
|
620 changeNr < last ifTrue:[ |
|
621 self autoSelect:changeNr |
|
622 ] ifFalse:[ |
|
623 changeListView selection:last . |
|
624 self changeSelection:last. |
|
625 ] |
|
626 ! |
|
627 |
|
628 withSelectedChangeDo:aBlock |
|
629 "just a helper, check for a selected change and evaluate aBlock |
|
630 with busy cursor" |
|
631 |
|
632 |changeNr| |
|
633 |
|
634 changeNr := changeListView selection. |
|
635 changeNr notNil ifTrue:[ |
|
636 self withCursor:(Cursor execute) do:[ |
|
637 aBlock value:changeNr |
|
638 ] |
|
639 ] |
|
640 ! |
|
641 |
|
642 autoSelectLast |
|
643 "select the last change" |
|
644 |
|
645 self autoSelect:(changePositions size) |
|
646 ! |
|
647 |
|
648 compareChange:changeNr |
|
649 "compare a change with current version" |
|
650 |
|
651 |aStream chunk sawExcla parseTree thisClass cat oldSource newSource |
|
652 parser sel oldMethod outcome showDiff d t1 t2| |
|
653 |
|
654 aStream := self streamForChange:changeNr. |
|
655 aStream isNil ifTrue:[^ self]. |
|
656 |
|
657 sawExcla := aStream peekFor:(aStream class chunkSeparator). |
|
658 chunk := aStream nextChunk. |
|
659 sawExcla ifFalse:[ |
|
660 outcome := 'not comparable ...' |
|
661 ] ifTrue:[ |
|
662 parseTree := Parser parseExpression:chunk. |
|
663 (parseTree notNil and:[parseTree isMessage]) ifTrue:[ |
|
664 (parseTree selector == #methodsFor:) ifTrue:[ |
|
665 thisClass := (parseTree receiver evaluate). |
|
666 thisClass isBehavior ifTrue:[ |
|
667 showDiff := false. |
|
668 |
|
669 cat := parseTree arg1 evaluate. |
|
670 newSource := aStream nextChunk. |
|
671 parser := Parser parseMethod:newSource in:thisClass. |
|
672 (parser notNil and:[parser ~~ #Error]) ifTrue:[ |
|
673 sel := parser selector. |
|
674 oldMethod := thisClass compiledMethodAt:sel. |
|
675 oldMethod notNil ifTrue:[ |
|
676 (oldMethod category = cat) ifFalse:[ |
|
677 Transcript showCr:'category changed.'. |
|
678 ]. |
|
679 oldSource := oldMethod source. |
|
680 (oldSource = newSource) ifTrue:[ |
|
681 outcome := 'same source' |
|
682 ] ifFalse:[ |
|
683 "/ |
|
684 "/ compare for tabulator <-> space changes |
|
685 "/ before showing diff ... |
|
686 "/ |
|
687 t1 := oldSource asString withTabsExpanded. |
|
688 t2 := newSource asString withTabsExpanded. |
|
689 t1 = t2 ifTrue:[ |
|
690 outcome := 'same source (tabs <-> spaces)' |
|
691 ] ifFalse:[ |
|
692 outcome := 'source changed.'. |
|
693 showDiff := true |
|
694 ] |
|
695 ] |
|
696 ] ifFalse:[ |
|
697 outcome := 'method does not exist.' |
|
698 ] |
|
699 ] ifFalse:[ |
|
700 outcome := 'change unparsable.' |
|
701 ]. |
|
702 (showDiff and:[oldSource notNil and:[newSource notNil]]) ifTrue:[ |
|
703 d := DiffTextView openOn:oldSource and:newSource. |
|
704 d label:'differences (current left; change right)'. |
|
705 ] |
|
706 ] ifFalse:[ |
|
707 outcome := 'class does not exist.' |
|
708 ] |
|
709 ] ifFalse:[ |
|
710 outcome := 'not comparable.' |
|
711 ] |
|
712 ] ifFalse:[ |
|
713 outcome := 'not comparable.' |
|
714 ] |
|
715 ]. |
|
716 Transcript showCr:outcome. |
|
717 aStream close. |
644 ! |
718 ! |
645 |
719 |
646 writeBackChanges |
720 writeBackChanges |
647 "write back the changes file" |
721 "write back the changes file" |
648 |
722 |
708 self silentDeleteChange:changeNr. |
782 self silentDeleteChange:changeNr. |
709 self setChangeList |
783 self setChangeList |
710 |
784 |
711 ! |
785 ! |
712 |
786 |
713 queryCloseText |
|
714 "made this a method for easy redefinition in subclasses" |
|
715 |
|
716 ^ 'Quit without updating changeFile ?' |
|
717 ! |
|
718 |
|
719 compareChange:changeNr |
|
720 "compare a change with current version" |
|
721 |
|
722 |aStream chunk sawExcla parseTree thisClass cat oldSource newSource |
|
723 parser sel oldMethod outcome showDiff d| |
|
724 |
|
725 aStream := self streamForChange:changeNr. |
|
726 aStream isNil ifTrue:[^ self]. |
|
727 |
|
728 sawExcla := aStream peekFor:(aStream class chunkSeparator). |
|
729 chunk := aStream nextChunk. |
|
730 sawExcla ifFalse:[ |
|
731 outcome := 'not comparable ...' |
|
732 ] ifTrue:[ |
|
733 parseTree := Parser parseExpression:chunk. |
|
734 (parseTree notNil and:[parseTree isMessage]) ifTrue:[ |
|
735 (parseTree selector == #methodsFor:) ifTrue:[ |
|
736 thisClass := (parseTree receiver evaluate). |
|
737 thisClass isBehavior ifTrue:[ |
|
738 showDiff := false. |
|
739 cat := parseTree arg1 evaluate. |
|
740 newSource := aStream nextChunk. |
|
741 parser := Parser parseMethod:newSource in:thisClass. |
|
742 (parser notNil and:[parser ~~ #Error]) ifTrue:[ |
|
743 sel := parser selector. |
|
744 oldMethod := thisClass compiledMethodAt:sel. |
|
745 oldMethod notNil ifTrue:[ |
|
746 (oldMethod category = cat) ifFalse:[ |
|
747 Transcript showCr:'category changed.'. |
|
748 ]. |
|
749 oldSource := oldMethod source. |
|
750 (oldSource = newSource) ifTrue:[ |
|
751 outcome := 'same source' |
|
752 ] ifFalse:[ |
|
753 outcome := 'source changed.'. |
|
754 showDiff := true |
|
755 ] |
|
756 ] ifFalse:[ |
|
757 outcome := 'method does not exist.' |
|
758 ] |
|
759 ] ifFalse:[ |
|
760 outcome := 'change unparsable.' |
|
761 ]. |
|
762 (showDiff and:[oldSource notNil and:[newSource notNil]]) ifTrue:[ |
|
763 d := DiffTextView openOn:oldSource and:newSource. |
|
764 d label:'differences (current left; change right)'. |
|
765 ] |
|
766 ] ifFalse:[ |
|
767 outcome := 'class does not exist.' |
|
768 ] |
|
769 ] ifFalse:[ |
|
770 outcome := 'not comparable.' |
|
771 ] |
|
772 ] ifFalse:[ |
|
773 outcome := 'not comparable.' |
|
774 ] |
|
775 ]. |
|
776 Transcript showCr:outcome. |
|
777 aStream close. |
|
778 ! |
|
779 |
|
780 deleteChangesFrom:start to:stop |
787 deleteChangesFrom:start to:stop |
781 "delete a range of changes" |
788 "delete a range of changes" |
782 |
789 |
783 changeListView deselect. |
790 changeListView deselect. |
784 stop to:start by:-1 do:[:changeNr | |
791 stop to:start by:-1 do:[:changeNr | |
785 self silentDeleteChange:changeNr |
792 self silentDeleteChange:changeNr |
786 ]. |
793 ]. |
787 self setChangeList |
794 self setChangeList |
788 |
795 |
|
796 ! |
|
797 |
|
798 queryCloseText |
|
799 "made this a method for easy redefinition in subclasses" |
|
800 |
|
801 ^ 'Quit without updating changeFile ?' |
789 ! |
802 ! |
790 |
803 |
791 changeFileName:aFileName |
804 changeFileName:aFileName |
792 changeFileName := aFileName |
805 changeFileName := aFileName |
793 ! |
806 ! |
871 index := index - 1 |
884 index := index - 1 |
872 ] |
885 ] |
873 |
886 |
874 ! ! |
887 ! ! |
875 |
888 |
876 !ChangesBrowser methodsFor:'initialize / release'! |
|
877 |
|
878 initialize |
|
879 |frame v| |
|
880 |
|
881 super initialize. |
|
882 |
|
883 changeFileName := 'changes'. |
|
884 |
|
885 frame := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
886 corner:(1.0 @ 1.0) |
|
887 borderWidth:0 |
|
888 in:self. |
|
889 |
|
890 v := ScrollableView for:SelectionInListView in:frame. |
|
891 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.3). |
|
892 changeListView := v scrolledView. |
|
893 changeListView delegate:self. |
|
894 |
|
895 v := HVScrollableView for:CodeView miniScrollerH:true miniScrollerV:false in:frame. |
|
896 v origin:(0.0 @ 0.3) corner:(1.0 @ 1.0). |
|
897 codeView := v scrolledView. |
|
898 codeView readOnly. |
|
899 |
|
900 anyChanges := false. |
|
901 ObjectMemory addDependent:self. "to get shutdown-update" |
|
902 ! |
|
903 |
|
904 initializeMiddleButtonMenu |
|
905 |labels| |
|
906 |
|
907 labels := resources array:#( |
|
908 'apply change' |
|
909 'apply changes to end' |
|
910 'apply changes for this class to end' |
|
911 'apply all changes' |
|
912 '-' |
|
913 'delete' |
|
914 'delete to end' |
|
915 'delete changes for this class to end' |
|
916 'delete all changes for this class' |
|
917 '-' |
|
918 'update' |
|
919 'compress' |
|
920 'compare with current version' |
|
921 'browse class' |
|
922 '-' |
|
923 'make change a patch' |
|
924 "/ 'update sourcefile from change' |
|
925 "/ '-' |
|
926 'save change in file ...' |
|
927 'save changes to end in file ...' |
|
928 'save changes for this class to end in file ...' |
|
929 'save all changes for this class in file ...' |
|
930 '-' |
|
931 'writeback changeFile'). |
|
932 |
|
933 changeListView |
|
934 middleButtonMenu:(PopUpMenu |
|
935 labels:labels |
|
936 selectors:#( |
|
937 doApply |
|
938 doApplyRest |
|
939 doApplyClassRest |
|
940 doApplyAll |
|
941 nil |
|
942 doDelete |
|
943 doDeleteRest |
|
944 doDeleteClassRest |
|
945 doDeleteClassAll |
|
946 nil |
|
947 doUpdate |
|
948 doCompress |
|
949 doCompare |
|
950 doBrowse |
|
951 nil |
|
952 doMakePatch |
|
953 "/ doMakePermanent |
|
954 "/ nil |
|
955 doSave |
|
956 doSaveRest |
|
957 doSaveClassRest |
|
958 doSaveClassAll |
|
959 nil |
|
960 doWriteBack) |
|
961 receiver:self |
|
962 for:changeListView) |
|
963 ! |
|
964 |
|
965 realize |
|
966 super realize. |
|
967 self readChangesFileInBackground:true. |
|
968 self setChangeList. |
|
969 changeListView action:[:lineNr | self changeSelection:lineNr]. |
|
970 self disableMenuEntries. |
|
971 ! |
|
972 |
|
973 focusSequence |
|
974 ^ Array with:changeListView with:codeView |
|
975 ! |
|
976 |
|
977 update:what |
|
978 |box| |
|
979 |
|
980 (what == #aboutToExit) ifTrue:[ |
|
981 " |
|
982 smalltalk is about to shut down - |
|
983 - if change list was modified, ask user and save if requested. |
|
984 " |
|
985 anyChanges ifTrue:[ |
|
986 shown ifFalse:[ |
|
987 self unrealize. |
|
988 self realize |
|
989 ]. |
|
990 self raise. |
|
991 |
|
992 box := YesNoBox new. |
|
993 box title:(resources at:'ChangesBrowser:\changefile has not been updated from the modified changelist.\\Update before exiting ?') withCRs. |
|
994 box noText:(resources at:'don''t update'). |
|
995 box okText:(resources at:'update'). |
|
996 box yesAction:[self writeBackChanges] |
|
997 noAction:[]. |
|
998 box showAtPointer |
|
999 ]. |
|
1000 ^ self |
|
1001 ]. |
|
1002 super update:what |
|
1003 ! ! |
|
1004 |
|
1005 !ChangesBrowser methodsFor:'event handling '! |
|
1006 |
|
1007 keyPress:key x:x y:y view:view |
|
1008 "this method is reached via delegation from the changeListView" |
|
1009 |
|
1010 key == #Delete ifTrue:[ |
|
1011 self doDelete. |
|
1012 ^ self |
|
1013 ]. |
|
1014 changeListView keyPress:key x:x y:y |
|
1015 ! ! |
|
1016 |
|
1017 !ChangesBrowser methodsFor:'user interaction'! |
889 !ChangesBrowser methodsFor:'user interaction'! |
|
890 |
|
891 doApply |
|
892 "user wants a change to be applied" |
|
893 |
|
894 self withSelectedChangeDo:[:changeNr | |
|
895 skipSignal := nil. |
|
896 self applyChange:changeNr. |
|
897 self autoSelect:(changeNr + 1) |
|
898 ] |
|
899 ! |
1018 |
900 |
1019 changeSelection:lineNr |
901 changeSelection:lineNr |
1020 "show a change in the codeView" |
902 "show a change in the codeView" |
1021 |
903 |
1022 |aStream sawExcla chunk| |
904 |aStream sawExcla chunk| |
1093 ] |
960 ] |
1094 ] |
961 ] |
1095 ] |
962 ] |
1096 ! |
963 ! |
1097 |
964 |
|
965 doCompare |
|
966 "compare change with current system version |
|
967 - give a note in transcript" |
|
968 |
|
969 |changeNr| |
|
970 |
|
971 changeNr := changeListView selection. |
|
972 changeNr notNil ifTrue:[ |
|
973 self withCursor:(Cursor execute) do:[ |
|
974 self compareChange:changeNr |
|
975 ] |
|
976 ] |
|
977 ! |
|
978 |
1098 saveClass:aClassName from:startNr |
979 saveClass:aClassName from:startNr |
1099 "user wants changes from current to end to be appended to a file" |
980 "user wants changes from current to end to be appended to a file" |
1100 |
981 |
1101 |changeNr fileBox| |
982 |changeNr fileName| |
1102 |
983 |
1103 changeNr := changeListView selection. |
984 changeNr := changeListView selection. |
1104 changeNr notNil ifTrue:[ |
985 changeNr notNil ifTrue:[ |
1105 fileBox := FileSelectionBox new. |
986 fileName := DialogView |
1106 fileBox title:'append change to:'. |
987 requestFileName:'append changes for class to:' |
1107 fileBox okText:'append'. |
988 default:'' |
1108 fileBox abortText:'cancel'. |
989 ok:'append' |
1109 fileBox action:[:fileName | |
990 abort:'abort' |
1110 |thisClassName| |
991 pattern:'*.chg'. |
1111 |
992 |
1112 self withCursor:(Cursor write) do:[ |
993 fileName notNil ifTrue:[ |
1113 startNr to:(changePositions size) do:[:changeNr | |
994 self withCursor:(Cursor write) do:[ |
1114 thisClassName := self classNameOfChange:changeNr. |
995 startNr to:(changePositions size) do:[:changeNr | |
1115 thisClassName = aClassName ifTrue:[ |
996 |thisClassName| |
1116 changeListView selection:changeNr. |
997 |
1117 (self appendChange:changeNr toFile:fileName) ifFalse:[ |
998 thisClassName := self classNameOfChange:changeNr. |
1118 ^ self |
999 thisClassName = aClassName ifTrue:[ |
1119 ] |
1000 changeListView selection:changeNr. |
1120 ] |
1001 (self appendChange:changeNr toFile:fileName) ifFalse:[ |
1121 ] |
1002 ^ self |
1122 ] |
1003 ] |
1123 ]. |
1004 ] |
1124 |
1005 ] |
1125 fileBox pattern:'*.chg'. |
1006 ] |
1126 fileBox showAtPointer |
1007 ]. |
|
1008 ] |
|
1009 ! |
|
1010 |
|
1011 doDelete |
|
1012 "delete currently selected change" |
|
1013 |
|
1014 |changeNr| |
|
1015 |
|
1016 changeNr := changeListView selection. |
|
1017 changeNr notNil ifTrue:[ |
|
1018 self deleteChange:changeNr. |
|
1019 self autoSelectOrEnd:changeNr |
1127 ] |
1020 ] |
1128 ! |
1021 ! |
1129 |
1022 |
1130 doSaveClassFrom:startNr |
1023 doSaveClassFrom:startNr |
1131 "user wants changes from current to end to be appended to a file" |
1024 "user wants changes from current to end to be appended to a file" |
1142 ! |
1035 ! |
1143 |
1036 |
1144 doSaveRest |
1037 doSaveRest |
1145 "user wants changes from current to end to be appended to a file" |
1038 "user wants changes from current to end to be appended to a file" |
1146 |
1039 |
1147 |changeNr fileBox| |
1040 |changeNr fileName| |
1148 |
1041 |
1149 changeNr := changeListView selection. |
1042 changeNr := changeListView selection. |
1150 changeNr notNil ifTrue:[ |
1043 changeNr notNil ifTrue:[ |
1151 fileBox := FileSelectionBox new. |
1044 fileName := DialogView |
1152 fileBox title:'append change to:'. |
1045 requestFileName:'append changes to:' |
1153 fileBox okText:'append'. |
1046 default:'' |
1154 fileBox abortText:'cancel'. |
1047 ok:'append' |
1155 fileBox action:[:fileName | |
1048 abort:'abort' |
1156 self withCursor:(Cursor write) do:[ |
1049 pattern:'*.chg'. |
1157 changeNr to:(changePositions size) do:[:changeNr | |
1050 |
1158 changeListView selection:changeNr. |
1051 fileName notNil ifTrue:[ |
1159 (self appendChange:changeNr toFile:fileName) ifFalse:[ |
1052 self withCursor:(Cursor write) do:[ |
1160 ^ self |
1053 changeNr to:(changePositions size) do:[:changeNr | |
1161 ] |
1054 changeListView selection:changeNr. |
1162 ] |
1055 (self appendChange:changeNr toFile:fileName) ifFalse:[ |
1163 ] |
1056 ^ self |
1164 ]. |
1057 ] |
1165 |
1058 ] |
1166 fileBox pattern:'*.chg'. |
1059 ] |
1167 fileBox showAtPointer |
1060 ]. |
1168 ] |
1061 ] |
1169 ! |
1062 ! |
1170 |
1063 |
1171 doDelete |
1064 doSave |
1172 "delete currently selected change" |
1065 "user wants a change to be appended to a file" |
1173 |
1066 |
1174 |changeNr| |
1067 |changeNr fileName| |
1175 |
1068 |
1176 changeNr := changeListView selection. |
1069 changeNr := changeListView selection. |
1177 changeNr notNil ifTrue:[ |
1070 changeNr notNil ifTrue:[ |
1178 self deleteChange:changeNr. |
1071 fileName := DialogView |
1179 self autoSelectOrEnd:changeNr |
1072 requestFileName:'append change to:' |
1180 ] |
1073 default:'' |
1181 ! |
1074 ok:'append' |
1182 |
1075 abort:'abort' |
1183 doSave |
1076 pattern:'*.chg'. |
1184 "user wants a change to be appended to a file" |
1077 |
1185 |
1078 fileName notNil ifTrue:[ |
1186 |changeNr fileBox| |
1079 self withCursor:(Cursor write) do:[ |
1187 |
1080 self appendChange:changeNr toFile:fileName. |
1188 changeNr := changeListView selection. |
1081 ]. |
1189 changeNr notNil ifTrue:[ |
1082 self autoSelect:(changeNr + 1) |
1190 fileBox := FileSelectionBox new. |
1083 ]. |
1191 fileBox title:'append change to:'. |
|
1192 fileBox okText:'append'. |
|
1193 fileBox abortText:'cancel'. |
|
1194 fileBox action:[:fileName | |
|
1195 self withCursor:(Cursor write) do:[ |
|
1196 self appendChange:changeNr toFile:fileName. |
|
1197 ]. |
|
1198 self autoSelect:(changeNr + 1) |
|
1199 ]. |
|
1200 |
|
1201 fileBox pattern:'*.chg'. |
|
1202 fileBox showAtPointer |
|
1203 ] |
1084 ] |
1204 ! |
1085 ! |
1205 |
1086 |
1206 doUpdate |
1087 doUpdate |
1207 "reread the changes-file" |
1088 "reread the changes-file" |
1208 |
1089 |
1209 self readChangesFileInBackground:true. |
1090 self readChangesFileInBackground:true. |
1210 realized ifTrue:[ |
1091 realized ifTrue:[ |
1211 self setChangeList. |
1092 self setChangeList. |
1212 changeListView hasSelection ifTrue:[self enableMenuEntries] |
1093 ] |
1213 ] |
1094 |
1214 ! |
1095 ! |
1215 |
1096 |
1216 doMakePermanent |
1097 doMakePermanent |
1217 "user wants a change to be made permanent |
1098 "user wants a change to be made permanent |
1218 - rewrite the source file where this change has to go" |
1099 - rewrite the source file where this change has to go" |
1485 ] |
1324 ] |
1486 ] |
1325 ] |
1487 ] |
1326 ] |
1488 ! |
1327 ! |
1489 |
1328 |
|
1329 doDeleteClassRest |
|
1330 "delete rest of changes with same class as currently selected change" |
|
1331 |
|
1332 self withSelectedChangeDo:[:changeNr | |
|
1333 | classNameToDelete | |
|
1334 |
|
1335 classNameToDelete := self classNameOfChange:changeNr. |
|
1336 classNameToDelete notNil ifTrue:[ |
|
1337 changeListView selection:nil. |
|
1338 self silentDeleteChangesFor:classNameToDelete |
|
1339 from:changeNr |
|
1340 to:(changePositions size). |
|
1341 self setChangeList. |
|
1342 self autoSelectOrEnd:changeNr |
|
1343 ] |
|
1344 ] |
|
1345 ! |
|
1346 |
1490 doDeleteClassAll |
1347 doDeleteClassAll |
1491 "delete all changes with same class as currently selected change" |
1348 "delete all changes with same class as currently selected change" |
1492 |
1349 |
1493 |changeNr| |
1350 self withSelectedChangeDo:[:changeNr | |
1494 |
1351 | classNameToDelete | |
1495 changeNr := changeListView selection. |
1352 |
1496 changeNr notNil ifTrue:[ |
1353 classNameToDelete := self classNameOfChange:changeNr. |
1497 self withCursor:(Cursor execute) do:[ |
1354 classNameToDelete notNil ifTrue:[ |
1498 | classNameToDelete | |
1355 changeListView selection:nil. |
1499 |
1356 self silentDeleteChangesFor:classNameToDelete |
1500 classNameToDelete := self classNameOfChange:changeNr. |
1357 from:1 |
1501 classNameToDelete notNil ifTrue:[ |
1358 to:(changePositions size). |
1502 changeListView selection:nil. |
1359 self setChangeList. |
1503 self silentDeleteChangesFor:classNameToDelete |
1360 self autoSelectOrEnd:changeNr |
1504 from:1 |
|
1505 to:(changePositions size). |
|
1506 self setChangeList. |
|
1507 self autoSelectOrEnd:changeNr |
|
1508 ] |
|
1509 ] |
1361 ] |
1510 ] |
1362 ] |
1511 ! |
1363 ! |
1512 |
1364 |
1513 doApplyClassRest |
1365 doApplyClassRest |
1514 "user wants all changes for this class from changeNr to be applied" |
1366 "user wants all changes for this class from changeNr to be applied" |
1515 |
1367 |
1516 |changeNr| |
1368 self withSelectedChangeDo:[:changeNr | |
1517 |
1369 |thisClassName classNameToApply lastChange| |
1518 changeNr := changeListView selection. |
1370 |
1519 changeNr notNil ifTrue:[ |
1371 classNameToApply := self classNameOfChange:changeNr. |
1520 self withCursor:(Cursor execute) do:[ |
1372 classNameToApply notNil ifTrue:[ |
1521 |thisClassName classNameToApply lastChange| |
1373 self clearCodeView. |
1522 |
1374 skipSignal isNil ifTrue:[skipSignal := Signal new]. |
1523 classNameToApply := self classNameOfChange:changeNr. |
1375 changeNr to:(changePositions size) do:[:changeNr | |
1524 classNameToApply notNil ifTrue:[ |
1376 thisClassName := self classNameOfChange:changeNr. |
1525 self clearCodeView. |
1377 thisClassName = classNameToApply ifTrue:[ |
1526 skipSignal isNil ifTrue:[skipSignal := Signal new]. |
1378 changeListView selection:changeNr. |
1527 changeNr to:(changePositions size) do:[:changeNr | |
1379 self applyChange:changeNr. |
1528 thisClassName := self classNameOfChange:changeNr. |
1380 lastChange := changeNr |
1529 thisClassName = classNameToApply ifTrue:[ |
|
1530 changeListView selection:changeNr. |
|
1531 self applyChange:changeNr. |
|
1532 lastChange := changeNr |
|
1533 ]. |
|
1534 ]. |
1381 ]. |
1535 self autoSelect:lastChange. |
1382 ]. |
1536 ] |
1383 self autoSelect:lastChange. |
1537 ] |
1384 ] |
1538 ] |
1385 ] |
|
1386 ! ! |
|
1387 |
|
1388 !ChangesBrowser methodsFor:'initialize / release'! |
|
1389 |
|
1390 initialize |
|
1391 |frame v| |
|
1392 |
|
1393 super initialize. |
|
1394 |
|
1395 changeFileName := 'changes'. |
|
1396 |
|
1397 frame := VariableVerticalPanel origin:(0.0 @ 0.0) |
|
1398 corner:(1.0 @ 1.0) |
|
1399 borderWidth:0 |
|
1400 in:self. |
|
1401 |
|
1402 v := ScrollableView for:SelectionInListView in:frame. |
|
1403 v origin:(0.0 @ 0.0) corner:(1.0 @ 0.3). |
|
1404 changeListView := v scrolledView. |
|
1405 changeListView delegate:self. |
|
1406 changeListView model:self; menu:#changeListMenu. |
|
1407 |
|
1408 v := HVScrollableView for:CodeView miniScrollerH:true miniScrollerV:false in:frame. |
|
1409 v origin:(0.0 @ 0.3) corner:(1.0 @ 1.0). |
|
1410 codeView := v scrolledView. |
|
1411 codeView readOnly. |
|
1412 |
|
1413 anyChanges := false. |
|
1414 ObjectMemory addDependent:self. "to get shutdown-update" |
|
1415 ! |
|
1416 |
|
1417 focusSequence |
|
1418 ^ Array with:changeListView with:codeView |
|
1419 ! |
|
1420 |
|
1421 realize |
|
1422 super realize. |
|
1423 self readChangesFileInBackground:true. |
|
1424 self setChangeList. |
|
1425 changeListView action:[:lineNr | self changeSelection:lineNr]. |
|
1426 |
|
1427 ! |
|
1428 |
|
1429 update:what |
|
1430 |box| |
|
1431 |
|
1432 (what == #aboutToExit) ifTrue:[ |
|
1433 " |
|
1434 smalltalk is about to shut down - |
|
1435 - if change list was modified, ask user and save if requested. |
|
1436 " |
|
1437 anyChanges ifTrue:[ |
|
1438 shown ifFalse:[ |
|
1439 self unrealize. |
|
1440 self realize |
|
1441 ]. |
|
1442 self raise. |
|
1443 |
|
1444 box := YesNoBox new. |
|
1445 box title:(resources at:'ChangesBrowser:\changefile has not been updated from the modified changelist.\\Update before exiting ?') withCRs. |
|
1446 box noText:(resources at:'don''t update'). |
|
1447 box okText:(resources at:'update'). |
|
1448 box yesAction:[self writeBackChanges] |
|
1449 noAction:[]. |
|
1450 box showAtPointer |
|
1451 ]. |
|
1452 ^ self |
|
1453 ]. |
|
1454 super update:what |
|
1455 ! |
|
1456 |
|
1457 changeListMenu |
|
1458 |labels selectors m| |
|
1459 |
|
1460 labels := #( |
|
1461 'apply change' |
|
1462 'apply changes to end' |
|
1463 'apply changes for this class to end' |
|
1464 'apply all changes' |
|
1465 '-' |
|
1466 'delete' |
|
1467 'delete to end' |
|
1468 'delete changes for this class to end' |
|
1469 'delete all changes for this class' |
|
1470 '-' |
|
1471 'update' |
|
1472 'compress' |
|
1473 'compare with current version' |
|
1474 'browse class' |
|
1475 '-' |
|
1476 'make change a patch' |
|
1477 "/ 'update sourcefile from change' |
|
1478 "/ '-' |
|
1479 'save change in file ...' |
|
1480 'save changes to end in file ...' |
|
1481 'save changes for this class to end in file ...' |
|
1482 'save all changes for this class in file ...' |
|
1483 '-' |
|
1484 'writeback changeFile'). |
|
1485 |
|
1486 selectors := #( |
|
1487 doApply |
|
1488 doApplyRest |
|
1489 doApplyClassRest |
|
1490 doApplyAll |
|
1491 nil |
|
1492 doDelete |
|
1493 doDeleteRest |
|
1494 doDeleteClassRest |
|
1495 doDeleteClassAll |
|
1496 nil |
|
1497 doUpdate |
|
1498 doCompress |
|
1499 doCompare |
|
1500 doBrowse |
|
1501 nil |
|
1502 doMakePatch |
|
1503 "/ doMakePermanent |
|
1504 "/ nil |
|
1505 doSave |
|
1506 doSaveRest |
|
1507 doSaveClassRest |
|
1508 doSaveClassAll |
|
1509 nil |
|
1510 doWriteBack |
|
1511 ). |
|
1512 |
|
1513 m := PopUpMenu |
|
1514 labels:(resources array:labels) |
|
1515 selectors:selectors. |
|
1516 |
|
1517 changeListView hasSelection ifFalse:[ |
|
1518 #(doApply doApplyClassRest doApplyRest doDelete doDeleteRest doDeleteClassRest |
|
1519 doDeleteClassAll doCompare doMakePatch doSaveChangeInFile doMakePermanent |
|
1520 doSave doSaveRest doSaveClassAll doSaveClassRest doBrowse) |
|
1521 do:[:sel | |
|
1522 m disable:sel |
|
1523 ]. |
|
1524 ]. |
|
1525 ^ m |
|
1526 |
|
1527 |
|
1528 ! ! |
|
1529 |
|
1530 !ChangesBrowser methodsFor:'event handling '! |
|
1531 |
|
1532 keyPress:key x:x y:y view:view |
|
1533 "this method is reached via delegation from the changeListView" |
|
1534 |
|
1535 key == #Delete ifTrue:[ |
|
1536 self doDelete. |
|
1537 ^ self |
|
1538 ]. |
|
1539 changeListView keyPress:key x:x y:y |
1539 ! ! |
1540 ! ! |
1540 |
1541 |
1541 !ChangesBrowser methodsFor:'termination'! |
1542 !ChangesBrowser methodsFor:'termination'! |
1542 |
1543 |
1543 terminate |
1544 terminate |
1544 "window manager wants us to go away" |
1545 "window manager wants us to go away" |
1545 |
1546 |
1546 |box| |
1547 |box action| |
1547 |
1548 |
1548 anyChanges ifTrue:[ |
1549 anyChanges ifTrue:[ |
1549 box := OptionBox title:'' numberOfOptions:3. |
1550 action := OptionBox |
1550 box title:(resources at:'close ChangesBrowser.\\changefile has not been updated from the modified changelist.\\Update before closing ?') withCRs. |
1551 request:(resources at:'changefile has not been updated from the modified changelist.\\Update before closing ?') withCRs |
1551 box buttonTitles:(resources array:#('abort' 'don''t update' 'update')). |
1552 label:'ChangesBrowser' |
1552 box actions:(Array with:[^ self] |
1553 form:(WarningBox iconBitmap) |
1553 with:[self destroy] |
1554 buttonLabels:#('abort' 'don''t update' 'update') |
1554 with:[self writeBackChanges. self destroy] |
1555 values:#(#abort #ignore #save). |
1555 ). |
1556 action == #abort ifTrue:[^ self]. |
1556 box showAtPointer. |
1557 action == #save ifTrue:[ |
1557 ] ifFalse:[ |
1558 self writeBackChanges |
1558 self destroy |
1559 ]. |
1559 ] |
1560 ]. |
|
1561 self destroy |
1560 ! |
1562 ! |
1561 |
1563 |
1562 destroy |
1564 destroy |
1563 "destroy the receiver; make certain, that boxes are destroyed too" |
1565 "destroy the receiver; make certain, that boxes are destroyed too" |
1564 |
1566 |
1583 "compiler notifys us of an error - this should really not happen since |
1585 "compiler notifys us of an error - this should really not happen since |
1584 changes ought to be correct (did someone edit the changes file ??). |
1586 changes ought to be correct (did someone edit the changes file ??). |
1585 Show the bad change in the codeView and let codeView hilight the error; |
1587 Show the bad change in the codeView and let codeView hilight the error; |
1586 no corrections allowed here therefore return false" |
1588 no corrections allowed here therefore return false" |
1587 |
1589 |
1588 |action| |
1590 self error:aString position:relPos to:relEndPos. |
1589 |
|
1590 (changeNrProcessed ~~ changeNrShown) ifTrue:[ |
|
1591 self changeSelection:changeNrProcessed |
|
1592 ]. |
|
1593 (skipSignal notNil) ifTrue:[ |
|
1594 |
|
1595 codeView highlightingErrorPosition:relPos to:relEndPos do:[ |
|
1596 |box| |
|
1597 |
|
1598 " |
|
1599 start dialog - make certain cleanup is done |
|
1600 " |
|
1601 box := OptionBox title:aString numberOfOptions:3. |
|
1602 box buttonTitles:#('abort' 'skip' 'continue'). |
|
1603 box actions:(Array with:[action := #abort] |
|
1604 with:[action := #skip] |
|
1605 with:[action := #continue]). |
|
1606 box showAtPointer |
|
1607 ]. |
|
1608 |
|
1609 action == #abort ifTrue:[ |
|
1610 Object abortSignal raise. |
|
1611 ^ false |
|
1612 ]. |
|
1613 action == #skip ifTrue:[ |
|
1614 skipSignal raise. |
|
1615 ^ false |
|
1616 ]. |
|
1617 ^ false |
|
1618 ]. |
|
1619 codeView error:aString position:relPos to:relEndPos. |
|
1620 ^ false |
1591 ^ false |
1621 ! |
1592 ! |
1622 |
1593 |
1623 warning:aString position:relPos to:relEndPos |
1594 warning:aString position:relPos to:relEndPos |
1624 "compiler notifys us of a warning - ignore it" |
1595 "compiler notifys us of a warning - ignore it" |