diff --git a/TeamMaker.groovy b/TeamMaker.groovy index 221dccd..8cd7f17 100644 --- a/TeamMaker.groovy +++ b/TeamMaker.groovy @@ -1,5 +1,17 @@ +import groovy.beans.Bindable import groovy.swing.SwingBuilder +import java.awt.Color +import java.awt.Component import java.awt.GridBagConstraints as GBC +import java.awt.GridBagLayout +import java.awt.BorderLayout +import javax.swing.AbstractListModel +import javax.swing.DefaultListModel +import javax.swing.JFrame +import javax.swing.JLabel +import javax.swing.JList +import javax.swing.JOptionPane +import javax.swing.JPanel import javax.swing.ListCellRenderer public class TeamMaker { @@ -8,17 +20,35 @@ public class TeamMaker { public static def swing = new SwingBuilder() public static final String version = "0.2" + public static final Random rand = new Random(System.currentTimeMillis()) def frame def team1List def team2List + def team1WinsButton + def team2WinsButton + def newGameButton def sittingList - class Player { + @Bindable boolean inGame = false + @Bindable int teamSize = 4 + + class Player implements Comparable { String name int gamesSat + + public int compareTo(Player that) { + int r = this.gamesSat - that.gamesSat + if (r == 0) r = this.name.compareTo(that.name) + return r + } } + class SortedPlayerModel extends AbstractListModel { + + } + + /* ======== VIEW ======== */ /* @@ -47,14 +77,15 @@ public class TeamMaker { private void init() { frame = swing.frame(title: "JDB TeamMaker v$version", - size: [600, 400], locationRelativeTo: null) { + size: [600, 400], locationRelativeTo: null, + defaultCloseOperation: JFrame.EXIT_ON_CLOSE) { panel() { gridBagLayout() - - panel(constraints: gbc(gridx: 0, gridy: 0, - insets: [5, 5, 5, 5]), - border: titleBorder(title: 'Current Game')) { + + panel(constraints: gbc(gridx: 0, gridy: 0, fill: GBC.BOTH, + insets: [5, 5, 5, 0], weightx: 3, weighty: 1), + border: titledBorder(title: 'Current Game')) { gridBagLayout() @@ -64,35 +95,158 @@ public class TeamMaker { label('Team B', constraints: gbc(gridx: 1, gridy: 0, fill: GBC.BOTH, insets: [5, 5, 0, 5])) - def teamListRenderer = new PlayerRenderer(showStats: false + def teamListRenderer = new PlayerRenderer(showStats: false, colored: false) team1List = list(cellRenderer: teamListRenderer, - constraints: gbc(gridx: 0, gridy: 0, fill: GBC.BOTH, - insets: [5, 5, 5, 0], weightx: 2, weighty: 2)) + constraints: gbc(gridx: 0, gridy: 1, fill: GBC.BOTH, + insets: [5, 5, 0, 0], weightx: 2, weighty: 2), + model: new DefaultListModel()) + + team1WinsButton = button('Team A Wins', + constraints: gbc(gridx: 0, gridy: 2, anchor: + GBC.CENTER, insets: [5, 5, 5, 0]), + enabled: false, + actionPerformed: { + sittingList.model.each { it.gamesSat++ } + team1List.model.each { player -> + player.gamesSat = 0 + sittingList.model.addElement(player) + } + team1List.model.clear() + team1List.repaint() + sittingList.repaint() + inGame = false + team1WinsButton.enabled = false + team2WinsButton.enabled = false + }) team2List = list(cellRenderer: teamListRenderer, constraints: gbc(gridx: 1, gridy: 1, fill: GBC.BOTH, - insets: [5, 5, 5, 5], weightx: 2, weighty: 2)) - } - } + insets: [5, 5, 0, 5], weightx: 2, weighty: 2), + model: new DefaultListModel()) + + team2WinsButton = button('Team B Wins', + constraints: gbc(gridx: 1, gridy: 2, + anchor: GBC.CENTER, insets: [5, 5, 5, 5]), + enabled: false, + actionPerformed: { + sittingList.model.each { it.gamesSat++ } + team2List.model.each { player -> + player.gamesSat = 0 + sittingList.model.addElement(player) + } + team2List.model.clear() + team2List.repaint() + sittingList.repaint() + inGame = false + team1WinsButton.enabled = false + team2WinsButton.enabled = false + }) + + } + + scrollPane(constraints: gbc(gridx: 1, gridy: 0, gridwidth: 2, + fill: GBC.BOTH, insets: [5, 5, 0, 5], weighty: 1), + border: titledBorder(title: 'Sitting Players')) { + + sittingList = list(cellRenderer: new PlayerRenderer( + showStats: true, colored: true), + model: new DefaultListModel()) + } + + button('Next Game', constraints: gbc(gridx: 0, gridy: 1, + anchor: GBC.CENTER, insets: [5, 5, 5, 0]), + actionPerformed: { newGame() }) + + button('Add Player', constraints: gbc(gridx: 1, gridy: 1, + anchor: GBC.CENTER, insets: [5, 5, 5, 0]), + actionPerformed: { + def name = JOptionPane.showInputDialog(frame, + "Enter the new player's name: ", "New Player...", + JOptionPane.QUESTION_MESSAGE) + def player = new Player() + player.name = name + player.gamesSat = 0 + sittingList.model.addElement(player) + }) + + newGameButton = button('Delete Player', + constraints: gbc(gridx: 2, gridy: 1, anchor: GBC.CENTER, + insets: [5, 5, 5, 5]), + actionPerformed: { + sittingList.model.removeElement( + sittingList.selectedValue) }) - sittingList = list( - cellRenderer: new PlayerRenderer( - showStats: true, colored: true), - constraints: gbc(gridx: 1, gridy: 0, gridheight: 2) { } } + swing.bind(source: this, sourceProperty: 'inGame', + target: team1WinsButton, targetProperty: 'enabled') + + swing.bind(source: this, sourceProperty: 'inGame', + target: team2WinsButton, targetProperty: 'enabled') + } - class PlayerRenderer implements ListCellRenderer extends JLabel { + class PlayerRenderer extends JPanel implements ListCellRenderer { boolean showStats boolean colored - PlayerRenderer + private JLabel nameLabel + private JLabel statsLabel + private static def linedBorder + private static def emptyBorder + + private def colors = [Color.getHSBColor(0.32f, 1f, 1f), + Color.getHSBColor(0.24f,1f,1f), Color.getHSBColor(0.16f, 1f, 1f), + Color.getHSBColor(0.08f, 1f, 1f), Color.getHSBColor(0.0f, 1f, 1f)] + + public PlayerRenderer(Map params) { + showStats = params.showStats ?: false + colored = params.colored ?: false + + setLayout(new BorderLayout()) + setOpaque(colored) + + linedBorder = TeamMaker.swing.lineBorder(color: Color.BLACK) + emptyBorder = TeamMaker.swing.emptyBorder(1) + + nameLabel = TeamMaker.swing.label(opaque: false, + horizontalAlignment: JLabel.LEADING) + add(nameLabel, BorderLayout.WEST) + + if (showStats) { + statsLabel = TeamMaker.swing.label( + horizontalAlignment: JLabel.TRAILING, + opaque: false) + add(statsLabel, BorderLayout.EAST) + } + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + + assert value instanceof Player + + nameLabel.setText(value.name) + + if (isSelected) setBorder(linedBorder) + else setBorder(emptyBorder) + + if (showStats) + statsLabel.text = value.gamesSat + + if (colored) { + def c = colors[Math.min(4, value.gamesSat)] + setBackground(c) + } + + return this + } } + /* ======== CONTROLLER ======== */ @@ -102,6 +256,37 @@ public class TeamMaker { } TeamMaker() { + init() + } + + private void newGame() { + if (team1List.model.size() < teamSize) + populate(team1List, sittingList, teamSize) + + if (team2List.model.size() < teamSize) + populate(team2List, sittingList, teamSize) + + team1WinsButton.enabled = true + team2WinsButton.enabled = true + newGameButton.enabled = false + } + + private static void populate(def teamList, def sittingList, int teamSize) { + while (teamList.model.size() < teamSize) { + def player = choosePlayer(sittingList) + teamList.model.addElement(player) + sittingList.model.removeElement(player) + } + } + + private static Player choosePlayer(def list) { + def choices = [] + list.model.each { choices << it } + choices.sort { rand.nextInt() } + return choices[0] + } + + private float calculatePercentage(Player p, def sittingList) { } }