summaryrefslogtreecommitdiff
path: root/jfr_playoff/gui/frames
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2019-06-21 18:13:07 +0200
committeremkael <emkael@tlen.pl>2019-06-21 18:13:07 +0200
commit2efa8b15abd451c31b377ff3de975ade8d24516c (patch)
tree23c19dc6d78d5e060793fcf9a88c0e1c5f588faa /jfr_playoff/gui/frames
parenteb6a945a122446d605f147289592ce21f9f7e92f (diff)
Position/team selection buttons and frames made reusable and extendable
Diffstat (limited to 'jfr_playoff/gui/frames')
-rw-r--r--jfr_playoff/gui/frames/__init__.py89
-rw-r--r--jfr_playoff/gui/frames/match.py32
-rw-r--r--jfr_playoff/gui/frames/team.py130
-rw-r--r--jfr_playoff/gui/frames/visual.py13
4 files changed, 168 insertions, 96 deletions
diff --git a/jfr_playoff/gui/frames/__init__.py b/jfr_playoff/gui/frames/__init__.py
index 9665663..4c4950e 100644
--- a/jfr_playoff/gui/frames/__init__.py
+++ b/jfr_playoff/gui/frames/__init__.py
@@ -4,6 +4,7 @@ from functools import partial
import tkinter as tk
from tkinter import ttk
+import tkMessageBox
def getIntVal(widget, default=0):
try:
@@ -219,3 +220,91 @@ class WidgetSelectionFrame(ScrollableFrame):
if self.callback is not None:
self.callback(self.value.get())
self.winfo_toplevel().destroy()
+
+class SelectionButton(ttk.Button):
+ @property
+ def defaultPrompt(self):
+ pass
+
+ @property
+ def title(self):
+ pass
+
+ @property
+ def errorMessage(self):
+ pass
+
+ def getOptions(self):
+ pass
+
+ def __init__(self, *args, **kwargs):
+ for arg in ['callback', 'prompt', 'dialogclass']:
+ setattr(self, arg, kwargs[arg] if arg in kwargs else None)
+ if arg in kwargs:
+ del kwargs[arg]
+ kwargs['command'] = self._choosePositions
+ if self.prompt is None:
+ self.prompt = self.defaultPrompt
+ ttk.Button.__init__(self, *args, **kwargs)
+ self.setPositions([])
+
+ def setPositions(self, values):
+ self.selected = values
+ self.configure(
+ text='[wybrano: %d]' % (len(values)))
+ if self.callback is not None:
+ self.callback(values)
+
+ def _choosePositions(self):
+ options = self.getOptions()
+ if not len(options):
+ tkMessageBox.showerror(
+ self.title, self.errorMessage)
+ self.setPositions([])
+ else:
+ dialog = tk.Toplevel(self)
+ dialog.title(self.title)
+ dialog.grab_set()
+ dialog.focus_force()
+ selectionFrame = self.dialogclass(
+ dialog, title=self.prompt,
+ options=options,
+ selected=lambda idx, option: idx+1 in self.selected,
+ callback=self.setPositions, vertical=True)
+ selectionFrame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
+
+class SelectionFrame(ScrollableFrame):
+
+ def renderOption(self, container, option, idx):
+ pass
+
+ def __init__(self, master, title='', options=[],
+ selected=None, callback=None, *args, **kwargs):
+ self.values = []
+ self.title = title
+ self.options = options
+ self.selected = selected
+ self.callback = callback
+ ScrollableFrame.__init__(self, master=master, *args, **kwargs)
+ (ttk.Button(master, text='Zapisz', command=self._save)).pack(
+ side=tk.BOTTOM, fill=tk.Y)
+
+ def _save(self):
+ if self.callback:
+ self.callback(
+ [idx+1 for idx, value
+ in enumerate(self.values) if value.get()])
+ self.master.destroy()
+
+ def renderHeader(self, container):
+ container.columnconfigure(1, weight=1)
+ (ttk.Label(container, text=self.title)).grid(
+ row=0, column=0, columnspan=2)
+
+ def renderContent(self, container):
+ self.renderHeader(container)
+ for idx, option in enumerate(self.options):
+ self.values.append(tk.IntVar())
+ self.renderOption(container, option, idx)
+ if self.selected and self.selected(idx, option):
+ self.values[idx].set(True)
diff --git a/jfr_playoff/gui/frames/match.py b/jfr_playoff/gui/frames/match.py
index 9c7dfc7..922e4cf 100644
--- a/jfr_playoff/gui/frames/match.py
+++ b/jfr_playoff/gui/frames/match.py
@@ -6,7 +6,9 @@ from tkinter import ttk
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
from ..frames import WidgetRepeater, RepeatableEntry, getIntVal
-from ..frames.team import DBSelectionField
+from ..frames import SelectionFrame, SelectionButton
+from ..frames.team import DBSelectionField, TeamList, TeamSelectionButton
+from ..frames.visual import PositionsSelectionFrame
class SwissSettingsFrame(RepeatableFrame):
SOURCE_LINK = 0
@@ -139,3 +141,31 @@ class SwissesFrame(ScrollableFrame):
self.swisses.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
__all__ = ['SwissesFrame']
+
+class MatchSelectionButton(SelectionButton):
+ @property
+ def defaultPrompt(self):
+ return 'Wybierz mecze:'
+
+ @property
+ def title(self):
+ return 'Wybór meczów'
+
+ @property
+ def errorMessage(self):
+ return 'W turnieju nie zdefiniowano żadnych meczów'
+
+ def getOptions(self):
+ return self.winfo_toplevel().getMatches()
+
+
+class MatchSelectionFrame(SelectionFrame):
+ def renderOption(self, container, option, idx):
+ (ttk.Label(container, text='[%d]' % (idx+1))).grid(
+ row=idx+1, column=0)
+ (ttk.Checkbutton(
+ container, text='Mecz nr %d' % (option.getMatchID()),
+ variable=self.values[idx]
+ )).grid(row=idx+1, column=1, sticky=tk.W)
+
+
diff --git a/jfr_playoff/gui/frames/team.py b/jfr_playoff/gui/frames/team.py
index 6ae5ad3..9056070 100644
--- a/jfr_playoff/gui/frames/team.py
+++ b/jfr_playoff/gui/frames/team.py
@@ -3,10 +3,10 @@
import tkinter as tk
from tkinter.font import Font
from tkinter import ttk
-import tkMessageBox
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
from ..frames import WidgetRepeater, RepeatableEntry
+from ..frames import SelectionButton, SelectionFrame
from ..frames import getIntVal, setPanelState
class ManualTeamRow(RepeatableFrame):
@@ -53,84 +53,30 @@ class TeamManualSettingsFrame(GuiFrame):
def getTeams(self):
return [val for val in self.repeater.getValue() if len(val[0].strip())]
-class TeamSelectionFrame(ScrollableFrame):
- def __init__(self, master, title='', teams=[],
- selected=None, callback=None, *args, **kwargs):
- self.values = []
- self.title = title
- self.teams = teams
- self.selected = selected
- self.callback = callback
- ScrollableFrame.__init__(self, master=master, *args, **kwargs)
- (ttk.Button(master, text='Zapisz', command=self._save)).pack(
- side=tk.BOTTOM, fill=tk.Y)
-
- def _save(self):
- if self.callback:
- self.callback(
- [idx+1 for idx, value
- in enumerate(self.values) if value.get()])
- self.master.destroy()
-
- def renderHeader(self, container):
- container.columnconfigure(1, weight=1)
- (ttk.Label(container, text=self.title)).grid(
- row=0, column=0, columnspan=2)
-
- def renderTeam(self, container, team, idx):
+class TeamSelectionFrame(SelectionFrame):
+ def renderOption(self, container, option, idx):
(ttk.Label(container, text='[%d]' % (idx+1))).grid(
row=idx+1, column=0)
(ttk.Checkbutton(
- container, text=team[0],
+ container, text=option[0],
variable=self.values[idx]
)).grid(row=idx+1, column=1, sticky=tk.W)
- def renderContent(self, container):
- self.renderHeader(container)
- for idx, team in enumerate(self.teams):
- self.values.append(tk.IntVar())
- self.renderTeam(container, team, idx)
- if self.selected and self.selected(idx, team):
- self.values[idx].set(True)
-
-class TeamSelectionButton(ttk.Button):
- def __init__(self, *args, **kwargs):
- for arg in ['callback', 'prompt', 'dialogclass']:
- setattr(self, arg, kwargs[arg] if arg in kwargs else None)
- if arg in kwargs:
- del kwargs[arg]
- kwargs['command'] = self._choosePositions
- if self.dialogclass is None:
- self.dialogclass = TeamSelectionFrame
- if self.prompt is None:
- self.prompt = 'Wybierz teamy:'
- ttk.Button.__init__(self, *args, **kwargs)
- self.setPositions([])
-
- def setPositions(self, values):
- self.selected = values
- self.configure(
- text='[wybrano: %d]' % (len(values)))
- if self.callback is not None:
- self.callback(values)
-
- def _choosePositions(self):
- teams = self.winfo_toplevel().getTeams()
- if not len(teams):
- tkMessageBox.showerror(
- 'Wybór teamów', 'W turnieju nie ma teamów do wyboru')
- self._setFinishingPositions([])
- else:
- dialog = tk.Toplevel(self)
- dialog.title('Wybór teamów')
- dialog.grab_set()
- dialog.focus_force()
- selectionFrame = self.dialogclass(
- dialog, title=self.prompt,
- teams=teams,
- selected=lambda idx, team: idx+1 in self.selected,
- callback=self.setPositions, vertical=True)
- selectionFrame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
+class TeamSelectionButton(SelectionButton):
+ @property
+ def prompt(self):
+ return 'Wybierz teamy:'
+
+ @property
+ def title(self):
+ return 'Wybór teamów'
+
+ @property
+ def errorMessage(self):
+ return 'W turnieju nie ma teamów do wyboru'
+
+ def getOptions(self):
+ return self.winfo_toplevel().getTeams()
class DBSelectionField(ttk.Entry):
@@ -268,7 +214,8 @@ class TeamFetchSettingsFrame(GuiFrame):
finishingPositionsBtn = TeamSelectionButton(
self, callback=self._setFinishingPositions,
prompt='Wybierz teamy, które zakończyły rozgrywki ' + \
- 'na swojej pozycji:')
+ 'na swojej pozycji:',
+ dialogclass=TeamSelectionFrame)
finishingPositionsBtn.grid(row=3, column=3, sticky=tk.W)
finishingPositionsBtn.setPositions([])
@@ -329,34 +276,39 @@ class TeamSettingsFrame(ScrollableFrame):
return self.fetchSettingsFrame.getTeams()
return []
+class TeamList(ttk.OptionMenu):
+ def __init__(self, *args, **kwargs):
+ ttk.OptionMenu.__init__(self, *args, **kwargs)
+ self.winfo_toplevel().bind(
+ '<<TeamListChanged>>', self._refreshTeams, add='+')
+ self._refreshTeams(None)
+ self.configure(width=10)
+
+ def _refreshTeams(self, event):
+ oldValue = self._variable.get()
+ options = [team[0] for team in self.winfo_toplevel().getTeams()]
+ self['menu'].delete(0, tk.END)
+ for option in options:
+ self['menu'].add_command(
+ label=option, command=tk._setit(self._variable, option))
+ if oldValue not in options:
+ self._variable.set('')
+
class TeamAliasRow(RepeatableFrame):
def renderContent(self):
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.teamName = tk.StringVar()
- self._createList([])
+ (TeamList(self, self.teamName, self.teamName.get())).grid(
+ row=0, column=0, sticky=tk.W+tk.E+tk.N)
self.names = WidgetRepeater(self, RepeatableEntry)
self.names.grid(row=0, column=1, sticky=tk.W+tk.E)
- self.winfo_toplevel().bind(
- '<<TeamListChanged>>', self.refreshTeams, add='+')
- self.refreshTeams(None)
-
- def _createList(self, options):
- if self.teamName.get() not in options:
- self.teamName.set('')
- self.teamList = ttk.OptionMenu(
- self, self.teamName, self.teamName.get(), *options)
- self.teamList.grid(row=0, column=0, sticky=tk.W+tk.E+tk.N)
def getValue(self):
return (
self.teamName.get().strip(),
[val.strip() for val in self.names.getValue()])
- def refreshTeams(self, event):
- options = [team[0] for team in self.winfo_toplevel().getTeams()]
- self.teamList.destroy()
- self._createList(options)
class TeamAliasFrame(ScrollableFrame):
def renderContent(self, container):
diff --git a/jfr_playoff/gui/frames/visual.py b/jfr_playoff/gui/frames/visual.py
index 6ef7bf6..eea87f0 100644
--- a/jfr_playoff/gui/frames/visual.py
+++ b/jfr_playoff/gui/frames/visual.py
@@ -6,7 +6,8 @@ import tkColorChooser as tkcc
from ..frames import GuiFrame, RepeatableFrame, ScrollableFrame
from ..frames import WidgetRepeater
-from ..frames.team import TeamSelectionButton, TeamSelectionFrame
+from ..frames import SelectionFrame
+from ..frames.team import TeamSelectionButton
class VisualSettingsFrame(GuiFrame):
def renderContent(self):
@@ -232,22 +233,22 @@ class LineStylesFrame(GuiFrame):
(ttk.Label(self, text='Kolory linii')).grid(
row=0, column=0, columnspan=2, sticky=tk.W)
-class FinalPositionsSelectionFrame(TeamSelectionFrame):
+class PositionsSelectionFrame(SelectionFrame):
COLUMN_COUNT=10
def __init__(self, *args, **kwargs):
- TeamSelectionFrame.__init__(self, *args, **kwargs)
+ SelectionFrame.__init__(self, *args, **kwargs)
self.winfo_toplevel().geometry(
'%dx%d' % (
self.COLUMN_COUNT * 40,
- (len(self.teams) / self.COLUMN_COUNT + 2) * 25 + 30
+ (len(self.options) / self.COLUMN_COUNT + 2) * 25 + 30
))
def renderHeader(self, container):
(ttk.Label(container, text=self.title)).grid(
row=0, column=0, columnspan=self.COLUMN_COUNT, sticky=tk.W)
- def renderTeam(self, container, team, idx):
+ def renderOption(self, container, option, idx):
(ttk.Checkbutton(
container, text=str(idx+1),
variable=self.values[idx]
@@ -266,7 +267,7 @@ class PositionStyleFrame(RepeatableFrame):
(ttk.Label(self, text='Pozycje końcowe:')).grid(row=0, column=2)
self.positionBtn = TeamSelectionButton(
self, prompt='Wybierz pozycje końcowe:',
- dialogclass=FinalPositionsSelectionFrame,
+ dialogclass=PositionsSelectionFrame,
callback=self._setPositions)
self.positionBtn.grid(row=0, column=3)
(ttk.Label(self, text='Opis w legendzie:')).grid(row=0, column=4)