class EdaPlacer(tk.Frame): def __init__(self, master=None): tk.Frame.__init__(self, master, relief=tk.SUNKEN, bd=2) self.create_menubar() self.master.config(menu=self.menubar) #self.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.canvas = XCanvas(self.master, bg="white", width=900, height=540, scalewidget=False, bd=0, highlightthickness=0) self.tkcon = TkConsole(self.master, height=12, width=90, background='ivory') self.status = StatusBar(self.master) self.canvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.tkcon.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.status.pack(side=tk.BOTTOM, fill=tk.X, expand=True) self.tkcon.focus_set() self.lastdir = os.environ['HOMEPATH'] self.units = [] self.title() self.status.set("Level Placer Status") #self.update() def create_menubar(self): self.menubar = tk.Menu(self) # File menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="File", menu=menu) menu.add_command(label="New", command=self.new) menu.add_command(label="Open", command=self.open) menu.add_command(label="Exit", command=self.exit) # Edit menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Edit", menu=menu) menu.add_command(label="Run Placer", command=self.place) menu.add_command(label="Collapse", command=self.collapse) menu.add_command(label="Clear ALL", command=self.clear) menu.add_separator() self.showNets = tk.IntVar(master=self.menubar, value=True) menu.add_checkbutton(label="Show nets", variable=self.showNets, command=self.draw_nets) # Help menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Help", menu=menu) menu.add_command(label="About", command=self.about) menu.add_command(label="Help", command=self.help) def new(self): easygui.msgbox("The 'new' method is not implemented yet", "Not implemented") def open(self, locfile=None): if locfile is None: filetypes = [['.loc', 'LOCATION files']] #lastdir = self.lastdir + '/*.loc' lastdir = self.lastdir locfile = easygui.fileopenbox('Dialog', 'Select Location File', default=lastdir, filetypes=filetypes) if locfile is None: return design_dir, locfile = os.path.split(locfile) design_name = os.path.splitext(locfile)[0] self.design = Design(design_dir, design_name) self.title(self.design.name) self.clear() #self.canvas.fit() self.draw_units() self.draw_nets(True) self.status.set("units=%s nets=%s Total Area = %s Total Length = %s" % \ (len(self.design.units), len(self.design.nets), self.design.total_area(), self.design.total_length())) def draw_units(self): width = self.design.tech['design_width'] height = self.design.tech['design_height'] self.canvas.config(scrollregion=(-50, -50, width + 50, height + 50)) self.canvas.draw_axis(10, 10) self.design.chip.draw(self.canvas, outline='maroon', width=3, fill=None, stipple=None, tags=['root', 'chip']) for u in self.design.units: u.draw(self.canvas, fill='red', stipple='gray12') def draw_nets(self, show=None): if show is None: show = self.showNets.get() if show: for net in self.design.nets: net.draw(self.canvas) else: self.canvas.delete('net') def place(self, netlist=None): self.clear('eda&&net') if self.units is None: print("You must open a loc file first!") return self.placer = LevelPlacer(self.design.chip, self.design.units) self.placer.run() self.unplaced_units = self.placer.list_unplaced_units() print("Unplaced units:", self.unplaced_units) for u in self.placer.list_placed_units(): #print(u) self.canvas.delete(u.name) u.draw(self.canvas, fill='green', stipple='gray12') #self.update() #time.sleep(0.05) for u in self.unplaced_units: self.canvas.tag_raise(u.name) if netlist is not None: nets = read_nets(netlist, udict) for n in nets: n.draw(self.canvas) #self.update() #time.sleep(1) self.canvas.delete(n.name) self.unplaced() def unplaced(self): "Put the unplaced units in a special container called unchip" x1 = self.design.chip.x1 y1 = self.design.chip.y1 + self.design.chip.height() + 40 x2 = self.design.chip.x2 y2 = self.design.chip.y2 + self.design.chip.height() + 40 self.unchip = Unit("unchip", x1, y1, x2, y2) self.unchip.draw(self.canvas, outline='blue', width=3, tags=['unchip', 'unplaced']) self.canvas.config(scrollregion=(-50, -50, x2 + 50, y2 + 50)) placer = LevelPlacer(self.unchip, list(self.unplaced_units), False) placer.run() for u in placer.list_placed_units(): #print(u) self.canvas.delete(u.name) u.draw(self.canvas, fill='red', stipple='gray12', tags=['unplaced']) #self.update() #time.sleep(0.05) def collapse(self): self.clear() for u in self.units: u.place(0, 0) self.draw_units() def exit(self): answer = easygui.ynbox("Exit?", "Are you sure you want to exit?") if answer: sys.exit(0) def clear(self, tag='eda'): self.canvas.delete(tag) def help(self): try: self.help_top.destroy() except: pass self.help_top = tk.Tk() self.help_top.wm_title('HELP WINDOW') t = tk.Text(self.help_top, font=('Consolas', 10, 'bold'), width=80, height=24, background='cornsilk', foreground='blue') t.insert( END, "Edit the help method:\nRead some help file and insert it here") t.pack(fill=BOTH, expand=True) def title(self, postfix=None): ttl = "Simple Shelf Placer" if not postfix is None: ttl += ":" + " " + postfix self.master.wm_title(ttl) def about(self): easygui.msgbox( "Engineering Design Project\nEEE Depatment\nSimpleton College", "About EDA Application") def debug(self, event): #print(event.keysym) #print(self.panwin.cget('sashwidth')) #self.panwin.config(sashwidth=6) #print(self.winfo_geometry()) #self.panwin.paneconfigure(self.tkcon, minsize=100) pass
class MainWindow(tk.Tk): def __init__(self): super().__init__() self.title('THEE') self.minsize(550, 40) # (width, height) self.winfo_screenwidth = self.winfo_screenwidth() self.winfo_screenheight = self.winfo_screenheight() self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.width = int(self.winfo_screenwidth / 3) self.height = int(self.winfo_screenheight / 3) self.geometry(f'{self.width}x{self.height}') self.thee_mode = 0 # 0: welcome, 1: editor, 2: terminal, 3: help self.count_text_changed = 0 self.editor_mode_buffer = "" self.terminal_mode_buffer = "" self.key_buffer = [] self.file_name = "untitled" self.status = "unsaved" self.spaces = 4 self.line = 1 self.column = 1 self.foreground = config.color['foreground'] self.background = config.color['background'] self.text_foreground = config.color['text_foreground'] self.text_background = config.color['text_background'] self.insertbackground = config.color['insertbackground'] self.statusbar_background = config.color['statusbarbg'] self.frame1 = tk.Frame(self, bg=self.background, width=self.width, height=self.height - 15) self.frame2 = tk.Frame(self, bg=self.statusbar_background, width=self.width, height=10) self.frame1.grid(row=0, column=0, sticky='wens') self.frame2.grid(row=1, column=0, sticky='wens') self.frame1.grid_columnconfigure(1, weight=1) self.frame1.grid_rowconfigure(0, weight=1) self.config_dir = os.path.join(str(Path.home()), '.thee') self.text_font_size = config.font['text']['size'] self.text_font_family = config.font['text']['family'] self.statusbar_font_size = config.font['statusbar']['size'] self.statusbar_font_family = config.font['statusbar']['family'] self.create_widget() # Entry point ==========# self.terminal = Terminal(self, self.text_area) # run terminal self.bind_events() self.open_file = '' self.protocol("WM_DELETE_WINDOW", self.close_window) def create_widget(self): self.text_area = TextArea(self.frame1, bg=self.text_background, fg=self.text_foreground, undo=True, relief=tk.FLAT, font=(self.text_font_family, self.text_font_size), insertbackground=self.insertbackground) self.text_area.config(highlightthickness=0) self.text_area.grid(row=0, column=1, sticky='wens') self.text_area.focus_set() self.welcome(event=None) self.status_bar1 = StatusBar(self.frame2, bg="pink", width=30, height=10) self.status_bar2 = StatusBar(self.frame2, bg="orange", width=30, height=10) self.status_bar3 = StatusBar(self.frame2, bg="blue", width=30, height=10) self.status_bar4 = StatusBar(self.frame2, bg="green", width=30, height=10) self.status_bar5 = StatusBar(self.frame2, bg="purple", width=30, height=10) self.status_bar1.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.status_bar2.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.status_bar3.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.status_bar4.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.status_bar5.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) def editor_mode(self, event=None): self.text_area.config(state=tk.NORMAL, tabs=4) self.text_area.delete('1.0', tk.END) self.text_area.insert(tk.END, self.editor_mode_buffer) self.highlighter = Highlighter(self.text_area) self.thee_mode = 1 self.line_numbers = LineNumbers(self.frame1, self.text_area) self.line_numbers.config(bg=self.text_background, width=len(self.line_numbers.line_number) * 10, highlightthickness=0) self.line_numbers.grid(row=0, column=0, sticky='ns') self.status_bar1.set("Line %d, Column %d" % (self.line, self.column)) self.status_bar3.set("%s" % self.file_name) self.status_bar4.set("Spaces: %d" % self.spaces) self.status_bar5.set("%s" % self.status) def terminal_mode(self, event=None): if self.thee_mode == 1: self.line_numbers.destroy() self.text_area.config(state=tk.NORMAL, tabs=4) self.text_area.delete('1.0', tk.END) self.text_area.insert(tk.END, self.terminal_mode_buffer) self.terminal.writeLoop() self.highlighter = Highlighter(self.text_area) self.thee_mode = 2 def text_been_modified(self, event=None): flag = self.text_area.edit_modified() if flag: # prevent from getting called twice if self.thee_mode == 1 and self.count_text_changed > 1: # editor mode self.editor_mode_buffer = self.text_area.get( 1.0, tk.END + "-1c") self.status = "unsaved" self.status_bar5.set("%s" % self.status) self.update_line_column() self.line_numbers.config( width=len(self.line_numbers.line_number) * 10) elif self.thee_mode == 2 and self.count_text_changed > 1: # terminal mode self.terminal_mode_buffer = self.text_area.get( 1.0, tk.END + "-1c") self.count_text_changed += 1 #reset so this will be called on the next change self.text_area.edit_modified(False) def retrieve_selected_line(self, event=None): if self.thee_mode == 1: self.current_line = self.text_area.get("1.0", 'end').rstrip() if event.keysym.isnumeric(): self.key_buffer.append(event.keysym) # check buffer after 500ms (0.5s) self.after(500, self.selected_line_action) def selected_line_action(self): if self.key_buffer: index = int(''.join(self.key_buffer)) - 1 self.key_buffer.clear() self.selected_line = self.current_line.split('\n')[index] selected_str = self.selected_line + "\n" # write selected code line(s) to the console in order to it running self.terminal.proc.stdin.write(selected_str.encode()) self.terminal.proc.stdin.flush() self.terminal_mode() def update_line_column(self, event=None): if self.thee_mode == 1: line, column = self.text_area.index(tk.INSERT).split('.') self.line = int(line) self.column = int(column) + 1 self.status_bar1.set("Line %d, Column %d" % (self.line, self.column)) def close_window(self): if self.editor_mode_buffer and self.status == "unsaved": #and self.status.get() == "unsaved": #SATUSBAR if msg.askokcancel("Quit", "Would you like to save the data?"): self.file_save() self.terminal.alive = False self.terminal.destroy() else: self.terminal.alive = False self.terminal.destroy() else: self.terminal.alive = False self.terminal.destroy() def bind_events(self): self.focus_set() self.text_area.bind_all('<<Modified>>', self.text_been_modified) self.text_area.bind('<Return>', self.enter) self.bind_all('<Button-1>', self.update_line_column) self.bind_all('<Control-e>', self.editor_mode) self.bind_all('<Control-t>', self.terminal_mode) self.bind_all('<Control-Key>', self.retrieve_selected_line) self.bind('<Control-f>', self.show_find_window) self.bind('<Control-n>', self.file_new) self.bind('<Control-o>', self.file_open) self.bind('<Control-s>', self.file_save) self.bind('<Control-S>', self.file_save_as) self.bind('<Control-w>', self.welcome) self.bind('<Control-h>', self.help_about) def enter(self, event=None): if self.thee_mode == 2: self.terminal.enter() def show_find_window(self, event=None): FindWindow(self.frame1, self.text_area) def show_welcome_page(self): if self.thee_mode == 1: self.line_numbers.destroy() self.text_area.config(state=tk.NORMAL) self.text_area.delete('1.0', tk.END) message = ''' \n\n THEE version 1.0 THE simple python key bindings Editor type Ctrl-h for help information by Fidel R. Monteiro <*****@*****.**> \n The Pynosso Project | Sat, Jun 26 2020 ''' self.text_area.insert(tk.END, message) self.text_area.config(state=tk.DISABLED) self.thee_mode = 0 def show_about_page(self): if self.thee_mode == 1: self.line_numbers.destroy() self.text_area.config(state=tk.NORMAL) self.text_area.delete('1.0', tk.END) message = ''' HELP Mode Commands Ctrl+e : Text mode Ctrl+t : Terminal mode Ctrl+<number> : Run selected line in python console Editing Commands Ctrl+a : Select all text Ctrl+x : Cut selected text Ctrl+c : Copy selected text Ctrl+v : Paste cut/copied text Ctrl+z : Undo Ctrl+y : Redo File Commands Ctrl+o : Open file Ctrl+s : Save current content Ctrl+S : Save current content as <filename> Ctrl+p : Print current content Ctrl+n : Open new file General Ctrl+m : Change syntax highlighting Ctrl+g : Change colour scheme Ctrl+l : Change font Ctrl+h : Display this help window AUTHOR Written by Fidel R. Monteiro (fm65) Sat, Jun 26 2020 thee version 1.0 "simple is better than complex" ''' self.text_area.insert(tk.END, message) self.text_area.config(state=tk.DISABLED) self.thee_mode = 3 def apply_colour_scheme(self, foreground, background, text_foreground, text_background): self.text_area.configure(fg=text_foreground, bg=text_background) self.background = background self.foreground = foreground for menu in self.all_menus: menu.configure(bg=self.background, fg=self.foreground) def update_font(self): #self.load_font_file(self.font_scheme_path) self.text_area.configure(font=(self.text_font_family, self.text_font_size)) def create_config_directory_if_needed(self): if not os.path.exists(self.config_dir): os.mkdir(self.config_dir) # =========== Menu Functions ============== def file_new(self, event=None): """ Ctrl+N """ self.text_area.delete(1.0, tk.END) self.open_file = None self.editor_mode() self.line_numbers.force_update() def file_open(self, event=None): """ Ctrl+O """ self.editor_mode() file_to_open = filedialog.askopenfilename(filetypes=[('Python files', '*.py')], defaultextension='.py') if file_to_open: self.open_file = file_to_open self.file_name = self.open_file.split('/')[-1] self.status_bar3.set("%s" % self.file_name) self.text_area.display_file_contents(file_to_open) self.highlighter.force_highlight() self.line_numbers.force_update() def file_save(self, event=None): """ Ctrl+s """ current_file = self.open_file if self.open_file else None if not current_file: current_file = filedialog.asksaveasfilename(filetypes=[ ('Python files', '*.py') ], defaultextension='.py') self.open_file = current_file self.file_name = current_file.split('/')[-1] self.status_bar3.set("%s" % self.file_name) if current_file: contents = self.text_area.get(1.0, tk.END) with open(current_file, 'w') as file: file.write(contents) self.status = "saved" self.status_bar5.set("%s" % self.status) def file_save_as(self, event=None): """ Ctrl+S """ new_file_name = filedialog.asksaveasfilename(filetypes=[ ('Python files', '*.py') ], defaultextension='.py', confirmoverwrite=False) f = open(self.new_file_name, 'w') f.write(self.get('1.0', 'end')) f.close() self.status = "saved" self.status_bar5.set("%s" % self.status) def edit_cut(self, event=None): """ Ctrl+X """ self.text_area.event_generate("<Control-x>") self.line_numbers.force_update() def edit_paste(self, event=None): """ Ctrl+V """ self.text_area.event_generate("<Control-v>") self.line_numbers.force_update() self.highlighter.force_highlight() def edit_copy(self, event=None): """ Ctrl+C """ self.text_area.event_generate("<Control-c>") def edit_select_all(self, event=None): """ Ctrl+A """ self.text_area.event_generate("<Control-a>") def edit_find_and_replace(self, event=None): """ Ctrl+F """ self.show_find_window() def welcome(self, event=None): """ Ctrl+W """ self.show_welcome_page() def help_about(self, event=None): """ Ctrl+H """ self.show_about_page()
class EdaApp(Frame): def __init__(self, master=None): Frame.__init__(self, master, relief=SUNKEN, bd=2) self.create_menubar() self.master.config(menu=self.menubar) self.pack(side=TOP, fill=BOTH, expand=True) panwin = PanedWindow(self, orient=VERTICAL, sashwidth=5, bd=0, bg='gray80', opaqueresize=0) self.canvas = XCanvas(self.master, bg="white", width=1200, height=640, x_axis=11, scalewidget=False, bd=0, highlightthickness=0) self.tkcon = TkConsole(self.master, height=12, width=90, background='ivory') self.status = StatusBar(self.master) self.canvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.tkcon.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.status.pack(side=BOTTOM, fill=X, expand=False) self.tkcon.focus_set() # Put here all initializations you want to have in console # However it's better to use an initialization file for tkcon (look at tkcon.py) self.tkcon.eval('import os') self.tkcon.eval('import sys') self.tkcon.eval('from basics import *') self.status.set("%-60s %-16s %-16s", "Status line for this eda app (60 chars)", "Part2 (16c)", "Part3 (16c)") def create_menubar(self): self.menubar = tk.Menu(self) # File menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="File", menu=menu) menu.add_command(label="New", command=self.new) menu.add_command(label="Open", command=self.open) menu.add_command(label="Exit", command=self.exit) # Edit menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Edit", menu=menu) menu.add_command(label="Cut", command=self.cut) menu.add_command(label="Copy", command=self.copy) menu.add_command(label="Paste", command=self.paste) menu.add_command(label="Clear ALL", command=self.clear) # Help menu menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Help", menu=menu) menu.add_command(label="About", command=self.about) menu.add_command(label="Help", command=self.help) def debug(self, event): #print(event.keysym) #print(self.panwin.cget('sashwidth')) #self.panwin.config(sashwidth=6) #print(self.winfo_geometry()) #self.panwin.paneconfigure(self.tkcon, minsize=100) pass def new(self): messagebox.showwarning("Not implemented", "The 'new' method is not implemented yet") def open(self): messagebox.showwarning("Not implemented", "The 'open' method is not implemented yet") def exit(self): answer = messagebox.askyesno("Exit?", "Are you sure you want to exit?") if answer: sys.exit(0) def clear(self): self.tkcon.clear() def cut(self): messagebox.showwarning("Not implemented", "The 'cut' method is not implemented yet") def copy(self): messagebox.showwarning("Not implemented", "The 'copy' method is not implemented yet") def paste(self): messagebox.showwarning("Not implemented", "The 'paste' method is not implemented yet") def help(self): try: self.help_top.destroy() except: pass self.help_top = tk.Tk() self.help_top.wm_title('HELP WINDOW') t = tk.Text(self.help_top, font=('Consolas', 10, 'bold'), width=80, height=24, background='cornsilk', foreground='blue') t.insert( END, "Edit the help method:\nRead some help file and insert it here") t.pack(fill=BOTH, expand=True) def about(self): messagebox.showinfo( "About EDA Application", "Engineering Design Project\nEEE Depatment\nPublic Education College" )