/*
* Copyright 2003 (C) Devon Jones
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
package plugin.network;
import gmgen.GMGenSystem;
import gmgen.GMGenSystemView;
import gmgen.gui.ExtendedHTMLDocument;
import gmgen.gui.ExtendedHTMLEditorKit;
import gmgen.plugin.Combatant;
import gmgen.plugin.InitHolder;
import gmgen.plugin.InitHolderList;
import gmgen.util.LogReceiver;
import gmgen.util.LogUtilities;
import gmgen.util.MiscUtilities;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import pcgen.core.SettingsHandler;
import plugin.network.gui.NetworkView;
/**
*
* @author soulcatcher
*/
public class NetworkModel
{
private NetworkView view = new NetworkView();
static List<Color> colorList = new ArrayList<Color>();
static
{
colorList.add(Color.BLACK);
colorList.add(Color.BLUE);
colorList.add(Color.RED);
colorList.add(Color.GREEN);
colorList.add(Color.DARK_GRAY);
colorList.add(Color.ORANGE);
colorList.add(Color.CYAN);
colorList.add(Color.MAGENTA);
colorList.add(Color.LIGHT_GRAY);
colorList.add(Color.YELLOW);
colorList.add(Color.GRAY);
colorList.add(Color.PINK);
}
private NetworkServer server;
private NetworkClient client;
private InitHolderList combat;
private HashMap<String, Combatant> sentCombatants =
new HashMap<String, Combatant>();
private HashMap<String, NetworkCombatant> recievedCombatants =
new HashMap<String, NetworkCombatant>();
public NetworkModel()
{
applyPrefs();
initLogging();
initView();
addListeners();
}
public NetworkView getView()
{
return view;
}
/**
* This method currently does nothing
*/
public void closeWindow()
{
// Do Nothing
}
/**
* This method currently does nothing
*/
public void applyPrefs()
{
// Do Nothing
}
public void handleServerPcgMessage(String uid, String messagetext,
Socket sock)
{
if (sentCombatants.containsKey(uid))
{
Combatant cbt = sentCombatants.get(uid);
NetworkCombatant.recieveServerMessage(messagetext, cbt);
}
}
public void handlePcgMessage(String uid, String messagetext, Socket sock)
{
if (recievedCombatants.containsKey(uid))
{
NetworkCombatant cbt = recievedCombatants.get(uid);
cbt.recieveNetMessage(messagetext);
}
else
{
NetworkCombatant cbt = new NetworkCombatant(uid, sock);
cbt.recieveNetMessage(messagetext);
recievedCombatants.put(uid, cbt);
combat.add(cbt);
}
}
public void sendCombatant(Combatant cbt)
{
String user =
SettingsHandler.getGMGenOption(NetworkPlugin.LOG_NAME
+ ".username", "Player");
if (client != null)
{
sentCombatants
.put(NetworkCombatant.getCombatantUid(cbt, user), cbt);
NetworkCombatant.sendCombatant(cbt, client);
}
}
public void combatantUpdated(Combatant cbt)
{
if (combat != null)
{
for (InitHolder iH : combat)
{
if (iH == cbt)
{
sendCombatant(cbt);
}
}
}
}
private void initView()
{
view.getClientRadioButton().setSelected(true);
view.getServerAddressTextField().setText(
SettingsHandler.getGMGenOption(NetworkPlugin.LOG_NAME
+ ".ipAddress", "0.0.0.0"));
initList();
}
private void initList()
{
view.getUserList().setModel(new DefaultListModel());
addUser("Broadcast");
}
private void addListeners()
{
view.getServerRadioButton()
.addActionListener(new RadioActionListener());
view.getClientRadioButton()
.addActionListener(new RadioActionListener());
view.getConnectButton().addActionListener(
new ConnectionButtonActionListener());
view.getLogPane().addFocusListener(new TabFocusListener());
view.getMessageButton().addActionListener(
new MessageButtonActionListener());
}
private void displayClientToolbar()
{
view.showClientPanel();
view.showConnectionPanel();
}
private void displayServerToolbar()
{
view.hideClientPanel();
}
private void startServer()
{
server = new NetworkServer(this);
server.start();
}
private void stopServer()
{
if (server != null)
{
NetworkServer serverThread = null;
ThreadGroup tg = server.getThreadGroup();
// The Thread Group could be null if the server never started properly
if (tg != null)
{
Thread[] tl = new Thread[tg.activeCount()];
tg.enumerate(tl);
for (Thread t : tl)
{
if (t instanceof NetworkServer)
{
serverThread = (NetworkServer) t;
}
else if (t instanceof NetworkServer.Handler)
{
((NetworkServer.Handler) t).setRun(false);
}
}
if (serverThread != null)
{
serverThread.setRun(false);
}
}
}
server = null;
log("Local", "Local", "Server Shut Down");
initList();
}
private void startClient()
{
view.getConnectButton().setText("Disconnect");
client = new NetworkClient(this);
client.startClient();
}
private void stopClient()
{
if (client != null)
{
client.sendExitMessage();
}
}
public void resetClient()
{
client = null;
view.getConnectButton().setText("Connect");
getView()
.setConnectionText("Client Status", "Disconnected from Server");
initList();
}
private void initLogging()
{
LogUtilities.inst().addReceiver(new NetworkLogReciever());
JTabbedPane logPane = view.getLogPane();
JTextPane pane = new JTextPane();
pane.setEditable(false);
ExtendedHTMLEditorKit htmlKit = new ExtendedHTMLEditorKit();
pane.setEditorKit(htmlKit);
ExtendedHTMLDocument extDoc =
(ExtendedHTMLDocument) (htmlKit.createDefaultDocument());
extDoc.putProperty("number", Integer.valueOf(0));
logPane.add("Logs", new JScrollPane(pane));
JTextPane pane2 = new JTextPane();
EditorKit kit = pane2.getEditorKit();
Document doc = kit.createDefaultDocument();
doc.putProperty("number", Integer.valueOf(1));
}
public void log(String title, String message)
{
JTextPane logsPane = getLogPane("Logs");
SimpleDateFormat dateFmt = new SimpleDateFormat("hh.mm.ss a z");
ExtendedHTMLDocument logsDoc =
(ExtendedHTMLDocument) logsPane.getDocument();
int i = getUserNumber(title);
Color c = getLineColor(i);
try
{
logsDoc.insertAfterEnd(logsDoc.getCharacterElement(logsDoc
.getLength()), "<br>\n<b>"
+ dateFmt.format(Calendar.getInstance().getTime())
+ " <font color='#" + Integer.toHexString(c.getRGB()) + "'>" + title
+ "</b></font>: " + message);
setPaneIcon();
}
catch (Exception e)
{
//damn
}
}
public void log(String title, String owner, String message)
{
JTextPane logsPane = getLogPane("Logs");
SimpleDateFormat dateFmt = new SimpleDateFormat("hh.mm.ss a z");
ExtendedHTMLDocument logsDoc =
(ExtendedHTMLDocument) logsPane.getDocument();
int i = getUserNumber(title);
Color c = getLineColor(i);
try
{
logsDoc.insertAfterEnd(logsDoc.getCharacterElement(logsDoc
.getLength()), "<br>\n<b>"
+ dateFmt.format(Calendar.getInstance().getTime())
+ " <font color='#" + Integer.toHexString(c.getRGB()) + "'>" + title
+ "</b></font> " + owner + ": " + message);
setPaneIcon();
}
catch (Exception e)
{
//damn
}
}
public int getUserNumber(String user)
{
JList list = view.getUserList();
DefaultListModel model = (DefaultListModel) list.getModel();
if (model.contains(user))
{
return model.indexOf(user);
}
return 0;
}
public void addUser(String user)
{
JList list = view.getUserList();
DefaultListModel model = (DefaultListModel) list.getModel();
if (!model.contains(user))
{
model.addElement(user);
}
}
public void removeUser(String user)
{
JList list = view.getUserList();
DefaultListModel model = (DefaultListModel) list.getModel();
model.removeElement(user);
}
public String getSelectedUser()
{
JList list = view.getUserList();
return list.getSelectedValue().toString();
}
private Color getLineColor(int num)
{
return colorList.get(num >= colorList.size() ? num % colorList.size()
: num);
}
private JTextPane getLogPane(String title)
{
JTabbedPane logPane = view.getLogPane();
for (int i = 0; i < logPane.getTabCount(); i++)
{
if (logPane.getTitleAt(i).equals(title))
{
return (JTextPane) ((JScrollPane) logPane.getComponent(i))
.getViewport().getView();
}
}
//doesn't exist, create a new pane
JTextPane pane = new JTextPane();
EditorKit kit = pane.getEditorKit();
kit.createDefaultDocument();
logPane.add(title, new JScrollPane(pane));
return pane;
}
public void setPaneIcon()
{
JTabbedPane logPane = view.getLogPane();
JTabbedPane gmgenPane = GMGenSystemView.getTabPane();
if (gmgenPane.getSelectedComponent() instanceof NetworkView
&& GMGenSystem.inst.isFocused())
{
return;
}
logPane.setIconAt(logPane.indexOfTab("Logs"),
new javax.swing.ImageIcon(getClass().getResource(
"/pcgen/resource/images/NewEnvelope.gif")));
if (!(gmgenPane.getSelectedComponent() instanceof NetworkView))
{
int index = gmgenPane.indexOfComponent(view);
javax.swing.ImageIcon icon =
new javax.swing.ImageIcon(getClass().getResource(
"/pcgen/resource/images/NewEnvelope.gif"));
gmgenPane.setIconAt(index, icon);
}
}
public void clearIcon()
{
JTabbedPane logPane = view.getLogPane();
logPane.setIconAt(logPane.getSelectedIndex(), null);
}
public void sendMessage()
{
try
{
if (server != null)
{
server.sendIM("GM", getSelectedUser(), view
.getMessageTextField().getText());
}
else if (client != null)
{
if (getSelectedUser().equals("Broadcast"))
{
client.sendBroadcast(view.getMessageTextField().getText());
}
else
{
client.sendIM(getSelectedUser(), view.getMessageTextField()
.getText());
}
}
}
finally
{
view.getMessageTextField().setText("");
}
}
public void setCombat(InitHolderList combat)
{
this.combat = combat;
}
public InitHolderList getCombat()
{
return combat;
}
public void refresh()
{
if (combat != null)
{
for (InitHolder iH : combat)
{
if (iH instanceof Combatant)
{
sendCombatant((Combatant) iH);
}
}
}
}
private class NetworkLogReciever implements LogReceiver
{
public NetworkLogReciever()
{
// Empty Constructor
}
/**
* Logs a message associated with a specific owner.
*
* @param owner the owner of the message being logged.
* @param message the message to log.
*@since GMGen 3.3
*/
@Override
public void logMessage(String owner, String message)
{
log("Local", owner, message);
if (client != null)
{
client.sendLogMessage(owner, message);
}
}
/**
* Logs a message not associated with a specific owner.
*
* @param message the message to log.
*@since GMGen 3.3
*/
@Override
public void logMessage(String message)
{
logMessage("Misc", message);
}
}
private class RadioActionListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent evt)
{
if (view.getServerRadioButton().isSelected())
{
displayServerToolbar();
startServer();
}
else
{
try
{
stopServer();
}
catch (Exception e)
{
log("Local", "Local", "Failed to Shutdown Server.");
}
try
{
displayClientToolbar();
}
catch (Exception e)
{
log("Local", "Local",
"Failed to Display the client tool bar.");
}
}
}
}
private class ConnectionButtonActionListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent evt)
{
if (client == null)
{
startClient();
}
else
{
stopClient();
}
}
}
private class TabFocusListener implements FocusListener
{
@Override
public void focusGained(FocusEvent evt)
{
clearIcon();
}
/**
* This method currently does nothing
* @param evt
*/
@Override
public void focusLost(FocusEvent evt)
{
// Do Nothing
}
}
private class MessageButtonActionListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent evt)
{
sendMessage();
}
}
}