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
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
25 self.selected_state = None
26 self.is_started = False
29 for index, state in enumerate(automata.states):
30 self.keys[state.key] = index
33 def start(self, event=None):
34 if not self.is_started:
35 self.is_started = True
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
48 def next_step(self, event=None):
50 canvas.after_cancel(self.after_id)
51 self.is_started = False
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')])
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')])
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
75 self.hide_automata_window()
78 def new_file(self, event=None):
79 if tkMessageBox.askyesno("Save?",
80 "Save current automata?"):
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
90 self.hide_automata_window()
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
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
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
114 def faster(self, event=None, speed_rate=2):
115 self.delay = self.delay / speed_rate
120 def change_size(self):
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)
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)
138 automata.change_size(dy, 2)
140 self.hide_size_window()
141 self.change_scroll_area()
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)
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,
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):
173 if abs(x1 - x2) > abs(y1 - y2):
178 x1 = x1 + dx / abs_dx
179 y1 = y1 + dy / abs_dx
180 answer.append((self.rounding(y1), x1))
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)
197 for row, col in cells:
198 if col >= 0 and row >= 0:
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))
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)])
226 self.draw_line(self.col1, self.row1, col, 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)
246 self.draw_line(self.col3, self.row3, col, row, -1)
250 def press_key(self, event):
251 self.char = event.char
253 def release_key(self, event):
257 selected = self.selected_state
258 if selected is not None:
260 state = automata.states[index]
261 del automata.states[index]
262 automata.states.insert(0, state)
263 self.selected_state = 0
268 selected = self.selected_state
269 if selected is not None:
271 state = automata.states[index]
272 del automata.states[index]
273 automata.states.append(state)
274 self.selected_state = len(automata.states) - 1
279 selected = self.selected_state
280 if selected is not None:
283 state = automata.states[index]
284 del automata.states[index]
285 automata.states.insert(index - 1, state)
286 self.selected_state = index - 1
291 selected = self.selected_state
292 if selected is not None:
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
302 def delete_state(self):
303 selected = self.selected_state
304 if selected is not None and len(automata.states) != 1:
306 symbol = automata.states[index].symbol
307 del automata.states[index]
309 if index in automata.states:
310 self.selected_state = index
312 self.selected_state = len(automata.states) - 1
314 self.select_item(self.selected_state)
315 self.draw_changed_state(symbol, automata.states[0].symbol)
317 error.config(text="Operation is refused")
318 error.after(2000, self.clear_error)
321 name = state_name.get()
322 symbol = state_symbol.get()
323 key = state_key.get().lower()
324 color = state_color.cget("bg")
326 for i, value in enumerate(ckeckbox_nums):
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)
334 error.config(text="Bad key for state")
335 error.after(2000, self.clear_error)
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)
341 elif len(symbol) != 1:
342 error.config(text="Bad symbol for state")
343 error.after(2000, self.clear_error)
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
353 self.select_item(self.selected_state)
354 automata.st_sym[symbol] = state
357 selected = self.selected_state
358 if selected is not None:
360 name = state_name.get()
361 symbol = state_symbol.get()
362 key = state_key.get().lower()
363 color = state_color.cget("bg")
365 for i, value in enumerate(ckeckbox_nums):
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)
373 error.config(text="Bad key for state")
374 error.after(2000, self.clear_error)
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)
381 elif len(symbol) != 1:
382 error.config(text="Bad symbol for state")
383 error.after(2000, self.clear_error)
386 state = State(name, symbol, color, key, nums)
387 symbol_old = automata.states[index].symbol
388 automata.states[index] = state
390 self.draw_changed_state(symbol_old, symbol)
393 def draw_changed_state(self, symbol_old, symbol_new):
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)
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)
438 ckeckbox_nums[i].set(i in state.nums)
440 state_name.delete(0, "end")
441 state_symbol.delete(0, "end")
442 state_key.delete(0, "end")
443 state_color.config(bg="white")
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])
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
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):
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 = {}
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?"):
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)
508 speed = 512 / self.delay
509 status_state.config(text="status: " + state)
510 status_speed.config(text="speed: " + str(speed))
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")
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,
686 r0.grid(row=0, column=0)
687 r1 = Radiobutton(expansion, variable=side, value=1, indicatoron=0,
689 r1.grid(row=0, column=1)
690 r2 = Radiobutton(expansion, variable=side, value=2, indicatoron=0,
692 r2.grid(row=0, column=2)
693 r3 = Radiobutton(expansion, variable=side, value=3, indicatoron=0,
695 r3.grid(row=1, column=0)
696 r4 = Radiobutton(expansion, variable=side, value=4, indicatoron=0,
698 r4.grid(row=1, column=1)
699 r5 = Radiobutton(expansion, variable=side, value=5, indicatoron=0,
701 r5.grid(row=1, column=2)
702 r6 = Radiobutton(expansion, variable=side, value=6, indicatoron=0,
704 r6.grid(row=2, column=0)
705 r7 = Radiobutton(expansion, variable=side, value=7, indicatoron=0,
707 r7.grid(row=2, column=1)
708 r8 = Radiobutton(expansion, variable=side, value=8, indicatoron=0,
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")
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,
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,
755 menu_action.bind_all("<Alt-f>", handlers.faster)
756 menu_action.add_command(label="Decrease speed", command=handlers.slower,
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)