Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/cca/file/a308291203ea/interface.py
Дата изменения: Unknown
Дата индексирования: Sun Feb 3 10:42:50 2013
Кодировка:
cca: a308291203ea interface.py

cca

view interface.py @ 102:a308291203ea

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