/* * $Id$ * * Copyright (c) 2000-2013 by Rodney Kinney, Brent Easton * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.chat.ui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.net.URL; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import javax.swing.tree.TreePath; import VASSAL.build.AbstractBuildable; import VASSAL.build.Buildable; import VASSAL.build.GameModule; import VASSAL.build.module.GlobalOptions; import VASSAL.chat.ChatServerConnection; import VASSAL.chat.ServerAddressBook; import VASSAL.configure.IconConfigurer; import VASSAL.configure.NamedHotKeyConfigurer; import VASSAL.i18n.Resources; import VASSAL.preferences.PositionOption; import VASSAL.preferences.VisibilityOption; import VASSAL.tools.ComponentSplitter; import VASSAL.tools.NamedKeyStroke; import VASSAL.tools.NamedKeyStrokeListener; import VASSAL.tools.menu.MenuManager; import net.miginfocom.swing.MigLayout; public class ChatServerControls extends AbstractBuildable { protected RoomTree currentRoom; protected JTextField newRoom; protected JLabel newRoomLabel; protected JToolBar toolbar; protected RoomTree roomTree; protected JButton newRoomButton; protected JButton launch; protected ChatServerConnection client; protected JPanel controlPanel; protected ComponentSplitter.SplitPane splitter; protected ChatControlsInitializer oldClient; protected BasicChatControlsInitializer basicControls; protected JButton configServerButton; protected String configServerText; public ChatServerControls() { final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); split.setResizeWeight(0.5); final JPanel roomPanel = new JPanel(new MigLayout("fill, nogrid, hidemode 3")); roomPanel.setBorder(BorderFactory.createTitledBorder( BorderFactory.createRaisedBevelBorder(), Resources.getString("Chat.active_games")) ); newRoom = new JTextField(12); newRoomLabel = new JLabel(Resources.getString("Chat.new_game")); newRoomLabel.setLabelFor(newRoom); roomPanel.add(newRoomLabel, ""); roomPanel.add(newRoom, "growx, pushx"); newRoomButton = new JButton("..."); //$NON-NLS-1$ newRoomButton.setPreferredSize(new Dimension(20, 20)); newRoomButton.setVisible(false); roomPanel.add(newRoomButton, "hidemode 3"); roomTree = new RoomTree(); final JScrollPane roomScroll = new JScrollPane(roomTree); roomPanel.add(roomScroll, "newline, spanx, grow, push"); split.setLeftComponent(roomPanel); currentRoom = new RoomTree(); currentRoom.addTreeWillExpandListener(new javax.swing.event.TreeWillExpandListener() { public void treeWillCollapse(javax.swing.event.TreeExpansionEvent evt) throws javax.swing.tree.ExpandVetoException { throw new javax.swing.tree.ExpandVetoException(evt); } public void treeWillExpand(javax.swing.event.TreeExpansionEvent evt) throws javax.swing.tree.ExpandVetoException { } }); JScrollPane scroll = new JScrollPane(currentRoom); scroll.setBorder(BorderFactory.createTitledBorder(BorderFactory.createRaisedBevelBorder(), Resources.getString("Chat.current_game"))); //$NON-NLS-1$ split.setRightComponent(scroll); split.setDividerLocation(160); split.setPreferredSize(new Dimension(320, 120)); controlPanel = new JPanel(); controlPanel.setLayout(new BorderLayout()); controlPanel.add("Center", split); //$NON-NLS-1$ toolbar = new JToolBar(); controlPanel.add("North", toolbar); //$NON-NLS-1$ toolbar.addSeparator(); configServerButton = new JButton(); configServerButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { ServerAddressBook.editCurrentServer(!client.isConnected()); }}); configServerButton.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e) { if (!client.isConnected() && e.isMetaDown()) { showChangeServerMenu(); } } }); toolbar.add(configServerButton); } private void showChangeServerMenu() { ServerAddressBook.changeServerPopup(configServerButton); } public void updateClientDisplay(Icon icon, String text) { configServerButton.setIcon(icon); configServerText = text; updateConfigServerToolTipText(); } private void updateConfigServerToolTipText() { if (client.isConnected()) { configServerButton.setToolTipText(configServerText); } else { configServerButton.setToolTipText("<html><center>" + configServerText + "<br>" + "Right-click to change server"); } } public Component getExtendedControls() { return null; } public void addTo(Buildable b) { final GameModule gm = GameModule.getGameModule(); setClient((ChatServerConnection) gm.getServer()); launch = new JButton(Resources.getString("Chat.server")); //$NON-NLS-1$ launch.setAlignmentY(0.0F); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent evt) { toggleVisible(); } }; launch.addActionListener(al); final NamedKeyStrokeListener l = new NamedKeyStrokeListener(al); l.setKeyStroke(NamedKeyStroke.getNamedKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK)); URL iconURL = getClass().getResource("/images/connect.gif"); //$NON-NLS-1$ if (iconURL != null) { launch.setIcon(new ImageIcon(iconURL)); launch.setText(null); } final IconConfigurer iconConfig = new IconConfigurer("serverControlsIcon", Resources.getString("Chat.server_controls_button_icon"), "/images/connect.gif"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ iconConfig.setValue("/images/connect.gif"); //$NON-NLS-1$ GlobalOptions.getInstance().addOption(iconConfig); iconConfig.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { launch.setIcon(iconConfig.getIconValue()); } }); iconConfig.fireUpdate(); final NamedHotKeyConfigurer keyConfig = new NamedHotKeyConfigurer("serverControlsHotKey", Resources.getString("Chat.server_controls_hotkey"), l.getNamedKeyStroke()); //$NON-NLS-1$ //$NON-NLS-2$ GlobalOptions.getInstance().addOption(keyConfig); keyConfig.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { l.setKeyStroke(keyConfig.getValueNamedKeyStroke()); launch.setToolTipText(Resources.getString("Chat.server_controls_tooltip", NamedHotKeyConfigurer.getString(l.getKeyStroke()))); //$NON-NLS-1$ } }); keyConfig.fireUpdate(); gm.addKeyStrokeListener(l); gm.getToolBar().add(launch); } public void toggleVisible() { if (controlPanel.getTopLevelAncestor() == null) { if (GlobalOptions.getInstance().isUseSingleWindow()) { splitter = new ComponentSplitter().splitRight(GameModule.getGameModule().getControlPanel(), controlPanel, false); splitter.revalidate(); final Runnable runnable = new Runnable() { public void run() { splitter.showComponent(); } }; SwingUtilities.invokeLater(runnable); } else { final JFrame frame = new JFrame(Resources.getString("Chat.server")); //$NON-NLS-1$ frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); frame.add(controlPanel); frame.setJMenuBar(MenuManager.getInstance().getMenuBarFor(frame)); final String key = "BoundsOfClientWindow"; //$NON-NLS-1$ final PositionOption pos = new VisibilityOption(key, frame); GameModule.getGameModule().getPrefs().addOption(pos); frame.setVisible(true); } } else if (splitter != null) { splitter.toggleVisibility(); } else { controlPanel.getTopLevelAncestor().setVisible(!controlPanel.getTopLevelAncestor().isVisible()); } } public JPanel getControls() { return controlPanel; } public void setClient(ChatServerConnection c) { client = c; if (c instanceof ChatControlsInitializer) { if (basicControls != null) { basicControls.uninitializeControls(this); } if (oldClient != null) { oldClient.uninitializeControls(this); } basicControls = new BasicChatControlsInitializer(c); basicControls.initializeControls(this); ((ChatControlsInitializer)c).initializeControls(this); oldClient = (ChatControlsInitializer) c; } PropertyChangeListener roomUpdater = new PropertyChangeListener() { public void propertyChange(final PropertyChangeEvent evt) { final Runnable runnable = new Runnable() { public void run() { roomTree.setRooms((VASSAL.chat.Room[]) evt.getNewValue()); } }; SwingUtilities.invokeLater(runnable); } }; client.addPropertyChangeListener(ChatServerConnection.AVAILABLE_ROOMS, roomUpdater); PropertyChangeListener currentRoomUpdater = new PropertyChangeListener() { public void propertyChange(final PropertyChangeEvent evt) { final Runnable runnable = new Runnable() { public void run() { if (evt.getNewValue() == null) { currentRoom.setRooms(new VASSAL.chat.Room[0]); } else { currentRoom.setRooms(new VASSAL.chat.Room[]{(VASSAL.chat.Room) evt.getNewValue()}); final Object root = currentRoom.getModel().getRoot(); final Object room = currentRoom.getModel().getChild(root, 0); currentRoom.expandPath(new TreePath(new Object[]{root, room})); } } }; SwingUtilities.invokeLater(runnable); } }; client.addPropertyChangeListener(ChatServerConnection.ROOM, currentRoomUpdater); client.addPropertyChangeListener(ChatServerConnection.CONNECTED, new PropertyChangeListener(){ public void propertyChange(PropertyChangeEvent e) { updateConfigServerToolTipText(); }}); } public ChatServerConnection getClient() { return client; } public String[] getAttributeNames() { return new String[0]; } public void setAttribute(String name, Object value) { } public String getAttributeValueString(String name) { return null; } public JToolBar getToolbar() { return toolbar; } public RoomTree getCurrentRoom() { return currentRoom; } public JTextField getNewRoom() { return newRoom; } public void addExtendedNewRoomHandler(ActionListener l) { newRoomButton.addActionListener(l); newRoomButton.setVisible(true); } public void removeExtendedNewRoomHandler(ActionListener l) { newRoomButton.removeActionListener(l); newRoomButton.setVisible(false); } public void setRoomControlsVisible (boolean visible) { newRoom.setVisible(visible); newRoomLabel.setVisible(visible); } public RoomTree getRoomTree() { return roomTree; } }