예제 #1
0
    def __init__(self, controller):
        View.__init__(self, controller)

        # Lade Hilfe zu Befehlen
        # TODO aus Datei laden
        self.max_taktrate = 5
        self.schriftart = "helvetica"
        self.schriftgröße = 10
        #self.befehle = {"LDAD": ("n", "Lädt n in Akkumulator")}
        self.befehle = eval(open("befehle.txt").read(-1), {"__builtins__": None})
        
        # Hauptfenster
        self.haupt = tk.Tk()
        self.dateiname = None
        self.setze_titel()
        self.haupt.protocol("WM_DELETE_WINDOW", self.beende)
        self.haupt.resizable(True, True)
        try:
            self.haupt.iconbitmap(default = "gui.ico")
        except TclError:
            pass
        self.haupt.rowconfigure(1, weight = 1)
        self.haupt.columnconfigure(0, weight = 1)

        menü = tk.Menu(self.haupt)
        menü_datei = tk.Menu(menü)
        menü_datei.add_command(label = "Neu", command = self.menü_datei_neu)
        menü_datei.add_command(label = "Öffnen", command = self.menü_datei_öffnen)
        menü_datei.add_command(label = "Speichern", command = self.menü_datei_speichern)
        menü_datei.add_command(label = "Speichern unter", command = self.menü_datei_speichern_unter)
        menü_datei.add_command(label = "Beenden", command = self.beende)
        menü.add_cascade(label = "Datei", menu = menü_datei)
        menü_bearbeiten = tk.Menu(menü)
        menü_bearbeiten.add_command(label = "Rückgängig", command = self.menü_bearbeiten_rückgängig)
        menü_bearbeiten.add_command(label = "Wiederherstellen", command = self.menü_bearbeiten_wiederherstellen)
        menü_bearbeiten.add_command(label = "Ausschneiden", command = self.menü_bearbeiten_ausschneiden)
        menü_bearbeiten.add_command(label = "Kopieren", command = self.menü_bearbeiten_kopieren)
        menü_bearbeiten.add_command(label = "Einfügen", command = self.menü_bearbeiten_einfügen)
        menü.add_cascade(label = "Bearbeiten", menu = menü_bearbeiten)
        menü_rechner = tk.Menu(menü)
        menü_rechner.add_command(label = "Starten", command = self.menü_rechner_starten)
        menü.add_cascade(label = "Rechner", menu = menü_rechner)
        menü_hilfe = tk.Menu(menü)
        menü_hilfe.add_command(label = "Über", command = self.menü_hilfe_über)
        menü.add_cascade(label = "Hilfe", menu = menü_hilfe)
        self.haupt.config(menu = menü)
        
        self.lbl_programm_code = tk.Label(self.haupt, text = "Programm-Code")
        self.lbl_programm_code.grid(row = 0, column = 0, sticky = "W")

        self.txt_code = SyntaxText(self.haupt, wrap = "none", bg = "#FFFFFF", schriftgröße = self.schriftgröße, schriftart = self.schriftart, befehle = list(self.befehle))
        self.scy_code = tk.Scrollbar(self.haupt, command = self.txt_code.yview)
        self.scx_code = tk.Scrollbar(self.haupt, command = self.txt_code.xview, orient = "horizontal")
        self.txt_code.config(yscrollcommand = self.scy_code.set, xscrollcommand = self.scx_code.set)
        self.scx_code.grid(row = 6, column = 0, sticky = "EW")
        self.scy_code.grid(row = 1, column = 1, rowspan = 5, sticky = "NS")
        self.txt_code.grid(row = 1, column = 0, rowspan = 5, sticky = "NSEW")

        self.lst_befehle = tk.Listbox(self.haupt, activestyle = "dotbox", exportselection = 0, bg = "#FFFFFF")
        self.scy_befehle = tk.Scrollbar(command = self.lst_befehle.yview)
        self.lst_befehle.config(yscrollcommand = self.scy_befehle.set)
        self.lst_befehle.insert("end", *list(sorted(self.befehle)))
        self.scy_befehle.grid(row = 1, column = 3, rowspan = 5, sticky = "NS")        
        self.lst_befehle.grid(row = 1, column = 2, rowspan = 5, sticky = "NSEW")
        self.lst_befehle.bind('<ButtonRelease-1>', self.befehl_anzeigen)
        self.lst_befehle.bind('<Return>', self.befehl_einfügen)

        self.lbl_befehl = tk.Label(self.haupt, text = "", width = 30, justify = "left")
        self.lbl_befehl.grid(row = 1, column = 4, sticky = "NW")
        self.lbl_befehl_erklärung = tk.Label(self.haupt, text = "n: Natürliche Zahl\na: Adresse\nU: unmittelbar\nD: direkt\nI: indirekt", justify = "left")
        self.lbl_befehl_erklärung.grid(row = 2, column = 4, sticky = "NW")
        
        # Rechner-Fenster
        self.rechner = tk.Toplevel(self.haupt)
        self.rechner.withdraw()
        self.rechner.title("Simulation - Von-Neumann-Rechner")
        self.rechner.protocol("WM_DELETE_WINDOW", self.rechner_beenden)
        self.rechner.rowconfigure(1, weight = 1)
        self.rechner.columnconfigure(4, weight = 1)
        self.rechner.resizable(False, False)

        self.img_schritt = tk.PhotoImage(file = "buttons/schritt.gif")
        self.btn_schritt = tk.Button(self.rechner, command = self.rechner_schritt, text = "Schritt", image = self.img_schritt)
        self.btn_schritt.grid(row = 0, column = 0, sticky = "NSW")
        self.img_start = tk.PhotoImage(file = "buttons/start.gif")
        self.btn_start = tk.Button(self.rechner, command = self.rechner_start, image = self.img_start)
        self.btn_start.grid(row = 0, column = 1, sticky = "NSW")
        self.img_pause = tk.PhotoImage(file = "buttons/pause.gif")
        self.btn_pause = tk.Button(self.rechner, command = self.rechner_pause, image = self.img_pause)
        self.btn_pause.grid(row = 0, column = 2, sticky = "NSW")
        self.img_stop = tk.PhotoImage(file = "buttons/stop.gif")
        self.btn_stop = tk.Button(self.rechner, command = self.rechner_beenden, image = self.img_stop)
        self.btn_stop.grid(row = 0, column = 3, sticky = "NSW")

        self.diagramm = RechnerDiagramm(self.rechner)
        self.diagramm.grid(row = 1, column = 0, columnspan = 5, sticky = "NSWE")
예제 #2
0
class ViewGUI(View):
    filetypes = [("Assembler-Code", "*.asm"), ("Text-Datei", "*.txt")]
    
    def __init__(self, controller):
        View.__init__(self, controller)

        # Lade Hilfe zu Befehlen
        # TODO aus Datei laden
        self.max_taktrate = 5
        self.schriftart = "helvetica"
        self.schriftgröße = 10
        #self.befehle = {"LDAD": ("n", "Lädt n in Akkumulator")}
        self.befehle = eval(open("befehle.txt").read(-1), {"__builtins__": None})
        
        # Hauptfenster
        self.haupt = tk.Tk()
        self.dateiname = None
        self.setze_titel()
        self.haupt.protocol("WM_DELETE_WINDOW", self.beende)
        self.haupt.resizable(True, True)
        try:
            self.haupt.iconbitmap(default = "gui.ico")
        except TclError:
            pass
        self.haupt.rowconfigure(1, weight = 1)
        self.haupt.columnconfigure(0, weight = 1)

        menü = tk.Menu(self.haupt)
        menü_datei = tk.Menu(menü)
        menü_datei.add_command(label = "Neu", command = self.menü_datei_neu)
        menü_datei.add_command(label = "Öffnen", command = self.menü_datei_öffnen)
        menü_datei.add_command(label = "Speichern", command = self.menü_datei_speichern)
        menü_datei.add_command(label = "Speichern unter", command = self.menü_datei_speichern_unter)
        menü_datei.add_command(label = "Beenden", command = self.beende)
        menü.add_cascade(label = "Datei", menu = menü_datei)
        menü_bearbeiten = tk.Menu(menü)
        menü_bearbeiten.add_command(label = "Rückgängig", command = self.menü_bearbeiten_rückgängig)
        menü_bearbeiten.add_command(label = "Wiederherstellen", command = self.menü_bearbeiten_wiederherstellen)
        menü_bearbeiten.add_command(label = "Ausschneiden", command = self.menü_bearbeiten_ausschneiden)
        menü_bearbeiten.add_command(label = "Kopieren", command = self.menü_bearbeiten_kopieren)
        menü_bearbeiten.add_command(label = "Einfügen", command = self.menü_bearbeiten_einfügen)
        menü.add_cascade(label = "Bearbeiten", menu = menü_bearbeiten)
        menü_rechner = tk.Menu(menü)
        menü_rechner.add_command(label = "Starten", command = self.menü_rechner_starten)
        menü.add_cascade(label = "Rechner", menu = menü_rechner)
        menü_hilfe = tk.Menu(menü)
        menü_hilfe.add_command(label = "Über", command = self.menü_hilfe_über)
        menü.add_cascade(label = "Hilfe", menu = menü_hilfe)
        self.haupt.config(menu = menü)
        
        self.lbl_programm_code = tk.Label(self.haupt, text = "Programm-Code")
        self.lbl_programm_code.grid(row = 0, column = 0, sticky = "W")

        self.txt_code = SyntaxText(self.haupt, wrap = "none", bg = "#FFFFFF", schriftgröße = self.schriftgröße, schriftart = self.schriftart, befehle = list(self.befehle))
        self.scy_code = tk.Scrollbar(self.haupt, command = self.txt_code.yview)
        self.scx_code = tk.Scrollbar(self.haupt, command = self.txt_code.xview, orient = "horizontal")
        self.txt_code.config(yscrollcommand = self.scy_code.set, xscrollcommand = self.scx_code.set)
        self.scx_code.grid(row = 6, column = 0, sticky = "EW")
        self.scy_code.grid(row = 1, column = 1, rowspan = 5, sticky = "NS")
        self.txt_code.grid(row = 1, column = 0, rowspan = 5, sticky = "NSEW")

        self.lst_befehle = tk.Listbox(self.haupt, activestyle = "dotbox", exportselection = 0, bg = "#FFFFFF")
        self.scy_befehle = tk.Scrollbar(command = self.lst_befehle.yview)
        self.lst_befehle.config(yscrollcommand = self.scy_befehle.set)
        self.lst_befehle.insert("end", *list(sorted(self.befehle)))
        self.scy_befehle.grid(row = 1, column = 3, rowspan = 5, sticky = "NS")        
        self.lst_befehle.grid(row = 1, column = 2, rowspan = 5, sticky = "NSEW")
        self.lst_befehle.bind('<ButtonRelease-1>', self.befehl_anzeigen)
        self.lst_befehle.bind('<Return>', self.befehl_einfügen)

        self.lbl_befehl = tk.Label(self.haupt, text = "", width = 30, justify = "left")
        self.lbl_befehl.grid(row = 1, column = 4, sticky = "NW")
        self.lbl_befehl_erklärung = tk.Label(self.haupt, text = "n: Natürliche Zahl\na: Adresse\nU: unmittelbar\nD: direkt\nI: indirekt", justify = "left")
        self.lbl_befehl_erklärung.grid(row = 2, column = 4, sticky = "NW")
        
        # Rechner-Fenster
        self.rechner = tk.Toplevel(self.haupt)
        self.rechner.withdraw()
        self.rechner.title("Simulation - Von-Neumann-Rechner")
        self.rechner.protocol("WM_DELETE_WINDOW", self.rechner_beenden)
        self.rechner.rowconfigure(1, weight = 1)
        self.rechner.columnconfigure(4, weight = 1)
        self.rechner.resizable(False, False)

        self.img_schritt = tk.PhotoImage(file = "buttons/schritt.gif")
        self.btn_schritt = tk.Button(self.rechner, command = self.rechner_schritt, text = "Schritt", image = self.img_schritt)
        self.btn_schritt.grid(row = 0, column = 0, sticky = "NSW")
        self.img_start = tk.PhotoImage(file = "buttons/start.gif")
        self.btn_start = tk.Button(self.rechner, command = self.rechner_start, image = self.img_start)
        self.btn_start.grid(row = 0, column = 1, sticky = "NSW")
        self.img_pause = tk.PhotoImage(file = "buttons/pause.gif")
        self.btn_pause = tk.Button(self.rechner, command = self.rechner_pause, image = self.img_pause)
        self.btn_pause.grid(row = 0, column = 2, sticky = "NSW")
        self.img_stop = tk.PhotoImage(file = "buttons/stop.gif")
        self.btn_stop = tk.Button(self.rechner, command = self.rechner_beenden, image = self.img_stop)
        self.btn_stop.grid(row = 0, column = 3, sticky = "NSW")

        self.diagramm = RechnerDiagramm(self.rechner)
        self.diagramm.grid(row = 1, column = 0, columnspan = 5, sticky = "NSWE")

    def setze_schriftart(self, art, größe):
        self.txt_code.setze_schriftart(art, größe)

    def befehl_anzeigen(self, event):
        b = self.lst_befehle.get(self.lst_befehle.curselection()[0])
        befehl = self.befehle[b]
        self.lbl_befehl.config(text = b+" "+befehl[0]+"\n"+befehl[1])

    def befehl_einfügen(self, event):
        b = self.lst_befehle.get(self.lst_befehle.curselection()[0])
        self.txt_code.insert("insert", b+" ")
        self.txt_code.changed()

    def setze_titel(self):
        if (self.dateiname==None):
            self.haupt.title("Von-Neumann-Rechner")
        else:
            self.haupt.title(basename(self.dateiname)+" - Von-Neumann-Rechner")

    def beende(self):
        self.haupt.destroy()
        self.controller.beende()
        
    def schritt(self):
        self.haupt.update()

    def menü_datei_neu(self):
        self.dateiname = None
        self.txt_code.delete(1.0, "end")
        self.txt_code.changed()
        self.setze_titel()

    def menü_datei_öffnen(self):
        dateiname = tk.filedialog.askopenfilename(parent = self.haupt,
                                                  title = "Datei öffnen",
                                                  defaultextension = ".asm",
                                                  filetypes = self.filetypes,
                                                  initialdir = "programme/")
        if (dateiname!=""):
            try:
                f = open(dateiname)
                code = f.read(-1)
                f.close()

                self.dateiname = dateiname
                self.setze_titel()
                self.txt_code.delete("1.0", "end")
                self.txt_code.insert("1.0", code)
                self.txt_code.changed()
            except IOError:
                tk.messagebox.showerror("Fehler", "Konnte Datei '"+dateiname+"' nicht öffnen.")
        
    def datei_speichern(self, datei):
        print("Datei speichern: "+str(datei))
        if (type(datei)==str):
            dateiname = datei
            try:
                f = open(dateiname, "w")
            except:
                tk.messagebox.showerror("Fehler", "Konnte Datei '"+dateiname+"' nicht öffnen.")
                return False
        else:
            dateiname = datei.name
            f = datei

        f.write(self.txt_code.get(1.0, "end"))
        f.close()

        self.dateiname = dateiname
        self.setze_titel()
        return True

    def menü_datei_speichern(self):
        # TODO bei jedem Speichern Unter wird am Ende eine neue Zeile hinzugefügt. Warum?
        if (self.dateiname==None):
            self.menü_datei_speichern_unter()
        else:
            self.datei_speichern(self.dateiname)

    def menü_datei_speichern_unter(self):
        datei = tk.filedialog.asksaveasfile(parent = self.haupt,
                                            title = "Datei speichern",
                                            defaultextension = ".asm",
                                            filetypes = self.filetypes,
                                            initialdir = "programme/")
        self.datei_speichern(datei)

    def menü_bearbeiten_rückgängig(self):
        self.txt_code.edit_undo()

    def menü_bearbeiten_wiederherstellen(self):
        self.txt_code.edit_redo()

    def menü_bearbeiten_ausschneiden(self):
        self.txt_code.event_generate("<<Cut>>")

    def menü_bearbeiten_kopieren(self):
        self.txt_code.event_generate("<<Copy>>")

    def menü_bearbeiten_einfügen(self):
        self.txt_code.event_generate("<<Paste>>")

    def menü_rechner_starten(self):
        self.controller.erzeuge_rechner()
        try:
            self.asmhints = self.controller.lade_programm(self.txt_code.get(1.0, "end"))
            self.rechner_zeige_status()
            self.rechner.deiconify()
            self.rechner.lift(self.haupt)
        except (SyntaxError, RuntimeError) as e:
            self.programm_fehler(e)

    def menü_hilfe_über(self):
        über = "Von-Neumann-Rechner "+self.controller.version+"\n"+\
               "von Janosch Gräf <*****@*****.**>\n\n"+\
               "Dieses Programm simuliert einen einfachen Computer nach der von-Neumann-Architektur"
        tk.messagebox.showinfo("Über Von-Neumann-Rechner", über, parent = self.haupt)

    def programm_fehler(self, e):
        if (type(e)==SyntaxError):
            tk.messagebox.showerror("Syntax-Fehler", str(e), parent = self.haupt)
        else:
            tk.messagebox.showerror("Fehler", str(e), parent = self.haupt)

    def rechner_eingabe(self, p):
        wert = PIOEingabeDialog(self.rechner, p).warte()
        self.diagramm.set_eingabe(p, wert)
        return wert


    def rechner_ausgabe(self, p, wert):
        self.diagramm.set_ausgabe(p, wert)
        tk.messagebox.showinfo("PIO-Ausgabe", "Port "+str(p)+":\n"+str(wert), parent = self.rechner)

    def rechner_beenden(self):
        self.rechner.withdraw()
        self.controller.zerstöre_rechner()

    def rechner_schritt(self):
        self.controller.rechner.schritt()
        self.rechner_zeige_status()

    def rechner_start(self):
        pass

    def rechner_pause(self):
        pass

    def rechner_zeige_status(self):
        r = self.controller.rechner
        d = self.diagramm

        for reg in d.register:
            if (reg=="BR" and r.register[reg] in r.befehle):
                d.set_register(reg, r.befehle[r.register[reg]][0])
            else:
                d.set_register(reg, str(r.register[reg]))

        d.set_speicher(r, self.asmhints)