3
3
from eztk import setEntry , clearEntry
4
4
from random import randrange , shuffle , randint
5
5
import ez , ezs , os
6
+ import numpy as np
6
7
from dialogs import *
7
8
from constants import *
8
9
@@ -91,6 +92,10 @@ def __init__(self, master):
91
92
self .cmdMenu .add_command (label = MULTIPLY , accelerator = shortcuts [MULTIPLY ], command = self .multiply )
92
93
self .cmdMenu .add_separator ()
93
94
self .cmdMenu .add_command (label = TRANSPOSE , accelerator = shortcuts [TRANSPOSE ], command = self .transpose )
95
+ self .cmdMenu .add_command (label = f'Rotate ({ CLOCKWISE } )' , command = lambda : self .rotate (CLOCKWISE ))
96
+ self .cmdMenu .add_command (label = f'Rotate ({ COUNTER } )' , command = lambda : self .rotate (COUNTER ))
97
+ self .cmdMenu .add_command (label = f'Flip ({ HORIZONTAL } )' , command = lambda : self .flip (HORIZONTAL ))
98
+ self .cmdMenu .add_command (label = f'Flip ({ VERTICAL } )' , command = lambda : self .flip (VERTICAL ))
94
99
self .cmdMenu .add_command (label = RESHAPE , command = self .reshape )
95
100
self .cmdMenu .add_separator ()
96
101
self .cmdMenu .add_command (label = LOWER_TRIANGULAR , accelerator = shortcuts [LOWER_TRIANGULAR ], command = lambda : self .triangularMatrix (LOWER ))
@@ -336,7 +341,7 @@ def onResultTypeChange(self):
336
341
self .generateEntries (row , 1 )
337
342
if entries :
338
343
for i in range (1 , col ):
339
- setEntry (self .entries [( i , 0 ) ], entries [i ])
344
+ setEntry (self .entries [i , 0 ], entries [i ])
340
345
341
346
def setResultFormat (self , resultFormat ):
342
347
if self .resultFormat .get () == resultFormat :
@@ -385,12 +390,12 @@ def generateEntries(self, row, col):
385
390
continue
386
391
label = Label (self .entryFrame , width = columnLabelWidth , text = i )
387
392
label .grid (row = 0 , column = i )
388
- self .entryLabels [( 0 , i ) ] = label
393
+ self .entryLabels [0 , i ] = label
389
394
for i in range (row ):
390
395
if (i + 1 , 0 ) not in self .entryLabels :
391
396
label = Label (self .entryFrame , text = i + 1 )
392
397
label .grid (row = i + 1 , column = 0 )
393
- self .entryLabels [( i + 1 , 0 ) ] = label
398
+ self .entryLabels [i + 1 , 0 ] = label
394
399
for j in range (col ):
395
400
if (i , j ) in self .entries :
396
401
continue
@@ -401,18 +406,18 @@ def generateEntries(self, row, col):
401
406
bindtags = entry .bindtags ()
402
407
entry .bindtags ((bindtags [2 ], bindtags [0 ], bindtags [1 ], bindtags [3 ]))
403
408
entry .grid (row = i + 1 , column = j + 1 , sticky = NSEW )
404
- self .entries [( i , j ) ] = entry
409
+ self .entries [i , j ] = entry
405
410
for i , j in self .entries .copy ():
406
411
if i >= row or j >= col :
407
- self .entries [( i , j ) ].grid_forget ()
408
- del self .entries [( i , j ) ]
412
+ self .entries [i , j ].grid_forget ()
413
+ del self .entries [i , j ]
409
414
for i , j in self .entryLabels .copy ():
410
415
if i > row :
411
- self .entryLabels [( i , 0 ) ].grid_forget ()
412
- del self .entryLabels [( i , 0 ) ]
416
+ self .entryLabels [i , 0 ].grid_forget ()
417
+ del self .entryLabels [i , 0 ]
413
418
elif j > col :
414
- self .entryLabels [( 0 , j ) ].grid_forget ()
415
- del self .entryLabels [( 0 , j ) ]
419
+ self .entryLabels [0 , j ].grid_forget ()
420
+ del self .entryLabels [0 , j ]
416
421
417
422
def beforeDelete (self , event ):
418
423
entry = self .getFocusEntry ()
@@ -423,9 +428,9 @@ def beforeDelete(self, event):
423
428
if r == 0 and c == 0 :
424
429
self .colEntry .focus ()
425
430
elif c == 0 :
426
- self .entries [( r - 1 , col - 1 ) ].focus ()
431
+ self .entries [r - 1 , col - 1 ].focus ()
427
432
else :
428
- self .entries [( r , c - 1 ) ].focus ()
433
+ self .entries [r , c - 1 ].focus ()
429
434
430
435
def onEntryChange (self , event ):
431
436
self .modifyState ()
@@ -448,7 +453,7 @@ def moveFocus(self, event):
448
453
else :
449
454
# check empty
450
455
if not self .entries : return
451
- fEntry = self .entries [( row - 1 if key == UP else 0 , 0 if entry == self .rowEntry else col - 1 ) ]
456
+ fEntry = self .entries [row - 1 if key == UP else 0 , 0 if entry == self .rowEntry else col - 1 ]
452
457
else :
453
458
info = entry .grid_info ()
454
459
r , c = info ['row' ] - 1 , info ['column' ] - 1
@@ -458,7 +463,7 @@ def moveFocus(self, event):
458
463
x , y = {UP : (- 1 , 0 ), DOWN : (1 , 0 ), LEFT : (0 , - 1 ), RIGHT : (0 , 1 )}[key ]
459
464
r = (r + x ) % row
460
465
c = (c + y ) % col
461
- fEntry = self .entries [( r , c ) ]
466
+ fEntry = self .entries [r , c ]
462
467
fEntry .focus ()
463
468
if key in [UP , DOWN ]:
464
469
fEntry .icursor (END if isEnd else min (len (fEntry .get ()), cursorIndex ))
@@ -539,7 +544,7 @@ def collectEntries(self, evaluate: bool = True, nested: bool = False, withEmpty:
539
544
for i in range (self .row ):
540
545
if nested : lst = []
541
546
for j in range (self .col ):
542
- text = self .entries [( i , j ) ].get ()
547
+ text = self .entries [i , j ].get ()
543
548
if not withEmpty and not text : continue
544
549
if evaluate and text : text = ezs .numEval (text )
545
550
if nested : lst .append (text )
@@ -665,15 +670,15 @@ def insert(self, fromFormat):
665
670
self .generateEntries (r , c )
666
671
for i in range (r ):
667
672
for j in range (c ):
668
- setEntry (self .entries [( i , j ) ], matrix [i ][j ])
673
+ setEntry (self .entries [i , j ], matrix [i ][j ])
669
674
self .modifyState ()
670
675
671
676
def appendIndex (self ):
672
677
isLatex = self .resultFormat .get () == LATEX
673
678
for i in range (self .getRow ()):
674
679
for j in range (self .getCol ()):
675
680
text = f'{ i + 1 } { j + 1 } '
676
- self .entries [( i , j ) ].insert (END , '_{%s}' % text if isLatex else text )
681
+ self .entries [i , j ].insert (END , '_{%s}' % text if isLatex else text )
677
682
678
683
def fillRC (self , title ):
679
684
isRow = title == FILL_ROW
@@ -721,10 +726,10 @@ def copyRC(self, title):
721
726
continue
722
727
if isRow :
723
728
for _ in range (c ):
724
- setEntry (self .entries [( j , _ ) ], self .entries [( i , _ ) ].get ())
729
+ setEntry (self .entries [j , _ ], self .entries [i , _ ].get ())
725
730
else :
726
731
for _ in range (r ):
727
- setEntry (self .entries [( _ , j ) ], self .entries [( _ , i ) ].get ())
732
+ setEntry (self .entries [_ , j ], self .entries [_ , i ].get ())
728
733
break
729
734
fEntry .focus ()
730
735
@@ -771,7 +776,7 @@ def duplicateRC(self, title):
771
776
entries = [[entries [i ][result ]] * c for i in range (r )]
772
777
for i in range (r ):
773
778
for j in range (c ):
774
- setEntry (self .entries [( i , j ) ], entries [i ][j ])
779
+ setEntry (self .entries [i , j ], entries [i ][j ])
775
780
break
776
781
fEntry .focus ()
777
782
@@ -782,7 +787,7 @@ def identityMatrix(self):
782
787
if row != col :
783
788
self .syncRowCol (max (row , col ))
784
789
for i , j in self .entries :
785
- setEntry (self .entries [( i , j ) ], 1 if i == j else 0 )
790
+ setEntry (self .entries [i , j ], 1 if i == j else 0 )
786
791
self .modifyState ()
787
792
788
793
def append (self , position ):
@@ -818,7 +823,7 @@ def onFind(self, dialog, target, direction, findNext = True):
818
823
r , c = self .getRowCol ()
819
824
for i in range (r ):
820
825
for j in range (c ):
821
- text = self .entries [( i , j ) ].get ()
826
+ text = self .entries [i , j ].get ()
822
827
for index in ez .find (text ).all (target ):
823
828
self .findResult .append (((i , j ), index , index + targetLen ))
824
829
if self .currentEntry and divmod (self .currentEntry [1 ], c ) == (i , j ) and self .currentEntry [2 ] == index :
@@ -861,7 +866,7 @@ def find(self, findType):
861
866
break
862
867
try :
863
868
x , y = result .replace (' ' , '' ).split (',' )
864
- entry = self .entries [( int (x ) - 1 , int (y ) - 1 ) ]
869
+ entry = self .entries [int (x ) - 1 , int (y ) - 1 ]
865
870
entry .focus ()
866
871
entry .select_range (0 , END )
867
872
break
@@ -969,19 +974,41 @@ def switch(self, target):
969
974
self .modifyState ()
970
975
971
976
def transpose (self ):
972
- resultType = self .resultType .get ()
973
- if resultType not in [MATRIX , DETERMINANT , VECTOR ]:
974
- return
977
+ entries = { key : entry .get () for key , entry in self .entries .items () }
978
+ row , col = self .getRowCol ()
979
+ if row != col :
980
+ if self .resultType .get () == VECTOR :
981
+ self .setResultType (MATRIX )
982
+ self .setRowCol (col , row )
983
+ self .generateEntries (col , row )
984
+ row , col = col , row
985
+ for i in range (row ):
986
+ for j in range (col ):
987
+ setEntry (self .entries [i , j ], entries [j , i ])
988
+ self .modifyState ()
989
+
990
+ def rotate (self , direction ):
991
+ entries = self .collectEntries (nested = True )
992
+ entries = np .rot90 (entries , axes = (0 , 1 ) if direction == COUNTER else (1 , 0 ))
975
993
row , col = self .getRowCol ()
976
- entries = { key : self .entries [key ].get () for key in self .entries }
977
994
if row != col :
978
- if resultType == VECTOR :
995
+ if self . resultType . get () == VECTOR :
979
996
self .setResultType (MATRIX )
980
997
self .setRowCol (col , row )
981
998
self .generateEntries (col , row )
999
+ row , col = col , row
1000
+ for i in range (row ):
1001
+ for j in range (col ):
1002
+ setEntry (self .entries [i , j ], entries [i ][j ])
1003
+ self .modifyState ()
1004
+
1005
+ def flip (self , direction ):
1006
+ entries = self .collectEntries (nested = True )
1007
+ entries = np .fliplr (entries ) if direction == HORIZONTAL else np .flipud (entries )
1008
+ row , col = self .getRowCol ()
982
1009
for i in range (row ):
983
1010
for j in range (col ):
984
- setEntry (self .entries [( j , i ) ], entries [( i , j ) ])
1011
+ setEntry (self .entries [i , j ], entries [i ][ j ])
985
1012
self .modifyState ()
986
1013
987
1014
def zeroMatrix (self ):
@@ -1112,7 +1139,7 @@ def sort(self, target):
1112
1139
vars = []
1113
1140
for i in range (row ):
1114
1141
for j in range (col ):
1115
- text = self .entries [( i , j ) ].get ()
1142
+ text = self .entries [i , j ].get ()
1116
1143
fText = ez .find (text )
1117
1144
varNumber = ez .Eval (fText .between ('_{' , '}' ))
1118
1145
varType = type (varNumber )
@@ -1146,7 +1173,7 @@ def sort(self, target):
1146
1173
values = sorted (values )
1147
1174
for i in range (row ):
1148
1175
for j in range (col ):
1149
- setEntry (self .entries [( i , j ) ], values [i ][j ])
1176
+ setEntry (self .entries [i , j ], values [i ][j ])
1150
1177
self .modifyState ()
1151
1178
1152
1179
def reverse (self , target ):
@@ -1156,7 +1183,7 @@ def reverse(self, target):
1156
1183
if target == ALL :
1157
1184
for i in range (row * col // 2 ):
1158
1185
r , c = divmod (i , col )
1159
- e1 , e2 = self .entries [( r , c ) ], self .entries [( row - r - 1 , col - c - 1 ) ]
1186
+ e1 , e2 = self .entries [r , c ], self .entries [row - r - 1 , col - c - 1 ]
1160
1187
t1 , t2 = e2 .get (), e1 .get ()
1161
1188
setEntry (e1 , t1 )
1162
1189
setEntry (e2 , t2 )
@@ -1168,7 +1195,7 @@ def reverse(self, target):
1168
1195
values = list (reversed (values ))
1169
1196
for i in range (row ):
1170
1197
for j in range (col ):
1171
- setEntry (self .entries [( i , j ) ], values [i ][j ])
1198
+ setEntry (self .entries [i , j ], values [i ][j ])
1172
1199
self .modifyState ()
1173
1200
1174
1201
def reshape (self ):
@@ -1209,7 +1236,7 @@ def reshape(self):
1209
1236
def triangularMatrix (self , mode ):
1210
1237
for i , j in self .entries :
1211
1238
if i < j if mode == LOWER else i > j :
1212
- setEntry (self .entries [( i , j ) ], 0 )
1239
+ setEntry (self .entries [i , j ], 0 )
1213
1240
self .modifyState ()
1214
1241
1215
1242
def unitMatrix (self ):
@@ -1227,8 +1254,8 @@ def permutationMatrix(self):
1227
1254
shuffle (cols )
1228
1255
for i in range (size ):
1229
1256
for j in range (size ):
1230
- setEntry (self .entries [( i , j ) ], 0 )
1231
- setEntry (self .entries [( i , cols .pop () )], 1 )
1257
+ setEntry (self .entries [i , j ], 0 )
1258
+ setEntry (self .entries [i , cols .pop ()], 1 )
1232
1259
self .modifyState ()
1233
1260
1234
1261
def unknownMatrix (self ):
@@ -1262,7 +1289,7 @@ def permutationConversion(self):
1262
1289
for i , row in enumerate (entries ):
1263
1290
if row .count (1 ) != 1 and row .count (0 ) != len (row ) - 1 :
1264
1291
return
1265
- setEntry (self .entries [( i , 0 ) ], row .index (1 ) + isNormal )
1292
+ setEntry (self .entries [i , 0 ], row .index (1 ) + isNormal )
1266
1293
self .setResultType (VECTOR )
1267
1294
else :
1268
1295
if any (i not in entries for i in range (isNormal , r + isNormal )):
@@ -1271,7 +1298,7 @@ def permutationConversion(self):
1271
1298
self .syncRowCol (r )
1272
1299
for i in range (r ):
1273
1300
for j in range (r ):
1274
- setEntry (self .entries [( i , j ) ], entries [i ] == j + isNormal )
1301
+ setEntry (self .entries [i , j ], entries [i ] == j + isNormal )
1275
1302
self .modifyState ()
1276
1303
1277
1304
def calculateDet (self ):
@@ -1339,7 +1366,7 @@ def modifyEntryWidth(self, dialog, value):
1339
1366
for entry in self .entries .values ():
1340
1367
entry ['width' ] = value
1341
1368
for i in range (1 , self .getCol () + 1 ):
1342
- self .entryLabels [( 0 , i ) ]['width' ] = value
1369
+ self .entryLabels [0 , i ]['width' ] = value
1343
1370
1344
1371
def adjustWidth (self ):
1345
1372
dialog = SliderDialog (self , 20 )
@@ -1368,7 +1395,7 @@ def resumeState(self):
1368
1395
self .setResultType (resultType )
1369
1396
for i , row in enumerate (entries ):
1370
1397
for j , entry in enumerate (row ):
1371
- setEntry (self .entries [( i , j ) ], entry )
1398
+ setEntry (self .entries [i , j ], entry )
1372
1399
entry = self .getLastFocusEntry (c )
1373
1400
entry .focus ()
1374
1401
entry .icursor (focus [2 ])
0 commit comments