rev |
line source |
darkhan@105
|
1 """Copyright 2010 Aydarkhanov Ruslan, Kurochkin Ilya, Rusinov Ivan |
darkhan@105
|
2 |
darkhan@105
|
3 This file is part of Foobar. |
darkhan@105
|
4 |
darkhan@105
|
5 Foobar is free software: you can redistribute it and/or modify it under |
darkhan@105
|
6 the terms of the GNU General Public License as published |
darkhan@105
|
7 by the Free Software Foundation, either version 2 of the License, |
darkhan@105
|
8 or (at your option) any later version. |
darkhan@105
|
9 |
darkhan@105
|
10 Foobar is distributed in the hope that it will be useful, |
darkhan@105
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty |
darkhan@105
|
12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
darkhan@105
|
13 See the GNU General Public License for more details. |
darkhan@105
|
14 |
darkhan@105
|
15 You should have received a copy of the GNU General Public License |
darkhan@105
|
16 along with Foobar. If not, see http://www.gnu.org/licenses/. |
darkhan@105
|
17 """ |
darkhan@105
|
18 |
is_rusinov@64
|
19 import math |
is_rusinov@91
|
20 import pickle |
is_rusinov@69
|
21 import random |
is_rusinov@64
|
22 import tkColorChooser |
is_rusinov@70
|
23 import tkFileDialog |
is_rusinov@73
|
24 import tkMessageBox |
is_rusinov@95
|
25 import webbrowser |
Ilia@6
|
26 from Tkinter import * |
Ilia@2
|
27 |
is_rusinov@91
|
28 from state import * |
is_rusinov@91
|
29 from automata import * |
is_rusinov@18
|
30 |
is_rusinov@18
|
31 |
Ilia@2
|
32 class Handlers(object): |
is_rusinov@5
|
33 |
is_rusinov@91
|
34 def __init__(self, cell_size=8, line_width=1 ,delay=8, dx=0, dy=0): |
is_rusinov@7
|
35 self.cell_size = cell_size |
is_rusinov@18
|
36 self.line_width = line_width |
is_rusinov@7
|
37 self.delay = delay |
is_rusinov@85
|
38 self.dx = dx |
is_rusinov@85
|
39 self.dy = dy |
is_rusinov@5
|
40 self.after_id = 0 |
is_rusinov@18
|
41 self.mouse_zoom = 0 |
is_rusinov@54
|
42 self.zoom_divisor = 1 |
is_rusinov@64
|
43 self.selected_state = None |
is_rusinov@7
|
44 self.is_started = False |
is_rusinov@54
|
45 self.char = None |
is_rusinov@70
|
46 self.keys = {} |
is_rusinov@70
|
47 for index, state in enumerate(automata.states): |
is_rusinov@70
|
48 self.keys[state.key] = index |
is_rusinov@29
|
49 self.draw() |
is_rusinov@91
|
50 |
is_rusinov@75
|
51 def start(self, event=None): |
is_rusinov@8
|
52 if not self.is_started: |
is_rusinov@7
|
53 self.is_started = True |
is_rusinov@43
|
54 self.repeat() |
is_rusinov@87
|
55 self.update_status() |
is_rusinov@86
|
56 |
is_rusinov@43
|
57 def repeat(self): |
is_rusinov@86
|
58 self.draw_cell(automata.next_step()) |
is_rusinov@43
|
59 self.after_id = canvas.after(self.delay, self.repeat) |
is_rusinov@5
|
60 |
is_rusinov@75
|
61 def stop(self, event=None): |
is_rusinov@29
|
62 canvas.after_cancel(self.after_id) |
is_rusinov@7
|
63 self.is_started = False |
is_rusinov@87
|
64 self.update_status() |
is_rusinov@5
|
65 |
is_rusinov@75
|
66 def next_step(self, event=None): |
is_rusinov@86
|
67 if self.is_started: |
is_rusinov@86
|
68 canvas.after_cancel(self.after_id) |
is_rusinov@86
|
69 self.is_started = False |
is_rusinov@87
|
70 self.update_status() |
is_rusinov@86
|
71 else: |
is_rusinov@86
|
72 self.draw_cell(automata.next_step()) |
is_rusinov@5
|
73 |
is_rusinov@75
|
74 def save_file(self, event=None): |
is_rusinov@91
|
75 file = tkFileDialog.asksaveasfile(defaultextension=".caf", |
is_rusinov@91
|
76 title="Save automata as", |
darkhan@105
|
77 filetypes=[('CCA File', '*.caf')], |
darkhan@105
|
78 mode="wb") |
is_rusinov@91
|
79 if file is not None: |
is_rusinov@76
|
80 pickle.dump([automata.field, automata.states], file) |
is_rusinov@5
|
81 |
is_rusinov@75
|
82 def open_file(self, event=None): |
is_rusinov@91
|
83 file = tkFileDialog.askopenfile(title="Open file", |
darkhan@105
|
84 filetypes=[('CCA File', '*.caf')], |
darkhan@105
|
85 mode="rb") |
is_rusinov@91
|
86 if file is not None: |
is_rusinov@70
|
87 from_file = pickle.load(file) |
is_rusinov@70
|
88 automata.field = from_file[0] |
is_rusinov@70
|
89 automata.height = len(automata.field) |
is_rusinov@70
|
90 automata.width = len(automata.field[0]) |
is_rusinov@70
|
91 automata.states = from_file[1] |
is_rusinov@70
|
92 self.selected_state = None |
is_rusinov@70
|
93 self.refresh_dicts() |
is_rusinov@70
|
94 self.refresh_list() |
is_rusinov@70
|
95 self.hide_automata_window() |
is_rusinov@70
|
96 self.draw() |
is_rusinov@5
|
97 |
is_rusinov@75
|
98 def new_file(self, event=None): |
is_rusinov@91
|
99 if tkMessageBox.askyesno("Save?", |
is_rusinov@91
|
100 "Save current automata?"): |
is_rusinov@73
|
101 self.save_file() |
is_rusinov@73
|
102 new_automata = Automata() |
is_rusinov@73
|
103 automata.field = new_automata.field |
is_rusinov@73
|
104 automata.height = len(automata.field) |
is_rusinov@73
|
105 automata.width = len(automata.field[0]) |
is_rusinov@73
|
106 automata.states = new_automata.states |
is_rusinov@73
|
107 self.selected_state = None |
is_rusinov@73
|
108 self.refresh_dicts() |
is_rusinov@73
|
109 self.refresh_list() |
is_rusinov@73
|
110 self.hide_automata_window() |
is_rusinov@73
|
111 self.draw() |
is_rusinov@73
|
112 |
is_rusinov@95
|
113 def show_help_window(self): |
Ilia@103
|
114 url = 'Help.html' |
Ilia@103
|
115 webbrowser.open(url, new=1, autoraise=True) |
is_rusinov@8
|
116 |
Ilia@79
|
117 def zoom_in(self, event=None, zoom_rate=1): |
is_rusinov@7
|
118 if self.cell_size < 50: |
is_rusinov@8
|
119 self.cell_size = self.cell_size + zoom_rate |
is_rusinov@7
|
120 self.draw() |
is_rusinov@78
|
121 self.change_scroll_area() |
is_rusinov@5
|
122 |
Ilia@79
|
123 def zoom_out(self, event=None, zoom_rate=1): |
is_rusinov@7
|
124 if self.cell_size > 1: |
is_rusinov@8
|
125 self.cell_size = self.cell_size - zoom_rate |
is_rusinov@7
|
126 self.draw() |
is_rusinov@78
|
127 self.change_scroll_area() |
is_rusinov@5
|
128 |
Ilia@77
|
129 def slower(self, event=None, speed_rate=2): |
is_rusinov@87
|
130 if self.delay <= 500: |
is_rusinov@87
|
131 self.delay = self.delay * speed_rate |
is_rusinov@87
|
132 self.update_status() |
is_rusinov@5
|
133 |
Ilia@77
|
134 def faster(self, event=None, speed_rate=2): |
is_rusinov@74
|
135 self.delay = self.delay / speed_rate |
is_rusinov@74
|
136 if self.delay == 0: |
is_rusinov@74
|
137 self.delay = 1 |
is_rusinov@87
|
138 self.update_status() |
is_rusinov@5
|
139 |
is_rusinov@70
|
140 def change_size(self): |
is_rusinov@70
|
141 try: |
is_rusinov@70
|
142 dx = int(size_x.get()) - automata.width |
is_rusinov@70
|
143 dy = int(size_y.get()) - automata.height |
is_rusinov@70
|
144 position = side.get() |
is_rusinov@8
|
145 if position == 0 or position == 3 or position == 6: |
is_rusinov@8
|
146 automata.change_size(dx, 3) |
is_rusinov@8
|
147 elif position == 1 or position == 4 or position == 7: |
is_rusinov@8
|
148 automata.change_size(dx / 2, 3) |
is_rusinov@8
|
149 automata.change_size(dx - dx / 2, 1) |
is_rusinov@18
|
150 else: |
is_rusinov@8
|
151 automata.change_size(dx, 1) |
is_rusinov@8
|
152 if position == 0 or position == 1 or position == 2: |
is_rusinov@8
|
153 automata.change_size(dy, 0) |
is_rusinov@8
|
154 elif position == 3 or position == 4 or position == 5: |
is_rusinov@8
|
155 automata.change_size(dy / 2, 0) |
is_rusinov@8
|
156 automata.change_size(dy - dy / 2, 2) |
is_rusinov@18
|
157 else: |
is_rusinov@8
|
158 automata.change_size(dy, 2) |
is_rusinov@8
|
159 self.draw() |
is_rusinov@70
|
160 self.hide_size_window() |
is_rusinov@78
|
161 self.change_scroll_area() |
is_rusinov@87
|
162 self.update_status() |
is_rusinov@70
|
163 except Exception: |
is_rusinov@70
|
164 message.config(text="Operation is refused") |
is_rusinov@70
|
165 message.after(2000, self.clear_message) |
is_rusinov@87
|
166 |
darkhan@50
|
167 def draw_cell(self, cells): |
darkhan@50
|
168 for row, col in cells: |
darkhan@42
|
169 index = automata.symbols[automata.field[row][col]] |
darkhan@42
|
170 color = automata.states[index].color |
darkhan@42
|
171 canvas.itemconfig(self.cells[row][col], fill=color) |
darkhan@42
|
172 |
darkhan@32
|
173 def draw(self): |
darkhan@31
|
174 canvas.delete("all") |
darkhan@42
|
175 self.cells = [] |
darkhan@31
|
176 shift = self.cell_size + self.line_width |
is_rusinov@85
|
177 left = self.line_width |
is_rusinov@85
|
178 top = self.line_width |
darkhan@31
|
179 for row in range(automata.height): |
darkhan@42
|
180 self.cells.append([]) |
darkhan@31
|
181 for col in range(automata.width): |
darkhan@31
|
182 index = automata.symbols[automata.field[row][col]] |
darkhan@31
|
183 color = automata.states[index].color |
darkhan@42
|
184 cell = canvas.create_rectangle(left + col * shift, |
darkhan@31
|
185 top + row * shift, |
darkhan@31
|
186 left + col * shift + self.cell_size, |
darkhan@31
|
187 top + row * shift + self.cell_size, |
darkhan@50
|
188 fill=color, outline="", tag="cell") |
darkhan@42
|
189 self.cells[row].append(cell) |
is_rusinov@5
|
190 |
is_rusinov@64
|
191 def draw_line(self, x1, y1, x2, y2, order=1): |
is_rusinov@64
|
192 answer = [] |
is_rusinov@64
|
193 if abs(x1 - x2) > abs(y1 - y2): |
is_rusinov@64
|
194 dx = x2 - x1 |
is_rusinov@64
|
195 abs_dx = abs(dx) |
is_rusinov@64
|
196 dy = float(y2 - y1) |
is_rusinov@64
|
197 while x1 != x2: |
is_rusinov@64
|
198 x1 = x1 + dx / abs_dx |
is_rusinov@64
|
199 y1 = y1 + dy / abs_dx |
is_rusinov@64
|
200 answer.append((self.rounding(y1), x1)) |
is_rusinov@64
|
201 else: |
is_rusinov@64
|
202 dx = float(x2 - x1) |
is_rusinov@64
|
203 dy = y2 - y1 |
is_rusinov@64
|
204 abs_dy = abs(dy) |
is_rusinov@64
|
205 while y1 != y2: |
is_rusinov@64
|
206 x1 = x1 + dx / abs_dy |
is_rusinov@64
|
207 y1 = y1 + dy / abs_dy |
is_rusinov@64
|
208 answer.append((y1, self.rounding(x1))) |
is_rusinov@64
|
209 self.new_state(answer, order) |
is_rusinov@64
|
210 |
is_rusinov@64
|
211 def rounding(self, num): |
is_rusinov@64
|
212 return int(num + math.copysign(0.5, num)) |
is_rusinov@64
|
213 |
is_rusinov@64
|
214 def new_state(self, cells, order=1): |
is_rusinov@64
|
215 num_states = len(automata.states) |
is_rusinov@64
|
216 changed_cells = [] |
is_rusinov@64
|
217 for row, col in cells: |
is_rusinov@64
|
218 if col >= 0 and row >= 0: |
is_rusinov@64
|
219 try: |
is_rusinov@91
|
220 index = (automata.symbols[automata.field[row][col]] + |
is_rusinov@91
|
221 num_states + order) % num_states |
is_rusinov@91
|
222 if self.char is not None and self.char in self.keys: |
is_rusinov@64
|
223 index = self.keys[self.char] |
is_rusinov@64
|
224 automata.field[row][col] = automata.states[index].symbol |
is_rusinov@64
|
225 changed_cells.append((row, col)) |
is_rusinov@64
|
226 except: |
is_rusinov@64
|
227 pass |
is_rusinov@64
|
228 self.draw_cell(changed_cells) |
is_rusinov@64
|
229 |
is_rusinov@91
|
230 def press1(self, event): |
is_rusinov@85
|
231 scr_reg = canvas.cget("scrollregion").split() |
is_rusinov@85
|
232 self.dx = int(scroll_x.get()[0] * int(scr_reg[2])) |
is_rusinov@85
|
233 self.dy = int(scroll_y.get()[0] * int(scr_reg[3])) |
is_rusinov@85
|
234 self.col1 = (event.x + self.dx) / (self.cell_size + self.line_width) |
is_rusinov@85
|
235 self.row1 = (event.y + self.dy) / (self.cell_size + self.line_width) |
is_rusinov@64
|
236 if self.col1 >= 0 and self.row1 >= 0: |
is_rusinov@64
|
237 self.new_state([(self.row1, self.col1)]) |
is_rusinov@69
|
238 |
is_rusinov@91
|
239 def motion1(self, event): |
is_rusinov@85
|
240 col = (event.x + self.dx) / (self.cell_size + self.line_width) |
is_rusinov@85
|
241 row = (event.y + self.dy) / (self.cell_size + self.line_width) |
is_rusinov@64
|
242 if not (self.col1 == col and self.row1 == row): |
is_rusinov@64
|
243 if abs(self.col1 - col) <= 1 and abs(self.row1 - row) <= 1: |
is_rusinov@64
|
244 self.new_state([(row, col)]) |
is_rusinov@64
|
245 else: |
is_rusinov@64
|
246 self.draw_line(self.col1, self.row1, col, row) |
is_rusinov@64
|
247 self.col1 = col |
is_rusinov@64
|
248 self.row1 = row |
is_rusinov@5
|
249 |
is_rusinov@91
|
250 def press3(self, event): |
is_rusinov@85
|
251 scr_reg = canvas.cget("scrollregion").split() |
is_rusinov@85
|
252 self.dx = int(scroll_x.get()[0] * int(scr_reg[2])) |
is_rusinov@85
|
253 self.dy = int(scroll_y.get()[0] * int(scr_reg[3])) |
is_rusinov@85
|
254 self.col3 = (event.x + self.dx) / (self.cell_size + self.line_width) |
is_rusinov@85
|
255 self.row3 = (event.y + self.dy) / (self.cell_size + self.line_width) |
is_rusinov@64
|
256 if self.col1 >= 0 and self.row1 >= 0: |
is_rusinov@64
|
257 self.new_state([(self.row3, self.col3)], -1) |
is_rusinov@54
|
258 |
is_rusinov@91
|
259 def motion3(self, event): |
is_rusinov@85
|
260 col = (event.x + self.dx) / (self.cell_size + self.line_width) |
is_rusinov@85
|
261 row = (event.y + self.dy) / (self.cell_size + self.line_width) |
is_rusinov@64
|
262 if not (self.col3 == col and self.row3 == row): |
is_rusinov@64
|
263 if abs(self.col3 - col) <= 1 and abs(self.row3 - row) <= 1: |
is_rusinov@64
|
264 self.new_state([(row, col)], -1) |
is_rusinov@64
|
265 else: |
is_rusinov@64
|
266 self.draw_line(self.col3, self.row3, col, row, -1) |
is_rusinov@64
|
267 self.col3 = col |
is_rusinov@64
|
268 self.row3 = row |
is_rusinov@5
|
269 |
is_rusinov@91
|
270 def press_key(self, event): |
is_rusinov@54
|
271 self.char = event.char |
is_rusinov@5
|
272 |
is_rusinov@91
|
273 def release_key(self, event): |
is_rusinov@54
|
274 self.char = None |
is_rusinov@18
|
275 |
is_rusinov@91
|
276 def to_top(self): |
is_rusinov@64
|
277 selected = self.selected_state |
is_rusinov@91
|
278 if selected is not None: |
is_rusinov@64
|
279 index = selected |
is_rusinov@58
|
280 state = automata.states[index] |
is_rusinov@58
|
281 del automata.states[index] |
is_rusinov@58
|
282 automata.states.insert(0, state) |
is_rusinov@64
|
283 self.selected_state = 0 |
is_rusinov@69
|
284 self.refresh_dicts() |
is_rusinov@58
|
285 self.refresh_list() |
is_rusinov@7
|
286 |
is_rusinov@91
|
287 def to_bottom(self): |
is_rusinov@64
|
288 selected = self.selected_state |
is_rusinov@91
|
289 if selected is not None: |
is_rusinov@64
|
290 index = selected |
is_rusinov@58
|
291 state = automata.states[index] |
is_rusinov@58
|
292 del automata.states[index] |
is_rusinov@58
|
293 automata.states.append(state) |
is_rusinov@64
|
294 self.selected_state = len(automata.states) - 1 |
is_rusinov@69
|
295 self.refresh_dicts() |
is_rusinov@58
|
296 self.refresh_list() |
is_rusinov@7
|
297 |
is_rusinov@8
|
298 def upwards(self): |
is_rusinov@64
|
299 selected = self.selected_state |
is_rusinov@91
|
300 if selected is not None: |
is_rusinov@64
|
301 index = selected |
is_rusinov@58
|
302 if index > 0: |
is_rusinov@58
|
303 state = automata.states[index] |
is_rusinov@58
|
304 del automata.states[index] |
is_rusinov@58
|
305 automata.states.insert(index - 1, state) |
is_rusinov@64
|
306 self.selected_state = index - 1 |
is_rusinov@69
|
307 self.refresh_dicts() |
is_rusinov@58
|
308 self.refresh_list() |
is_rusinov@7
|
309 |
is_rusinov@8
|
310 def downwards(self): |
is_rusinov@64
|
311 selected = self.selected_state |
is_rusinov@91
|
312 if selected is not None: |
is_rusinov@64
|
313 index = selected |
is_rusinov@58
|
314 if index < state_list.size() - 1: |
is_rusinov@58
|
315 state = automata.states[index] |
is_rusinov@58
|
316 del automata.states[index] |
is_rusinov@58
|
317 automata.states.insert(index + 1, state) |
is_rusinov@64
|
318 self.selected_state = index + 1 |
is_rusinov@69
|
319 self.refresh_dicts() |
is_rusinov@58
|
320 self.refresh_list() |
is_rusinov@7
|
321 |
is_rusinov@91
|
322 def delete_state(self): |
is_rusinov@64
|
323 selected = self.selected_state |
is_rusinov@91
|
324 if selected is not None and len(automata.states) != 1: |
is_rusinov@64
|
325 index = selected |
is_rusinov@69
|
326 symbol = automata.states[index].symbol |
is_rusinov@65
|
327 del automata.states[index] |
is_rusinov@69
|
328 self.refresh_dicts() |
is_rusinov@65
|
329 if index in automata.states: |
is_rusinov@65
|
330 self.selected_state = index |
is_rusinov@69
|
331 else: |
is_rusinov@65
|
332 self.selected_state = len(automata.states) - 1 |
is_rusinov@58
|
333 self.refresh_list() |
is_rusinov@65
|
334 self.select_item(self.selected_state) |
is_rusinov@69
|
335 self.draw_changed_state(symbol, automata.states[0].symbol) |
is_rusinov@69
|
336 else: |
is_rusinov@69
|
337 error.config(text="Operation is refused") |
is_rusinov@69
|
338 error.after(2000, self.clear_error) |
is_rusinov@7
|
339 |
is_rusinov@91
|
340 def add(self): |
is_rusinov@29
|
341 name = state_name.get() |
is_rusinov@48
|
342 symbol = state_symbol.get() |
is_rusinov@54
|
343 key = state_key.get().lower() |
is_rusinov@64
|
344 color = state_color.cget("bg") |
is_rusinov@29
|
345 nums = [] |
is_rusinov@29
|
346 for i, value in enumerate(ckeckbox_nums): |
is_rusinov@65
|
347 if value.get() == 1: |
is_rusinov@65
|
348 nums.append(i) |
is_rusinov@54
|
349 if self.keys.has_key(key): |
is_rusinov@29
|
350 error.config(text="State with such key has already existed") |
is_rusinov@69
|
351 error.after(2000, self.clear_error) |
is_rusinov@29
|
352 state_key.focus() |
is_rusinov@29
|
353 elif len(key) != 1: |
is_rusinov@29
|
354 error.config(text="Bad key for state") |
is_rusinov@69
|
355 error.after(2000, self.clear_error) |
is_rusinov@29
|
356 state_key.focus() |
is_rusinov@29
|
357 elif automata.symbols.has_key(symbol): |
is_rusinov@29
|
358 error.config(text="State with such symbol has already existed") |
is_rusinov@69
|
359 error.after(2000, self.clear_error) |
is_rusinov@29
|
360 state_symbol.focus() |
is_rusinov@29
|
361 elif len(symbol) != 1: |
is_rusinov@29
|
362 error.config(text="Bad symbol for state") |
is_rusinov@69
|
363 error.after(2000, self.clear_error) |
is_rusinov@29
|
364 state_symbol.focus() |
is_rusinov@29
|
365 else: |
is_rusinov@69
|
366 state = State(name, symbol, color, key, nums) |
is_rusinov@29
|
367 automata.states.append(state) |
is_rusinov@34
|
368 automata.symbols[symbol] = len(automata.states) - 1 |
is_rusinov@34
|
369 self.keys[key] = len(automata.states) - 1 |
is_rusinov@58
|
370 error.config(text="") |
is_rusinov@65
|
371 self.selected_state = len(automata.states) - 1 |
is_rusinov@58
|
372 self.refresh_list() |
is_rusinov@65
|
373 self.select_item(self.selected_state) |
is_rusinov@66
|
374 automata.st_sym[symbol] = state |
is_rusinov@5
|
375 |
is_rusinov@91
|
376 def change(self): |
is_rusinov@64
|
377 selected = self.selected_state |
is_rusinov@91
|
378 if selected is not None: |
is_rusinov@64
|
379 index = selected |
is_rusinov@58
|
380 name = state_name.get() |
is_rusinov@58
|
381 symbol = state_symbol.get() |
is_rusinov@58
|
382 key = state_key.get().lower() |
is_rusinov@64
|
383 color = state_color.cget("bg") |
is_rusinov@58
|
384 nums = [] |
is_rusinov@58
|
385 for i, value in enumerate(ckeckbox_nums): |
is_rusinov@58
|
386 if value.get() == 1: |
is_rusinov@58
|
387 nums.append(i) |
is_rusinov@58
|
388 if self.keys.has_key(key) and self.keys[key] != index: |
is_rusinov@91
|
389 error.config(text="This key is already used") |
is_rusinov@69
|
390 error.after(2000, self.clear_error) |
is_rusinov@58
|
391 state_key.focus() |
is_rusinov@58
|
392 elif len(key) != 1: |
is_rusinov@58
|
393 error.config(text="Bad key for state") |
is_rusinov@69
|
394 error.after(2000, self.clear_error) |
is_rusinov@58
|
395 state_key.focus() |
is_rusinov@91
|
396 elif (automata.symbols.has_key(symbol) and |
is_rusinov@93
|
397 automata.symbols[symbol] != index): |
is_rusinov@91
|
398 error.config(text="This symbol is already used") |
is_rusinov@69
|
399 error.after(2000, self.clear_error) |
is_rusinov@58
|
400 state_symbol.focus() |
is_rusinov@58
|
401 elif len(symbol) != 1: |
is_rusinov@58
|
402 error.config(text="Bad symbol for state") |
is_rusinov@69
|
403 error.after(2000, self.clear_error) |
is_rusinov@58
|
404 state_symbol.focus() |
is_rusinov@58
|
405 else: |
is_rusinov@69
|
406 state = State(name, symbol, color, key, nums) |
is_rusinov@72
|
407 symbol_old = automata.states[index].symbol |
is_rusinov@66
|
408 automata.states[index] = state |
is_rusinov@69
|
409 self.refresh_dicts() |
is_rusinov@72
|
410 self.draw_changed_state(symbol_old, symbol) |
is_rusinov@58
|
411 self.refresh_list() |
is_rusinov@54
|
412 |
is_rusinov@69
|
413 def draw_changed_state(self, symbol_old, symbol_new): |
is_rusinov@69
|
414 cells = [] |
is_rusinov@69
|
415 for row in range(automata.height): |
is_rusinov@69
|
416 for col in range(automata.width): |
is_rusinov@69
|
417 if automata.field[row][col] == symbol_old: |
is_rusinov@69
|
418 automata.field[row][col] = symbol_new |
is_rusinov@69
|
419 cells.append((row, col)) |
is_rusinov@69
|
420 self.draw_cell(cells) |
is_rusinov@69
|
421 |
is_rusinov@75
|
422 def show_size_window(self, event=None): |
is_rusinov@91
|
423 sizes = str(len(automata.field[0])) + " x " + str(len(automata.field)) |
is_rusinov@91
|
424 size_label.config(text=sizes) |
is_rusinov@18
|
425 size_window.deiconify() |
Ilia@55
|
426 |
is_rusinov@75
|
427 def hide_size_window(self, event=None): |
is_rusinov@18
|
428 size_window.withdraw() |
Ilia@55
|
429 |
Ilia@55
|
430 def show_automata_window(self): |
is_rusinov@70
|
431 self.select_item(self.selected_state) |
is_rusinov@70
|
432 self.refresh_list |
Ilia@55
|
433 automata_window.deiconify() |
Ilia@55
|
434 |
Ilia@55
|
435 def hide_automata_window(self): |
Ilia@55
|
436 automata_window.withdraw() |
is_rusinov@65
|
437 |
is_rusinov@58
|
438 def refresh_list(self): |
is_rusinov@58
|
439 state_list.delete(0, "end") |
is_rusinov@58
|
440 for state in automata.states: |
is_rusinov@58
|
441 state_list.insert("end", state) |
is_rusinov@91
|
442 if self.selected_state is not None: |
is_rusinov@64
|
443 state_list.selection_set(self.selected_state) |
is_rusinov@65
|
444 |
is_rusinov@65
|
445 def select_item(self, index): |
is_rusinov@91
|
446 if index is not None: |
is_rusinov@58
|
447 state = automata.states[index] |
is_rusinov@58
|
448 state_name.delete(0, "end") |
is_rusinov@58
|
449 state_name.insert(0, state.name) |
is_rusinov@58
|
450 state_symbol.delete(0, "end") |
is_rusinov@58
|
451 state_symbol.insert(0, state.symbol) |
is_rusinov@58
|
452 for key in self.keys.keys(): |
is_rusinov@58
|
453 if self.keys[key] == index: |
is_rusinov@58
|
454 state_key.delete(0, "end") |
is_rusinov@58
|
455 state_key.insert(0, key) |
is_rusinov@64
|
456 state_color.config(bg=state.color) |
is_rusinov@58
|
457 for i in range(9): |
is_rusinov@58
|
458 ckeckbox_nums[i].set(i in state.nums) |
is_rusinov@65
|
459 else: |
is_rusinov@65
|
460 state_name.delete(0, "end") |
is_rusinov@65
|
461 state_symbol.delete(0, "end") |
is_rusinov@65
|
462 state_key.delete(0, "end") |
is_rusinov@65
|
463 state_color.config(bg="white") |
is_rusinov@65
|
464 for i in range(9): |
is_rusinov@65
|
465 ckeckbox_nums[i].set(False) |
is_rusinov@64
|
466 |
is_rusinov@65
|
467 def list_mouse_release(self, event): |
is_rusinov@65
|
468 selected = state_list.curselection() |
is_rusinov@65
|
469 self.selected_state = int(selected[0]) |
is_rusinov@91
|
470 if selected: |
is_rusinov@65
|
471 self.select_item(self.selected_state) |
is_rusinov@69
|
472 |
is_rusinov@64
|
473 def choose_color(self, event): |
is_rusinov@64
|
474 state_color.config(bg=tkColorChooser.askcolor()[1]) |
is_rusinov@69
|
475 |
is_rusinov@69
|
476 def clear_error(self): |
is_rusinov@69
|
477 error.config(text="") |
is_rusinov@69
|
478 |
is_rusinov@70
|
479 def clear_message(self): |
is_rusinov@70
|
480 message.config(text="") |
is_rusinov@70
|
481 |
is_rusinov@75
|
482 def clean_field(self, event=None): |
is_rusinov@69
|
483 symbol = automata.states[0].symbol |
is_rusinov@69
|
484 cells = [] |
is_rusinov@69
|
485 for row in range(automata.height): |
is_rusinov@69
|
486 for col in range(automata.width): |
is_rusinov@69
|
487 if automata.field[row][col] != symbol: |
is_rusinov@69
|
488 automata.field[row][col] = symbol |
is_rusinov@69
|
489 cells.append((row, col)) |
is_rusinov@69
|
490 self.draw_cell(cells) |
is_rusinov@69
|
491 |
is_rusinov@75
|
492 def fill_randomly(self, event=None): |
is_rusinov@69
|
493 cells = [] |
is_rusinov@69
|
494 for row in range(automata.height): |
is_rusinov@69
|
495 for col in range(automata.width): |
is_rusinov@91
|
496 rand_index = random.randint(0, len(automata.states) - 1) |
is_rusinov@91
|
497 automata.field[row][col] = automata.states[rand_index].symbol |
is_rusinov@69
|
498 cells.append((row, col)) |
is_rusinov@69
|
499 self.draw_cell(cells) |
is_rusinov@69
|
500 |
is_rusinov@69
|
501 def refresh_dicts(self): |
is_rusinov@69
|
502 automata.symbols = {} |
is_rusinov@69
|
503 automata.st_sym = {} |
is_rusinov@69
|
504 self.keys = {} |
is_rusinov@69
|
505 for index, state in enumerate(automata.states): |
is_rusinov@69
|
506 automata.symbols[state.symbol] = index |
is_rusinov@69
|
507 automata.st_sym[state.symbol] = state |
is_rusinov@69
|
508 self.keys[state.key] = index |
is_rusinov@69
|
509 |
Ilia@77
|
510 def exit(self, event=None): |
is_rusinov@91
|
511 if tkMessageBox.askyesno("Save?", "Save current automata?"): |
is_rusinov@78
|
512 self.save_file() |
is_rusinov@78
|
513 root.destroy() |
is_rusinov@78
|
514 |
is_rusinov@78
|
515 def change_scroll_area(self): |
is_rusinov@91
|
516 step = self.cell_size + self.line_width |
is_rusinov@91
|
517 width = automata.width * step + self.line_width |
is_rusinov@91
|
518 height = automata.height * step + self.line_width |
is_rusinov@78
|
519 canvas.config(scrollregion=(0, 0, width, height)) |
is_rusinov@91
|
520 |
is_rusinov@87
|
521 def update_status(self): |
is_rusinov@91
|
522 size = str(len(automata.field[0])) + " x " + str(len(automata.field)) |
is_rusinov@91
|
523 status_size.config(text="size: " + size) |
is_rusinov@87
|
524 state = "paused" |
is_rusinov@87
|
525 speed = 0 |
is_rusinov@87
|
526 if self.is_started: |
is_rusinov@87
|
527 state = "running" |
is_rusinov@87
|
528 speed = 512 / self.delay |
is_rusinov@87
|
529 status_state.config(text="status: " + state) |
is_rusinov@87
|
530 status_speed.config(text="speed: " + str(speed)) |
Ilia@55
|
531 |
Ilia@6
|
532 |
Ilia@6
|
533 root = Tk() |
Ilia@36
|
534 root.title("Cyclic Cellular Automata") |
Ilia@6
|
535 |
darkhan@42
|
536 canvas = Canvas(root, background="grey") |
Ilia@6
|
537 canvas.config(width=500, height=400) |
Ilia@6
|
538 |
is_rusinov@54
|
539 automata = Automata() |
Ilia@36
|
540 handlers = Handlers() |
Ilia@36
|
541 |
is_rusinov@54
|
542 canvas.tag_bind("cell", "<1>", handlers.press1) |
is_rusinov@64
|
543 canvas.tag_bind("cell", "<B1-Motion>", handlers.motion1) |
is_rusinov@54
|
544 canvas.tag_bind("cell", "<3>", handlers.press3) |
is_rusinov@64
|
545 canvas.tag_bind("cell", "<B3-Motion>", handlers.motion3) |
is_rusinov@54
|
546 canvas.bind_all("<KeyPress>", handlers.press_key) |
is_rusinov@54
|
547 canvas.bind_all("<KeyRelease>", handlers.release_key) |
Ilia@36
|
548 |
is_rusinov@87
|
549 scroll_x = Scrollbar(root, orient="horizontal") |
is_rusinov@87
|
550 scroll_y = Scrollbar(root, orient="vertical") |
is_rusinov@87
|
551 statusline = Frame(root) |
is_rusinov@87
|
552 status_size = Label(statusline) |
is_rusinov@87
|
553 status_state = Label(statusline) |
is_rusinov@87
|
554 status_speed = Label(statusline) |
is_rusinov@87
|
555 |
is_rusinov@87
|
556 handlers.update_status() |
Ilia@79
|
557 |
Ilia@79
|
558 canvas.grid(row=0, column=0, sticky="nsew") |
Ilia@79
|
559 scroll_y.grid(row=0, column=1, sticky="ns") |
Ilia@79
|
560 scroll_x.grid(row=1, column=0, sticky="ew") |
is_rusinov@87
|
561 statusline.grid(row=2, column=0, sticky="ew") |
is_rusinov@87
|
562 status_size.grid(row=0, column=0, sticky="w") |
is_rusinov@87
|
563 status_state.grid(row=0, column=1, sticky="w") |
is_rusinov@87
|
564 status_speed.grid(row=0, column=2, sticky="w") |
Ilia@79
|
565 |
Ilia@79
|
566 handlers.change_scroll_area() |
Ilia@79
|
567 canvas.config(xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set) |
Ilia@79
|
568 scroll_x.config(command=canvas.xview) |
Ilia@79
|
569 scroll_y.config(command=canvas.yview) |
Ilia@79
|
570 root.columnconfigure(0, weight=1) |
Ilia@79
|
571 root.rowconfigure(0, weight=1) |
is_rusinov@87
|
572 statusline.columnconfigure(0, weight=1) |
is_rusinov@87
|
573 statusline.columnconfigure(1, weight=1) |
is_rusinov@87
|
574 statusline.columnconfigure(2, weight=1) |
Ilia@79
|
575 |
Ilia@55
|
576 automata_window = Toplevel(root) |
darkhan@98
|
577 automata_window.title("Automaton") |
Ilia@55
|
578 automata_window.withdraw() |
Ilia@55
|
579 automata_window.resizable(False, False) |
Ilia@55
|
580 automata_window.protocol("WM_DELETE_WINDOW", handlers.hide_automata_window) |
Ilia@9
|
581 |
darkhan@98
|
582 headline = Label(automata_window, text="Automaton Panel", font=16) |
Ilia@55
|
583 headline.pack(side="top",fill="both", expand="no") |
Ilia@9
|
584 |
is_rusinov@91
|
585 Label(automata_window, text="State Box:").pack(side="top", fill="x") |
Ilia@56
|
586 |
is_rusinov@91
|
587 list_frame = Frame(automata_window) |
Ilia@56
|
588 scrollbar = Scrollbar(list_frame) |
Ilia@57
|
589 scrollbar.pack(side="right", fill="y") |
is_rusinov@91
|
590 state_list = Listbox(list_frame, yscrollcommand=scrollbar.set, |
is_rusinov@91
|
591 activestyle="none", selectmode="single") |
is_rusinov@58
|
592 handlers.refresh_list() |
is_rusinov@58
|
593 state_list.bind("<ButtonRelease-1>", handlers.list_mouse_release) |
is_rusinov@7
|
594 state_list.pack(side="top", fill="y") |
Ilia@56
|
595 scrollbar.config(command=state_list.yview) |
Ilia@56
|
596 list_frame.pack(side="top") |
Ilia@56
|
597 |
Ilia@59
|
598 manip_frame1 = Frame(automata_window, padx=10, pady=5) |
Ilia@59
|
599 up = Button(manip_frame1, text="Up", command=handlers.upwards, width=10) |
me@94
|
600 to_top = Button(manip_frame1, text="To Top", |
me@94
|
601 command=handlers.to_top, width=10) |
Ilia@59
|
602 up.pack(side="left", fill="x") |
Ilia@59
|
603 to_top.pack(side="right", fill="x") |
Ilia@59
|
604 manip_frame1.pack(side="top", fill="x") |
Ilia@59
|
605 |
Ilia@59
|
606 manip_frame2 = Frame(automata_window, padx=10, pady=5) |
me@94
|
607 down = Button(manip_frame2, text="Down", |
me@94
|
608 command=handlers.downwards, width=10) |
is_rusinov@91
|
609 to_bottom = Button(manip_frame2, text="To Bottom", |
is_rusinov@91
|
610 command=handlers.to_bottom, width=10) |
Ilia@59
|
611 down.pack(side="left", fill="x") |
Ilia@59
|
612 to_bottom.pack(side="right", fill="x") |
Ilia@59
|
613 manip_frame2.pack(side="top", fill="x") |
Ilia@59
|
614 |
is_rusinov@91
|
615 delete = Button(automata_window, text="Delete", |
is_rusinov@91
|
616 command=handlers.delete_state, width=10) |
Ilia@59
|
617 delete.pack(side="top") |
Ilia@6
|
618 |
is_rusinov@91
|
619 information = Label(automata_window, text="Information of State") |
Ilia@9
|
620 information.pack(side="top", fill="x") |
is_rusinov@91
|
621 info_frame = Frame(automata_window) |
Ilia@9
|
622 Label(info_frame, text="Name").grid(row=0, column=0) |
Ilia@9
|
623 state_name = Entry(info_frame) |
Ilia@9
|
624 state_name.grid(row=0, column=1) |
Ilia@9
|
625 Label(info_frame, text="Symbol").grid(row=1, column=0) |
Ilia@9
|
626 state_symbol = Entry(info_frame) |
Ilia@9
|
627 state_symbol.grid(row=1, column=1) |
Ilia@60
|
628 Label(info_frame, text="Key").grid(row=2, column=0) |
Ilia@9
|
629 state_key = Entry(info_frame) |
Ilia@60
|
630 state_key.grid(row=2, column=1) |
Ilia@60
|
631 Label(info_frame, text="Color").grid(row=3, column=0) |
Ilia@60
|
632 state_color = Label(info_frame, background="white", cursor="plus") |
Ilia@60
|
633 state_color.grid(row=3, column=1, sticky="ew") |
is_rusinov@64
|
634 state_color.bind('<1>', handlers.choose_color) |
Ilia@9
|
635 info_frame.pack(side="top") |
Ilia@9
|
636 |
Ilia@36
|
637 ckeckbox_nums = [IntVar(), IntVar(), IntVar(), IntVar(), IntVar(), |
Ilia@36
|
638 IntVar(), IntVar(), IntVar(), IntVar()] |
Ilia@33
|
639 |
is_rusinov@91
|
640 condition = Label(automata_window, text="Condition of conversion") |
Ilia@9
|
641 condition.pack(side="top", fill="x") |
is_rusinov@91
|
642 condition_frame = Frame(automata_window) |
Ilia@9
|
643 Label(condition_frame, text="0: ").grid(row=0, column=0) |
Ilia@39
|
644 c_button_0 = Checkbutton(condition_frame, variable=ckeckbox_nums[0]) |
Ilia@36
|
645 c_button_0.grid(row=0, column=1) |
Ilia@9
|
646 Label(condition_frame, text="1: ").grid(row=0, column=2) |
Ilia@39
|
647 c_button_1 = Checkbutton(condition_frame, variable=ckeckbox_nums[1]) |
Ilia@36
|
648 c_button_1.grid(row=0, column=3) |
Ilia@9
|
649 Label(condition_frame, text="2: ").grid(row=0, column=4) |
Ilia@39
|
650 c_button_2 = Checkbutton(condition_frame, variable=ckeckbox_nums[2]) |
Ilia@36
|
651 c_button_2.grid(row=0, column=5) |
Ilia@9
|
652 Label(condition_frame, text="3: ").grid(row=1, column=0) |
Ilia@39
|
653 c_button_3 = Checkbutton(condition_frame, variable=ckeckbox_nums[3]) |
Ilia@36
|
654 c_button_3.grid(row=1, column=1) |
Ilia@9
|
655 Label(condition_frame, text="4: ").grid(row=1, column=2) |
Ilia@39
|
656 c_button_4 = Checkbutton(condition_frame, variable=ckeckbox_nums[4]) |
Ilia@36
|
657 c_button_4.grid(row=1, column=3) |
Ilia@9
|
658 Label(condition_frame, text="5: ").grid(row=1, column=4) |
Ilia@39
|
659 c_button_5 = Checkbutton(condition_frame, variable=ckeckbox_nums[5]) |
Ilia@36
|
660 c_button_5.grid(row=1, column=5) |
Ilia@9
|
661 Label(condition_frame, text="6: ").grid(row=2, column=0) |
Ilia@39
|
662 c_button_6 = Checkbutton(condition_frame, variable=ckeckbox_nums[6]) |
Ilia@36
|
663 c_button_6.grid(row=2, column=1) |
Ilia@9
|
664 Label(condition_frame, text="7: ").grid(row=2, column=2) |
Ilia@39
|
665 c_button_7 = Checkbutton(condition_frame, variable=ckeckbox_nums[7]) |
Ilia@36
|
666 c_button_7.grid(row=2, column=3) |
Ilia@9
|
667 Label(condition_frame, text="8: ").grid(row=2, column=4) |
Ilia@39
|
668 c_button_8 = Checkbutton(condition_frame, variable=ckeckbox_nums[8]) |
Ilia@36
|
669 c_button_8.grid(row=2, column=5) |
Ilia@9
|
670 condition_frame.pack(side="top") |
Ilia@9
|
671 |
Ilia@59
|
672 add_frame = Frame(automata_window, padx=10, pady=5) |
Ilia@59
|
673 add_state = Button(add_frame, text="Add", command=handlers.add, width=10) |
is_rusinov@91
|
674 change_state = Button(add_frame, text="Change", |
is_rusinov@91
|
675 command=handlers.change, width=10) |
Ilia@59
|
676 add_state.pack(side="left", fill="x") |
Ilia@59
|
677 change_state.pack(side="right", fill="x") |
Ilia@59
|
678 add_frame.pack(side="top", fill="x") |
Ilia@9
|
679 |
is_rusinov@91
|
680 error = Label(automata_window) |
Ilia@9
|
681 error.pack(side="top", fill="x") |
is_rusinov@8
|
682 |
is_rusinov@70
|
683 side = IntVar() |
Ilia@12
|
684 |
Ilia@12
|
685 size_window = Toplevel(root) |
Ilia@12
|
686 size_window.title("") |
Ilia@13
|
687 size_window.withdraw() |
Ilia@55
|
688 size_window.resizable(False, False) |
Ilia@12
|
689 size_window.protocol("WM_DELETE_WINDOW", handlers.hide_size_window) |
me@94
|
690 Label(size_window, text="Current window size:").pack(side="top", fill="x") |
is_rusinov@93
|
691 size_label = Label(size_window) |
is_rusinov@91
|
692 size_label.pack(side="top", fill="x") |
is_rusinov@91
|
693 Label(size_window, text="New size:").pack(side="top", fill="x") |
Ilia@12
|
694 new_size = Frame(size_window) |
Ilia@12
|
695 size_x = Entry(new_size, width=5) |
Ilia@12
|
696 size_x.grid(row=0, column=0) |
Ilia@12
|
697 Label(new_size, text=" x ").grid(row=0, column=1) |
Ilia@12
|
698 size_y = Entry(new_size, width=5) |
Ilia@12
|
699 size_y.grid(row=0, column=2) |
Ilia@12
|
700 new_size.pack(side="top") |
is_rusinov@91
|
701 Label(size_window, text="Expansion of window:").pack(side="top", fill="x") |
Ilia@12
|
702 expansion = Frame(size_window) |
is_rusinov@91
|
703 r0 = Radiobutton(expansion, variable=side, value=0, indicatoron=0, |
is_rusinov@91
|
704 width=2, height=1) |
Ilia@12
|
705 r0.select() |
is_rusinov@91
|
706 r0.grid(row=0, column=0) |
is_rusinov@91
|
707 r1 = Radiobutton(expansion, variable=side, value=1, indicatoron=0, |
is_rusinov@91
|
708 width=2, height=1) |
is_rusinov@91
|
709 r1.grid(row=0, column=1) |
is_rusinov@91
|
710 r2 = Radiobutton(expansion, variable=side, value=2, indicatoron=0, |
is_rusinov@91
|
711 width=2, height=1) |
is_rusinov@91
|
712 r2.grid(row=0, column=2) |
is_rusinov@91
|
713 r3 = Radiobutton(expansion, variable=side, value=3, indicatoron=0, |
is_rusinov@91
|
714 width=2, height=1) |
is_rusinov@91
|
715 r3.grid(row=1, column=0) |
is_rusinov@91
|
716 r4 = Radiobutton(expansion, variable=side, value=4, indicatoron=0, |
is_rusinov@91
|
717 width=2, height=1) |
is_rusinov@91
|
718 r4.grid(row=1, column=1) |
is_rusinov@91
|
719 r5 = Radiobutton(expansion, variable=side, value=5, indicatoron=0, |
is_rusinov@91
|
720 width=2, height=1) |
is_rusinov@91
|
721 r5.grid(row=1, column=2) |
is_rusinov@91
|
722 r6 = Radiobutton(expansion, variable=side, value=6, indicatoron=0, |
is_rusinov@91
|
723 width=2, height=1) |
is_rusinov@91
|
724 r6.grid(row=2, column=0) |
is_rusinov@91
|
725 r7 = Radiobutton(expansion, variable=side, value=7, indicatoron=0, |
is_rusinov@91
|
726 width=2, height=1) |
is_rusinov@91
|
727 r7.grid(row=2, column=1) |
is_rusinov@91
|
728 r8 = Radiobutton(expansion, variable=side, value=8, indicatoron=0, |
is_rusinov@91
|
729 width=2, height=1) |
Ilia@12
|
730 r8.grid(row=2, column=2) |
Ilia@12
|
731 expansion.pack(side="top") |
Ilia@12
|
732 Label(size_window).pack(side="top", fill="x") |
Ilia@12
|
733 apply_frame = Frame(size_window, padx=10, pady=5) |
is_rusinov@91
|
734 apply_size = Button(apply_frame, text="Apply", width=6, |
is_rusinov@91
|
735 command=handlers.change_size) |
Ilia@12
|
736 apply_size.pack(side="left", fill="x") |
is_rusinov@91
|
737 close_size = Button(apply_frame, text="Close", width=6, |
is_rusinov@91
|
738 command=handlers.hide_size_window) |
Ilia@12
|
739 close_size.pack(side="right", fill="x") |
Ilia@12
|
740 apply_frame.pack(side="top", fill="x") |
is_rusinov@70
|
741 message = Label(size_window, text="") |
is_rusinov@70
|
742 message.pack(side="top", fill="x") |
Ilia@6
|
743 menubar = Menu(root) |
Ilia@6
|
744 root.config(menu=menubar) |
Ilia@6
|
745 |
Ilia@6
|
746 menu_file = Menu(menubar) |
is_rusinov@91
|
747 menu_file.add_command(label="New", command=handlers.new_file, |
is_rusinov@91
|
748 accelerator="Ctrl+N") |
Ilia@77
|
749 menu_file.bind_all("<Control-n>", handlers.new_file) |
is_rusinov@91
|
750 menu_file.add_command(label="Open...", command=handlers.open_file, |
is_rusinov@91
|
751 accelerator="Ctrl+O") |
Ilia@77
|
752 menu_file.bind_all("<Control-o>", handlers.open_file) |
is_rusinov@91
|
753 menu_file.add_command(label="Save...", command=handlers.save_file, |
is_rusinov@91
|
754 accelerator="Ctrl+S") |
is_rusinov@76
|
755 menu_file.bind_all("<Control-s>", handlers.save_file) |
Ilia@6
|
756 menu_file.add_separator() |
is_rusinov@91
|
757 menu_file.add_command(label="Exit", command=handlers.exit, |
is_rusinov@91
|
758 accelerator="Ctrl+Q") |
Ilia@77
|
759 menu_file.bind_all("<Control-q>", handlers.exit) |
Ilia@6
|
760 menubar.add_cascade(label="File", menu=menu_file) |
Ilia@6
|
761 |
Ilia@6
|
762 menu_action = Menu(menubar) |
is_rusinov@91
|
763 menu_action.add_command(label="Start", command=handlers.start, |
is_rusinov@91
|
764 accelerator="Ctrl+G") |
Ilia@77
|
765 menu_action.bind_all("<Control-g>", handlers.start) |
is_rusinov@91
|
766 menu_action.add_command(label="Stop", command=handlers.stop, |
is_rusinov@91
|
767 accelerator="Ctrl+F") |
Ilia@77
|
768 menu_action.bind_all("<Control-f>", handlers.stop) |
is_rusinov@91
|
769 menu_action.add_command(label="Next Step", command=handlers.next_step, |
is_rusinov@91
|
770 accelerator="Space") |
Ilia@77
|
771 menu_action.bind_all("<space>", handlers.next_step) |
Ilia@12
|
772 menu_action.add_separator() |
is_rusinov@91
|
773 menu_action.add_command(label="Increase speed", command=handlers.faster, |
is_rusinov@91
|
774 accelerator="Alt+F") |
Ilia@77
|
775 menu_action.bind_all("<Alt-f>", handlers.faster) |
is_rusinov@91
|
776 menu_action.add_command(label="Decrease speed", command=handlers.slower, |
is_rusinov@91
|
777 accelerator="Alt+S") |
Ilia@77
|
778 menu_action.bind_all("<Alt-s>", handlers.slower) |
Ilia@12
|
779 menu_action.add_separator() |
is_rusinov@91
|
780 menu_action.add_command(label="Zoom In", command=handlers.zoom_in, |
is_rusinov@91
|
781 accelerator="Ctrl+Z") |
Ilia@77
|
782 menu_action.bind_all("<Control-z>", handlers.zoom_in) |
is_rusinov@91
|
783 menu_action.add_command(label="Zoom Out", command=handlers.zoom_out, |
is_rusinov@91
|
784 accelerator="Ctrl+X") |
Ilia@77
|
785 menu_action.bind_all("<Control-x>", handlers.zoom_out) |
Ilia@12
|
786 menu_action.add_separator() |
is_rusinov@91
|
787 menu_action.add_command(label="Clean field", command=handlers.clean_field, |
is_rusinov@91
|
788 accelerator="Ctrl+C") |
Ilia@77
|
789 menu_action.bind_all("<Control-c>", handlers.clean_field) |
me@94
|
790 menu_action.add_command(label="Fill randomly", |
me@94
|
791 command=handlers.fill_randomly, |
is_rusinov@91
|
792 accelerator="Ctrl+R") |
Ilia@77
|
793 menu_action.bind_all("<Control-r>", handlers.fill_randomly) |
Ilia@13
|
794 menu_action.add_separator() |
me@94
|
795 menu_action.add_command(label="Change size", |
me@94
|
796 command=handlers.show_size_window, |
is_rusinov@91
|
797 accelerator="Ctrl+D") |
Ilia@77
|
798 menu_action.bind_all("<Control-d>", handlers.show_size_window) |
Ilia@6
|
799 menubar.add_cascade(label="Action", menu=menu_action) |
Ilia@6
|
800 |
darkhan@98
|
801 menubar.add_command(label="Automaton", command=handlers.show_automata_window) |
Ilia@6
|
802 |
is_rusinov@43
|
803 menubar.add_command(label="Help", command=handlers.show_help_window) |
Ilia@6
|
804 |
Ilia@6
|
805 root.mainloop() |