class GameTab(Frame): def __init__(self, master): Frame.__init__(self, master) self._main_window = self.master.master self._land_land_roll = False self._heading = Frame(self) self._inventory_display = Frame(self) self._die_field = Frame(self) self._score_field = LabelFrame(self) self._turn_order = Frame(self) self.die = None if self._main_window.is_game_in_progress.get(): self._load_content() @property def _current_player(self): return self._main_window.engine.aktivjatekos def reset_content(self): self._heading.destroy() self._heading = Frame(self) self._inventory_display.destroy() self._inventory_display = Frame(self) self._die_field.destroy() self._die_field = Frame(self) self._score_field.destroy() self._score_field = LabelFrame(self) self._turn_order.destroy() self._turn_order = Frame(self) if self.die: self.die.destroy() self.die = None self._load_content() def _load_content(self): self.master.tab( 1, state=NORMAL) # TODO fix it when window is being resized. self._build_heading(0) self._build_inventory_display(1) self._build_score_field(2) self._build_state_display(3) self._horizontal_line(4) self._build_die_field(5) self._horizontal_line(6) self._build_turn_order(7) def _build_heading(self, position): flag = Gallery.get( f"flag_{self._current_player.empire.adjective.lower()}") Label(self._heading, text=self._current_player.name).grid(row=0, column=0) Label(self._heading, image=flag).grid(row=1, column=0) self._heading.grid(row=position, column=0, pady=5) def _build_inventory_display(self, position): gold_frame = LabelFrame(self._inventory_display, text=s.language.treasure) Label(gold_frame, image=Gallery.get("penz-d2")).grid(row=0, column=0) Label(gold_frame, textvariable=self._current_player.gold).grid(row=0, column=1) gold_frame.grid(row=0, column=0, sticky=N + E + W + S, padx=5) crew_frame = LabelFrame(self._inventory_display, text=s.language.crew) Label(crew_frame, image=Gallery.get("crew")).grid(row=0, column=0) Label(crew_frame, textvariable=self._current_player.crew).grid(row=0, column=1) crew_frame.grid(row=0, column=1, sticky=N + E + W + S, padx=5) self._inventory_display.grid(row=position, column=0) self._inventory_display.columnconfigure( ALL, minsize=(self.master.width - 20) / 2) def _horizontal_line(self, position): Separator(self, orient=HORIZONTAL).grid(row=position, column=0, sticky=E + W, padx=5, pady=5) def _build_score_field(self, position): self._score_field.config(text=s.language.scores) score_fields = {} target_empires = [empire.value for empire in Empires] target_empires.remove(self._current_player.empire) for index, empire in enumerate(target_empires): score_fields[empire.adjective] = Frame(self._score_field) flag = Gallery.get(f"flag_{empire.adjective.lower()}") Label(score_fields[empire.adjective], image=flag).grid(row=0, column=0) Label(score_fields[empire.adjective], text=':').grid(row=0, column=1) Label(score_fields[empire.adjective], textvariable=self._current_player.scores[ empire.adjective]).grid(row=0, column=2) score_fields[empire.adjective].grid(row=int((index / 2) % 2), column=index % 2, sticky=E + W) self._score_field.grid(row=position, column=0) self._score_field.columnconfigure(ALL, minsize=(self.master.width - 34) / 2) def _build_die_field(self, position): self._die_field.columnconfigure(0, weight=1) self._die_field.rowconfigure(0, weight=1) self._die_field.grid(row=position, column=0, ipady=5, ipadx=5) should_miss_turn = self._current_player.turns_to_miss.get() if should_miss_turn > 0: self._build_miss_turn_button(should_miss_turn) else: self._build_die() def _build_miss_turn_button(self, should_miss_turn): if should_miss_turn > 1: message = s.language.miss_turn % should_miss_turn else: message = s.language.miss_turn_last_time Button(self._die_field, text=message, command=self._main_window.engine.kimaradas).pack() if "leviathan" in self._current_player.states: command = self._main_window.engine.leviathan_kijatszasa Button(self._die_field, text=s.language.play_leviathan, command=command).pack() def _build_die(self): self._die_field.config(relief=RAISED, bd=2) self.die = Die(self._die_field, self.master.width / 4, self._current_player.color, self._current_player.secondary_color, self._current_player.last_roll) castaway_tiles = self._main_window.game_board.locations["castaways"] player_is_on_castaway_island = self._current_player.coordinates in castaway_tiles player_has_no_crew = not self._current_player.crew.get() if player_is_on_castaway_island and player_has_no_crew: self.die.bind('<Button-1>', self._main_window.engine.szamuzottek) else: self.die.bind('<Button-1>', self._roll_die) self.die.grid(row=0, column=0) def _build_turn_order(self, position): players = [] turn_order_label = Label(self._turn_order, text=s.language.turn_order) turn_order_label.grid(row=0, column=0, sticky=W) for index, player_name in enumerate(self._main_window.player_order): player = self._main_window.players[player_name] players.append( Label(self._turn_order, text=str(index + 1) + '. ' + player.name, bg=player.color, fg=player.secondary_color)) players[-1].grid(row=index + 1, column=0, sticky=W, padx=10) self._turn_order.grid(row=position, column=0, sticky=W, padx=5) def _build_state_display(self, position): state_field = LabelFrame(self, text=s.language.cards, relief=RAISED, width=self.master.width - 31) state_slots_per_row = int((self.master.width - 31) / 32) state_slot_height = 24 + ( (int(len(self._current_player.states) / state_slots_per_row) + 1) * 32) if self._current_player.states: for index, state in enumerate(self._current_player.states): if state not in self._main_window.engine.nemKartyaStatusz: if state in self._main_window.engine.eventszotar.keys(): origin = self._main_window.engine.eventszotar prefix = "event" else: origin = self._main_window.engine.kincsszotar prefix = "treasure" icon = f"{prefix}_{self._main_window.engine.eventszotar[state].kep}_i" icon = icon[(icon.find('_') + 1):] button = Button( state_field, image=Gallery.get(icon), command=lambda s=state: origin[s].megjelenik(1)) button.grid(row=int(index / state_slots_per_row), column=index % state_slots_per_row) state_field.config(height=state_slot_height) if state_field.winfo_children(): state_field.grid(row=position, column=0) state_field.grid_propagate(False) def _roll_die(self, event): if self._land_land_roll: self._main_window.game_board.turn_off_blinker() self._main_window.engine.dobasMegtortent.set(False) if not self._main_window.engine.dobasMegtortent.get(): dobas = self.die.roll() if "landland" in self._current_player.states: debug("New roll is possible because of Land, land! bonus.") self._main_window.status_bar.log(s.language.land_log) self._current_player.remove_state("landland") self._land_land_roll = True else: self._main_window.status_bar.log('') self._die_field.config(relief=SUNKEN) self._main_window.engine.set_dobasMegtortent() self._main_window.is_turn_in_progress.set(1) self._main_window.engine.aktivjatekos.last_roll = dobas self._main_window.engine.mozgas(dobas, 1) def disable_additional_roll(self): if self._land_land_roll is False: self._main_window.status_bar.log('') self._die_field.config(relief=SUNKEN) self._land_land_roll = False
class UserInterface: def __init__(self): #colours********** self.FG_COLOR = "#ccedd2" self.BACK_COLOR = "#655c56" self.BG_COLOR = '#deebde' self.ORANGE = '#FFCC66' # *** sizing ***** self.width = 1050 self.height = 600 # main window self.ventana = Tk() self.ventana.geometry( str(self.width) + "x" + str(self.height) + "+200+100") self.ventana.config(bg=self.BG_COLOR) self.ventana.resizable(width=False, height=False) self.ventana.title("PY-POST") # fonts ****** self.font_entry = fnt.Font(family="Monospace", size=16) self.font_h6 = fnt.Font(family="San Serif", size=11) # navigator and menu ---------- self.nav_bar = Frame(self.ventana, width=self.width, height=35, bg=self.BACK_COLOR) self.nav_bar.place(x=0, y=0) self.title = Label(self.nav_bar, text="PY-POST", bg=self.BACK_COLOR, fg=self.FG_COLOR) self.title.place(x=50, y=5) self.version_label = Label(self.nav_bar, text="v - 1.1 ", bg=self.BACK_COLOR, fg=self.FG_COLOR) self.version_label.place(x=930, y=5) #---- special vars---------------------- self.despy = 35 self.c_t = StringVar() self.url_var = StringVar() self.status = StringVar() self.length = StringVar() #--- set headers area ----------------- self.frame2 = Frame(self.ventana, width=700, height=220) self.frame2.place(relx=0.05, y=140 + self.despy) self.frame3 = Frame(self.frame2, width=684, height=34, bg=self.BACK_COLOR) self.frame3.place(relx=0.01, y=181) #-- memory panel-------------------- self.frame_memory = LabelFrame(self.ventana, width=250, height=220, text="Recent requests", labelanchor='nw', relief='ridge') self.frame_memory.place(x=780, y=130 + self.despy) self.memory_frame() self.memory_panel() self.create_widgets() self.ventana.mainloop() # ------- errors methods ----------- @staticmethod def error_dialog(msg): messagebox.showerror("Error", msg) #--- widget methods ----------------------------- def memory_frame(self): self.frame_memory = LabelFrame(self.ventana, width=250, height=220, text="Recent requests", labelanchor='n', relief='ridge') self.frame_memory.place(x=780, y=130 + self.despy) def memory_panel(self): self.memory_frame() self.objects = parse_log() for obj in self.objects: b_g = None if self.objects.index(obj) > 7: break if obj['method'] == 'GET': b_g = "#B2E6C7" elif obj['method'] == 'POST': b_g = "#EAE658" elif obj['method'] == 'UPDATE': b_g = "#F5A66F" elif obj['method'] == 'DELETE': b_g = "#F53333" self.recent_button = Button( self.frame_memory, width=35, text="{} - {}".format(obj['method'][:3], obj['url'][:35]), bg=b_g, command=lambda obj=obj: self.set_var_url(obj['url'])) self.recent_button.pack() def save_reg_to_file(self, dat): self.objects.append(dat) def create_widgets(self): self.label_url = Label(self.ventana, text="Url:", bg=self.BG_COLOR, font=self.font_h6) self.label_url.place(relx=0.05, y=50) self.url_bar = Text(self.ventana, width='70', height=1.2) self.url_bar.place(relx=0.05, y=40 + self.despy) self.url_bar.config(font=self.font_entry) self.get_button = Button(self.ventana, text=" GET ", command=lambda: self.send_request("GET")) self.get_button.place(relx=0.05, y=75 + self.despy) self.get_button.config(fg=self.ORANGE, bg=self.BACK_COLOR) self.post_button = Button(self.ventana, text="POST", command=lambda: self.send_request("POST")) self.post_button.place(relx=0.10, y=75 + self.despy) self.post_button.config(fg=self.ORANGE, bg=self.BACK_COLOR) self.update_button = Button( self.ventana, text=" UPDATE ", command=lambda: self.send_request("UPDATE")) self.update_button.place(relx=0.15, y=75 + self.despy) self.update_button.config(fg=self.ORANGE, bg=self.BACK_COLOR) self.delete_button = Button( self.ventana, text=" DELETE ", command=lambda: self.send_request("DELETE")) self.delete_button.place(relx=0.22, y=75 + self.despy) self.delete_button.config(fg=self.ORANGE, bg=self.BACK_COLOR) self.status_widgets() self.content_type_widgets() #---- RESPONSE AREA WIDGETS------------- self.response_area = Text(self.frame2, width='85', height=10, font=self.font_h6, bd=2) self.response_area.place(relx=0.01, y=4) self.save_button = Button(self.ventana, text="EXPORT TO FILE", bg=self.BACK_COLOR, fg=self.ORANGE, command=self.save_to_file) self.save_button.place(relx=0.63, y=365 + self.despy) self.clear_button = Button(self.ventana, text=" CLEAR ", bg=self.BACK_COLOR, fg=self.ORANGE, command=self.clear) self.clear_button.place(relx=0.56, y=365 + self.despy) def set_var_url(self, url): self.url_bar.delete("1.0", "end") self.url_bar.insert("1.0", url) def clear(self): self.response_area.delete("1.0", "end") self.status.set('') self.c_t.set('') self.length.set('') def status_widgets(self): self.status_label = Label(self.ventana, text="Status : ") self.status_label.place(relx=0.07, y=110 + self.despy) self.status_label.config(bg=self.BG_COLOR, font=self.font_h6) self.status_entry = Entry(self.ventana, textvariable=self.status, width=5, font=self.font_h6) self.status_entry.place(relx=0.13, y=110 + self.despy) self.length_label = Label(self.ventana, text="Content Length:", bg=self.BG_COLOR, font=self.font_h6) self.length_label.place(relx=0.55, y=110 + self.despy) self.length_entry = Entry(self.ventana, textvariable=self.length, width=5, font=self.font_h6) self.length_entry.place(relx=0.67, y=110 + self.despy) def content_type_widgets(self): self.content_label = Label(self.ventana, text='Content-Type:') self.content_label.place(relx=0.20, y=110 + self.despy) self.content_label.config(bg=self.BG_COLOR, font=self.font_h6) self.content_entry = Entry(self.ventana, textvariable=self.c_t, width=28, font=self.font_h6) self.content_entry.place(relx=0.30, y=110 + self.despy) #----------------methods ------------------- def send_request(self, method): self.url = self.url_bar.get("1.0", 'end-1c') if method == 'GET': self.response = SendRequest.get(self.url) elif method == 'POST': data = { 'method': 'POST', 'body': { 'title': 'foo', 'body': 'bar', 'userId': 1 }, 'headers': { "Content-type": "application/json; charset=UTF-8" } } jsondata = json.dumps(data) self.response = SendRequest.post(self.url, jsondata) elif method == 'UPDATE': data = self.response_area.get("1.0", 'end-1c') jsondata = json.dumps(data) self.response = SendRequest.update(self.url, jsondata) elif method == 'DELETE': self.response = SendRequest.delete(self.url) if self.response: self.new_reg_memory = { "method": method, "url": self.url, "time": str(datetime.datetime.now()) } save_reg_url(self.new_reg_memory) if self.response == "err1": self.error_dialog("Debe ingresar una url.") else: self.deploy_data(self.response) else: self.response_area.insert( "1.0", "No se pudo establecer conexión con el servidor") self.frame_memory.destroy() self.memory_panel() def deploy_data(self, response): self.clear() self.headers = self.response.headers self.content_type = self.headers['Content-Type'] self.c_t.set(self.content_type) self.status.set(self.response.status_code) text = self.response.content self.response_area.insert("1.0", text.strip()) try: self.length.set(self.response.headers['content-length']) except: self.length.set('N/A') def save_to_file(self): if self.response_area.get("1.0", 'end-1c') == '': self.error_dialog("No hay contenido para guradar.") return my_filetypes = [('all files', '.*'), ('text files', '.txt'), ('web', '.html'), ('directories', '/*/')] answer = filedialog.asksaveasfilename( parent=self.ventana, initialdir=os.getcwd(), title="Seleccione el nombre de archivo y su ubicación: ", filetype=my_filetypes) if answer: f = open(answer, "w") f.write(self.response_area.get("1.0", 'end-1c')) f.close()