Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/cca/annotate/ef8839e99f34/interface.py
Дата изменения: Unknown
Дата индексирования: Fri Feb 28 23:48:40 2014
Кодировка:
cca: interface.py annotate

cca

annotate interface.py @ 105:ef8839e99f34

Adding GPLv2
author darkhan
date Sat, 18 Dec 2010 13:58:03 +0300
parents 136a16e31a57
children
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()