/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2004-2011 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package tic.tac.toe;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.jivesoftware.resource.Res;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ChatRoom;
import org.jivesoftware.spark.ui.ChatRoomButton;
import org.jivesoftware.spark.ui.ChatRoomListener;
import org.jivesoftware.spark.ui.ChatRoomListenerAdapter;
import org.jivesoftware.spark.ui.rooms.ChatRoomImpl;
import tic.tac.toe.packet.GameOfferPacket;
import tic.tac.toe.packet.InvalidMove;
import tic.tac.toe.packet.MovePacket;
import tic.tac.toe.ui.GamePanel;
/**
* Tic Tac Toe plugin for Spark
*
* @author wolf.posdorfer
* @version 16.06.2011
*
*/
public class TicTacToePlugin implements Plugin {
private ChatRoomListener _chatRoomListener;
private PacketListener _gameOfferListener;
private HashSet<String> _currentInvitations;
private ImageIcon buttonimg;
@Override
public void initialize() {
ClassLoader cl = getClass().getClassLoader();
buttonimg = new ImageIcon(cl.getResource("ttt.button.png"));
_currentInvitations = new HashSet<String>();
ProviderManager.getInstance().addIQProvider(GameOfferPacket.ELEMENT_NAME, GameOfferPacket.NAMESPACE,GameOfferPacket.class);
ProviderManager.getInstance().addExtensionProvider(MovePacket.ELEMENT_NAME, MovePacket.NAMESPACE, MovePacket.class);
ProviderManager.getInstance().addExtensionProvider(InvalidMove.ELEMENT_NAME, InvalidMove.NAMESPACE, InvalidMove.class);
// Add IQ listener to listen for incoming game invitations.
_gameOfferListener = new PacketListener() {
public void processPacket(Packet packet) {
GameOfferPacket invitation = (GameOfferPacket) packet;
if (invitation.getType() == IQ.Type.GET) {
showInvitationAlert(invitation);
}
}
};
SparkManager.getConnection().addPacketListener(_gameOfferListener,
new PacketTypeFilter(GameOfferPacket.class));
addButtonToToolBar();
}
/**
* Add the TTT-Button to every opening Chatroom
* and create Listeners for it
*/
private void addButtonToToolBar() {
_chatRoomListener = new ChatRoomListenerAdapter() {
@Override
public void chatRoomOpened(final ChatRoom room) {
if(!(room instanceof ChatRoomImpl))
{
// Don't do anything if this is not a 1on1-Chat
return;
}
final ChatRoomButton sendGameButton = new ChatRoomButton(buttonimg);
room.getToolBar().addChatRoomButton(sendGameButton);
final String opponentJID = ((ChatRoomImpl) room).getJID();
sendGameButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(_currentInvitations.contains(StringUtils.parseBareAddress(opponentJID)))
{
return;
}
final GameOfferPacket offer = new GameOfferPacket();
offer.setTo(opponentJID);
offer.setType(IQ.Type.GET );
_currentInvitations.add(StringUtils.parseBareAddress(opponentJID));
room.getTranscriptWindow().insertCustomText
(TTTRes.getString("ttt.request.sent"), false, false, Color.BLUE);
SparkManager.getConnection().sendPacket(offer);
SparkManager.getConnection().addPacketListener(
new PacketListener() {
@Override
public void processPacket(Packet packet) {
GameOfferPacket answer = (GameOfferPacket)packet;
answer.setStartingPlayer(offer.isStartingPlayer());
answer.setGameID(offer.getGameID());
if (answer.getType() == IQ.Type.RESULT) {
// ACCEPT
_currentInvitations.remove(StringUtils.parseBareAddress(opponentJID));
room.getTranscriptWindow().insertCustomText
(TTTRes.getString("ttt.request.accept"), false, false, Color.BLUE);
createTTTWindow(answer, opponentJID);
} else {
// DECLINE
room.getTranscriptWindow().insertCustomText
(TTTRes.getString("ttt.request.decline"), false, false, Color.RED);
_currentInvitations.remove(StringUtils.parseBareAddress(opponentJID));
}
}
},
new PacketIDFilter(offer.getPacketID()));
}
});
}
@Override
public void chatRoomClosed(ChatRoom room) {
if (room instanceof ChatRoomImpl) {
ChatRoomImpl cri = (ChatRoomImpl) room;
_currentInvitations.remove(cri.getParticipantJID());
}
}
};
SparkManager.getChatManager().addChatRoomListener(_chatRoomListener);
}
@Override
public void shutdown() {
_currentInvitations.clear();
SparkManager.getChatManager().removeChatRoomListener(_chatRoomListener);
SparkManager.getConnection().removePacketListener(_gameOfferListener);
}
@Override
public boolean canShutDown() {
return false;
}
@Override
public void uninstall() {
}
/**
* insert the Invitation Dialog into the Chat
*
* @param invitation
*/
private void showInvitationAlert(final GameOfferPacket invitation) {
invitation.setType(IQ.Type.RESULT);
invitation.setTo(invitation.getFrom());
final ChatRoom room = SparkManager.getChatManager().getChatRoom(StringUtils.parseBareAddress(invitation.getFrom()));
String name = StringUtils.parseName(invitation.getFrom());
final JPanel panel = new JPanel();
JLabel text = new JLabel(TTTRes.getString("ttt.game.request",name));
JLabel game = new JLabel(TTTRes.getString("ttt.game.name"));
game.setFont(new Font("Dialog", Font.BOLD, 24));
game.setForeground(Color.RED);
JButton accept = new JButton(Res.getString("button.accept").replace("&", ""));
JButton decline = new JButton(Res.getString("button.decline").replace("&", ""));
panel.add(text);
panel.add(game);
panel.add(accept);
panel.add(decline);
room.getTranscriptWindow().addComponent(panel);
accept.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SparkManager.getConnection().sendPacket(invitation);
invitation.setStartingPlayer(!invitation.isStartingPlayer());
createTTTWindow(invitation, invitation.getFrom());
panel.remove(3);
panel.remove(2);
panel.repaint();
panel.revalidate();
}
});
decline.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
invitation.setType(IQ.Type.ERROR);
SparkManager.getConnection().sendPacket(invitation);
panel.remove(3);
panel.remove(2);
panel.repaint();
panel.revalidate();
}
});
}
/**
* Creates The TicTacToe Window and starts the Game
* @param gop
* @param opponentJID
*/
private void createTTTWindow(GameOfferPacket gop, String opponentJID) {
String name = StringUtils.parseName(opponentJID);
// tictactoe versus ${name}
JFrame f = new JFrame(TTTRes.getString("ttt.window.title", TTTRes.getString("ttt.game.name"),name));
f.setIconImage(buttonimg.getImage());
GamePanel gp = new GamePanel(SparkManager.getConnection(),
gop.getGameID(), gop.isStartingPlayer(), opponentJID,f);
f.add(gp);
f.pack();
f.setLocationRelativeTo(SparkManager.getChatManager().getChatContainer());
f.setVisible(true);
}
}