package com.ianonavy.netflixsync import scala.swing.GridBagPanel.Fill import scala.swing._ import scala.swing.event.ButtonClicked /** * Main swing panel for the main frame. */ class MainPanel extends FlowPanel { var socketEventPublisher: SocketEventPublisher = null var client: Client = null val SYNC_LABEL_DEFAULT_TEXT = "Please place me in the middle of your " + "Netflix window" val serverField = new TextField { text = "localhost" } val roomField = new TextField val nameField = new TextField val registerButton = new Button { text = "Register" } val setLocationButton = new Button { text = "Set Location" } val setLocationLabel = new TextArea { text = SYNC_LABEL_DEFAULT_TEXT editable = false opaque = false focusable = false cursor = null lineWrap = true wordWrap = true } /** * @return A panel containing the elements relevant to registration */ def registerPanel: Panel = new BoxPanel(Orientation.Vertical) { contents += new Label("Server:") contents += serverField contents += new Label("Room:") contents += roomField contents += new Label("Name:") contents += nameField contents += registerButton border = Swing.EmptyBorder(30, 30, 30, 30) } /** * @return A panel used for setting the location of the Netflix window */ def setLocationPanel: Panel = new GridBagPanel() { val c = new Constraints c.fill = Fill.Vertical c.gridx = 0 c.gridy = 0 layout(setLocationLabel) = c c.gridx = 0 c.gridy = 1 c.insets = new Insets(32, 0, 0, 0) layout(setLocationButton) = c border = Swing.EmptyBorder(30, 30, 30, 30) } /** * The master control panel for a particular room. Shown only to the first * user who registeres into a room. * @param room The room to control * @return The master control panel */ def masterPanel(room: String): Panel = new BoxPanel(Orientation.Vertical) { val label = new Label { text = "0 people have joined the room." } val clickButton = new Button { text = "Send Click" } val spacebarButton = new Button { text = "Send Spacebar" } val refreshButton = new Button { text = "Refresh Count" } contents += label contents += clickButton contents += spacebarButton contents += refreshButton border = Swing.EmptyBorder(30, 30, 30, 30) listenTo(clickButton) listenTo(spacebarButton) listenTo(refreshButton) reactions += { case ButtonClicked(`clickButton`) => label.text = "Sending..." client.sendClick(room) case ButtonClicked(`spacebarButton`) => label.text = "Sending..." client.sendSpacebar(room) case ButtonClicked(`refreshButton`) => val numPeople = client.getNumberRegistered(room) label.text = s"$numPeople people have joined the room." } } /** * Frame for the master panel * @param room The room to control * @return The master frame */ def masterFrame(room: String) = new MainFrame { title = "Netflix Sync" contents = masterPanel(room) } /** * Registers a user to a client at a particular server based on the results * of the form elements usually contained in the registerPanel. Starts the * socket event publisher, configures the Netflix Sync client and * optionally spawns the master frame. */ def register() { client = new Client(serverField.text, 10) client.calculateAverageTime() val room = roomField.text val watcherName = nameField.text contents.clear() contents += setLocationPanel revalidate() repaint() socketEventPublisher = new SocketEventPublisher(client, room, watcherName) listenTo(socketEventPublisher) val isMaster = client.registerName(roomField.text, nameField.text) if (isMaster) { masterFrame(room).open() } } contents += registerPanel listenTo(registerButton) listenTo(setLocationButton) // Netflix location var (x, y) = (0, 0) reactions += { case ButtonClicked(`registerButton`) => register() case ButtonClicked(`setLocationButton`) => socketEventPublisher.startPublishing() val myLocation = self.getLocationOnScreen x = myLocation.getX.toInt - 10 y = myLocation.getY.toInt - 10 setLocationLabel.text = "Netflix location set. You may now minimize this window." case ServerSaidClick(delay) => client.synchronizedClick(delay.toLong, x, y) setLocationLabel.text = SYNC_LABEL_DEFAULT_TEXT case ServerSaidSpacebar(delay) => client.synchronizedClick(delay.toLong, x, y) client.synchronizedSpacebar(delay.toLong) setLocationLabel.text = SYNC_LABEL_DEFAULT_TEXT } }