diff --git a/pom.xml b/pom.xml index fe82203..49462c8 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.mattyr urchat - 0.5.1 + 0.6.0 urchat https://github.com/matty-r/urChat @@ -41,6 +41,21 @@ 4.13 test + + org.apache.logging.log4j + log4j-api + 2.22.1 + + + org.apache.logging.log4j + log4j-core + 2.22.1 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.22.1 + @@ -49,9 +64,9 @@ - src/images + src/resources - images/ + resources/ tests/ @@ -62,10 +77,10 @@ maven-compiler-plugin 3.11.0 - - maven-jar-plugin - 3.3.0 - + + maven-jar-plugin + 3.3.0 + org.jacoco jacoco-maven-plugin @@ -103,15 +118,15 @@ org.jacoco - jacoco-maven-plugin - + jacoco-maven-plugin + default-prepare-agent prepare-agent - - + + @@ -130,4 +145,4 @@ - + \ No newline at end of file diff --git a/src/images/Go.png b/src/resources/images/Go.png similarity index 100% rename from src/images/Go.png rename to src/resources/images/Go.png diff --git a/src/images/Room.png b/src/resources/images/Room.png similarity index 100% rename from src/images/Room.png rename to src/resources/images/Room.png diff --git a/src/images/Server.png b/src/resources/images/Server.png similarity index 100% rename from src/images/Server.png rename to src/resources/images/Server.png diff --git a/src/images/Stop.png b/src/resources/images/Stop.png similarity index 100% rename from src/images/Stop.png rename to src/resources/images/Stop.png diff --git a/src/images/User.png b/src/resources/images/User.png similarity index 100% rename from src/images/User.png rename to src/resources/images/User.png diff --git a/src/images/Wait.png b/src/resources/images/Wait.png similarity index 100% rename from src/images/Wait.png rename to src/resources/images/Wait.png diff --git a/src/images/urChat Icon.png b/src/resources/images/urChat Icon.png similarity index 100% rename from src/images/urChat Icon.png rename to src/resources/images/urChat Icon.png diff --git a/src/resources/log4j2.xml b/src/resources/log4j2.xml new file mode 100644 index 0000000..59fea91 --- /dev/null +++ b/src/resources/log4j2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/urChatBasic/backend/Connection.java b/src/urChatBasic/backend/Connection.java index fc1750e..51f9750 100644 --- a/src/urChatBasic/backend/Connection.java +++ b/src/urChatBasic/backend/Connection.java @@ -6,16 +6,15 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; -import java.net.Proxy; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Date; -import java.util.logging.Level; import urChatBasic.backend.MessageHandler.Message; import urChatBasic.base.ConnectionBase; import urChatBasic.base.Constants; import urChatBasic.base.IRCServerBase; +import urChatBasic.base.proxy.ProxyTypes; import urChatBasic.frontend.DriverGUI; import urChatBasic.frontend.dialogs.MessageDialog; import java.awt.event.ActionEvent; @@ -38,11 +37,13 @@ public class Connection implements ConnectionBase private MessageHandler messageHandler; - // Connection keep alive stuff // Starts the timer with an start delay - private Timer keepAliveTimer = new Timer((int) Duration.ofSeconds(30).toMillis(), new PingKeepalive()); + private final int INITIAL_PING_RATE_MS = (int) Duration.ofSeconds(30).toMillis(); // Rate in which to send a PING to the server private final int PING_RATE_MS = (int) Duration.ofMinutes(5).toMillis(); + // Connection keep alive stuff + private Timer keepAliveTimer = new Timer(INITIAL_PING_RATE_MS, new PingKeepalive()); + private boolean pingReceived = true; private final int MAX_RESPONSE_FAILURES = 2; private int currentFailures = 0; @@ -86,24 +87,20 @@ private void startUp () throws IOException localMessage("Attempting to connect to " + server); // Determine the socket type to be used - InetSocketAddress address = new InetSocketAddress(server.getName(), Integer.parseInt(getServer().getPort())); + InetSocketAddress endPointAddress = new InetSocketAddress(server.getName(), Integer.parseInt(getServer().getPort())); - if (getServer().usingSOCKS()) + if (!getServer().usingProxy().equals(ProxyTypes.NONE.getType())) { - Proxy proxy = new Proxy(Proxy.Type.SOCKS, - new InetSocketAddress(getServer().getProxyHost(), Integer.parseInt(getServer().getProxyPort()))); - Socket proxySocket = new Socket(proxy); + getServer().usingProxy().createProxy(getServer().getProxyHost(), Integer.parseInt(getServer().getProxyPort())); + Socket proxySocket = getServer().usingProxy().connectThroughProxy(endPointAddress); if (getServer().usingTLS()) { - proxySocket.connect(address, 5000); - SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); - mySocket = sslsocketfactory.createSocket(proxySocket, address.getHostName(), address.getPort(), true); + mySocket = sslsocketfactory.createSocket(proxySocket, endPointAddress.getHostName(), endPointAddress.getPort(), true); mySocket.setKeepAlive(true); } else { - proxySocket.connect(address, 5000); mySocket = proxySocket; } } else @@ -116,7 +113,7 @@ private void startUp () throws IOException { mySocket = new Socket(); } - mySocket.connect(address, 500); + mySocket.connect(endPointAddress, 500); } writer = new BufferedWriter(new OutputStreamWriter(mySocket.getOutputStream())); @@ -124,6 +121,7 @@ private void startUp () throws IOException // if we got this far, we established a connection to the server DriverGUI.gui.setupServerTab(server); + DriverGUI.gui.addToCreatedServers(getServer()); localMessage("Initiating authentication..."); @@ -135,8 +133,7 @@ private void startUp () throws IOException Thread.sleep(500); } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } // Initiate connection to the server. @@ -146,8 +143,9 @@ private void startUp () throws IOException localMessage("Connecting with nick " + getServer().getNick()); writer.flush(); + keepAliveTimer.setInitialDelay(INITIAL_PING_RATE_MS); keepAliveTimer.setDelay(PING_RATE_MS); - keepAliveTimer.start(); + keepAliveTimer.restart(); while ((line = reader.readLine()) != null && !shutdown) { @@ -171,7 +169,7 @@ private void startUp () throws IOException mySocket.close(); } catch (IOException e) { - Constants.LOGGER.log(Level.SEVERE, "Error stopping connected.. " + e.getLocalizedMessage()); + Constants.LOGGER.error( "Error stopping connected.. " + e.getLocalizedMessage()); } } } @@ -186,7 +184,13 @@ public void run () { try { - if (shutdown) + if (shutdown && reconnect) + { + pingReceived = true; + + writer.write("PING " + new Date().toInstant().toEpochMilli() + "\r\n"); + writer.flush(); + } else if (shutdown) { keepAliveTimer.stop(); } else @@ -213,8 +217,7 @@ public void run () } } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } }); @@ -226,7 +229,9 @@ public void setPingReceived () { // Reset the fails currentFailures = 0; + reconnectAttempts = 0; pingReceived = true; + reconnect = false; } public MessageHandler getMessageHandler () @@ -254,7 +259,7 @@ public void sendClientText (String clientText, String fromChannel) throws IOExce } if (clientText.toLowerCase().startsWith("/join")) { - outText = "JOIN " + clientText.replace("/join ", "") + "\r\n"; + outText = "JOIN " + clientText.replace("/join ", "").toLowerCase() + "\r\n"; } else if (clientText.toLowerCase().startsWith("/nick")) { outText = "NICK " + clientText.replace("/nick ", "") + "\r\n"; @@ -282,7 +287,7 @@ public void sendClientText (String clientText, String fromChannel) throws IOExce } else if (clientText.toLowerCase().startsWith("/quit")) { outText = "QUIT :" + clientText.replace("/quit ", "") + "\r\n"; - } else if (clientText.toLowerCase().startsWith("/part")) + } else if (clientText.toLowerCase().startsWith("/part") || clientText.toLowerCase().startsWith("/leave")) { outText = "PART " + fromChannel + " :" + clientText.replace("/part ", "") + "\r\n"; } else if (clientText.toLowerCase().startsWith("/me") || clientText.toLowerCase().startsWith("/action")) @@ -317,7 +322,7 @@ public void sendClientText (String clientText, String fromChannel) throws IOExce writer.flush(); } catch (Exception e) { - Constants.LOGGER.log(Level.SEVERE, "Problem writing to socket: " + e.toString() + outText); + Constants.LOGGER.error( "Problem writing to socket: " + e.toString() + outText); } try @@ -328,15 +333,15 @@ public void sendClientText (String clientText, String fromChannel) throws IOExce } } catch (Exception e) { - Constants.LOGGER.log(Level.SEVERE, + Constants.LOGGER.error( "Problem writing out client message: " + e.toString() + clientMessage.getRawMessage()); } - Constants.LOGGER.log(Level.FINE, "Client Text:- " + fromChannel + " " + outText); + Constants.LOGGER.debug( "Client Text:- " + fromChannel + " " + outText.trim()); } else { - Constants.LOGGER.log(Level.WARNING, + Constants.LOGGER.error( "Not connected. Unable to send text:- " + fromChannel + " " + clientMessage.getRawMessage()); } } @@ -345,7 +350,7 @@ public void sendClientText (String clientText, String fromChannel) throws IOExce private void localMessage (String message) { server.printServerText(message); - Constants.LOGGER.log(Level.INFO, "Local Text:-" + message); + Constants.LOGGER.info( "Local Text:-" + message); } private void serverMessage (Message newMessage) @@ -355,10 +360,10 @@ private void serverMessage (Message newMessage) try { messageHandler.parseMessage(newMessage); - Constants.LOGGER.log(Level.FINE, newMessage.toString()); + Constants.LOGGER.debug( newMessage.toString()); } catch (Exception e) { - Constants.LOGGER.log(Level.WARNING, e.toString() + newMessage); + Constants.LOGGER.error(e.toString() + newMessage); } } } @@ -378,7 +383,7 @@ public void run () startUp(); } else { - Constants.LOGGER.log(Level.SEVERE, "Incomplete settings: (Port " + getServer().getPort() + ") (Server " + Constants.LOGGER.error( "Incomplete settings: (Port " + getServer().getPort() + ") (Server " + getServer() + ") (Nick " + getServer().getNick() + ") "); } @@ -392,18 +397,18 @@ public void run () run(); } else if (shutdown) { - Constants.LOGGER.log(Level.INFO, "Disconnected safely!"); + Constants.LOGGER.info( "Disconnected safely!"); } else { shutdown = true; reader.close(); writer.close(); mySocket.close(); - Constants.LOGGER.log(Level.WARNING, "Disconnected unsafely!"); + Constants.LOGGER.error("Disconnected unsafely!"); } } catch (IOException e) { - Constants.LOGGER.log(Level.SEVERE, "startUp() failed! " + e.getLocalizedMessage()); + Constants.LOGGER.error( "startUp() failed! " + e.getLocalizedMessage()); MessageDialog dialog = new MessageDialog("startUp() failed! " + e.getLocalizedMessage(), "Error", JOptionPane.ERROR_MESSAGE); dialog.setVisible(true); @@ -415,4 +420,14 @@ public void disconnect () { shutdown = true; } + + @Override + public void reconnect () + { + reconnectAttempts = 0; + shutdown = true; + reconnect = true; + keepAliveTimer.setInitialDelay(100); + keepAliveTimer.restart(); + } } diff --git a/src/urChatBasic/backend/LookAndFeelLoader.java b/src/urChatBasic/backend/LookAndFeelLoader.java index 8d1e24d..412d8e2 100644 --- a/src/urChatBasic/backend/LookAndFeelLoader.java +++ b/src/urChatBasic/backend/LookAndFeelLoader.java @@ -9,7 +9,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.logging.Level; import javax.swing.LookAndFeel; import javax.swing.UIManager; import urChatBasic.base.Constants; @@ -61,29 +60,29 @@ public LookAndFeelLoader(ClassLoader parentLoader) throws IOException { String classShortName = className.replaceAll(".*/([^/]+)", "$1"); className = className.replace('/', '.'); - Class c = cl.loadClass(className); + Class c = cl.loadClass(className); // We only want LAF classes - Class parentClass = LookAndFeel.class; + Class parentClass = LookAndFeel.class; // Class is a LookAndFeel if (parentClass.isAssignableFrom(c)) { try { UIManager.installLookAndFeel(classShortName, className); } catch (Exception installEx) { - Constants.LOGGER.log(Level.WARNING, installEx.getMessage()); + Constants.LOGGER.error(installEx.getMessage()); } } } } catch (NoClassDefFoundError | Exception classEx) { - Constants.LOGGER.log(Level.WARNING, classEx.getMessage()); + Constants.LOGGER.error(classEx.getMessage()); } } } } catch (Exception e) { // Handle URL creation exception - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } - Constants.LOGGER.log(Level.INFO, "Done loading JARs! "); + Constants.LOGGER.info( "Done loading JARs! "); } } diff --git a/src/urChatBasic/backend/MessageHandler.java b/src/urChatBasic/backend/MessageHandler.java index 5971c1c..da46fe4 100644 --- a/src/urChatBasic/backend/MessageHandler.java +++ b/src/urChatBasic/backend/MessageHandler.java @@ -1,21 +1,22 @@ package urChatBasic.backend; +import static urChatBasic.base.Constants.LOGGER; import java.time.Duration; import java.time.Instant; import java.util.Date; import java.util.HashSet; import java.util.Set; -import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.swing.JOptionPane; import urChatBasic.base.*; import urChatBasic.base.capabilities.CapabilityTypes; import urChatBasic.base.capabilities.SaslCapSubTypes; import urChatBasic.frontend.DriverGUI; +import urChatBasic.frontend.dialogs.MessageDialog; /** - * This class will Handle the message it has received and assign an approriate class that will parse - * the string and then + * This class will Handle the message it has received and assign an approriate class that will parse the string and then * * @author Matt * @@ -35,7 +36,7 @@ public class MessageHandler * @param server * @param messageID */ - public MessageHandler(IRCServerBase server) + public MessageHandler (IRCServerBase server) { this.serverBase = server; @@ -45,12 +46,12 @@ public MessageHandler(IRCServerBase server) addSingles(); } - public void parseMessage(Message receivedMessage) + public void parseMessage (Message receivedMessage) { receivedMessage.exec(); } - private Boolean isBetween(String line, char start, String middle, char end) + private Boolean isBetween (String line, char start, String middle, char end) { int startIndex = line.indexOf(start); int middleIndex = line.indexOf(middle); @@ -69,14 +70,14 @@ public class IDRange private MessageBase handlerType; private MessageIdType type = MessageIdType.NUMBER_ID; - public IDRange(int min, int max, MessageBase handlerType) + public IDRange (int min, int max, MessageBase handlerType) { this.min = min; this.max = max; this.handlerType = handlerType; } - public boolean inRange(int checkNumber) + public boolean inRange (int checkNumber) { return checkNumber >= this.min && checkNumber <= this.max; } @@ -89,28 +90,28 @@ public class IDSingle private MessageBase handlerType; private MessageIdType type; - public IDSingle(int id, MessageBase handlerType) + public IDSingle (int id, MessageBase handlerType) { this.idArray = new int[] {id}; this.handlerType = handlerType; type = MessageIdType.NUMBER_ID; } - public IDSingle(int[] id, MessageBase handlerType) + public IDSingle (int[] id, MessageBase handlerType) { this.idArray = id; this.handlerType = handlerType; type = MessageIdType.NUMBER_ID; } - public IDSingle(String id, MessageBase handlerType) + public IDSingle (String id, MessageBase handlerType) { this.id = id; this.handlerType = handlerType; type = MessageIdType.STRING_ID; } - public boolean isEqual(String testId) + public boolean isEqual (String testId) { try { @@ -123,7 +124,7 @@ public boolean isEqual(String testId) return false; } - public boolean isEqual(int testId) + public boolean isEqual (int testId) { for (int x : idArray) if (x == testId) @@ -135,7 +136,7 @@ public boolean isEqual(int testId) } } - private void addRanges() + private void addRanges () { rangeIDs.add(new IDRange(1, 4, new UserRegistrationMessage())); rangeIDs.add(new IDRange(332, 333, new ChannelTopicMessage())); @@ -145,7 +146,7 @@ private void addRanges() rangeIDs.add(new IDRange(471, 477, new JoinFailureMessage())); } - private void addSingles() + private void addSingles () { singleIDs.add(new IDSingle((new int[] {5, 328}), new NoticeMessage())); singleIDs.add(new IDSingle(353, new UsersListMessage())); @@ -167,8 +168,8 @@ private void addSingles() singleIDs.add(new IDSingle("PART", new PartMessage())); singleIDs.add(new IDSingle("KICK", new KickMessage())); singleIDs.add(new IDSingle("JOIN", new JoinMessage())); - singleIDs.add(new IDSingle(":Closing", new DisconnectMessage())); - singleIDs.add(new IDSingle("ERROR", new DisconnectMessage())); + // singleIDs.add(new IDSingle(":Closing", new DisconnectMessage())); + singleIDs.add(new IDSingle("ERROR", new DisconnectErrorMessage())); singleIDs.add(new IDSingle("QUIT", new DisconnectMessage())); singleIDs.add(new IDSingle("NICK", new RenameUserMessage())); singleIDs.add(new IDSingle("PONG", new PongMessage())); @@ -192,25 +193,27 @@ public class Message MessageIdType type; private String rawMessage = ""; String nick = ""; - String subType = ""; + String subType = ""; MessageBase messageBase; MessageBase subTypeBase; MessageHandler messageHandler; - public Message(String fullMessage) + public Message (String fullMessage) { rawMessage = fullMessage; messageHandler = MessageHandler.this; - // System.out.println(fullMessage); + LOGGER.debug(fullMessage); setPrefix(); - try{ + try + { setIdCommand(); setChannel(); setMessageBody(); setNick(); setSubType(); - } catch (Exception e) { + } catch (Exception e) + { this.channel = ""; } @@ -223,7 +226,7 @@ public Message(String fullMessage) this.type = MessageIdType.STRING_ID; // requires special handling - if(channel.isEmpty() && nick.isEmpty() && subType.isEmpty()) + if (channel.isEmpty() && nick.isEmpty() && subType.isEmpty()) { idCommand = prefix; } @@ -233,104 +236,109 @@ public Message(String fullMessage) } // Run the subType if it is set - public void exec() + public void exec () { - if(getSubTypeBase() != null) + if (getSubTypeBase() != null) { getSubTypeBase().messageExec(this); - } else { + } else + { getMessageBase().messageExec(this); } } - public String toPrettyString() + public String toPrettyString () { String prettyString = String.format(""" - Body: %s - channel: %s - idCommand: %s - prefix: %s - subType: %s - messageBase: %s - """, - body, - channel, - idCommand, - prefix, - subType, - messageBase.getClass().toGenericString() - ); + Body: %s + channel: %s + idCommand: %s + prefix: %s + subType: %s + messageBase: %s + """, body, channel, idCommand, prefix, subType, messageBase.getClass().toGenericString()); return prettyString; } - public String toString() + public String toString () { return rawMessage; } - public String getPrefix() { + public String getPrefix () + { return prefix; } - public String getIdCommand() { + public String getIdCommand () + { return idCommand; } - public int getIdCommandNumber() { + public int getIdCommandNumber () + { return idCommandNumber; } - public String getChannel() { + public String getChannel () + { return channel; } - public String getBody() { + public String getBody () + { return body; } - public MessageIdType getType() { + public MessageIdType getType () + { return type; } - public String getRawMessage() { + public String getRawMessage () + { return rawMessage; } - public String getNick() { + public String getNick () + { return nick; } - public String getSubType() { + public String getSubType () + { return subType; } - public MessageBase getMessageBase() { + public MessageBase getMessageBase () + { return messageBase; } - public MessageBase getSubTypeBase() { + public MessageBase getSubTypeBase () + { return subTypeBase; } - private void setPrefix() + private void setPrefix () { prefix = rawMessage.split(" ")[0]; } - private void setNick() + private void setNick () { if (isBetween(rawMessage, ':', "!", '@')) this.nick = rawMessage.substring(1, rawMessage.indexOf("!")).trim(); } - private void setChannel() + private void setChannel () { String withoutPrefix = rawMessage.replace(prefix, "").trim(); // int messageBegin = posnOfOccurrence(withoutPrefix, Constants.SPACES_AHEAD_DELIMITER, 1); int messageBegin = withoutPrefix.indexOf(Constants.SPACES_AHEAD_DELIMITER); - if(messageBegin < 0) + if (messageBegin < 0) { messageBegin = withoutPrefix.length(); } @@ -344,25 +352,27 @@ private void setChannel() Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(withoutPrefix); - if(matcher.find()) + if (matcher.find()) { this.channel = matcher.group(1); - } else { + } else + { regex = "\\!(#?\\w+)\\@"; pattern = Pattern.compile(regex); matcher = pattern.matcher(prefix); - if(matcher.find()) + if (matcher.find()) + { + this.channel = "#" + matcher.group(1); + } else { - this.channel = "#"+matcher.group(1); - } else { this.channel = withoutPrefix.split(" ")[1]; } } } } - private void setMessageBody() + private void setMessageBody () { try { @@ -374,50 +384,56 @@ private void setMessageBody() this.body = withoutPrefixIdChannel; } catch (IndexOutOfBoundsException e) { - Constants.LOGGER.log(Level.SEVERE, - "Failed to extract a message from received text. " + e.getLocalizedMessage()); + Constants.LOGGER.error("Failed to extract a message from received text. " + e.getLocalizedMessage()); } } // TODO: This should be improved. Flatten all the IDs into a single list - support for testing against // this.subType (only under MessageIdType.STRING_ID) as well as this.idCommand - private void setBases() { + private void setBases () + { boolean messageBaseSet = false; MessageBase newBase = new MessageHandler.DefaultMesssage(); - for (IDSingle testSingle : singleIDs) { - if (testSingle.type.equals(MessageIdType.NUMBER_ID) && testSingle.isEqual(idCommandNumber)) { + for (IDSingle testSingle : singleIDs) + { + if (testSingle.type.equals(MessageIdType.NUMBER_ID) && testSingle.isEqual(idCommandNumber)) + { newBase = testSingle.handlerType; messageBaseSet = true; } - if(testSingle.type.equals(MessageIdType.STRING_ID)) + if (testSingle.type.equals(MessageIdType.STRING_ID)) { - if (testSingle.isEqual(idCommand)) { + if (testSingle.isEqual(idCommand)) + { newBase = testSingle.handlerType; messageBaseSet = true; } - if(testSingle.isEqual(subType)) + if (testSingle.isEqual(subType)) { subTypeBase = testSingle.handlerType; } } - if(messageBaseSet && subType.isEmpty()) + if (messageBaseSet && subType.isEmpty()) { break; } } - if (!messageBaseSet) { - for (IDRange testRange : rangeIDs) { - if (testRange.type.equals(MessageIdType.NUMBER_ID) && testRange.inRange(idCommandNumber)) { + if (!messageBaseSet) + { + for (IDRange testRange : rangeIDs) + { + if (testRange.type.equals(MessageIdType.NUMBER_ID) && testRange.inRange(idCommandNumber)) + { newBase = testRange.handlerType; messageBaseSet = true; } - if(messageBaseSet && subType.isEmpty()) + if (messageBaseSet && subType.isEmpty()) { break; } @@ -429,14 +445,15 @@ private void setBases() { - private void setIdCommand() + private void setIdCommand () { - if(prefix.indexOf(':') >= 0) - { - idCommand = rawMessage.split(" ")[1];} - else - { idCommand = rawMessage.split(" ")[0]; + if (prefix.indexOf(':') >= 0) + { + idCommand = rawMessage.split(" ")[1]; + } else + { + idCommand = rawMessage.split(" ")[0]; } } @@ -447,14 +464,15 @@ private void setSubType () if (rawBody.contains(":")) rawBody = rawBody.substring(rawBody.indexOf(":") + 1); - if(rawBody.charAt(0) == Constants.CTCP_DELIMITER) + if (rawBody.charAt(0) == Constants.CTCP_DELIMITER) { subType = rawBody.split(" ")[0].trim(); - } else { + } else + { subType = this.rawMessage.replaceFirst(Pattern.quote(this.prefix), ""); subType = subType.replaceFirst(Pattern.quote(this.idCommand), ""); subType = subType.replaceFirst(Pattern.quote(this.channel), ""); - subType = subType.replaceFirst(Pattern.quote(this.body),""); + subType = subType.replaceFirst(Pattern.quote(this.body), ""); subType = subType.trim(); subType = subType.split(" ")[0]; } @@ -465,7 +483,7 @@ public class UserRegistrationMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -476,7 +494,7 @@ public class CommandResponseMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -486,7 +504,7 @@ public class GeneralServerMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -496,7 +514,7 @@ public class GeneralChannelMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { myMessage.messageHandler.serverBase.printChannelText(myMessage.channel, myMessage.body, Constants.EVENT_USER); } @@ -506,7 +524,7 @@ public class JoinMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (myMessage.nick.equals(myMessage.messageHandler.serverBase.getNick())) { @@ -522,7 +540,7 @@ public class ChannelTopicMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { myMessage.messageHandler.serverBase.setChannelTopic(myMessage.channel, myMessage.body); } @@ -532,7 +550,7 @@ public class UsersListMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { myMessage.messageHandler.serverBase.addToUsersList(myMessage.channel, myMessage.body.split(" ")); } @@ -542,7 +560,7 @@ public class RenameUserMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (!myMessage.nick.equals(myMessage.messageHandler.serverBase.getNick())) myMessage.messageHandler.serverBase.renameUser(myMessage.nick, myMessage.body); @@ -553,7 +571,7 @@ public class JoinFailureMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); serverBase.callForAttention(); @@ -566,7 +584,7 @@ public class ModeMessage implements MessageBase @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { // printServerText(myMessage.body); if (myMessage.channel.equals(myMessage.messageHandler.serverBase.getNick())) @@ -582,7 +600,7 @@ public class WhoIsMessage implements MessageBase @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printPrivateText(myMessage.rawMessage.split(" ")[3], myMessage.body, myMessage.rawMessage.split(" ")[3]); } @@ -594,7 +612,7 @@ public class ServerChangeMessage implements MessageBase @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { // TODO } @@ -605,7 +623,7 @@ public class BadPrivateMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { // TODO Auto-generated method stub } @@ -614,7 +632,7 @@ public void messageExec(Message myMessage) public class SASLAuthenticateFailedMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -623,7 +641,7 @@ public void messageExec(Message myMessage) public class SASLAuthenticateSuccessMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); serverBase.saslCompleteAuthentication(); @@ -633,9 +651,9 @@ public void messageExec(Message myMessage) public class SASLAuthenticateMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { - if(myMessage.rawMessage.equals("AUTHENTICATE +")) + if (myMessage.rawMessage.equals("AUTHENTICATE +")) { printServerText(myMessage.rawMessage); serverBase.saslSendAuthentication(); @@ -646,14 +664,13 @@ public void messageExec(Message myMessage) public class PongMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { Instant pingTime = Instant.ofEpochMilli(Long.parseLong(myMessage.getBody())); long timeToResponse = Duration.between(pingTime, new Date().toInstant()).toMillis(); - printServerText("Took "+timeToResponse+"ms to respond."); - + printServerText("Took " + timeToResponse + "ms to respond."); serverBase.setPingReceived(); } } @@ -662,17 +679,21 @@ public class CapabilityMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { // CAP ACK or CAP LS? - switch (myMessage.subType) { - case "LS" -> { + switch (myMessage.subType) + { + case "LS" -> + { printServerText(myMessage.body); serverBase.setCapabilities(myMessage.body); - if (serverBase.hasCapability(CapabilityTypes.SASL)) { + if (serverBase.hasCapability(CapabilityTypes.SASL)) + { // Did the client have a sasl type selected? - if (gui.authenticationType().equals(SaslCapSubTypes.PLAIN)) { + if (serverBase.getAuthentication().equals(SaslCapSubTypes.PLAIN)) + { serverBase.saslRequestAuthentication(); break; } @@ -680,11 +701,13 @@ public void messageExec(Message myMessage) // end capability message serverBase.saslCompleteAuthentication(); - if (gui.authenticationType().equals(CapabilityTypes.NICKSERV.getType())) { + if (serverBase.getAuthentication().equals(CapabilityTypes.NICKSERV.getType())) + { serverBase.nickservRequestAuthentication(); } } - case "ACK" -> { + case "ACK" -> + { printServerText("Begin SASL Authentication"); serverBase.saslDoAuthentication(); } @@ -698,7 +721,7 @@ public class InvalidNickMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -708,19 +731,20 @@ public class NoticeMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (myMessage.nick != null && myMessage.nick.equalsIgnoreCase("NickServ")) { printPrivateText(myMessage.nick, myMessage.body, myMessage.nick); - gui.connectFavourites(myMessage.messageHandler.serverBase); + serverBase.reconnectChannels(); } else { IRCRoomBase messageChannel = myMessage.messageHandler.serverBase.getCreatedChannel(myMessage.getChannel()); - if(messageChannel != null) + if (messageChannel != null) { messageChannel.printText(myMessage.getBody(), Constants.EVENT_USER); - } else { + } else + { printServerText(myMessage.body); } } @@ -731,13 +755,13 @@ public class ActionMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { // Transform the body slightly to make it more unique? myMessage.body = myMessage.body.replaceFirst("ACTION", ">"); // only call the primary message base if this was set as the subtype - if(myMessage.getSubTypeBase().getClass().equals(this.getClass())) + if (myMessage.getSubTypeBase().getClass().equals(this.getClass())) myMessage.getMessageBase().messageExec(myMessage); } } @@ -746,7 +770,7 @@ public class PrivateMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (!myMessage.getSubType().equals(serverBase.getNick()) && !myMessage.getChannel().equals(serverBase.getNick())) { @@ -762,7 +786,7 @@ public void messageExec(Message myMessage) public class PartMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (!(myMessage.nick.equals(myMessage.messageHandler.serverBase.getNick()))) { @@ -782,16 +806,28 @@ public void messageExec(Message myMessage) public class KickMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { myMessage.messageHandler.serverBase.removeFromUsersList(myMessage.channel, myMessage.body); } } + public class DisconnectErrorMessage implements MessageBase + { + @Override + public void messageExec (Message myMessage) + { + Constants.LOGGER.error(myMessage.getBody()); + MessageDialog dialog = new MessageDialog("startUp() failed! " + myMessage.getBody(), "Error", JOptionPane.ERROR_MESSAGE); + dialog.setVisible(true); + // new DisconnectMessage().messageExec(myMessage); + } + } + public class DisconnectMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { if (myMessage.messageHandler.serverBase.getNick().equals(myMessage.nick) || myMessage.nick.isBlank()) { @@ -806,7 +842,7 @@ public void messageExec(Message myMessage) public class NoSuchChannelMessage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -815,7 +851,7 @@ public void messageExec(Message myMessage) public class NotEnoughParametersMesssage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); } @@ -824,19 +860,19 @@ public void messageExec(Message myMessage) public class DefaultMesssage implements MessageBase { @Override - public void messageExec(Message myMessage) + public void messageExec (Message myMessage) { printServerText(myMessage.body); - Constants.LOGGER.log(Level.WARNING, "NOT HANDLED: " + myMessage.rawMessage); + Constants.LOGGER.error("NOT HANDLED: " + myMessage.rawMessage); } } - private void printPrivateText(String userName, String line, String fromUser) + private void printPrivateText (String userName, String line, String fromUser) { serverBase.printPrivateText(userName, line, fromUser); } - private void printServerText(String message) + private void printServerText (String message) { serverBase.printServerText(message); } diff --git a/src/urChatBasic/backend/logging/URLogger.java b/src/urChatBasic/backend/logging/URLogger.java new file mode 100644 index 0000000..e846a30 --- /dev/null +++ b/src/urChatBasic/backend/logging/URLogger.java @@ -0,0 +1,136 @@ +package urChatBasic.backend.logging; + +import static urChatBasic.base.Constants.LOGGER; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.Filter.Result; +import org.apache.logging.log4j.core.appender.FileAppender; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.filter.MarkerFilter; +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; +import urChatBasic.base.Constants; +import urChatBasic.base.IRCRoomBase; +import urChatBasic.frontend.DriverGUI; + +public class URLogger +{ + private static final String LOG4J_CONFIG_FILE = Constants.RESOURCES_PATH + "log4j2.xml"; + + private static LoggerContext context; + static Configuration currentConfig; + + public static void init () throws IOException, URISyntaxException + { + File logDir = new File(Constants.DIRECTORY_LOGS); + if (!logDir.exists()) + { + logDir.mkdir(); + } + + System.setProperty("log4j2.configurationFile", DriverGUI.class.getResource(LOG4J_CONFIG_FILE).toURI().toString()); + // System.setProperty("log4j2.debug", "true"); + + LOGGER = LoggerFactory.getLogger(URLogger.class); + + Logger testLog = getLogger(LOGGER.getName(), Logger.class); + + // Initialize the logger context using the ConfigurationSource + context = testLog.getContext(); + currentConfig = context.getConfiguration(); + } + + public static T getLogger(final String loggerName, final Class loggerClass) { + final org.slf4j.Logger logger = LoggerFactory.getLogger(loggerName); + try { + final Class loggerIntrospected = logger.getClass(); + final Field fields[] = loggerIntrospected.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + final String fieldName = fields[i].getName(); + if (fieldName.equals("logger")) { + fields[i].setAccessible(true); + return loggerClass.cast(fields[i].get(logger)); + } + } + } catch (final Exception e) { + logger.error(e.getMessage()); + } + return null; + } + + public static Marker getMarker (String markerName) + { + return MarkerFactory.getMarker(markerName); + } + + // private static String loadConfigFile (String fileName) throws IOException + // { + // // Load the configuration file content from the classpath + // try (InputStream inputStream = DriverGUI.class.getResourceAsStream(fileName)) + // { + // if (inputStream == null) + // { + // throw new IOException("Configuration file not found: " + fileName); + // } + + // String configFileString = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + // return configFileString; + // } + // } + + public static void logChannelComms (IRCRoomBase ircChannel, String message) + { + + LOGGER.info(getMarker(ircChannel.getMarker()), message); + } + + /** + * Copy the default FileAppender and create a new one for the new Marker + * + * @param markerName + */ + public static void addChannelMarker (String markerName) + { + String appenderName = markerName + "Appender"; // Replace with your appender name + String loggerName = markerName; // Replace with your logger name + + // Get the root LoggerConfig + Configuration rootLoggerConfig = currentConfig; + Logger rootLogger; + + if (currentConfig.getLoggerContext() != null) + { + rootLogger = currentConfig.getLoggerContext().getRootLogger(); + } else + { + return; + } + + FileAppender existingFileAppender = (FileAppender) rootLoggerConfig.getAppenders().get("BaseChannelAppender"); + + // Create a new FileAppender using the existingFileAppender as a base + FileAppender.Builder newAppenderBuilder = + FileAppender.newBuilder().setName(appenderName).withFileName("Logs/" + loggerName + ".log").setLayout(existingFileAppender.getLayout()); + + // Add MarkerFilter for the specified markerName + MarkerFilter acceptNewMarker = MarkerFilter.createFilter(markerName, Result.ACCEPT, Result.DENY); + newAppenderBuilder.setFilter(acceptNewMarker); + + Appender newFileAppender = newAppenderBuilder.build(); + newFileAppender.start(); + + // Add the newFileAppender to the configuration + currentConfig.addAppender(newFileAppender); + currentConfig.addLoggerAppender(rootLogger, newFileAppender); + + // Update the context with the new configuration + context.updateLoggers(currentConfig); + } + +} diff --git a/src/urChatBasic/backend/utils/URPreferencesUtil.java b/src/urChatBasic/backend/utils/URPreferencesUtil.java index 111928b..f56a601 100644 --- a/src/urChatBasic/backend/utils/URPreferencesUtil.java +++ b/src/urChatBasic/backend/utils/URPreferencesUtil.java @@ -2,7 +2,6 @@ import java.awt.Color; import java.awt.Font; -import java.awt.List; import java.awt.font.TextAttribute; import java.util.ArrayList; import java.util.Arrays; @@ -11,12 +10,10 @@ import java.util.Hashtable; import java.util.Map; import java.util.Optional; -import java.util.logging.Level; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import javax.swing.UIManager; import urChatBasic.base.Constants; -import urChatBasic.frontend.DriverGUI; import urChatBasic.frontend.utils.URColour; public class URPreferencesUtil { @@ -49,8 +46,7 @@ public static Font loadStyleFont(Font defaultFont, Preferences settingsPath) return defaultFont; } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); return defaultFont; } @@ -89,8 +85,7 @@ public static Map loadStyleColours(URStyle defaultStyle, Preferen return colourMap; } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); return colourMap; } @@ -140,13 +135,11 @@ else if (URProfilesUtil.getActiveProfilePath().nodeExists(styleName)) } catch (Exception e) { - Constants.LOGGER.log(Level.WARNING, "Active Profile: ["+URProfilesUtil.getActiveProfileName()+"] Unable to load ["+loadedStyle.getAttribute("name")+"]"+ " attempted with path: " + stylePrefPath); - // TODO Auto-generated catch block - // e.printStackTrace(); + Constants.LOGGER.error("Active Profile: ["+URProfilesUtil.getActiveProfileName()+"] Unable to load ["+loadedStyle.getAttribute("name")+"]"+ " attempted with path: " + stylePrefPath); return targetStyle; } - Constants.LOGGER.log(Level.FINE, "Load Style Path: " + stylePrefPath.toString()); + Constants.LOGGER.debug( "Load Style Path: " + stylePrefPath.toString()); Font loadedFont = loadStyleFont(loadedStyle.getFont(), stylePrefPath); Map loadedColours = loadStyleColours(loadedStyle, stylePrefPath); @@ -162,7 +155,7 @@ public static void deleteStyleFont(URStyle targetStyle, Preferences baseSettings Preferences settingsPath = baseSettingsPath.node(targetStyle.getName()); try { - Constants.LOGGER.log(Level.FINE, "Removing font keys: " + settingsPath.absolutePath()); + Constants.LOGGER.debug( "Removing font keys: " + settingsPath.absolutePath()); settingsPath.remove(Constants.KEY_FONT_BOLD); settingsPath.remove(Constants.KEY_FONT_ITALIC); settingsPath.remove(Constants.KEY_FONT_FAMILY); @@ -170,8 +163,7 @@ public static void deleteStyleFont(URStyle targetStyle, Preferences baseSettings settingsPath.remove(Constants.KEY_FONT_UNDERLINE); } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } @@ -180,20 +172,19 @@ public static void deleteStyleColours(URStyle targetStyle, Preferences baseSetti Preferences settingsPath = baseSettingsPath.node(targetStyle.getName()); try { - Constants.LOGGER.log(Level.INFO, "Removing font colours: " + settingsPath.absolutePath()); + Constants.LOGGER.info( "Removing font colours: " + settingsPath.absolutePath()); settingsPath.remove(Constants.KEY_FONT_FOREGROUND); settingsPath.remove(Constants.KEY_FONT_BACKGROUND); } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } public static void saveStyle(URStyle oldStyle, URStyle newStyle, Preferences baseSettingsPath) { Preferences stylePrefPath = baseSettingsPath.node(newStyle.getAttribute("name").toString()); - Constants.LOGGER.log(Level.INFO, "Save Style Path: " + stylePrefPath.toString()); + Constants.LOGGER.info( "Save Style Path: " + stylePrefPath.toString()); URStyle diffStyle = oldStyle.clone(); @@ -221,8 +212,7 @@ public static void saveStyle(URStyle oldStyle, URStyle newStyle, Preferences bas } } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } } @@ -255,7 +245,9 @@ public static void putPref(String name, Optional optionalValue, Preferences p } else if (value instanceof Boolean) { path.putBoolean(name, (boolean) value); } else { - Constants.LOGGER.log(Level.WARNING,"Unsupported data type for preference: " + value.getClass().getSimpleName()); + path.put(name, (String) value.toString()); + + Constants.LOGGER.info( "[" + value.getClass().getSimpleName() + "] is an unsupported data type for Preferences. Setting as String."); } } } @@ -311,8 +303,7 @@ public static ArrayList getAllNodes (Preferences rootPath) } } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } return prefPaths; diff --git a/src/urChatBasic/backend/utils/URProfilesUtil.java b/src/urChatBasic/backend/utils/URProfilesUtil.java index e0978e0..d060f2b 100644 --- a/src/urChatBasic/backend/utils/URProfilesUtil.java +++ b/src/urChatBasic/backend/utils/URProfilesUtil.java @@ -50,8 +50,7 @@ public static String[] getProfiles () } } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } // Use a Set, then convert to Array to drop any duplicates @@ -69,7 +68,7 @@ public static void deleteProfile (String profileName) if(allProfiles.length > 1) { - Constants.LOGGER.log(Level.INFO, "Deleting profile [" + profileName + "]."); + Constants.LOGGER.info( "Deleting profile [" + profileName + "]."); Constants.BASE_PREFS.node(profileName).removeNode(); fireListeners(EventType.DELETE); } @@ -88,7 +87,7 @@ public static void deleteProfile (String profileName) } catch (BackingStoreException e) { - Constants.LOGGER.log(Level.WARNING, "Problem deleting profile [" + profileName +"]." + e.getLocalizedMessage()); + Constants.LOGGER.error("Problem deleting profile [" + profileName +"]." + e.getLocalizedMessage()); } } @@ -116,7 +115,7 @@ public static void setActiveProfileName (String activeProfileName) // throws Con // UserGUI.fireProfileChangeListeners(); fireListeners(EventType.CHANGE); } else { - Constants.LOGGER.log(Level.WARNING, "Profile ["+activeProfileName+"] doesn't exist."); + Constants.LOGGER.error("Profile ["+activeProfileName+"] doesn't exist."); // throw new ConfigurationException("Profile ["+activeProfileName+"] doesn't exist."); } } @@ -158,10 +157,10 @@ public static boolean profileExists (String profileName) public static void cleanUpSettings () { - Constants.LOGGER.log(Level.INFO, "Cleaning up settings"); + Constants.LOGGER.info( "Cleaning up settings"); try { - Constants.LOGGER.log(Level.INFO, "Remove empty favourites"); + Constants.LOGGER.info( "Remove empty favourites"); ArrayList allNodes = URPreferencesUtil.getAllNodes(Constants.BASE_PREFS); List deletePreferences = new ArrayList<>(); @@ -183,7 +182,7 @@ public static void cleanUpSettings () } } catch (BackingStoreException e) { - Constants.LOGGER.log(Level.WARNING, e.getLocalizedMessage()); + Constants.LOGGER.error(e.getLocalizedMessage()); } } @@ -210,8 +209,7 @@ public static Preferences cloneProfile (String originalProfileName, Optional userHistory = new ArrayList(); - // TODO: This is logging stuff, should not be handled here - private DateFormat historyDateFormat = new SimpleDateFormat("ddMMyyyy"); - private String historyFileName; - private Date todayDate = new Date(); - private String channelTopic; // Tab complete stuff @@ -145,24 +143,22 @@ public void hideEventTicker() public void hideUsersList() { usersListShown = false; - // userScroller.setVisible(usersListShown); toggleUsersList(usersListShown); } public void showUsersList() { usersListShown = true; - // userScroller.setVisible(usersListShown); toggleUsersList(usersListShown); } - public IRCRoomBase(String roomName) + protected IRCRoomBase(String roomName) { this.roomName = roomName; initRoom(); } - public IRCRoomBase(IRCServerBase server, String roomName) + protected IRCRoomBase(IRCServerBase server, String roomName) { this.roomName = roomName; setServer(server); @@ -181,6 +177,7 @@ private void initRoom() if (getServer() != null) { String nodeName = getServer().getName() != null ? getServer().getName() : roomName; + markerName = getServer().getName() != null ? getServer().getName() + "-" + roomName : roomName; if(nodeName.equals(roomName)) setSettingsPath(URProfilesUtil.getActiveFavouritesPath().node(nodeName)); @@ -192,12 +189,16 @@ private void initRoom() lineFormatter = new LineFormatter(getFontPanel().getStyle(), channelTextArea , getServer(), roomPrefs); } else { + markerName = roomName; setSettingsPath(URProfilesUtil.getActiveFavouritesPath().node(roomName)); fontDialog = new FontDialog(roomName, gui.getStyle(), roomPrefs); lineFormatter = new LineFormatter(getFontPanel().getStyle() , channelTextArea, null, roomPrefs); } + // Add Logging Marker + URLogger.addChannelMarker(markerName); + URProfilesUtil.addListener(EventType.CHANGE, changeListener); setFont(getFontPanel().getFont()); @@ -235,6 +236,11 @@ public void actionPerformed (ActionEvent arg0) } + public void rejoin () + { + server.sendClientText("/join " + getName(), server.getName()); + } + public void setSettingsPath (Preferences settingsPath) { roomPrefs = settingsPath; @@ -394,7 +400,7 @@ public void mouseMoved(MouseEvent e) Element wordElement = doc.getCharacterElement(channelTextArea.viewToModel2D((e.getPoint()))); AttributeSet wordAttributeSet = wordElement.getAttributes(); ClickableText isClickableText = (ClickableText) wordAttributeSet.getAttribute("clickableText"); - if (isClickableText != null && gui.isClickableLinksEnabled()) + if (isClickableText != null && ((InterfacePanel) gui.interfacePanel).isClickableLinksEnabled()) { channelTextArea.setCursor(new Cursor(Cursor.HAND_CURSOR)); } else @@ -406,11 +412,11 @@ public void mouseMoved(MouseEvent e) public void createEvent(String eventText) { - if (gui.isJoinsQuitsMainEnabled() && !(this instanceof IRCPrivate)) + if (((InterfacePanel) gui.interfacePanel).isJoinsQuitsMainEnabled() && !(this instanceof IRCPrivate)) printText(eventText, Constants.EVENT_USER); - eventTickerTimer.setDelay(gui.getEventTickerDelay()); - if (gui.isJoinsQuitsTickerEnabled() && !(this instanceof IRCPrivate)) + eventTickerTimer.setDelay(((InterfacePanel) gui.interfacePanel).getEventTickerDelay()); + if (((InterfacePanel) gui.interfacePanel).isJoinsQuitsTickerEnabled() && !(this instanceof IRCPrivate)) { JLabel tempLabel = new JLabel(eventText); int tempX; @@ -452,6 +458,11 @@ public void callForAttention() myActions.callForAttention(); } + public String getMarker () + { + return markerName; + } + class MessagePair { private String line; private String fromUser; @@ -479,7 +490,7 @@ public void printText(String line, String fromUser) { handleMessageQueue(); } catch (InterruptedException e) { - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } @@ -513,10 +524,10 @@ public void run() Document document = lineFormatter.getDocument(); Element root = lineFormatter.getDocument().getDefaultRootElement(); - int lineLimit = gui.getLimitChannelLinesCount(); + int lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); if(IRCRoomBase.this instanceof IRCServer) - lineLimit = gui.getLimitServerLinesCount(); + lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitServerLinesCount(); if(null != messagePair && root.getElementCount() > lineLimit) { @@ -529,27 +540,16 @@ public void run() } catch(BadLocationException ble) { - Constants.LOGGER.log(Level.WARNING, ble.getLocalizedMessage()); + Constants.LOGGER.error(ble.getLocalizedMessage()); } } if (null == channelTextArea) { - Constants.LOGGER.log(Level.WARNING, "ChannelTextArea hasn't initialized or has disappeared.. not printing text."); + Constants.LOGGER.error("ChannelTextArea hasn't initialized or has disappeared.. not printing text."); return; } - if (gui.isChannelHistoryEnabled()) - { - try - { - writeHistoryFile(line); - } catch (IOException e) - { - Constants.LOGGER.log(Level.WARNING, e.getLocalizedMessage()); - } - } - // StyledDocument doc = channelTextArea.getStyledDocument(); IRCUser fromIRCUser = getCreatedUser(fromUser); @@ -563,7 +563,7 @@ public void run() // TODO: Re-add later? // addToUsersList(getName(), fromUser); // fromIRCUser = getCreatedUsers(fromUser); - // Constants.LOGGER.log(Level.WARNING, "Message from a user that isn't in the user list!"); + // Constants.LOGGER.error("Message from a user that isn't in the user list!"); fromIRCUser = server.getIRCUser(fromUser); addToUsersList(fromIRCUser); } @@ -574,6 +574,16 @@ public void run() { lineFormatter.formattedDocument(new Date(), fromIRCUser, fromUser, line); + if(IRCRoomBase.this instanceof IRCServerBase) + { + if (((InterfacePanel) gui.interfacePanel).saveServerHistory()) + URLogger.logChannelComms(IRCRoomBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); + } else if(!(IRCRoomBase.this instanceof IRCServerBase)) + { + if (((InterfacePanel) gui.interfacePanel).saveChannelHistory()) + URLogger.logChannelComms(IRCRoomBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); + } + if (server.getNick() != null && line.indexOf(server.getNick()) > -1) { callForAttention(); @@ -593,7 +603,7 @@ public void run() } } catch (InterruptedException e) { - Constants.LOGGER.log(Level.WARNING, e.getLocalizedMessage()); + Constants.LOGGER.error(e.getLocalizedMessage()); } } } @@ -608,9 +618,9 @@ public void run() * * @param showIt */ - public void toggleUsersList(Boolean showIt) + public void toggleUsersList (boolean showIt) { - if (usersListShown == showIt || usersListShown == null) + if (usersListShown == null || usersListShown == showIt) { // userScroller.setVisible(showIt); if (showIt) @@ -627,9 +637,9 @@ public void toggleUsersList(Boolean showIt) * * @param showIt */ - public void toggleEventTicker(Boolean showIt) + public void toggleEventTicker (boolean showIt) { - if (eventTickerShown == showIt || eventTickerShown == null) + if (eventTickerShown == null || eventTickerShown == showIt) { tickerPanel.setVisible(showIt); if (tickerPanel.isVisible()) @@ -759,23 +769,6 @@ public void setChannelTopic(String channelTopic) this.createEvent(channelTopic); } - public void writeHistoryFile(String line) throws IOException - { - if (gui.saveChannelHistory()) - { - if (historyFileName == null || historyFileName.isEmpty()) - { - historyFileName = historyDateFormat.format(todayDate) + " " + getName() + ".log"; - } - - FileWriter fw = new FileWriter(Constants.DIRECTORY_LOGS + historyFileName, true); - BufferedWriter bw = new BufferedWriter(fw); - PrintWriter outFile = new PrintWriter(bw); - outFile.println(line); - outFile.close(); - } - } - /** Rename user by removing old name and inserting new name. */ public void renameUser(final String oldUserName, final String newUserName) { @@ -888,13 +881,14 @@ public ChannelPopUp() @Override public void show(Component arg0, int arg1, int arg2) { - if (gui.isFavourite(IRCRoomBase.this)) - { - ((ChannelPopUp) IRCRoomBase.this.myMenu).addAsFavouriteItem.setText("Remove as Favourite"); - } else - { - ((ChannelPopUp) IRCRoomBase.this.myMenu).addAsFavouriteItem.setText("Add as Favourite"); - } + // TODO: Favourites handling to be done elsewhere + // if (gui.isFavourite(IRCRoomBase.this)) + // { + // ((ChannelPopUp) IRCRoomBase.this.myMenu).addAsFavouriteItem.setText("Remove as Favourite"); + // } else + // { + // ((ChannelPopUp) IRCRoomBase.this.myMenu).addAsFavouriteItem.setText("Add as Favourite"); + // } super.show(arg0, arg1, arg2); } @@ -906,16 +900,17 @@ private class AddAsFavourite implements ActionListener @Override public void actionPerformed(ActionEvent arg0) { - if (null != getServer()) - { - if (!gui.isFavourite(IRCRoomBase.this)) - { - gui.addFavourite(getServer().getName(), getName()); - } else - { - gui.removeFavourite(getServer().getName(), getName()); - } - } + // TODO: Favourites handling to be done elsewhere + // if (null != getServer()) + // { + // if (!gui.isFavourite(IRCRoomBase.this)) + // { + // gui.addFavourite(getServer().getName(), getName()); + // } else + // { + // gui.removeFavourite(getServer().getName(), getName()); + // } + // } } } @@ -989,7 +984,7 @@ public void actionPerformed(ActionEvent arg0) if (!getUserTextBox().getText().trim().isEmpty()) { sendClientText(clientTextBox.getText(), getName()); - if (gui.isClientHistoryEnabled()) + if (((InterfacePanel) gui.interfacePanel).isClientHistoryEnabled()) userHistory.add(clientTextBox.getText()); } clientTextBox.setText(""); @@ -1024,11 +1019,7 @@ public void setFont(Font f) { public void run() { - - // fontDialog.getFontPanel().setDefaultFont(f); lineFormatter.setFont(fontDialog.getFontPanel().getFont()); - // TODO: Should this updateStyles if the font is changed? - lineFormatter.updateStyles(fontDialog.getFontPanel().getStyle()); } }); } else @@ -1048,7 +1039,7 @@ public void actionPerformed(ActionEvent arg0) } } - public void quitRoom() + public void closeRoom() { URProfilesUtil.removeListener(EventType.CHANGE, changeListener); eventTickerTimer.stop(); @@ -1256,12 +1247,12 @@ private class TickerListener extends MouseInputAdapter { public void mouseEntered(MouseEvent e) { - eventTickerTimer.setDelay(gui.getEventTickerDelay() * 10); + eventTickerTimer.setDelay(((InterfacePanel) gui.interfacePanel).getEventTickerDelay() * 10); } public void mouseExited(MouseEvent e) { - eventTickerTimer.setDelay(gui.getEventTickerDelay()); + eventTickerTimer.setDelay(((InterfacePanel) gui.interfacePanel).getEventTickerDelay()); } } diff --git a/src/urChatBasic/base/IRCServerBase.java b/src/urChatBasic/base/IRCServerBase.java index c0cb1bb..93d0af2 100644 --- a/src/urChatBasic/base/IRCServerBase.java +++ b/src/urChatBasic/base/IRCServerBase.java @@ -1,6 +1,8 @@ package urChatBasic.base; +import urChatBasic.base.capabilities.CapTypeBase; import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypeBase; import urChatBasic.frontend.IRCChannel; import urChatBasic.frontend.IRCPrivate; import urChatBasic.frontend.IRCUser; @@ -18,10 +20,16 @@ public interface IRCServerBase public abstract String getPassword (); - public abstract void connect (); + public abstract CapTypeBase getAuthentication (); + + public abstract void connect (String[] autoConnectChannels); + + public abstract void reconnectChannels (); public abstract void disconnect (); + public abstract void reconnect (); + public abstract boolean isConnected (); public abstract boolean hasConnection (); @@ -38,7 +46,7 @@ public interface IRCServerBase public abstract Boolean usingTLS (); - public abstract Boolean usingSOCKS (); + public abstract ProxyTypeBase usingProxy (); /** * Get the IRCUser object from the userName - if the IRCUser isn't found, then create it. diff --git a/src/urChatBasic/base/UserGUIBase.java b/src/urChatBasic/base/UserGUIBase.java index 46b6f90..b87db66 100644 --- a/src/urChatBasic/base/UserGUIBase.java +++ b/src/urChatBasic/base/UserGUIBase.java @@ -1,15 +1,8 @@ package urChatBasic.base; -import java.util.prefs.Preferences; -import urChatBasic.base.capabilities.CapTypeBase; - public interface UserGUIBase { - public abstract int getLimitServerLinesCount(); - - public abstract int getLimitChannelLinesCount(); - /** * Sets the tab to the index number * @@ -32,10 +25,6 @@ public interface UserGUIBase */ public abstract int getTabIndex(String tabName); - public abstract Boolean saveChannelHistory(); - - public abstract Boolean saveServerHistory(); - /** * Return the appropriate created server * @@ -51,13 +40,6 @@ public interface UserGUIBase */ public abstract void setupServerTab(IRCServerBase server); - /** - * Creates a new server based on name - * - * @param serverName - */ - public abstract void addToCreatedServers(String serverName); - /** * Check to see if there are any Servers at all. * @@ -66,106 +48,40 @@ public interface UserGUIBase */ public abstract Boolean isCreatedServersEmpty(); - /** - * Show event ticker? - * - * @return Boolean - */ - public abstract Boolean isShowingEventTicker(); - - /** - * Show users list? - * - * @return Boolean - */ - public abstract Boolean isShowingUsersList(); - - /** - * Show users list? - * - * @return Boolean - */ - public abstract Boolean isClickableLinksEnabled(); - - public abstract CapTypeBase authenticationType(); - - /** - * Show joins/quits in the event ticker? - * - * @return Boolean - */ - public abstract Boolean isJoinsQuitsTickerEnabled(); - - /** - * Show joins/quits in the main window? - * - * @return Boolean - */ - public abstract Boolean isJoinsQuitsMainEnabled(); + public abstract void addToCreatedServers(IRCServerBase ircServer); + + // TODO: Favourites handling should be done elsewhere. + // /** + // * Adds the favourite as an element to the favourites list - also adds the item to the + // * clientSettings. + // * + // * @param server + // * @param channel + // */ + // public abstract void addFavourite(String server, String channel); + + // /** + // * Used to check if the channel is already a favourite from an IRCChannel + // * + // * @param channel + // * @return + // */ + // public abstract Boolean isFavourite(IRCRoomBase channel); - /** - * Save channel chat history? - * - * @return Boolean - */ - public abstract Boolean isChannelHistoryEnabled(); - - /** - * Limit the number of lines in the server activity window - * - * @return Boolean - */ - public abstract Boolean isLimitedServerActivity(); - - /** - * Limit the number of lines in the channel history - * - * @return Boolean - */ - public abstract Boolean isLimitedChannelActivity(); - - /** - * Add timestamp to chat text? - * - * @return Boolean - */ - public abstract Boolean isTimeStampsEnabled(); - - /** - * Save text that I type, this allows using the up and down arrows to repeat text. - * - * @return - */ - public abstract Boolean isClientHistoryEnabled(); + // public abstract void removeFavourite(String server, String channel); - /** - * Adds the favourite as an element to the favourites list - also adds the item to the - * clientSettings. - * - * @param server - * @param channel - */ - public abstract void addFavourite(String server, String channel); + // /** + // * Used to connect to all the favourites. This gets run from Connection once the socket has + // * successfully connected to the initial server. + // * + // * @param IRCServer + // */ + // public abstract void connectFavourites(IRCServerBase server); - /** - * Used to check if the channel is already a favourite from an IRCChannel - * - * @param channel - * @return - */ - public abstract Boolean isFavourite(IRCRoomBase channel); - - // public abstract void removeFavourite(String server, String channel); + // public abstract void removeFavourite(String favServer, String favChannel); public abstract void sendGlobalMessage(String message, String sender); - /** - * Used to connect to all the favourites. This gets run from Connection once the socket has - * successfully connected to the initial server. - * - * @param IRCServer - */ - public abstract void connectFavourites(IRCServerBase server); /** * Loops through all servers and disconnects and deletes the tab @@ -176,12 +92,9 @@ public interface UserGUIBase public abstract void removeClientSetting(String node, String key); - public abstract int getEventTickerDelay(); - public abstract void setClientSettings(); public abstract void run(); - public abstract void removeFavourite(String favServer, String favChannel); } diff --git a/src/urChatBasic/base/capabilities/CapabilityTypes.java b/src/urChatBasic/base/capabilities/CapabilityTypes.java index c05353f..9af65f6 100644 --- a/src/urChatBasic/base/capabilities/CapabilityTypes.java +++ b/src/urChatBasic/base/capabilities/CapabilityTypes.java @@ -3,28 +3,28 @@ import java.util.ArrayList; import java.util.Arrays; -public enum CapabilityTypes { - NONE(new NoAuthType()), - NICKSERV(new NickServType()), - SASL(new SaslCapType()); +public enum CapabilityTypes +{ + NONE(new NoAuthType()), NICKSERV(new NickServType()), SASL(new SaslCapType()); CapTypeBase type; - CapabilityTypes(CapTypeBase baseType) + CapabilityTypes (CapTypeBase baseType) { this.type = baseType; }; - public CapTypeBase getType() + public CapTypeBase getType () { return type; } - public static CapTypeBase[] getCategory(CapTypeBase.Category category) + public static CapTypeBase[] getCategory (CapTypeBase.Category category) { ArrayList allSubTypes = new ArrayList(); - for (CapabilityTypes capabilityType : CapabilityTypes.values()) { - if(capabilityType.getType().getCategory().equals(category)) + for (CapabilityTypes capabilityType : CapabilityTypes.values()) + { + if (capabilityType.getType().getCategory().equals(category)) { allSubTypes.addAll(Arrays.asList(capabilityType.getType().availableSubTypes())); } @@ -34,17 +34,19 @@ public static CapTypeBase[] getCategory(CapTypeBase.Category category) return allSubTypesArray; } - public static CapTypeBase getCapType(String capTypeName) + public static CapTypeBase getCapType (String capTypeName) { ArrayList allSubTypes = new ArrayList(); - for (CapabilityTypes capabilityType : CapabilityTypes.values()) { + for (CapabilityTypes capabilityType : CapabilityTypes.values()) + { allSubTypes.addAll(Arrays.asList(capabilityType.getType().availableSubTypes())); } CapTypeBase[] allSubTypesArray = new CapTypeBase[allSubTypes.size()]; allSubTypes.toArray(allSubTypesArray); - for (CapTypeBase capType : allSubTypes) { - if(capType.toString().equals(capTypeName)) + for (CapTypeBase capType : allSubTypes) + { + if (capType.toString().equals(capTypeName)) { return capType; } diff --git a/src/urChatBasic/base/proxy/HttpType.java b/src/urChatBasic/base/proxy/HttpType.java new file mode 100644 index 0000000..d3c2254 --- /dev/null +++ b/src/urChatBasic/base/proxy/HttpType.java @@ -0,0 +1,41 @@ +package urChatBasic.base.proxy; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; + +public class HttpType implements ProxyTypeBase +{ + String name = "HTTP"; + Socket proxySocket; + + @Override + public String getName () + { + return name; + } + + @Override + public String toString () + { + return getName(); + } + + @Override + public ProxyTypeBase createProxy (String hostName, int port) + { + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostName, port)); + proxySocket = new Socket(proxy); + + return this; + } + + @Override + public Socket connectThroughProxy (InetSocketAddress endPoint) throws IOException + { + proxySocket.connect(endPoint, 5000); + return proxySocket; + } + +} diff --git a/src/urChatBasic/base/proxy/NoProxyType.java b/src/urChatBasic/base/proxy/NoProxyType.java new file mode 100644 index 0000000..6c1a68b --- /dev/null +++ b/src/urChatBasic/base/proxy/NoProxyType.java @@ -0,0 +1,36 @@ +package urChatBasic.base.proxy; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +public class NoProxyType implements ProxyTypeBase { + String name = "None"; + Socket proxySocket; + + @Override + public String getName () + { + return name; + } + + @Override + public String toString () + { + return getName(); + } + + + @Override + public ProxyTypeBase createProxy (String hostName, int port) + { + return this; + } + + @Override + public Socket connectThroughProxy (InetSocketAddress endPoint) throws IOException + { + throw new IOException("No Proxy Needed"); + } + +} diff --git a/src/urChatBasic/base/proxy/ProxyTypeBase.java b/src/urChatBasic/base/proxy/ProxyTypeBase.java new file mode 100644 index 0000000..3921177 --- /dev/null +++ b/src/urChatBasic/base/proxy/ProxyTypeBase.java @@ -0,0 +1,30 @@ +package urChatBasic.base.proxy; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +public interface ProxyTypeBase +{ + + + /** + * Returns the name of the type of proxy. + * @return + */ + public abstract String getName(); + + /** + * Returns the newly created Proxy Socket + * @param hostName + * @param port + * @return + */ + public abstract ProxyTypeBase createProxy (String hostName, int port); + + /** + * Endpoint to connect to through the proxy + * @param endPoint + */ + public abstract Socket connectThroughProxy (InetSocketAddress endPoint) throws IOException; +} diff --git a/src/urChatBasic/base/proxy/ProxyTypes.java b/src/urChatBasic/base/proxy/ProxyTypes.java new file mode 100644 index 0000000..11583df --- /dev/null +++ b/src/urChatBasic/base/proxy/ProxyTypes.java @@ -0,0 +1,48 @@ +package urChatBasic.base.proxy; + +import java.util.Arrays; +import java.util.List; +public enum ProxyTypes +{ + NONE(new NoProxyType()), SOCKS(new SocksType()), HTTP(new HttpType()); + + ProxyTypeBase type; + + ProxyTypes (ProxyTypeBase baseType) + { + this.type = baseType; + }; + + public ProxyTypeBase getType () + { + return type; + } + + @Override + public String toString () + { + return type.getName(); + } + + public static ProxyTypeBase getProxyType (String proxyTypeName) + { + List allProxyTypes = Arrays.asList(getValues()); + + for (ProxyTypeBase proxyType : allProxyTypes) + { + if (proxyType.toString().equals(proxyTypeName)) + { + return proxyType; + } + } + + return null; + } + + public static ProxyTypeBase[] getValues () + { + return Arrays.stream(ProxyTypes.values()) + .map(ProxyTypes::getType) + .toArray(ProxyTypeBase[]::new); + } +} diff --git a/src/urChatBasic/base/proxy/SocksType.java b/src/urChatBasic/base/proxy/SocksType.java new file mode 100644 index 0000000..34f55e2 --- /dev/null +++ b/src/urChatBasic/base/proxy/SocksType.java @@ -0,0 +1,41 @@ +package urChatBasic.base.proxy; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; + +public class SocksType implements ProxyTypeBase +{ + String name = "SOCKS"; + Socket proxySocket; + + @Override + public String getName () + { + return name; + } + + @Override + public String toString () + { + return getName(); + } + + @Override + public ProxyTypeBase createProxy (String hostName, int port) + { + Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(hostName, port)); + proxySocket = new Socket(proxy); + + return this; + } + + @Override + public Socket connectThroughProxy (InetSocketAddress endPoint) throws IOException + { + proxySocket.connect(endPoint, 5000); + return proxySocket; + } + +} diff --git a/src/urChatBasic/frontend/DriverGUI.java b/src/urChatBasic/frontend/DriverGUI.java index ae8061e..3be0398 100644 --- a/src/urChatBasic/frontend/DriverGUI.java +++ b/src/urChatBasic/frontend/DriverGUI.java @@ -6,8 +6,6 @@ import java.io.IOException; import java.net.URL; import java.util.Optional; -import java.util.logging.Handler; -import java.util.logging.Level; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.SwingUtilities; @@ -15,6 +13,7 @@ import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.backend.utils.URUncaughtExceptionHandler; import urChatBasic.base.Constants; +import static urChatBasic.base.Constants.LOGGER; public class DriverGUI { @@ -28,15 +27,15 @@ public static void main(String[] args) throws IOException Constants.init(); try { - URL imgPath = new URL(Constants.RESOURCES_DIR + "urChat Icon.png"); + URL imgPath = new URL(Constants.IMAGES_DIR + "urChat Icon.png"); img = new ImageIcon(imgPath); } catch (Exception e) { - Constants.LOGGER.log(Level.INFO, "No Icon found."); + Constants.LOGGER.info( "No Icon found."); } - Constants.LOGGER.log(Level.INFO, "Starting up.."); + Constants.LOGGER.info( "Starting up.."); initLAFLoader(); frame = new JFrame("urChat"); @@ -71,6 +70,7 @@ public static UserGUI createGUI(Optional profileName) public static void startGUI() { frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setLocationRelativeTo(null); frame.setContentPane(gui); frame.pack(); @@ -80,7 +80,7 @@ public static void startGUI() SwingUtilities.invokeLater(gui); - Constants.LOGGER.log(Level.INFO, "Started"); + LOGGER.info( "Started"); frame.setVisible(true); @@ -115,8 +115,6 @@ public void windowClosing(WindowEvent e) URProfilesUtil.cleanUpSettings(); if (!gui.isCreatedServersEmpty()) gui.sendGlobalMessage("/quit Goodbye cruel world", "Server"); - for (Handler tempHandler : Constants.LOGGER.getHandlers()) - tempHandler.close(); } diff --git a/src/urChatBasic/frontend/IRCChannel.java b/src/urChatBasic/frontend/IRCChannel.java index db667fe..b430a8b 100644 --- a/src/urChatBasic/frontend/IRCChannel.java +++ b/src/urChatBasic/frontend/IRCChannel.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URL; -import java.util.logging.Level; import javax.swing.ImageIcon; import urChatBasic.base.Constants; import urChatBasic.base.IRCRoomBase; @@ -27,11 +26,11 @@ public IRCChannel(IRCServer server, String channelName) URL imgPath = null; try { - imgPath = new URL(Constants.RESOURCES_DIR + "Room.png"); + imgPath = new URL(Constants.IMAGES_DIR + "Room.png"); icon = new ImageIcon(imgPath); } catch (IOException e) { - Constants.LOGGER.log(Level.SEVERE, "COULD NOT LOAD Server.png " + e.getLocalizedMessage()); + Constants.LOGGER.warn( "COULD NOT LOAD Room.png " + e.getLocalizedMessage()); } } } diff --git a/src/urChatBasic/frontend/IRCPrivate.java b/src/urChatBasic/frontend/IRCPrivate.java index f9f0c50..9f59e1f 100644 --- a/src/urChatBasic/frontend/IRCPrivate.java +++ b/src/urChatBasic/frontend/IRCPrivate.java @@ -5,7 +5,6 @@ import java.awt.event.ActionListener; import java.io.IOException; import java.net.URL; -import java.util.logging.Level; import javax.swing.ImageIcon; import urChatBasic.base.Constants; import urChatBasic.base.IRCRoomBase; @@ -27,11 +26,11 @@ public IRCPrivate(IRCServer server, IRCUser user) URL imgPath = null; try { - imgPath = new URL(Constants.RESOURCES_DIR + "User.png"); + imgPath = new URL(Constants.IMAGES_DIR + "User.png"); icon = new ImageIcon(imgPath); } catch (IOException e) { - Constants.LOGGER.log(Level.SEVERE, "COULD NOT LOAD Server.png " + e.getLocalizedMessage()); + Constants.LOGGER.warn( "COULD NOT LOAD User.png " + e.getLocalizedMessage()); } } diff --git a/src/urChatBasic/frontend/IRCServer.java b/src/urChatBasic/frontend/IRCServer.java index abd6fc7..1f5c174 100644 --- a/src/urChatBasic/frontend/IRCServer.java +++ b/src/urChatBasic/frontend/IRCServer.java @@ -30,6 +30,8 @@ import urChatBasic.base.Constants.EventType; import urChatBasic.base.capabilities.CapTypeBase; import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypeBase; +import urChatBasic.frontend.utils.URPanels; public class IRCServer extends IRCRoomBase implements IRCServerBase { @@ -50,7 +52,8 @@ public class IRCServer extends IRCRoomBase implements IRCServerBase private Boolean isTLS; private String proxyHost; private String proxyPort; - private Boolean useSOCKS; + private ProxyTypeBase proxyType; + private CapTypeBase authentication; // Created channels/tabs public List createdRooms = new ArrayList(); @@ -59,8 +62,8 @@ public class IRCServer extends IRCRoomBase implements IRCServerBase private ArrayList capabilities = new ArrayList(); - public IRCServer(String serverName, String nick, String login, String password, String portNumber, Boolean isTLS, String proxyHost, - String proxyPort, Boolean useSOCKS) + public IRCServer (String serverName, String nick, String login, String password, String portNumber, Boolean isTLS, String proxyHost, String proxyPort, + ProxyTypeBase proxyType, CapTypeBase authentication) { super(serverName); setServer(this); @@ -74,89 +77,104 @@ public IRCServer(String serverName, String nick, String login, String password, this.proxyHost = proxyHost; this.proxyPort = proxyPort; - this.useSOCKS = useSOCKS; + this.proxyType = proxyType; this.name = serverName; this.password = password; this.login = login; this.nick = nick; + this.authentication = authentication; URL imgPath = null; try { - imgPath = new URL(Constants.RESOURCES_DIR + "Server.png"); + imgPath = new URL(Constants.IMAGES_DIR + "Server.png"); icon = new ImageIcon(imgPath); } catch (IOException e) { - Constants.LOGGER.log(Level.SEVERE, "COULD NOT LOAD Server.png " + e.getLocalizedMessage()); + Constants.LOGGER.warn( "COULD NOT LOAD Server.png " + e.getLocalizedMessage()); } } @Override - public void saslRequestAuthentication() + public void saslRequestAuthentication () { sendClientText("CAP REQ sasl", getName()); } @Override - public void nickservRequestAuthentication() + public void nickservRequestAuthentication () { - if(!getPassword().isEmpty()) + if (!getPassword().isEmpty()) { - sendClientText("/msg nickserv identify "+getNick()+" "+getPassword(), getName()); - } else { - sendClientText("/msg nickserv ACC",getName()); + sendClientText("/msg nickserv identify " + getNick() + " " + getPassword(), getName()); + } else + { + sendClientText("/msg nickserv ACC", getName()); } } @Override - public void saslCompleteAuthentication() + public void saslCompleteAuthentication () { sendClientText("CAP END", getName()); - gui.connectFavourites(this); + // TODO: gui.connectFavourites(this); + reconnectChannels(); } @Override - public void saslDoAuthentication() + public void saslDoAuthentication () { sendClientText("AUTHENTICATE PLAIN", getName()); } + public void reconnectChannels () + { + for (IRCRoomBase channel : createdRooms) + { + sendClientText("/join " + channel.getName(), getServer().getName()); + } + } + @Override - public void saslSendAuthentication() + public void saslSendAuthentication () { String escapedDelim = Character.toString(0x0); - String saslString = escapedDelim+getNick()+escapedDelim+getPassword(); + String saslString = escapedDelim + getNick() + escapedDelim + getPassword(); try { saslString = Base64.getEncoder().encodeToString(saslString.getBytes(StandardCharsets.UTF_8.toString())); } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } - sendClientText("AUTHENTICATE "+saslString, getName()); + sendClientText("AUTHENTICATE " + saslString, getName()); } @Override public void setCapabilities (String capabilityMessage) { - // example message: account-notify away-notify chghost extended-join multi-prefix sasl=PLAIN,ECDSA-NIST256P-CHALLENGE,EXTERNAL tls account-tag cap-notify echo-message server-time solanum.chat/identify-msg solanum.chat/oper solanum.chat/realhost + // example message: account-notify away-notify chghost extended-join multi-prefix sasl=PLAIN,ECDSA-NIST256P-CHALLENGE,EXTERNAL tls account-tag + // cap-notify echo-message server-time solanum.chat/identify-msg solanum.chat/oper solanum.chat/realhost String[] components = capabilityMessage.split(" "); - for (String component : components) { - for (CapabilityTypes capability : CapabilityTypes.values()) { - if(capability.getType().matches(component)) + for (String component : components) + { + for (CapabilityTypes capability : CapabilityTypes.values()) + { + if (capability.getType().matches(component)) { capabilities.add(capability); - } else if(component.startsWith(capability.name().toLowerCase() + "=")) + } else if (component.startsWith(capability.name().toLowerCase() + "=")) { capabilities.add(capability); String[] subComponents = component.replace(capability.name().toLowerCase() + "=", "").split(","); - for (String subComponent : subComponents) { - for (CapTypeBase subType : capability.getType().availableSubTypes()) { - if(subType.matches(subComponent)) + for (String subComponent : subComponents) + { + for (CapTypeBase subType : capability.getType().availableSubTypes()) + { + if (subType.matches(subComponent)) capability.getType().addSubtype(subType); } } @@ -168,8 +186,9 @@ public void setCapabilities (String capabilityMessage) @Override public boolean hasCapability (CapabilityTypes capability) { - for (CapabilityTypes capabilityType : capabilities) { - if(capabilityType.equals(capability)) + for (CapabilityTypes capabilityType : capabilities) + { + if (capabilityType.equals(capability)) { return true; } @@ -184,32 +203,38 @@ public boolean hasCapability (CapabilityTypes capability) * @see urChatBasic.backend.IRCServerBase#getNick() */ @Override - public String getNick() + public String getNick () { return nick; } @Override - public void setNick(String newNick) + public void setNick (String newNick) { nick = newNick; } @Override - public String getLogin() + public String getLogin () { return login; } @Override - public String getPassword() + public String getPassword () { return password; } @Override - public boolean isConnected() + public CapTypeBase getAuthentication () + { + return authentication; + } + + @Override + public boolean isConnected () { return hasConnection() && serverConnection.isConnected(); } @@ -221,19 +246,19 @@ public boolean hasConnection () } @Override - public String getPort() + public String getPort () { return this.port; } @Override - public Boolean usingSOCKS() + public ProxyTypeBase usingProxy () { - return useSOCKS; + return proxyType; } @Override - public Boolean usingTLS() + public Boolean usingTLS () { return isTLS; } @@ -254,7 +279,7 @@ public String getProxyPort () * Server doesn't need the User List, so don't set it up. */ @Override - protected void setupMainPanel() + protected void setupMainPanel () { mainPanel.setLayout(new BorderLayout()); setupMainTextArea(); @@ -274,9 +299,10 @@ class ServerPopUp extends JPopupMenu JMenuItem nameItem; JMenuItem quitItem; + JMenuItem reconnectItem; JMenuItem chooseFont; - public ServerPopUp() + public ServerPopUp () { nameItem = new JMenuItem(IRCServer.this.getName()); add(nameItem); @@ -285,6 +311,11 @@ public ServerPopUp() quitItem = new JMenuItem("Quit"); add(quitItem); quitItem.addActionListener(new QuitItem()); + + reconnectItem = new JMenuItem("Reconnect"); + add(reconnectItem); + reconnectItem.addActionListener(new ReconnectServerItem()); + // chooseFont = new JMenuItem("Show Font Dialog"); add(chooseFont); @@ -301,11 +332,11 @@ public void setPingReceived () private class QuitItem implements ActionListener { @Override - public void actionPerformed(ActionEvent arg0) + public void actionPerformed (ActionEvent arg0) { if (IRCServer.this.isConnected()) { - Constants.LOGGER.log(Level.INFO, "send quit message"); + Constants.LOGGER.info( "send quit message"); // Send the /quit message, which disconnects and remove the gui elements sendClientText("/quit Goodbye cruel world", getName()); } else @@ -316,11 +347,20 @@ public void actionPerformed(ActionEvent arg0) } } + private class ReconnectServerItem implements ActionListener + { + @Override + public void actionPerformed (ActionEvent arg0) + { + IRCServer.this.reconnect(); + } + } + private class ChooseFont implements ActionListener { @Override - public void actionPerformed(ActionEvent arg0) + public void actionPerformed (ActionEvent arg0) { fontDialog.setVisible(true); } @@ -330,26 +370,37 @@ public void actionPerformed(ActionEvent arg0) /* * (non-Javadoc) * - * @see urChatBasic.backend.IRCServerBase#serverConnect(java.lang.String, java.lang.String) - * serverConnect(nick, login, portNumber, isTLS, proxyHost, proxyPort, useSOCKS, - * Constants.BACKEND_CLASS); + * @see urChatBasic.backend.IRCServerBase#serverConnect(java.lang.String, java.lang.String) serverConnect(nick, login, portNumber, isTLS, proxyHost, + * proxyPort, useSOCKS, Constants.BACKEND_CLASS); */ @Override - public void connect() + public void connect (String[] autoConnectChannels) { try { serverConnection = new Connection(this); + + for (String autoChannel : autoConnectChannels) + { + IRCRoomBase newChannel = new IRCChannel(this, autoChannel); + createdRooms.add(newChannel); + } + } catch (Exception e) { - Constants.LOGGER.log(Level.SEVERE, "Failed to create backend! " + e.getLocalizedMessage()); + Constants.LOGGER.error( "Failed to create backend! " + e.getLocalizedMessage()); } new Thread(serverConnection).start(); } + public void reconnect () + { + serverConnection.reconnect(); + } + @Override - public void disconnect() + public void disconnect () { serverConnection.disconnect(); quitRooms(); @@ -361,7 +412,7 @@ public void disconnect() * @see urChatBasic.backend.IRCServerBase#toString() */ @Override - public String toString() + public String toString () { return this.name; } @@ -373,7 +424,7 @@ public String toString() * @see urChatBasic.backend.IRCServerBase#setName(java.lang.String) */ @Override - public void setName(String serverName) + public void setName (String serverName) { this.name = serverName; } @@ -384,7 +435,7 @@ public void setName(String serverName) * @see urChatBasic.backend.IRCServerBase#getName() */ @Override - public String getName() + public String getName () { return this.name; } @@ -395,7 +446,7 @@ public String getName() * @see urChatBasic.base.IRCServerBase#getIRCUser(java.lang.String) */ @Override - public IRCUser getIRCUser(String userName) + public IRCUser getIRCUser (String userName) { for (IRCRoomBase tempChannel : createdRooms) if (tempChannel.getCreatedUser(userName) != null) @@ -410,11 +461,11 @@ public IRCUser getIRCUser(String userName) * @see urChatBasic.backend.IRCServerBase#getCreatedPrivateRoom(java.lang.String) */ @Override - public IRCPrivate getCreatedPrivateRoom(String privateRoom) + public IRCPrivate getCreatedPrivateRoom (String privateRoom) { IRCRoomBase tempRoom = getCreatedRoom(privateRoom, true); - if(tempRoom != null) + if (tempRoom != null) { return (IRCPrivate) tempRoom; } @@ -422,17 +473,17 @@ public IRCPrivate getCreatedPrivateRoom(String privateRoom) return null; } - /* + /* * (non-Javadoc) * * @see urChatBasic.backend.IRCServerBase#getCreatedPrivateRoom(java.lang.String) */ @Override - public IRCChannel getCreatedChannel(String channelName) + public IRCChannel getCreatedChannel (String channelName) { IRCRoomBase tempRoom = getCreatedRoom(channelName, false); - if(tempRoom != null && tempRoom instanceof IRCChannel) + if (tempRoom != null && tempRoom instanceof IRCChannel) { return (IRCChannel) tempRoom; } @@ -441,7 +492,7 @@ public IRCChannel getCreatedChannel(String channelName) } @Override - public void quitRooms() + public void quitRooms () { URProfilesUtil.removeListener(EventType.CHANGE, changeListener); @@ -455,31 +506,31 @@ public void quitRooms() } @Override - public void quitRoom(IRCRoomBase ircRoom) + public void quitRoom (IRCRoomBase ircRoom) { - ircRoom.quitRoom(); + ircRoom.closeRoom(); createdRooms.remove(ircRoom); - boolean tabExists = Arrays.stream(gui.tabbedPane.getComponents()).anyMatch(room -> room.equals(gui.previousSelectedTab)); + boolean tabExists = Arrays.stream(gui.tabbedPane.getComponents()).anyMatch(room -> room.equals(ircRoom)); - if(tabExists) + if (tabExists && gui.tabbedPane.getSelectedComponent().equals(ircRoom)) gui.tabbedPane.setSelectedComponent(gui.previousSelectedTab); gui.tabbedPane.remove(ircRoom); } @Override - public IRCRoomBase getCreatedRoom(String roomName, boolean asPrivate) + public IRCRoomBase getCreatedRoom (String roomName, boolean asPrivate) { + IRCRoomBase returnChannel = null; + for (IRCRoomBase tempChannel : createdRooms) if (tempChannel.getName().equals(roomName)) { - if(asPrivate && tempChannel instanceof IRCPrivate) - return tempChannel; - else if(!asPrivate) - return tempChannel; + if (asPrivate && tempChannel instanceof IRCPrivate || !asPrivate) + returnChannel = tempChannel; } - return null; + return returnChannel; } /* @@ -488,34 +539,55 @@ else if(!asPrivate) * @see urChatBasic.backend.IRCServerBase#addToCreatedChannels(java.lang.String) */ @Override - public void addToCreatedRooms(String roomName, boolean asPrivate) + public void addToCreatedRooms (String roomName, boolean asPrivate) { + if (getCreatedRoom(roomName, asPrivate) == null) { - IRCRoomBase tempChannel = asPrivate ? new IRCPrivate(this, getIRCUser(roomName)) : new IRCChannel(this, roomName); - createdRooms.add(tempChannel); + createdRooms.add(asPrivate ? new IRCPrivate(this, getIRCUser(roomName)) : new IRCChannel(this, roomName)); + } - gui.tabbedPane.insertTab(roomName, tempChannel.icon, tempChannel, null, gui.tabbedPane.indexOfComponent(gui.currentSelectedTab) + 1); - //gui.tabbedPane.addTab(roomName, tempChannel.icon, tempChannel); - Component currentTab = gui.tabbedPane.getSelectedComponent(); - if(currentTab instanceof IRCRoomBase) - { - if(!((IRCRoomBase) currentTab).userIsTyping()) - { - gui.tabbedPane.setSelectedIndex(gui.tabbedPane.indexOfComponent(tempChannel)); - tempChannel.getUserTextBox().requestFocus(); - } else { - tempChannel.callForAttention(); - } - } else if(currentTab instanceof IRCServer) { - if(clientTextBox.getText().isEmpty()) - { - gui.tabbedPane.setSelectedIndex(gui.tabbedPane.indexOfComponent(tempChannel)); - tempChannel.getUserTextBox().requestFocus(); - } else { - tempChannel.callForAttention(); + if (getCreatedRoom(roomName, asPrivate) == null || DriverGUI.gui.getTabIndex(getCreatedRoom(roomName, asPrivate)) < 0) + { + boolean iconsShown = (boolean) URPanels.getKeyComponentValue(Constants.KEY_SHOW_TAB_ICON); + + + SwingUtilities.invokeLater( + new Runnable() { + + @Override + public void run () + { + IRCRoomBase tempChannel = getCreatedRoom(roomName, asPrivate); + int newIndex = gui.tabbedPane.indexOfComponent(gui.currentSelectedTab) + 1; + gui.tabbedPane.insertTab(roomName, iconsShown ? tempChannel.icon : null, tempChannel, null, gui.tabbedPane.indexOfComponent(gui.currentSelectedTab) + 1); + + // gui.tabbedPane.addTab(roomName, tempChannel.icon, tempChannel); + Component currentTab = gui.tabbedPane.getSelectedComponent(); + if (currentTab instanceof IRCRoomBase) + { + if (!((IRCRoomBase) currentTab).userIsTyping()) + { + gui.tabbedPane.setSelectedIndex(newIndex); + tempChannel.getUserTextBox().requestFocus(); + } else + { + tempChannel.callForAttention(); + } + } else if (currentTab instanceof IRCServer) + { + if (clientTextBox.getText().isEmpty()) + { + gui.tabbedPane.setSelectedIndex(newIndex); + tempChannel.getUserTextBox().requestFocus(); + } else + { + tempChannel.callForAttention(); + } + } + } } - } + ); } } @@ -525,7 +597,7 @@ public void addToCreatedRooms(String roomName, boolean asPrivate) * @see urChatBasic.backend.IRCServerBase#addToPrivateRooms(urChatBasic.frontend.IRCUser) */ @Override - public IRCPrivate addToPrivateRooms(IRCUser fromUser) + public IRCPrivate addToPrivateRooms (IRCUser fromUser) { IRCPrivate privateRoom = getCreatedPrivateRoom(fromUser.getName()); if (privateRoom == null) @@ -544,11 +616,10 @@ public IRCPrivate addToPrivateRooms(IRCUser fromUser) /* * (non-Javadoc) * - * @see urChatBasic.backend.IRCServerBase#printChannelText(java.lang.String, java.lang.String, - * java.lang.String) + * @see urChatBasic.backend.IRCServerBase#printChannelText(java.lang.String, java.lang.String, java.lang.String) */ @Override - public void printChannelText(String channelName, String line, String fromUser) + public void printChannelText (String channelName, String line, String fromUser) { IRCRoomBase tempChannel = getCreatedRoom(channelName, false); @@ -565,11 +636,10 @@ public void printChannelText(String channelName, String line, String fromUser) /* * (non-Javadoc) * - * @see urChatBasic.backend.IRCServerBase#printPrivateText(java.lang.String, java.lang.String, - * java.lang.String) + * @see urChatBasic.backend.IRCServerBase#printPrivateText(java.lang.String, java.lang.String, java.lang.String) */ @Override - public void printPrivateText(String userName, String line, String fromUser) + public void printPrivateText (String userName, String line, String fromUser) { // private messages aren't linked to a channel, so create it - also // if they aren't muted @@ -593,7 +663,7 @@ public void printPrivateText(String userName, String line, String fromUser) * @see urChatBasic.backend.IRCServerBase#printServerText(java.lang.String) */ @Override - public void printServerText(String line) + public void printServerText (String line) { printText(line, Constants.EVENT_USER); } @@ -604,7 +674,7 @@ public void printServerText(String line) * @see urChatBasic.backend.IRCServerBase#printEventTicker(java.lang.String, java.lang.String) */ @Override - public void printEventTicker(String channelName, String eventText) + public void printEventTicker (String channelName, String eventText) { getCreatedChannel(channelName).createEvent(eventText); } @@ -617,7 +687,7 @@ public void printEventTicker(String channelName, String eventText) * @see urChatBasic.backend.IRCServerBase#addToUsersList(java.lang.String, java.lang.String[]) */ @Override - public void addToUsersList(final String channelName, final String[] users) + public void addToUsersList (final String channelName, final String[] users) { if (!channelName.matches("Server")) { @@ -634,9 +704,9 @@ public void addToUsersList(final String channelName, final String[] users) * @see urChatBasic.backend.IRCServerBase#addToUsersList(java.lang.String, java.lang.String) */ @Override - public void addToUsersList(final String channelName, final String user) + public void addToUsersList (final String channelName, final String user) { - addToUsersList(channelName, new String[]{user}); + addToUsersList(channelName, new String[] {user}); } @@ -646,7 +716,7 @@ public void addToUsersList(final String channelName, final String user) * @see urChatBasic.backend.IRCServerBase#removeFromUsersList(java.lang.String, java.lang.String) */ @Override - public void removeFromUsersList(final String channelName, final String user) + public void removeFromUsersList (final String channelName, final String user) { String thisUser = user; if (user.startsWith(":")) @@ -675,7 +745,7 @@ public void removeFromUsersList(final String channelName, final String user) * @see urChatBasic.backend.IRCServerBase#setChannelTopic(java.lang.String, java.lang.String) */ @Override - public void setChannelTopic(String channelName, String channelTopic) + public void setChannelTopic (String channelName, String channelTopic) { getCreatedChannel(channelName).setChannelTopic(channelTopic); } @@ -686,7 +756,7 @@ public void setChannelTopic(String channelName, String channelTopic) * @see urChatBasic.backend.IRCServerBase#sendClientText(java.lang.String, java.lang.String) */ @Override - public void sendClientText(String line, String source) + public void sendClientText (String line, String source) { try { @@ -696,7 +766,7 @@ public void sendClientText(String line, String source) } } catch (IOException e) { - Constants.LOGGER.log(Level.WARNING, "Couldn't send text! " + e.getLocalizedMessage()); + Constants.LOGGER.error("Couldn't send text! " + e.getLocalizedMessage()); } } @@ -706,11 +776,11 @@ public void sendClientText(String line, String source) * @see urChatBasic.backend.IRCServerBase#renameUser(java.lang.String, java.lang.String) */ @Override - public void renameUser(final String oldUserName, final String newUserName) + public void renameUser (final String oldUserName, final String newUserName) { SwingUtilities.invokeLater(new Runnable() { - public void run() + public void run () { for (IRCRoomBase tempChannel : createdRooms) { diff --git a/src/urChatBasic/frontend/LineFormatter.java b/src/urChatBasic/frontend/LineFormatter.java index 2b2a29b..34a3d05 100644 --- a/src/urChatBasic/frontend/LineFormatter.java +++ b/src/urChatBasic/frontend/LineFormatter.java @@ -35,6 +35,7 @@ import urChatBasic.base.Constants; import urChatBasic.base.IRCServerBase; import urChatBasic.frontend.dialogs.YesNoDialog; +import urChatBasic.frontend.panels.InterfacePanel; import urChatBasic.frontend.utils.URColour; public class LineFormatter @@ -83,7 +84,7 @@ public LineFormatter(URStyle baseStyle, JTextPane docOwner ,final IRCServerBase initStyles(baseStyle); } - public void setFont(Font newFont) + public void setFont (Font newFont) { targetStyle.setFont(newFont); if (doc.getLength() > 0) @@ -339,7 +340,7 @@ public void execute() Desktop.getDesktop().browse(new URL(textLink).toURI()); } catch (Exception e) { - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } else if (!textLink.isEmpty() && attributeSet.getAttribute("type").equals("channel")) { @@ -360,7 +361,7 @@ public void execute() } } catch (Exception e) { - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } } @@ -427,14 +428,14 @@ private synchronized void setDocAttributes(int startPosition, int length, URStyl } } - Constants.LOGGER.log(Level.FINE, "Setting character attributes at: " + startPosition + " length: " + length); + Constants.LOGGER.debug( "Setting character attributes at: " + startPosition + " length: " + length); doc.setCharacterAttributes(startPosition, length, matchingStyle, true); } // Inserts the string at the position private synchronized void insertString(String insertedString, URStyle style, int position) { - Constants.LOGGER.log(Level.FINE, "Inserting a string: " + insertedString + " at position: " + position); + Constants.LOGGER.debug( "Inserting a string: [" + insertedString.trim() + "] at position: " + position); // Append the date to the first entry on this line, and don't append it elsewhere if(timeLine.isPresent() && insertedString.length() > 0) { @@ -446,7 +447,7 @@ private synchronized void insertString(String insertedString, URStyle style, int doc.insertString(position, insertedString, style); } catch (BadLocationException ble) { - Constants.LOGGER.log(Level.WARNING, ble.getLocalizedMessage()); + Constants.LOGGER.error(ble.getLocalizedMessage()); } setDocAttributes(position, insertedString.length(), style); @@ -517,17 +518,15 @@ public void run () { if(!updateStylesInProgress.get()) { - Constants.LOGGER.log(Level.INFO, "Updating styles."); + Constants.LOGGER.info( "Updating styles for " + settingsPath.name()); updateStylesTime.set(Instant.now().getEpochSecond()); updateDocStyles(0); } else { - Constants.LOGGER.log(Level.INFO, "Update already in progress."); + Constants.LOGGER.info( "Update already in progress."); } } catch (BadLocationException e) { - // TODO Auto-generated catch block - - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } finally { updateStylesInProgress.set(false); } @@ -549,13 +548,13 @@ private void updateDocStyles (int currentPosition) throws BadLocationException // looping all lines in the doc while (lineIndex < lineCount) { - Constants.LOGGER.log(Level.FINE, "Updating line "+lineIndex); + Constants.LOGGER.debug( "Updating line "+lineIndex); Element lineElement = root.getElement(lineIndex); // looping all the styles used in this line while (currentPosition < lineElement.getEndOffset()) { - Constants.LOGGER.log(Level.FINE, "Working at: " + currentPosition + " to: " + lineElement.getEndOffset()); + Constants.LOGGER.debug( "Working at: " + currentPosition + " to: " + lineElement.getEndOffset()); URStyle currentStyle = getStyleAtPosition(currentPosition, null); // Has style to update @@ -585,7 +584,7 @@ private void updateDocStyles (int currentPosition) throws BadLocationException } else { // it has a date but isn't a timestamp, so check date time is enabled and insert the timestamp string - if (DriverGUI.gui.isTimeStampsEnabled()) + if (((InterfacePanel) DriverGUI.gui.interfacePanel).isTimeStampsEnabled()) { // this removes the date from what will become the next style on the line so that we don't insert the timestamp // multiple times @@ -670,7 +669,7 @@ private void updateDocStyles (int currentPosition) throws BadLocationException lineIndex++; } - Constants.LOGGER.log(Level.INFO, "Took " + Duration.between(Instant.ofEpochSecond(updateStylesTime.get()), Instant.now()).toMillis() + "ms to update styles."); + Constants.LOGGER.info( "Took " + Duration.between(Instant.ofEpochSecond(updateStylesTime.get()), Instant.now()).toMillis() + "ms to update styles."); updateStylesTime.set(0); } @@ -781,7 +780,7 @@ public URStyle getStyleAtPosition(int position, String relativeLine) } catch (BadLocationException ble) { // TODO - Constants.LOGGER.log(Level.WARNING, ble.getLocalizedMessage()); + Constants.LOGGER.error(ble.getLocalizedMessage()); } AttributeSet textStyle = doc.getCharacterElement(position).getAttributes(); @@ -904,7 +903,7 @@ public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString // doc.insertString(doc.getLength(), timeLine, timeStyle); // if(null != timeLine && !timeLine.isBlank()) - if (DriverGUI.gui.isTimeStampsEnabled()) + if (((InterfacePanel) DriverGUI.gui.interfacePanel).isTimeStampsEnabled()) { // add the date to the end of the string to preserve the timestamp of the line // when updating styles @@ -945,7 +944,7 @@ public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString appendString(System.getProperty("line.separator"), linePositionStyle); } catch (BadLocationException e) { - Constants.LOGGER.log(Level.SEVERE, e.getLocalizedMessage()); + Constants.LOGGER.error( e.getLocalizedMessage()); } } diff --git a/src/urChatBasic/frontend/UserGUI.java b/src/urChatBasic/frontend/UserGUI.java index e47c522..a984604 100644 --- a/src/urChatBasic/frontend/UserGUI.java +++ b/src/urChatBasic/frontend/UserGUI.java @@ -2,7 +2,6 @@ import java.awt.*; import java.util.logging.Level; -import java.util.prefs.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -26,15 +25,16 @@ import urChatBasic.base.IRCRoomBase; import urChatBasic.base.IRCServerBase; import urChatBasic.frontend.dialogs.FontDialog; -import urChatBasic.frontend.dialogs.MessageDialog; +import urChatBasic.frontend.panels.MainOptionsPanel; +import urChatBasic.frontend.panels.ProfilePanel; +import urChatBasic.frontend.panels.ConnectionPanel; +import urChatBasic.frontend.panels.InterfacePanel; import urChatBasic.frontend.panels.UROptionsPanel; -import urChatBasic.frontend.utils.Panels; +import urChatBasic.frontend.utils.URPanels; import urChatBasic.base.UserGUIBase; import urChatBasic.base.Constants.EventType; import urChatBasic.base.Constants.Placement; import urChatBasic.base.Constants.Size; -import urChatBasic.base.capabilities.CapTypeBase; -import urChatBasic.base.capabilities.CapabilityTypes; import urChatBasic.frontend.LineFormatter.ClickableText; import urChatBasic.frontend.components.*; @@ -57,9 +57,9 @@ public class UserGUI extends JPanel implements Runnable, UserGUIBase // Options Panel private JPanel optionsMainPanel = new MainOptionsPanel(); // Server Options Panel - private final UROptionsPanel connectionPanel = new UROptionsPanel("Connection", (MainOptionsPanel) optionsMainPanel, Optional.of(0)); + private final UROptionsPanel connectionPanel = new ConnectionPanel((MainOptionsPanel) optionsMainPanel, Optional.of(0)); - private final UROptionsPanel interfacePanel = new UROptionsPanel("Interface", (MainOptionsPanel) optionsMainPanel, Optional.of(1)); + public final UROptionsPanel interfacePanel = new InterfacePanel((MainOptionsPanel) optionsMainPanel, Optional.of(1)); // Appearance Options Panel private final UROptionsPanel appearancePanel = new UROptionsPanel("Appearance", (MainOptionsPanel) optionsMainPanel, Optional.of(2)); @@ -67,23 +67,10 @@ public class UserGUI extends JPanel implements Runnable, UserGUIBase // Profile Panel private final UROptionsPanel profilePanel = new ProfilePanel((MainOptionsPanel) optionsMainPanel); - // public final JScrollPane interfaceScroller = new JScrollPane(interfacePanel); private final JComboBox lafOptions = new JComboBox(UIManager.getInstalledLookAndFeels()); - private final JCheckBox showEventTicker = new JCheckBox("Show Event Ticker"); - private final JCheckBox showUsersList = new JCheckBox("Show Users List"); - private final JCheckBox enableClickableLinks = new JCheckBox("Make links clickable"); - private final JCheckBox showJoinsQuitsEventTicker = new JCheckBox("Show Joins/Quits in the Event Ticker"); - private final JCheckBox showJoinsQuitsMainWindow = new JCheckBox("Show Joins/Quits in the Chat Window"); - private final JCheckBox logChannelText = new JCheckBox("Save and log all channel text"); - private final JCheckBox logServerActivity = new JCheckBox("Save and log all Server activity"); - private final JCheckBox logClientText = new JCheckBox("Log client text (Allows up or down history)"); - private final JCheckBox limitServerLines = new JCheckBox("Limit the number of lines in Server activity"); - private final JCheckBox limitChannelLines = new JCheckBox("Limit the number of lines in channel text"); - private final JCheckBox enableTimeStamps = new JCheckBox("Time Stamp chat messages"); - // Appearance Panel private FontPanel clientFontPanel; /** @@ -99,105 +86,9 @@ public class UserGUI extends JPanel implements Runnable, UserGUIBase public LineFormatter previewLineFormatter; - private final JTextField limitServerLinesCount = new JTextField(); - private final JTextField limitChannelLinesCount = new JTextField(); - - private final int TICKER_DELAY_MIN = 0; - private final int TICKER_DELAY_MAX = 30; - private final int TICKER_DELAY_INIT = 20; - private final int DEFAULT_LINES_LIMIT = 500; - private final JLabel eventTickerLabel = new JLabel("Event Ticker Delay:"); - private final JSlider eventTickerDelay = - new JSlider(JSlider.HORIZONTAL, TICKER_DELAY_MIN, TICKER_DELAY_MAX, TICKER_DELAY_INIT); - - // Identification - private final JLabel userNameLabel = new JLabel("Nick:"); - private final JTextField userNameTextField = new JTextField("", 12); - private final JLabel realNameLabel = new JLabel("Real name:"); - private final JTextField realNameTextField = new JTextField(""); - - // Authentication - private final JLabel authenticationTypeLabel = new JLabel("Authentication Type:"); - private final UCAuthTypeComboBox authenticationTypeChoice = new UCAuthTypeComboBox(); - private final JLabel passwordLabel = new JLabel("Password:"); - private final JPasswordField passwordTextField = new JPasswordField(""); - private final JLabel rememberPassLabel = new JLabel("Remember:"); - private final JCheckBox rememberPassCheckBox = new JCheckBox(); - - // Connection - private final JLabel serverNameLabel = new JLabel("Server:"); - private final JTextField servernameTextField = new JTextField("", 8); - private final JLabel serverPortLabel = new JLabel("Port:"); - private final JTextField serverPortTextField = new JTextField("", 4); - private final JLabel serverUseTLSLabel = new JLabel("TLS:"); - private final JCheckBox serverTLSCheckBox = new JCheckBox(); - private final JButton connectButton = new JButton("Connect"); - - // Proxy - private final JLabel proxyHostLabel = new JLabel("Proxy Host:"); - private final JTextField proxyHostNameTextField = new JTextField(""); - private final JLabel proxyPortLabel = new JLabel("Port:", 4); - private final JTextField proxyPortTextField = new JTextField(""); - private final JLabel serverUseProxyLabel = new JLabel("Use SOCKS:"); - private final JCheckBox serverProxyCheckBox = new JCheckBox(); - - private final JLabel firstChannelLabel = new JLabel("Channel:"); - private final JTextField firstChannelTextField = new JTextField(""); - - // Favourites Panel - private final JCheckBox autoConnectToFavourites = new JCheckBox("Automatically join favourite channels"); - private final DefaultListModel favouritesListModel = new DefaultListModel(); - private final JList favouritesList = new JList(favouritesListModel); - private final JScrollPane favouritesScroller = new JScrollPane(favouritesList); // Created Servers/Tabs - private final List createdServers = new ArrayList(); - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#getLimitServerLinesCount() - */ - @Override - public int getLimitServerLinesCount () - { - try - { - return Integer.parseInt(limitServerLinesCount.getText()); - } catch (Exception e) - { - // Was an error, default to 1000 - return DEFAULT_LINES_LIMIT; - } - } - - public void setLimitChannelLines (int limit) - { - limitChannelLinesCount.setText(Integer.toString(limit)); - } - - public void setLimitServerLines (int limit) - { - limitServerLinesCount.setText(Integer.toString(limit)); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#getLimitChannelLinesCount() - */ - @Override - public int getLimitChannelLinesCount () - { - try - { - return Integer.parseInt(limitChannelLinesCount.getText()); - } catch (Exception e) - { - // Was an error, set to default - return DEFAULT_LINES_LIMIT; - } - } + public final List createdServers = new ArrayList(); /* * (non-Javadoc) @@ -241,26 +132,18 @@ public int getTabIndex (String tabName) return -1; } - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#saveChannelHistory() - */ - @Override - public Boolean saveChannelHistory () + public int getTabIndex (IRCRoomBase targetTab) { - return logChannelText.isSelected(); - } + for (int i = 0; i < DriverGUI.gui.tabbedPane.getTabCount(); i++) + { + Component currentTab = DriverGUI.gui.tabbedPane.getComponentAt(i); + if (currentTab instanceof IRCRoomBase && currentTab.equals(targetTab)) + { + return i; + } + } - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#saveServerHistory() - */ - @Override - public Boolean saveServerHistory () - { - return logServerActivity.isSelected(); + return -1; } /* @@ -297,6 +180,11 @@ public UROptionsPanel getProfilePanel () return profilePanel; } + public UROptionsPanel getConnectionPanel () + { + return interfacePanel; + } + // /** // * Sets the current active profile - if the newProfileName doesn't exist it will be created. // * @param newProfileName @@ -321,21 +209,26 @@ public UROptionsPanel getProfilePanel () // getClientSettings(false); // } - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#addToCreatedServers(java.lang.String) - */ + // TODO: Is this needed any more or should we be adding IRCServer only? + // @Override + // public void addToCreatedServers (String serverName) + // { + // if (getCreatedServer(serverName) == null) + // { + // createdServers.add(new IRCServer(serverName.trim(), userNameTextField.getText().trim(), + // realNameTextField.getText().trim(), new String(passwordTextField.getPassword()), + // serverPortTextField.getText().trim(), serverTLSCheckBox.isSelected(), + // proxyHostNameTextField.getText(), proxyPortTextField.getText(), serverProxyCheckBox.isSelected())); + // } + // } + @Override - public void addToCreatedServers (String serverName) + public void addToCreatedServers (IRCServerBase newServer) { - if (getCreatedServer(serverName) == null) - { - createdServers.add(new IRCServer(serverName.trim(), userNameTextField.getText().trim(), - realNameTextField.getText().trim(), new String(passwordTextField.getPassword()), - serverPortTextField.getText().trim(), serverTLSCheckBox.isSelected(), - proxyHostNameTextField.getText(), proxyPortTextField.getText(), serverProxyCheckBox.isSelected())); - } + if(getCreatedServer(newServer.getName()) != null) + createdServers.remove(newServer); + + createdServers.add(newServer); } /* @@ -349,377 +242,9 @@ public Boolean isCreatedServersEmpty () return createdServers.isEmpty(); } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isShowingEventTicker() - */ - @Override - public Boolean isShowingEventTicker () - { - return showEventTicker.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isShowingUsersList() - */ - @Override - public Boolean isShowingUsersList () - { - return showUsersList.isSelected(); - } - - @Override - public Boolean isClickableLinksEnabled () - { - return enableClickableLinks.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isJoinsQuitsTickerEnabled() - */ - @Override - public Boolean isJoinsQuitsTickerEnabled () - { - return showJoinsQuitsEventTicker.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isJoinsQuitsMainEnabled() - */ - @Override - public Boolean isJoinsQuitsMainEnabled () - { - return showJoinsQuitsMainWindow.isSelected(); - } - - public void setJoinsQuitsMain (boolean enable) - { - showJoinsQuitsMainWindow.setSelected(enable); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isChannelHistoryEnabled() - */ - @Override - public Boolean isChannelHistoryEnabled () - { - return logChannelText.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isLimitedServerActivity() - */ - @Override - public Boolean isLimitedServerActivity () - { - return limitServerLines.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isLimitedChannelActivity() - */ - @Override - public Boolean isLimitedChannelActivity () - { - return limitChannelLines.isSelected(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isTimeStampsEnabled() - */ - @Override - public Boolean isTimeStampsEnabled () - { - return enableTimeStamps.isSelected(); - } - - @Override - public CapTypeBase authenticationType () - { - return (CapTypeBase) authenticationTypeChoice.getSelectedItem(); - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isClientHistoryEnabled() - */ - @Override - public Boolean isClientHistoryEnabled () - { - return logClientText.isSelected(); - - } - - /** - * Add the components to the Server Options Panel. - */ - private void setupConnectionPanel () - { - // connectionPanel.setLayout(new BoxLayout(connectionPanel, BoxLayout.PAGE_AXIS)); - setupConnectionLayout(); - - // User stuff - connectionPanel.add(userNameLabel); - connectionPanel.add(userNameTextField); - // userNameTextField.setPreferredSize(new Dimension(100, 24)); - // userNameTextField.setMinimumSize(new Dimension(100, 0)); - - connectionPanel.add(realNameLabel); - connectionPanel.add(realNameTextField); - // realNameTextField.setMinimumSize(new Dimension(100, 0)); - - connectionPanel.add(authenticationTypeLabel); - connectionPanel.add(authenticationTypeChoice); - authenticationTypeChoice.addActionListener(new UCAuthTypeComboBoxChangeHandler()); - // authenticationTypeChoice.setPreferredSize(new Dimension(200, 20)); - - connectionPanel.add(passwordLabel); - connectionPanel.add(passwordTextField); - passwordTextField.setEchoChar('*'); - - connectionPanel.add(rememberPassLabel); - connectionPanel.add(rememberPassCheckBox); - // passwordTextField.setPreferredSize(new Dimension(200, 20)); - - // Server Stuff - connectionPanel.add(serverNameLabel); - connectionPanel.add(servernameTextField); - // servernameTextField.setPreferredSize(new Dimension(100, 20)); - - connectionPanel.add(serverPortLabel); - connectionPanel.add(serverPortTextField); - // serverPortTextField.setPreferredSize(new Dimension(50, 20)); - - connectionPanel.add(serverUseTLSLabel); - connectionPanel.add(serverTLSCheckBox); - // serverTLSCheckBox.setPreferredSize(new Dimension(50, 20)); - - // Proxy Stuff - connectionPanel.add(proxyHostLabel); - connectionPanel.add(proxyHostNameTextField); - // proxyHostNameTextField.setPreferredSize(new Dimension(100, 20)); - - connectionPanel.add(proxyPortLabel); - connectionPanel.add(proxyPortTextField); - // proxyPortTextField.setPreferredSize(new Dimension(50, 20)); - - connectionPanel.add(serverUseProxyLabel); - connectionPanel.add(serverProxyCheckBox); - // serverProxyCheckBox.setPreferredSize(new Dimension(50, 20)); - - // Channel Stuff - connectionPanel.add(firstChannelLabel); - connectionPanel.add(firstChannelTextField); - // firstChannelTextField.setPreferredSize(new Dimension(100, 20)); - - connectionPanel.add(connectButton); - connectButton.addActionListener(new ConnectPressed()); - connectionPanel.add(autoConnectToFavourites); - - favouritesScroller.setPreferredSize(new Dimension(200, 100)); - favouritesList.addMouseListener(new FavouritesPopClickListener()); - connectionPanel.add(favouritesScroller); - } - - /** - * Aligns components on the Server Options Panel - */ - private void setupConnectionLayout () - { - SpringLayout connectionLayout = new SpringLayout(); - connectionPanel.setLayout(connectionLayout); - - // Used to make it more obvious what is going on - - // and perhaps more readable. - // 0 means THAT edge will be flush with the opposing components edge - // Yes, negative numbers will make it overlap - final int TOP_SPACING = 6; - final int TOP_ALIGNED = 0; - final int LEFT_ALIGNED = 0; - final int RIGHT_ALIGNED = 0; - final int LEFT_SPACING = 6; - - // Components are aligned off the top label - // User stuff - connectionLayout.putConstraint(SpringLayout.NORTH, userNameLabel, TOP_SPACING * 2, SpringLayout.NORTH, - connectionPanel); - connectionLayout.putConstraint(SpringLayout.WEST, userNameLabel, LEFT_SPACING * 2, SpringLayout.WEST, - connectionPanel); - - connectionLayout.putConstraint(SpringLayout.NORTH, userNameTextField, TOP_ALIGNED, SpringLayout.SOUTH, - userNameLabel); - connectionLayout.putConstraint(SpringLayout.WEST, userNameTextField, LEFT_ALIGNED, SpringLayout.WEST, - userNameLabel); - - connectionLayout.putConstraint(SpringLayout.NORTH, realNameLabel, TOP_SPACING, SpringLayout.SOUTH, - userNameTextField); - connectionLayout.putConstraint(SpringLayout.WEST, realNameLabel, LEFT_ALIGNED, SpringLayout.WEST, - userNameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, realNameTextField, TOP_ALIGNED, SpringLayout.SOUTH, - realNameLabel); - connectionLayout.putConstraint(SpringLayout.WEST, realNameTextField, LEFT_ALIGNED, SpringLayout.WEST, - realNameLabel); - connectionLayout.putConstraint(SpringLayout.EAST, realNameTextField, RIGHT_ALIGNED, SpringLayout.EAST, - userNameTextField); - - // Authentication Stuff - - connectionLayout.putConstraint(SpringLayout.NORTH, authenticationTypeLabel, TOP_SPACING, SpringLayout.SOUTH, - realNameTextField); - connectionLayout.putConstraint(SpringLayout.WEST, authenticationTypeLabel, LEFT_ALIGNED, SpringLayout.WEST, - realNameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, authenticationTypeChoice, TOP_ALIGNED, SpringLayout.SOUTH, - authenticationTypeLabel); - connectionLayout.putConstraint(SpringLayout.WEST, authenticationTypeChoice, LEFT_ALIGNED, SpringLayout.WEST, - authenticationTypeLabel); - connectionLayout.putConstraint(SpringLayout.EAST, authenticationTypeChoice, RIGHT_ALIGNED, SpringLayout.EAST, - realNameTextField); - - // Password - connectionLayout.putConstraint(SpringLayout.NORTH, passwordLabel, TOP_SPACING, SpringLayout.SOUTH, - authenticationTypeChoice); - connectionLayout.putConstraint(SpringLayout.WEST, passwordLabel, LEFT_ALIGNED, SpringLayout.WEST, - authenticationTypeChoice); - - connectionLayout.putConstraint(SpringLayout.NORTH, passwordTextField, TOP_ALIGNED, SpringLayout.SOUTH, - passwordLabel); - connectionLayout.putConstraint(SpringLayout.WEST, passwordTextField, LEFT_ALIGNED, SpringLayout.WEST, - passwordLabel); - connectionLayout.putConstraint(SpringLayout.EAST, passwordTextField, RIGHT_ALIGNED, SpringLayout.EAST, - authenticationTypeChoice); - - connectionLayout.putConstraint(SpringLayout.NORTH, rememberPassLabel, TOP_ALIGNED, SpringLayout.NORTH, - passwordLabel); - connectionLayout.putConstraint(SpringLayout.WEST, rememberPassLabel, LEFT_ALIGNED, SpringLayout.EAST, - passwordTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, rememberPassCheckBox, TOP_ALIGNED, SpringLayout.SOUTH, - rememberPassLabel); - connectionLayout.putConstraint(SpringLayout.WEST, rememberPassCheckBox, LEFT_ALIGNED, SpringLayout.EAST, - passwordTextField); - - - // Server stuff - connectionLayout.putConstraint(SpringLayout.NORTH, serverNameLabel, TOP_SPACING, SpringLayout.SOUTH, - passwordTextField); - connectionLayout.putConstraint(SpringLayout.WEST, serverNameLabel, LEFT_ALIGNED, SpringLayout.WEST, - passwordTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, servernameTextField, TOP_ALIGNED, SpringLayout.SOUTH, - serverNameLabel); - connectionLayout.putConstraint(SpringLayout.WEST, servernameTextField, LEFT_ALIGNED, SpringLayout.WEST, - serverNameLabel); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverPortLabel, TOP_ALIGNED, SpringLayout.NORTH, - serverNameLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverPortLabel, LEFT_ALIGNED, SpringLayout.EAST, - servernameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverPortTextField, TOP_ALIGNED, SpringLayout.SOUTH, - serverPortLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverPortTextField, LEFT_ALIGNED, SpringLayout.WEST, - serverPortLabel); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverUseTLSLabel, TOP_ALIGNED, SpringLayout.NORTH, - serverPortLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverUseTLSLabel, LEFT_ALIGNED, SpringLayout.EAST, - serverPortTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverTLSCheckBox, TOP_ALIGNED, SpringLayout.SOUTH, - serverUseTLSLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverTLSCheckBox, LEFT_ALIGNED, SpringLayout.WEST, - serverUseTLSLabel); - - // Proxy stuff - connectionLayout.putConstraint(SpringLayout.NORTH, proxyHostLabel, TOP_SPACING, SpringLayout.SOUTH, - servernameTextField); - connectionLayout.putConstraint(SpringLayout.WEST, proxyHostLabel, LEFT_ALIGNED, SpringLayout.WEST, - servernameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, proxyHostNameTextField, TOP_ALIGNED, SpringLayout.SOUTH, - proxyHostLabel); - connectionLayout.putConstraint(SpringLayout.WEST, proxyHostNameTextField, LEFT_ALIGNED, SpringLayout.WEST, - proxyHostLabel); - connectionLayout.putConstraint(SpringLayout.EAST, proxyHostNameTextField, RIGHT_ALIGNED, SpringLayout.EAST, - servernameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, proxyPortLabel, TOP_ALIGNED, SpringLayout.NORTH, - proxyHostLabel); - connectionLayout.putConstraint(SpringLayout.WEST, proxyPortLabel, LEFT_ALIGNED, SpringLayout.EAST, - proxyHostNameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, proxyPortTextField, TOP_ALIGNED, SpringLayout.SOUTH, - proxyPortLabel); - connectionLayout.putConstraint(SpringLayout.WEST, proxyPortTextField, LEFT_ALIGNED, SpringLayout.WEST, - proxyPortLabel); - connectionLayout.putConstraint(SpringLayout.EAST, proxyPortTextField, RIGHT_ALIGNED, SpringLayout.EAST, - serverPortTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverUseProxyLabel, TOP_ALIGNED, SpringLayout.NORTH, - proxyPortLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverUseProxyLabel, LEFT_ALIGNED, SpringLayout.EAST, - proxyPortTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, serverProxyCheckBox, TOP_ALIGNED, SpringLayout.SOUTH, - serverUseProxyLabel); - connectionLayout.putConstraint(SpringLayout.WEST, serverProxyCheckBox, LEFT_ALIGNED, SpringLayout.WEST, - serverUseProxyLabel); - - // Channel Stuff - connectionLayout.putConstraint(SpringLayout.NORTH, firstChannelLabel, TOP_SPACING, SpringLayout.SOUTH, - proxyHostNameTextField); - connectionLayout.putConstraint(SpringLayout.WEST, firstChannelLabel, LEFT_ALIGNED, SpringLayout.WEST, - proxyHostNameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, firstChannelTextField, TOP_ALIGNED, SpringLayout.SOUTH, - firstChannelLabel); - connectionLayout.putConstraint(SpringLayout.WEST, firstChannelTextField, LEFT_ALIGNED, SpringLayout.WEST, - firstChannelLabel); - connectionLayout.putConstraint(SpringLayout.EAST, firstChannelTextField, RIGHT_ALIGNED, SpringLayout.EAST, - proxyHostNameTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, connectButton, TOP_SPACING * TOP_SPACING, SpringLayout.SOUTH, - firstChannelTextField); - connectionLayout.putConstraint(SpringLayout.WEST, connectButton, LEFT_ALIGNED, SpringLayout.WEST, - firstChannelTextField); - - connectionLayout.putConstraint(SpringLayout.NORTH, autoConnectToFavourites, TOP_ALIGNED, SpringLayout.NORTH, - userNameLabel); - connectionLayout.putConstraint(SpringLayout.WEST, autoConnectToFavourites, LEFT_SPACING, SpringLayout.EAST, - serverUseProxyLabel); - - connectionLayout.putConstraint(SpringLayout.NORTH, favouritesScroller, TOP_SPACING, SpringLayout.SOUTH, - autoConnectToFavourites); - connectionLayout.putConstraint(SpringLayout.WEST, favouritesScroller, LEFT_ALIGNED, SpringLayout.WEST, - autoConnectToFavourites); - connectionLayout.putConstraint(SpringLayout.EAST, favouritesScroller, LEFT_ALIGNED, SpringLayout.EAST, - autoConnectToFavourites); - connectionLayout.putConstraint(SpringLayout.SOUTH, favouritesScroller, TOP_SPACING, SpringLayout.SOUTH, - connectButton); - } - private void setupAppearancePanel () { - Panels.addToPanel(appearancePanel, lafOptions, "Theme", Placement.DEFAULT, Size.MEDIUM); + URPanels.addToPanel(appearancePanel, lafOptions, "Theme", Placement.DEFAULT, Size.MEDIUM, null); // Set a custom renderer to display the look and feel names lafOptions.setRenderer(new DefaultListCellRenderer() @@ -791,12 +316,12 @@ public void keyReleased (KeyEvent e) updatePreviewTextArea(); - Panels.addToPanel(appearancePanel, clientFontPanel, "Profile Font", Placement.DEFAULT, null); - Panels.addToPanel(appearancePanel, timeStampField, "Timestamp Format", Placement.DEFAULT, Size.MEDIUM); - Panels.addToPanel(appearancePanel, nickFormatField, "Nick Format", Placement.RIGHT, Size.MEDIUM); + URPanels.addToPanel(appearancePanel, clientFontPanel, "Profile Font", Placement.DEFAULT, null, null); + URPanels.addToPanel(appearancePanel, timeStampField, "Timestamp", Placement.DEFAULT, Size.MEDIUM, null); + URPanels.addToPanel(appearancePanel, nickFormatField, "Nick", Placement.RIGHT, Size.MEDIUM, null); - Panels.addToPanel(appearancePanel, previewTextScroll, "Font Preview", Placement.DEFAULT, null); - Panels.addToPanel(appearancePanel, styleLabel, "Preview Style", Placement.DEFAULT, null); + URPanels.addToPanel(appearancePanel, previewTextScroll, "Font Preview", Placement.DEFAULT, null, null); + URPanels.addToPanel(appearancePanel, styleLabel, "Preview Style", Placement.DEFAULT, null, null); } public void updatePreviewTextArea () @@ -875,7 +400,7 @@ public void mouseMoved (MouseEvent e) else styleLabel.setText("Mouse over text to view style, right-click to edit."); - if (isClickableText != null && isClickableLinksEnabled()) + if (isClickableText != null && ((InterfacePanel) interfacePanel).isClickableLinksEnabled()) { previewTextArea.setCursor(new Cursor(Cursor.HAND_CURSOR)); } else @@ -931,409 +456,6 @@ public void setNickFormatString (String newFormat) nickFormatField.setText(newFormat); } - private void setupInterfacePanel () - { - interfacePanel.add(showEventTicker); - interfacePanel.add(showUsersList); - interfacePanel.add(enableClickableLinks); - interfacePanel.add(showJoinsQuitsEventTicker); - interfacePanel.add(showJoinsQuitsMainWindow); - interfacePanel.add(logChannelText); - interfacePanel.add(logServerActivity); - interfacePanel.add(logClientText); - interfacePanel.add(limitServerLines); - interfacePanel.add(limitServerLinesCount); - interfacePanel.add(limitChannelLines); - interfacePanel.add(limitChannelLinesCount); - interfacePanel.add(enableTimeStamps); - - // Turn on labels at major tick mark. - eventTickerDelay.setMajorTickSpacing(10); - eventTickerDelay.setMinorTickSpacing(1); - eventTickerDelay.setPaintTicks(true); - - eventTickerDelay.setPaintLabels(true); - // eventTickerDelay.setMaximumSize(new Dimension(400, 40)); - - eventTickerDelay.setToolTipText("Event Ticker movement delay (Lower is faster)"); - - interfacePanel.add(eventTickerLabel); - interfacePanel.add(eventTickerDelay); - - setupInterfaceLayout(); - } - - /** - * Aligns components on the Client Options Panel - */ - private void setupInterfaceLayout () - { - SpringLayout interfaceLayout = new SpringLayout(); - interfacePanel.setLayout(interfaceLayout); - - // Used to make it more obvious what is going on - - // and perhaps more readable. - // 0 means THAT edge will be flush with the opposing components edge - // Yes, negative numbers will make it overlap - final int TOP_SPACING = 6; - final int TOP_ALIGNED = 0; - final int LEFT_ALIGNED = 0; - final int LEFT_SPACING = 6; - - // Components are aligned off the top label - - interfaceLayout.putConstraint(SpringLayout.WEST, showEventTicker, LEFT_SPACING * 2, SpringLayout.WEST, - interfacePanel); - interfaceLayout.putConstraint(SpringLayout.NORTH, showEventTicker, TOP_SPACING * 2, SpringLayout.NORTH, - interfacePanel); - - interfaceLayout.putConstraint(SpringLayout.NORTH, showUsersList, TOP_SPACING, SpringLayout.SOUTH, - showEventTicker); - interfaceLayout.putConstraint(SpringLayout.WEST, showUsersList, LEFT_ALIGNED, SpringLayout.WEST, - showEventTicker); - - interfaceLayout.putConstraint(SpringLayout.NORTH, enableClickableLinks, TOP_SPACING, SpringLayout.SOUTH, - showUsersList); - - interfaceLayout.putConstraint(SpringLayout.WEST, enableClickableLinks, LEFT_ALIGNED, SpringLayout.WEST, - showUsersList); - - interfaceLayout.putConstraint(SpringLayout.NORTH, showJoinsQuitsEventTicker, TOP_SPACING, SpringLayout.SOUTH, - enableClickableLinks); - interfaceLayout.putConstraint(SpringLayout.WEST, showJoinsQuitsEventTicker, LEFT_ALIGNED, SpringLayout.WEST, - enableClickableLinks); - - interfaceLayout.putConstraint(SpringLayout.NORTH, showJoinsQuitsMainWindow, TOP_SPACING, SpringLayout.SOUTH, - showJoinsQuitsEventTicker); - interfaceLayout.putConstraint(SpringLayout.WEST, showJoinsQuitsMainWindow, LEFT_ALIGNED, SpringLayout.WEST, - showJoinsQuitsEventTicker); - - interfaceLayout.putConstraint(SpringLayout.NORTH, logChannelText, TOP_SPACING, SpringLayout.SOUTH, - showJoinsQuitsMainWindow); - interfaceLayout.putConstraint(SpringLayout.WEST, logChannelText, LEFT_ALIGNED, SpringLayout.WEST, - showJoinsQuitsMainWindow); - - interfaceLayout.putConstraint(SpringLayout.NORTH, logServerActivity, TOP_SPACING, SpringLayout.SOUTH, - logChannelText); - interfaceLayout.putConstraint(SpringLayout.WEST, logServerActivity, LEFT_ALIGNED, SpringLayout.WEST, - logChannelText); - - interfaceLayout.putConstraint(SpringLayout.NORTH, logClientText, TOP_SPACING, SpringLayout.SOUTH, - logServerActivity); - interfaceLayout.putConstraint(SpringLayout.WEST, logClientText, LEFT_ALIGNED, SpringLayout.WEST, - logServerActivity); - - interfaceLayout.putConstraint(SpringLayout.NORTH, limitServerLines, TOP_SPACING, SpringLayout.SOUTH, - logClientText); - interfaceLayout.putConstraint(SpringLayout.WEST, limitServerLines, LEFT_ALIGNED, SpringLayout.WEST, - logClientText); - - interfaceLayout.putConstraint(SpringLayout.NORTH, limitServerLinesCount, TOP_ALIGNED, SpringLayout.NORTH, - limitServerLines); - interfaceLayout.putConstraint(SpringLayout.WEST, limitServerLinesCount, TOP_SPACING, SpringLayout.EAST, - limitServerLines); - - interfaceLayout.putConstraint(SpringLayout.NORTH, limitChannelLines, TOP_SPACING, SpringLayout.SOUTH, - limitServerLines); - interfaceLayout.putConstraint(SpringLayout.WEST, limitChannelLines, LEFT_ALIGNED, SpringLayout.WEST, - limitServerLines); - - interfaceLayout.putConstraint(SpringLayout.NORTH, limitChannelLinesCount, TOP_ALIGNED, SpringLayout.NORTH, - limitChannelLines); - interfaceLayout.putConstraint(SpringLayout.WEST, limitChannelLinesCount, LEFT_SPACING, SpringLayout.EAST, - limitChannelLines); - - interfaceLayout.putConstraint(SpringLayout.NORTH, enableTimeStamps, TOP_SPACING, SpringLayout.SOUTH, - limitChannelLines); - interfaceLayout.putConstraint(SpringLayout.WEST, enableTimeStamps, LEFT_ALIGNED, SpringLayout.WEST, - limitChannelLines); - - interfaceLayout.putConstraint(SpringLayout.NORTH, eventTickerLabel, TOP_SPACING, SpringLayout.SOUTH, - enableTimeStamps); - interfaceLayout.putConstraint(SpringLayout.WEST, eventTickerLabel, LEFT_ALIGNED, SpringLayout.WEST, - enableTimeStamps); - - interfaceLayout.putConstraint(SpringLayout.NORTH, eventTickerDelay, TOP_SPACING, SpringLayout.SOUTH, - eventTickerLabel); - interfaceLayout.putConstraint(SpringLayout.WEST, eventTickerDelay, LEFT_ALIGNED, SpringLayout.WEST, - eventTickerLabel); - } - - /** - * Create an element in the favourites list. Contains a constructor plus a pop up menu for the - * element. - * - * @author Matt - * @param String server - * @param String channel - */ - // TODO update javadoc - class FavouritesItem - { - String favServer; - String favChannel; - Preferences settingsPath; - FavouritesPopUp myMenu; - FontDialog favFontDialog; - - public FavouritesItem (String favServer, String favChannel) - { - this.favServer = favServer; - this.favChannel = favChannel; - settingsPath = URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel); - - URProfilesUtil.addListener(EventType.CHANGE, e -> { - settingsPath = URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel); - }); - - createPopUp(); - } - - @Override - public String toString () - { - return favServer + ":" + favChannel; - } - - public void createPopUp () - { - myMenu = new FavouritesPopUp(); - } - - protected class SaveChannelFontListener implements ActionListener - { - @Override - public void actionPerformed (ActionEvent arg0) - { - for (int index = 0; index < tabbedPane.getTabCount(); index++) - { - Component tab = tabbedPane.getComponentAt(index); - - if (tab instanceof IRCRoomBase) - { - IRCRoomBase tabRoom = (IRCRoomBase) tab; - if (tabRoom.getServer().getName().equals(favServer) && tabRoom.getName().equals(favChannel)) - { - tabRoom.getFontPanel().setFont(favFontDialog.getFontPanel().getStyle(), true); - tabRoom.setFont(favFontDialog.getFontPanel().getFont()); - } - } - } - } - } - - private class FavouritesPopUp extends JPopupMenu - { - /** - * - */ - private final long serialVersionUID = -3599612559330380653L; - JMenuItem nameItem; - JMenuItem removeItem; - JMenuItem fontItem; - - public FavouritesPopUp () - { - nameItem = new JMenuItem(FavouritesItem.this.toString()); - add(nameItem); - this.addSeparator(); - // - fontItem = new JMenuItem("Channel Font"); - fontItem.addActionListener(new ShowFontDialog()); - add(fontItem); - // nameItem.setEnabled(false); - removeItem = new JMenuItem("Delete"); - removeItem.addActionListener(new RemoveFavourite()); - add(removeItem); - } - - } - - private class ShowFontDialog implements ActionListener - { - @Override - public void actionPerformed (ActionEvent arg0) - { - if(favFontDialog == null) - { - favFontDialog = new FontDialog(favChannel, UserGUI.this.getStyle(), settingsPath); - favFontDialog.addSaveListener(new SaveChannelFontListener()); - } - - if (favouritesList.getSelectedIndex() > -1) - { - FavouritesItem tempItem = favouritesListModel.elementAt(favouritesList.getSelectedIndex()); - tempItem.favFontDialog.getFontPanel().loadStyle(); - tempItem.favFontDialog.setVisible(true); - } - } - } - - private class RemoveFavourite implements ActionListener - { - @Override - public void actionPerformed (ActionEvent arg0) - { - if (favouritesList.getSelectedIndex() > -1) - { - FavouritesItem tempItem = favouritesListModel.elementAt(favouritesList.getSelectedIndex()); - removeFavourite(tempItem.favServer, tempItem.favChannel); - Preferences channelNode = URProfilesUtil.getActiveFavouritesPath().node(tempItem.favServer).node(tempItem.favChannel); - try - { - String[] channelKeys = channelNode.keys(); - if (channelKeys.length > 0) - { - int keyLength = channelKeys.length; - - do - { - channelNode.remove(channelKeys[keyLength - 1]); - keyLength = channelNode.keys().length; - } while (keyLength > 0); - } - } catch (BackingStoreException e) - { - Constants.LOGGER.log(Level.WARNING, e.getLocalizedMessage()); - } - } - } - } - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#addFavourite(java.lang.String, java.lang.String) - */ - @Override - public void addFavourite (String favServer, String favChannel) - { - favouritesListModel.addElement(new FavouritesItem(favServer, favChannel)); - - URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel).put("PORT", getCreatedServer(favServer).getPort()); - } - - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#isFavourite(urChatBasic.frontend.IRCChannel) - */ - @Override - public Boolean isFavourite (IRCRoomBase channel) - { - FavouritesItem castItem; - - for (Object tempItem : favouritesListModel.toArray()) - { - castItem = (FavouritesItem) tempItem; - if (castItem.favChannel.equals(channel.getName()) && castItem.favServer.equals(channel.getServer())) - { - return true; - } - } - - return false; - } - - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#removeFavourite(java.lang.String, java.lang.String) - */ - @Override - public void removeFavourite (String favServer, String favChannel) - { - FavouritesItem castItem; - - for (Object tempItem : favouritesListModel.toArray()) - { - castItem = (FavouritesItem) tempItem; - if (castItem.favChannel.equals(favChannel) && castItem.favServer.equals(favServer)) - { - favouritesListModel.removeElement(castItem); - break; - } - } - } - - - class FavouritesPopClickListener extends MouseAdapter - { - public void mousePressed (MouseEvent e) - { - if (e.isPopupTrigger()) - { - int row = favouritesList.locationToIndex(e.getPoint()); - if (row > -1) - { - favouritesList.setSelectedIndex(row); - doPop(e); - } - } - } - - public void mouseReleased (MouseEvent e) - { - if (e.isPopupTrigger()) - { - int row = favouritesList.locationToIndex(e.getPoint()); - if (row > -1) - { - favouritesList.setSelectedIndex(row); - doPop(e); - } - } - } - - private void doPop (MouseEvent e) - { - favouritesList.getSelectedValue().myMenu.show(e.getComponent(), e.getX(), e.getY()); - } - } - /** - * Used to initiate server connection - * - * @author Matt - * - */ - private class ConnectPressed implements ActionListener - { - @Override - public void actionPerformed (ActionEvent arg0) - { - if (passwordTextField.getPassword().length > 0 - || authenticationType().equals(CapabilityTypes.NONE.getType())) - { - addToCreatedServers(servernameTextField.getText().trim()); - - if (autoConnectToFavourites.isSelected()) - { - FavouritesItem castItem; - for (Object tempItem : favouritesListModel.toArray()) - { - castItem = (FavouritesItem) tempItem; - addToCreatedServers(castItem.favServer); - } - } - - for (IRCServerBase server : createdServers) - { - server.connect(); - } - - // profilePicker.setEnabled(false); - } else if (!authenticationType().equals(CapabilityTypes.NONE.getType())) - { - MessageDialog dialog = new MessageDialog( - "Password field is empty and is required for your chosen authentication method.", "Warning", - JOptionPane.WARNING_MESSAGE); - dialog.setVisible(true); - } - } - } - /** * (non-Javadoc) * @@ -1350,8 +472,13 @@ public void run () { if (server instanceof IRCServer) { - tabbedPane.addTab(server.getName(), ((IRCServer) server).icon, ((IRCServer) server)); - setCurrentTab(server.getName()); + boolean iconsShown = (boolean) URPanels.getKeyComponentValue(Constants.KEY_SHOW_TAB_ICON); + int currentServerIndex = DriverGUI.gui.getTabIndex((IRCRoomBase) server); + if(currentServerIndex < 0) + { + tabbedPane.addTab(server.getName(), iconsShown ? ((IRCRoomBase) server).icon : null, ((IRCServer) server)); + setCurrentTab(server.getName()); + } // ((IRCServer) server).getUserTextBox().requestFocus(); } } @@ -1371,31 +498,6 @@ public void sendGlobalMessage (String message, String sender) tempServer.sendClientText(message, sender); } - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#connectFavourites(urChatBasic.base.IRCServerBase) - */ - @Override - public void connectFavourites (IRCServerBase server) - { - if (servernameTextField.getText().trim().equals(server.getName())) - server.sendClientText("/join " + firstChannelTextField.getText().trim(), - servernameTextField.getText().trim()); - - if (autoConnectToFavourites.isSelected()) - { - FavouritesItem castItem; - for (Object tempItem : favouritesListModel.toArray()) - { - castItem = (FavouritesItem) tempItem; - if (castItem.favServer.equals(server.getName())) - if (server.getCreatedChannel(castItem.favChannel) == null) - server.sendClientText("/join " + castItem.favChannel, castItem.favServer); - } - } - } - /* * (non-Javadoc) * @@ -1441,51 +543,17 @@ public void quitServer (IRCServerBase server) */ public void setClientSettings () { - URPreferencesUtil.putPref(Constants.KEY_FIRST_CHANNEL, firstChannelTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_FIRST_CHANNEL, firstChannelTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_FIRST_SERVER, servernameTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_FIRST_PORT, serverPortTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_AUTH_TYPE, authenticationTypeChoice.getSelectedItem().toString(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_PASSWORD_REMEMBER, rememberPassCheckBox.isSelected(), URProfilesUtil.getActiveProfilePath()); - - String rememberString = ""; - - if (rememberPassCheckBox.isSelected()) - { - rememberString = new String(passwordTextField.getPassword()); - } - - URPreferencesUtil.putPref(Constants.KEY_PASSWORD, rememberString, URProfilesUtil.getActiveProfilePath()); - - URPreferencesUtil.putPref(Constants.KEY_USE_TLS, serverTLSCheckBox.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_PROXY_HOST, proxyHostNameTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_PROXY_PORT, proxyPortTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_USE_PROXY, serverProxyCheckBox.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_NICK_NAME, userNameTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_REAL_NAME, realNameTextField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_TIME_STAMPS, enableTimeStamps.isSelected(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_TIME_STAMP_FORMAT, timeStampField.getText(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_LAF_NAME, ((LookAndFeelInfo) lafOptions.getSelectedItem()).getClassName(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_EVENT_TICKER_ACTIVE, showEventTicker.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_USERS_LIST_ACTIVE, showUsersList.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_CLICKABLE_LINKS_ENABLED, enableClickableLinks.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_EVENT_TICKER_JOINS_QUITS, showJoinsQuitsEventTicker.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_MAIN_WINDOW_JOINS_QUITS, showJoinsQuitsMainWindow.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LOG_CHANNEL_ACTIVITY, logChannelText.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LOG_SERVER_ACTIVITY, logServerActivity.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LIMIT_CHANNEL_LINES, limitChannelLines.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_AUTO_CONNECT_FAVOURITES, autoConnectToFavourites.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LIMIT_CHANNEL_LINES_COUNT, limitChannelLinesCount.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LIMIT_SERVER_LINES, limitServerLines.isSelected(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LIMIT_SERVER_LINES_COUNT, limitServerLinesCount.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LOG_CLIENT_TEXT, logClientText.isSelected(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.saveStyle(defaultStyle, clientFontPanel.getStyle(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_EVENT_TICKER_DELAY, eventTickerDelay.getValue(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_WINDOW_X, (int) DriverGUI.frame.getBounds().getX(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_WINDOW_Y, (int) DriverGUI.frame.getBounds().getY(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_WINDOW_WIDTH, (int) DriverGUI.frame.getBounds().getWidth(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_WINDOW_HEIGHT, (int) DriverGUI.frame.getBounds().getHeight(), URProfilesUtil.getActiveProfilePath()); + + connectionPanel.putPreferences(); + interfacePanel.putPreferences(); + appearancePanel.putPreferences(); } /** @@ -1493,65 +561,8 @@ public void setClientSettings () */ public void getClientSettings (boolean loadWindowSettings) { - firstChannelTextField - .setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_FIRST_CHANNEL, Constants.DEFAULT_FIRST_CHANNEL)); - servernameTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_FIRST_SERVER, Constants.DEFAULT_FIRST_SERVER)); - serverPortTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_FIRST_PORT, Constants.DEFAULT_FIRST_PORT)); - serverTLSCheckBox.setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_USE_TLS, Constants.DEFAULT_USE_TLS)); - - authenticationTypeChoice.setSelectedItem(CapabilityTypes.getCapType(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_AUTH_TYPE, Constants.DEFAULT_AUTH_TYPE))); - - rememberPassCheckBox.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_PASSWORD_REMEMBER, Constants.DEFAULT_PASSWORD_REMEMBER)); - - if (rememberPassCheckBox.isSelected()) - { - passwordTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_PASSWORD, Constants.DEFAULT_PASSWORD)); - } - - proxyHostNameTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_PROXY_HOST, Constants.DEFAULT_PROXY_HOST)); - proxyPortTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_PROXY_PORT, Constants.DEFAULT_PROXY_PORT)); - serverProxyCheckBox - .setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_USE_PROXY, Constants.DEFAULT_USE_PROXY)); - - userNameTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_NICK_NAME, Constants.DEFAULT_NICK_NAME)); - realNameTextField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_REAL_NAME, Constants.DEFAULT_REAL_NAME)); - - showUsersList.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_USERS_LIST_ACTIVE, Constants.DEFAULT_USERS_LIST_ACTIVE)); - - showEventTicker.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_EVENT_TICKER_ACTIVE, Constants.DEFAULT_EVENT_TICKER_ACTIVE)); - - enableClickableLinks.setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_CLICKABLE_LINKS_ENABLED, - Constants.DEFAULT_CLICKABLE_LINKS_ENABLED)); - - enableTimeStamps - .setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_TIME_STAMPS, Constants.DEFAULT_TIME_STAMPS)); - lafOptions.setSelectedItem(getLAF(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_LAF_NAME, Constants.DEFAULT_LAF_NAME))); - // setNewLAF(((LookAndFeelInfo) lafOptions.getSelectedItem()).getClassName()); - - showJoinsQuitsEventTicker.setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_EVENT_TICKER_JOINS_QUITS, - Constants.DEFAULT_EVENT_TICKER_JOINS_QUITS)); - showJoinsQuitsMainWindow.setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_MAIN_WINDOW_JOINS_QUITS, - Constants.DEFAULT_MAIN_WINDOW_JOINS_QUITS)); - logChannelText.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_LOG_CHANNEL_ACTIVITY, Constants.DEFAULT_LOG_CHANNEL_ACTIVITY)); - logServerActivity.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_LOG_SERVER_ACTIVITY, Constants.DEFAULT_LOG_SERVER_ACTIVITY)); - limitChannelLines.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_LIMIT_CHANNEL_LINES, Constants.DEFAULT_LIMIT_CHANNEL_LINES)); - limitChannelLinesCount.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_LIMIT_CHANNEL_LINES_COUNT, - Constants.DEFAULT_LIMIT_CHANNEL_LINES_COUNT)); - limitServerLines.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_LIMIT_SERVER_LINES, Constants.DEFAULT_LIMIT_SERVER_LINES)); - limitServerLinesCount.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_LIMIT_SERVER_LINES_COUNT, - Constants.DEFAULT_LIMIT_SERVER_LINES_COUNT)); - logClientText.setSelected( - URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_LOG_CLIENT_TEXT, Constants.DEFAULT_LOG_CLIENT_TEXT)); - clientFontPanel.loadStyle(); timeStampField @@ -1563,11 +574,6 @@ public void getClientSettings (boolean loadWindowSettings) updatePreviewTextArea(); - eventTickerDelay.setValue( - URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_EVENT_TICKER_DELAY, Constants.DEFAULT_EVENT_TICKER_DELAY)); - autoConnectToFavourites.setSelected(URProfilesUtil.getActiveProfilePath().getBoolean(Constants.KEY_AUTO_CONNECT_FAVOURITES, - Constants.DEFAULT_AUTO_CONNECT_FAVOURITES)); - if (loadWindowSettings && DriverGUI.frame != null) { DriverGUI.frame.setBounds(URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_X, Constants.DEFAULT_WINDOW_X), @@ -1580,24 +586,6 @@ public void getClientSettings (boolean loadWindowSettings) URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_HEIGHT, Constants.DEFAULT_WINDOW_HEIGHT))); } - // TODO Add Port number to favourites. - try - { - favouritesListModel.removeAllElements(); - for (String serverNode : URProfilesUtil.getActiveFavouritesPath().childrenNames()) - { - for (String channelNode : URProfilesUtil.getActiveFavouritesPath().node(serverNode).childrenNames()) - { - if (URProfilesUtil.getActiveFavouritesPath().node(serverNode).node(channelNode).keys().length > 0) - { - favouritesListModel.addElement(new FavouritesItem(serverNode, channelNode)); - } - } - } - } catch (BackingStoreException e) - { - Constants.LOGGER.log(Level.WARNING, e.getLocalizedMessage()); - } } /* @@ -1611,41 +599,6 @@ public void removeClientSetting (String node, String key) URProfilesUtil.getActiveProfilePath().node(node).remove(key); } - /* - * (non-Javadoc) - * - * @see urChatBasic.frontend.UserGUIBase#getEventTickerDelay() - */ - @Override - public int getEventTickerDelay () - { - return eventTickerDelay.getValue(); - } - - class UCAuthTypeComboBoxChangeHandler implements ActionListener - { - @Override - public void actionPerformed (ActionEvent e) - { - authenticationTypeChoice.runChangeListener(); - - if (authenticationType().equals(CapabilityTypes.NONE.getType())) - { - passwordLabel.setVisible(false); - passwordTextField.setVisible(false); - rememberPassCheckBox.setVisible(false); - rememberPassLabel.setVisible(false); - } else - { - passwordLabel.setText(authenticationTypeChoice.getPasswordFieldName()); - passwordLabel.setVisible(true); - passwordTextField.setVisible(true); - rememberPassCheckBox.setVisible(true); - rememberPassLabel.setVisible(true); - } - } - } - class ChangeLAFListener implements ActionListener { @Override @@ -1683,9 +636,7 @@ public void mouseClicked (MouseEvent e) if (selectedComponent instanceof IRCPrivate) { - IRCServerBase tempServer = - getCreatedServer(((IRCRoomBase) selectedComponent).getServer().getName()); - tempServer.quitRoom((IRCRoomBase) selectedComponent); + ((IRCRoomBase) selectedComponent).getServer().quitRoom((IRCRoomBase) selectedComponent); } else { ((IRCRoomBase) selectedComponent).myMenu.show(tabbedPane, e.getX(), e.getY()); @@ -1711,8 +662,8 @@ private void TabbedPanel_stateChanged (ChangeEvent e) IRCRoomBase tempTab = (IRCRoomBase) selectedComponent; if (!(selectedComponent instanceof IRCServer)) { - tempTab.toggleEventTicker(isShowingEventTicker()); - tempTab.toggleUsersList(isShowingUsersList()); + tempTab.toggleEventTicker(((InterfacePanel) interfacePanel).isShowingEventTicker()); + tempTab.toggleUsersList(((InterfacePanel) interfacePanel).isShowingUsersList()); } tempTab.getUserTextBox().requestFocus(); @@ -1756,15 +707,16 @@ public void actionPerformed (ActionEvent arg0) } } - for (int index = 0; index < favouritesList.getModel().getSize(); index++) - { - FavouritesItem favouriteItem = favouritesList.getModel().getElementAt(index); - if(favouriteItem.favFontDialog != null) - { - favouriteItem.favFontDialog.getFontPanel().setDefaultStyle(getStyle()); - favouriteItem.favFontDialog.getFontPanel().loadStyle(); - } - } + // TODO: Favourites handling to be done elsewhere + // for (int index = 0; index < favouritesList.getModel().getSize(); index++) + // { + // FavouritesItem favouriteItem = favouritesList.getModel().getElementAt(index); + // if(favouriteItem.favFontDialog != null) + // { + // favouriteItem.favFontDialog.getFontPanel().setDefaultStyle(getStyle()); + // favouriteItem.favFontDialog.getFontPanel().loadStyle(); + // } + // } // defaultStyle = clientFontPanel.getStyle(); previewLineFormatter.updateStyles(getStyle()); @@ -1786,8 +738,6 @@ public void setupUserGUI () setLayout(new BorderLayout()); add(tabbedPane, BorderLayout.CENTER); - setupConnectionPanel(); - setupInterfacePanel(); setupAppearancePanel(); // this.setBackground(Color.gray); @@ -1854,7 +804,7 @@ private LookAndFeelInfo getLAF (String lafClassName) } } - Constants.LOGGER.log(Level.SEVERE, "Unable to set LAF to " + lafClassName); + Constants.LOGGER.error( "Unable to set LAF to " + lafClassName); // Set to the System LAF if we've chosen an invalid/unavailable LAF theme return getLAF(UIManager.getSystemLookAndFeelClassName()); @@ -1866,7 +816,7 @@ public void setNewLAF (String newLAFname) // String previousDefaultBackground = URColour.hexEncode(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING)); // Font previousDefaultFont = getFont(); - Constants.LOGGER.log(Level.INFO, "Setting to LookAndFeel to " + newLAFname); + Constants.LOGGER.info( "Setting to LookAndFeel to " + newLAFname); boolean flatLafAvailable = false; try { @@ -1889,7 +839,7 @@ public void setNewLAF (String newLAFname) } } catch (Exception e) { - Constants.LOGGER.log(Level.WARNING, "Failed to set Pluggable LAF! " + e.getLocalizedMessage()); + Constants.LOGGER.error("Failed to set Pluggable LAF! " + e.getLocalizedMessage()); } finally { if (!flatLafAvailable) @@ -1899,7 +849,7 @@ public void setNewLAF (String newLAFname) UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { - Constants.LOGGER.log(Level.WARNING, "Failed to setLookAndFeel! " + e.getLocalizedMessage()); + Constants.LOGGER.error("Failed to setLookAndFeel! " + e.getLocalizedMessage()); } } } @@ -1949,12 +899,6 @@ public void run () } } - for (int index = 0; index < favouritesList.getModel().getSize(); index++) - { - FavouritesItem favouriteItem = favouritesList.getModel().getElementAt(index); - SwingUtilities.updateComponentTreeUI(favouriteItem.myMenu); - } - // update the styles in the preview text area updatePreviewTextArea(); } diff --git a/src/urChatBasic/frontend/components/FontPanel.java b/src/urChatBasic/frontend/components/FontPanel.java index ae9ae9f..42e1a5f 100644 --- a/src/urChatBasic/frontend/components/FontPanel.java +++ b/src/urChatBasic/frontend/components/FontPanel.java @@ -11,7 +11,6 @@ import java.awt.font.TextAttribute; import java.util.Hashtable; import java.util.Map; -import java.util.logging.Level; import java.util.prefs.Preferences; import javax.swing.*; import javax.swing.event.EventListenerList; @@ -64,7 +63,7 @@ public void actionPerformed (ActionEvent arg0) colourDialog = new ColourDialog(styleName, getDefaultStyle(), getSettingsPath()); colourDialog.getColourPanel().addSaveListener(e -> { - Constants.LOGGER.log(Level.INFO, "Font Panel says: Save Colour pressed"); + Constants.LOGGER.info( "Font Panel says: Save Colour pressed"); }); // Forwards the save listeners to the colour panel save listeners diff --git a/src/urChatBasic/frontend/components/FontPreview.java b/src/urChatBasic/frontend/components/FontPreview.java index 9dae33f..1111d98 100644 --- a/src/urChatBasic/frontend/components/FontPreview.java +++ b/src/urChatBasic/frontend/components/FontPreview.java @@ -2,7 +2,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.JTextArea; import javax.swing.JTextPane; public class FontPreview extends JPanel diff --git a/src/urChatBasic/frontend/components/ProfilePicker.java b/src/urChatBasic/frontend/components/ProfilePicker.java index 5c9b49b..cfd4158 100644 --- a/src/urChatBasic/frontend/components/ProfilePicker.java +++ b/src/urChatBasic/frontend/components/ProfilePicker.java @@ -9,12 +9,10 @@ import urChatBasic.base.Constants; import urChatBasic.base.Constants.EventType; import urChatBasic.frontend.DriverGUI; -import urChatBasic.frontend.UserGUI; import urChatBasic.frontend.dialogs.MessageDialog; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.logging.Level; public class ProfilePicker extends JPanel { @@ -143,7 +141,7 @@ public void run () }); - Constants.LOGGER.log(Level.WARNING, "Initial Profile: [" + initialProfile + "] doesn't exist."); + Constants.LOGGER.error("Initial Profile: [" + initialProfile + "] doesn't exist."); } } } diff --git a/src/urChatBasic/frontend/components/UCAuthTypeComboBox.java b/src/urChatBasic/frontend/components/URAuthTypeComboBox.java similarity index 68% rename from src/urChatBasic/frontend/components/UCAuthTypeComboBox.java rename to src/urChatBasic/frontend/components/URAuthTypeComboBox.java index 852dff3..1cf2128 100644 --- a/src/urChatBasic/frontend/components/UCAuthTypeComboBox.java +++ b/src/urChatBasic/frontend/components/URAuthTypeComboBox.java @@ -7,11 +7,11 @@ import urChatBasic.base.capabilities.NickServType; import urChatBasic.base.capabilities.SaslCapSubTypes; -public class UCAuthTypeComboBox extends JComboBox +public class URAuthTypeComboBox extends JComboBox { private String passwordFieldName = "Password"; - public UCAuthTypeComboBox () + public URAuthTypeComboBox () { initialize(); } @@ -38,7 +38,7 @@ private void setPasswordFieldName (String passwordFieldName) public void runChangeListener () { - CapTypeBase selectedAuthType = (CapTypeBase) getSelectedItem(); + CapTypeBase selectedAuthType = getSelectedItem(); // Set the password field name based on the selected authentication type if (selectedAuthType.equals(SaslCapSubTypes.PLAIN) || selectedAuthType.getClass().equals(NickServType.class)) @@ -49,4 +49,23 @@ public void runChangeListener () setPasswordFieldName("Path to certificate"); // No matching authentication type } } + + public CapTypeBase getSelectedItem () + { + return (CapTypeBase) super.getSelectedItem(); + } + + @Override + public void setSelectedItem (Object newObject) + { + CapTypeBase newTypeBase = null; + + if (newObject instanceof CapTypeBase) + newTypeBase = (CapTypeBase) newObject; + else + newTypeBase = CapabilityTypes.getCapType((String) newObject); + + + super.setSelectedItem(newTypeBase); + } } diff --git a/src/urChatBasic/frontend/components/URProxyTypeComboBox.java b/src/urChatBasic/frontend/components/URProxyTypeComboBox.java new file mode 100644 index 0000000..1a31340 --- /dev/null +++ b/src/urChatBasic/frontend/components/URProxyTypeComboBox.java @@ -0,0 +1,50 @@ +package urChatBasic.frontend.components; + +import java.util.Arrays; +import javax.swing.JComboBox; +import urChatBasic.base.proxy.ProxyTypeBase; +import urChatBasic.base.proxy.ProxyTypes; + +public class URProxyTypeComboBox extends JComboBox +{ + public URProxyTypeComboBox () + { + initialize(); + } + + private void initialize () + { + ProxyTypeBase[] proxyTypes = ProxyTypes.getValues(); + + if (proxyTypes != null) + { + Arrays.stream(proxyTypes).forEach(this::addItem); + } + } + + public void runChangeListener () + { + // ProxyTypeBase selectedAuthType = getSelectedItem(); + + // do nothing + } + + public ProxyTypeBase getSelectedItem () + { + return (ProxyTypeBase) super.getSelectedItem(); + } + + @Override + public void setSelectedItem (Object newObject) + { + ProxyTypeBase newTypeBase = null; + + if (newObject instanceof ProxyTypeBase) + newTypeBase = (ProxyTypeBase) newObject; + else + newTypeBase = ProxyTypes.getProxyType((String) newObject); + + + super.setSelectedItem(newTypeBase); + } +} diff --git a/src/urChatBasic/frontend/components/URVersionLabel.java b/src/urChatBasic/frontend/components/URVersionLabel.java index c4bbcf7..92485ad 100644 --- a/src/urChatBasic/frontend/components/URVersionLabel.java +++ b/src/urChatBasic/frontend/components/URVersionLabel.java @@ -13,7 +13,6 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; public class URVersionLabel extends JPanel { @@ -46,7 +45,7 @@ public static void setVersion () } } catch (IOException $ex) { - Constants.LOGGER.log(Level.INFO, "Unable to determine .git folder. Not setting version string.", $ex); + Constants.LOGGER.info( "Unable to determine .git folder. Not setting version string.", $ex); } } } diff --git a/src/urChatBasic/frontend/panels/ConnectionPanel.java b/src/urChatBasic/frontend/panels/ConnectionPanel.java new file mode 100644 index 0000000..08c22a3 --- /dev/null +++ b/src/urChatBasic/frontend/panels/ConnectionPanel.java @@ -0,0 +1,485 @@ +package urChatBasic.frontend.panels; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.logging.Level; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; +import java.util.stream.Collectors; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import javax.swing.SwingUtilities; +import urChatBasic.backend.utils.URProfilesUtil; +import urChatBasic.base.Constants; +import urChatBasic.base.Constants.EventType; +import urChatBasic.base.Constants.Placement; +import urChatBasic.base.Constants.Size; +import urChatBasic.base.IRCRoomBase; +import urChatBasic.base.IRCServerBase; +import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypes; +import urChatBasic.frontend.DriverGUI; +import urChatBasic.frontend.IRCServer; +import urChatBasic.frontend.components.URAuthTypeComboBox; +import urChatBasic.frontend.components.URProxyTypeComboBox; +import urChatBasic.frontend.dialogs.FontDialog; +import urChatBasic.frontend.dialogs.MessageDialog; +import urChatBasic.frontend.utils.URPanels; + +public class ConnectionPanel extends UROptionsPanel { + public static final String PANEL_DISPLAY_NAME = "Connection"; + + // Identification + private final JTextField userNameTextField = new JTextField("", 12); + private final JTextField realNameTextField = new JTextField(""); + + // Authentication + private final URAuthTypeComboBox authenticationTypeChoice = new URAuthTypeComboBox(); + private final JPasswordField passwordTextField = new JPasswordField(""); + private final JCheckBox rememberPassCheckBox = new JCheckBox(); + + // Connection + private final JTextField servernameTextField = new JTextField("", 8); + private final JTextField serverPortTextField = new JTextField("", 4); + private final JCheckBox serverTLSCheckBox = new JCheckBox(); + private final JButton connectButton = new JButton("Connect"); + + // Proxy + private final JTextField proxyHostNameTextField = new JTextField(""); + private final JTextField proxyPortTextField = new JTextField(""); + private final URProxyTypeComboBox proxyTypeChoice = new URProxyTypeComboBox(); + + private final JTextField firstChannelTextField = new JTextField(""); + + // Favourites Panel + private final JCheckBox autoConnectToFavourites = new JCheckBox("Automatically join favourite channels"); + private final DefaultListModel favouritesListModel = new DefaultListModel(); + private final JList favouritesList = new JList(favouritesListModel); + private final JScrollPane favouritesScroller = new JScrollPane(favouritesList); + + + + public ConnectionPanel (MainOptionsPanel optionsPanel) + { + super(PANEL_DISPLAY_NAME, optionsPanel); + setupConnectionPanel(); + } + + public ConnectionPanel (MainOptionsPanel optionsPanel, Optional preferredIndex) + { + super(PANEL_DISPLAY_NAME, optionsPanel, preferredIndex); + setupConnectionPanel(); + } + + /** + * Adds all the components to the panel, with the related preference Keys for that component. + * i.e showEventTicker is set via the KEY_EVENT_TICKER_ACTIVE key ('show event ticker') + */ + private void setupConnectionPanel () + { + URPanels.addToPanel(this, userNameTextField, "Nick", Placement.DEFAULT, Size.LARGE, Constants.KEY_NICK_NAME); + URPanels.addToPanel(this, realNameTextField, "Real Name", Placement.DEFAULT, Size.LARGE, Constants.KEY_REAL_NAME); + + authenticationTypeChoice.addActionListener(new UCAuthTypeComboBoxChangeHandler()); + + URPanels.addToPanel(this, authenticationTypeChoice, "Authentication Type", Placement.DEFAULT, null, Constants.KEY_AUTH_TYPE); + URPanels.addToPanel(this, passwordTextField, "Password", Placement.DEFAULT, Size.LARGE, Constants.KEY_PASSWORD); + URPanels.addToPanel(this, rememberPassCheckBox, "Remember", Placement.RIGHT, null, Constants.KEY_PASSWORD_REMEMBER); + URPanels.addToPanel(this, servernameTextField, "Server", Placement.DEFAULT, Size.MEDIUM, Constants.KEY_FIRST_SERVER); + URPanels.addToPanel(this, serverPortTextField, "Port", Placement.RIGHT, Size.SMALL, Constants.KEY_FIRST_PORT); + URPanels.addToPanel(this, serverTLSCheckBox, "TLS", Placement.RIGHT, null, Constants.KEY_USE_TLS); + URPanels.addToPanel(this, proxyHostNameTextField, "Proxy Host", Placement.DEFAULT, Size.MEDIUM, Constants.KEY_PROXY_HOST); + URPanels.addToPanel(this, proxyPortTextField, "Port", Placement.RIGHT, Size.SMALL, Constants.KEY_PROXY_PORT); + URPanels.addToPanel(this, proxyTypeChoice, "Proxy Type", Placement.RIGHT, null, Constants.KEY_PROXY_TYPE); + URPanels.addToPanel(this, firstChannelTextField, "Channel", Placement.DEFAULT, Size.MEDIUM, Constants.KEY_FIRST_CHANNEL); + + add(connectButton); + connectButton.addActionListener(new ConnectPressed()); + add(autoConnectToFavourites); + + favouritesScroller.setPreferredSize(new Dimension(200, 100)); + favouritesList.addMouseListener(new FavouritesPopClickListener()); + add(favouritesScroller); + + final int TOP_SPACING = 6; + final int TOP_ALIGNED = 0; + final int LEFT_ALIGNED = 0; + final int RIGHT_ALIGNED = 0; + final int LEFT_SPACING = 6; + + SpringLayout connectionLayout = (SpringLayout) this.getLayout(); + + // Puts the connect button further below Channel + connectionLayout.putConstraint(SpringLayout.NORTH, connectButton, TOP_SPACING * TOP_SPACING, SpringLayout.SOUTH, + firstChannelTextField); + connectionLayout.putConstraint(SpringLayout.WEST, connectButton, LEFT_ALIGNED, SpringLayout.WEST, + firstChannelTextField); + + + // Aligns the autoConnectToFavourites checkbox to the label of userNameTextField + connectionLayout.putConstraint(SpringLayout.NORTH, autoConnectToFavourites, TOP_ALIGNED, SpringLayout.NORTH, + URPanels.getLabelForComponent(this,userNameTextField)); + connectionLayout.putConstraint(SpringLayout.WEST, autoConnectToFavourites, LEFT_SPACING, SpringLayout.EAST, + proxyTypeChoice); + + URPanels.addKeyAssociation(this, autoConnectToFavourites, Constants.KEY_AUTO_CONNECT_FAVOURITES); + + // Puts the Favourites box inline with the autoConnectToFavourites check box and the connect button + connectionLayout.putConstraint(SpringLayout.NORTH, favouritesScroller, TOP_SPACING, SpringLayout.SOUTH, + autoConnectToFavourites); + connectionLayout.putConstraint(SpringLayout.WEST, favouritesScroller, LEFT_ALIGNED, SpringLayout.WEST, + autoConnectToFavourites); + connectionLayout.putConstraint(SpringLayout.EAST, favouritesScroller, LEFT_ALIGNED, SpringLayout.EAST, + autoConnectToFavourites); + connectionLayout.putConstraint(SpringLayout.SOUTH, favouritesScroller, TOP_SPACING, SpringLayout.SOUTH, + connectButton); + + URProfilesUtil.addListener(EventType.CHANGE, e -> { + loadFavouritesList(); + }); + } + + public void addFavourite (String favServer, String favChannel) + { + favouritesListModel.addElement(new FavouritesItem(favServer, favChannel)); + + URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel).put("PORT", DriverGUI.gui.getCreatedServer(favServer).getPort()); + } + + public Boolean isFavourite (IRCRoomBase channel) + { + FavouritesItem castItem; + + for (Object tempItem : favouritesListModel.toArray()) + { + castItem = (FavouritesItem) tempItem; + if (castItem.favChannel.equals(channel.getName()) && castItem.favServer.equals(channel.getServer())) + { + return true; + } + } + + return false; + } + + public void loadFavouritesList () + { + try + { + favouritesListModel.removeAllElements(); + for (String serverNode : URProfilesUtil.getActiveFavouritesPath().childrenNames()) + { + for (String channelNode : URProfilesUtil.getActiveFavouritesPath().node(serverNode).childrenNames()) + { + if (URProfilesUtil.getActiveFavouritesPath().node(serverNode).node(channelNode).keys().length > 0) + { + favouritesListModel.addElement(new FavouritesItem(serverNode, channelNode)); + } + } + } + } catch (BackingStoreException e) + { + Constants.LOGGER.error(e.getLocalizedMessage()); + } + } + + /** + * Create an element in the favourites list. Contains a constructor plus a pop up menu for the + * element. + * + * @author Matt + * @param String server + * @param String channel + */ + // TODO update javadoc + class FavouritesItem + { + String favServer; + String favChannel; + Preferences settingsPath; + FavouritesPopUp myMenu; + FontDialog favFontDialog; + + public FavouritesItem (String favServer, String favChannel) + { + this.favServer = favServer; + this.favChannel = favChannel; + settingsPath = URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel); + + URProfilesUtil.addListener(EventType.CHANGE, e -> { + settingsPath = URProfilesUtil.getActiveFavouritesPath().node(favServer).node(favChannel); + }); + + createPopUp(); + } + + @Override + public String toString () + { + return favServer + ":" + favChannel; + } + + public String getChannelName () + { + return favChannel; + } + + public void createPopUp () + { + myMenu = new FavouritesPopUp(); + } + + private class FavouritesPopUp extends JPopupMenu + { + /** + * + */ + private final long serialVersionUID = -3599612559330380653L; + JMenuItem nameItem; + JMenuItem removeItem; + JMenuItem fontItem; + + public FavouritesPopUp () + { + nameItem = new JMenuItem(FavouritesItem.this.toString()); + add(nameItem); + this.addSeparator(); + // + fontItem = new JMenuItem("Channel Font"); + fontItem.addActionListener(new ShowFontDialog()); + add(fontItem); + // nameItem.setEnabled(false); + removeItem = new JMenuItem("Delete"); + removeItem.addActionListener(new RemoveFavourite()); + add(removeItem); + } + + } + + private class ShowFontDialog implements ActionListener + { + @Override + public void actionPerformed (ActionEvent arg0) + { + if(favFontDialog == null) + { + favFontDialog = new FontDialog(favChannel, DriverGUI.gui.getStyle(), settingsPath); + // favFontDialog.addSaveListener(new SaveChannelFontListener()); + } + + if (favouritesList.getSelectedIndex() > -1) + { + FavouritesItem tempItem = favouritesListModel.elementAt(favouritesList.getSelectedIndex()); + tempItem.favFontDialog.getFontPanel().loadStyle(); + tempItem.favFontDialog.setVisible(true); + } + } + } + + private class RemoveFavourite implements ActionListener + { + @Override + public void actionPerformed (ActionEvent arg0) + { + if (favouritesList.getSelectedIndex() > -1) + { + FavouritesItem tempItem = favouritesListModel.elementAt(favouritesList.getSelectedIndex()); + removeFavourite(tempItem.favServer, tempItem.favChannel); + Preferences channelNode = URProfilesUtil.getActiveFavouritesPath().node(tempItem.favServer).node(tempItem.favChannel); + try + { + String[] channelKeys = channelNode.keys(); + if (channelKeys.length > 0) + { + int keyLength = channelKeys.length; + + do + { + channelNode.remove(channelKeys[keyLength - 1]); + keyLength = channelNode.keys().length; + } while (keyLength > 0); + } + } catch (BackingStoreException e) + { + Constants.LOGGER.error(e.getLocalizedMessage()); + } + } + } + } + } + + public void removeFavourite (String favServer, String favChannel) + { + FavouritesItem castItem; + + for (Object tempItem : favouritesListModel.toArray()) + { + castItem = (FavouritesItem) tempItem; + if (castItem.favChannel.equals(favChannel) && castItem.favServer.equals(favServer)) + { + favouritesListModel.removeElement(castItem); + break; + } + } + } + + + class FavouritesPopClickListener extends MouseAdapter + { + public void mousePressed (MouseEvent e) + { + if (e.isPopupTrigger()) + { + int row = favouritesList.locationToIndex(e.getPoint()); + if (row > -1) + { + favouritesList.setSelectedIndex(row); + doPop(e); + } + } + } + + public void mouseReleased (MouseEvent e) + { + if (e.isPopupTrigger()) + { + int row = favouritesList.locationToIndex(e.getPoint()); + if (row > -1) + { + favouritesList.setSelectedIndex(row); + doPop(e); + } + } + } + + // Show the popup menu, update it's styling first. + private void doPop (MouseEvent e) + { + SwingUtilities.updateComponentTreeUI(favouritesList.getSelectedValue().myMenu); + favouritesList.getSelectedValue().myMenu.show(e.getComponent(), e.getX(), e.getY()); + } + } + + class UCAuthTypeComboBoxChangeHandler implements ActionListener + { + @Override + public void actionPerformed (ActionEvent e) + { + authenticationTypeChoice.runChangeListener(); + + if (authenticationTypeChoice.getSelectedItem().equals(CapabilityTypes.NONE.getType())) + { + passwordTextField.setVisible(false); + rememberPassCheckBox.setVisible(false); + + URPanels.getLabelForComponent(ConnectionPanel.this, passwordTextField).setVisible(false); + URPanels.getLabelForComponent(ConnectionPanel.this, rememberPassCheckBox).setVisible(false); + } else + { + passwordTextField.setVisible(true); + rememberPassCheckBox.setVisible(true); + + URPanels.getLabelForComponent(ConnectionPanel.this, passwordTextField).setVisible(true); + URPanels.getLabelForComponent(ConnectionPanel.this, rememberPassCheckBox).setVisible(true); + } + } + } + + // TODO: This should be a backend thing + public void connectFavourites (IRCServerBase server) + { + if (servernameTextField.getText().trim().equals(server.getName())) + server.sendClientText("/join " + firstChannelTextField.getText().trim(), + servernameTextField.getText().trim()); + + if (autoConnectToFavourites.isSelected()) + { + FavouritesItem castItem; + for (Object tempItem : favouritesListModel.toArray()) + { + castItem = (FavouritesItem) tempItem; + if (castItem.favServer.equals(server.getName())) + if (server.getCreatedChannel(castItem.favChannel) == null) + server.sendClientText("/join " + castItem.favChannel, castItem.favServer); + } + } + } + + + /** + * Used to initiate server connection + * + * @author Matt + * + */ + private class ConnectPressed implements ActionListener + { + @Override + public void actionPerformed (ActionEvent arg0) + { + if (!authenticationTypeChoice.getSelectedItem().equals(CapabilityTypes.NONE.getType()) && passwordTextField.getPassword().length == 0 ) + { + MessageDialog dialog = new MessageDialog( + "Password field is empty and is required for your chosen authentication method.", "Warning", + JOptionPane.WARNING_MESSAGE); + dialog.setVisible(true); + } else if (!proxyTypeChoice.getSelectedItem().equals(ProxyTypes.NONE.getType()) && (proxyHostNameTextField.getText().isBlank() || + proxyPortTextField.getText().isBlank()) ) + { + MessageDialog dialog = new MessageDialog( + "Hostname or Port field is empty which is required for your chosen Proxy method.", "Warning", + JOptionPane.WARNING_MESSAGE); + dialog.setVisible(true); + } else + { + // DriverGUI.gui.addToCreatedServers(servernameTextField.getText().trim()); + + IRCServerBase newServer = new IRCServer(servernameTextField.getText().trim(), userNameTextField.getText().trim(), + realNameTextField.getText().trim(), new String(passwordTextField.getPassword()), + serverPortTextField.getText().trim(), serverTLSCheckBox.isSelected(), + proxyHostNameTextField.getText(), proxyPortTextField.getText(), proxyTypeChoice.getSelectedItem(), authenticationTypeChoice.getSelectedItem()); + + // TODO: Revisit when considering adding support for multiple servers + // if (autoConnectToFavourites.isSelected()) + // { + // FavouritesItem castItem; + // for (Object tempItem : favouritesListModel.toArray()) + // { + // castItem = (FavouritesItem) tempItem; + // DriverGUI.gui.addToCreatedServers(castItem.favServer); + // } + // } + + List favouriteChannels = new ArrayList<>(); + if(autoConnectToFavourites.isSelected()) + favouriteChannels = Collections.list(favouritesListModel.elements()) + .stream() + .map(FavouritesItem::getChannelName) + .collect(Collectors.toList()); + + if(!firstChannelTextField.getText().isBlank()) + favouriteChannels.add(firstChannelTextField.getText()); + + newServer.connect(favouriteChannels.stream().toArray(size -> new String[size])); + + // profilePicker.setEnabled(false); + } + } + } +} diff --git a/src/urChatBasic/frontend/panels/InterfacePanel.java b/src/urChatBasic/frontend/panels/InterfacePanel.java new file mode 100644 index 0000000..cb1bd82 --- /dev/null +++ b/src/urChatBasic/frontend/panels/InterfacePanel.java @@ -0,0 +1,270 @@ +package urChatBasic.frontend.panels; + +import java.util.Optional; +import javax.swing.ImageIcon; +import javax.swing.JCheckBox; +import javax.swing.JSlider; +import javax.swing.JTextField; +import urChatBasic.base.Constants; +import urChatBasic.base.IRCRoomBase; +import urChatBasic.base.Constants.Placement; +import urChatBasic.frontend.DriverGUI; +import urChatBasic.frontend.utils.URPanels; + +public class InterfacePanel extends UROptionsPanel +{ + public static final String PANEL_DISPLAY_NAME = "Interface"; + + private final JCheckBox showTabIcons = new JCheckBox("Show Tab icons"); + private final JCheckBox showEventTicker = new JCheckBox("Show Event Ticker"); + private final JCheckBox showUsersList = new JCheckBox("Show Users List"); + private final JCheckBox enableClickableLinks = new JCheckBox("Make links clickable"); + private final JCheckBox showJoinsQuitsEventTicker = new JCheckBox("Show Joins/Quits in the Event Ticker"); + private final JCheckBox showJoinsQuitsMainWindow = new JCheckBox("Show Joins/Quits in the Chat Window"); + private final JCheckBox logChannelText = new JCheckBox("Save and log all channel text"); + private final JCheckBox logServerActivity = new JCheckBox("Save and log all Server activity"); + private final JCheckBox logClientText = new JCheckBox("Log client text (Allows up or down history)"); + private final JCheckBox limitServerLines = new JCheckBox("Limit the number of lines in Server activity"); + private final JCheckBox limitChannelLines = new JCheckBox("Limit the number of lines in channel text"); + private final JCheckBox enableTimeStamps = new JCheckBox("Time Stamp chat messages"); + + public JTextField limitServerLinesCount = new JTextField(); + public JTextField limitChannelLinesCount = new JTextField(); + + public final int TICKER_DELAY_MIN = 0; + public final int TICKER_DELAY_MAX = 30; + public final int TICKER_DELAY_INIT = 20; + public final int DEFAULT_LINES_LIMIT = Integer.parseInt(Constants.DEFAULT_LIMIT_CHANNEL_LINES_COUNT); + public JSlider eventTickerDelay = new JSlider(JSlider.HORIZONTAL, TICKER_DELAY_MIN, TICKER_DELAY_MAX, TICKER_DELAY_INIT); + + public InterfacePanel (MainOptionsPanel optionsPanel) + { + super(PANEL_DISPLAY_NAME, optionsPanel); + setupInterfacePanel(); + } + + public InterfacePanel (MainOptionsPanel optionsPanel, Optional preferredIndex) + { + super(PANEL_DISPLAY_NAME, optionsPanel, preferredIndex); + setupInterfacePanel(); + } + + /** + * Adds all the components to the panel, with the related preference Keys for that component. i.e showEventTicker is set via the KEY_EVENT_TICKER_ACTIVE key + * ('show event ticker') + */ + private void setupInterfacePanel () + { + URPanels.addToPanel(this, showTabIcons, null, Placement.DEFAULT, null, Constants.KEY_SHOW_TAB_ICON); + URPanels.addToPanel(this, showEventTicker, null, Placement.DEFAULT, null, Constants.KEY_EVENT_TICKER_ACTIVE); + URPanels.addToPanel(this, enableClickableLinks, null, Placement.DEFAULT, null, Constants.KEY_CLICKABLE_LINKS_ENABLED); + URPanels.addToPanel(this, showJoinsQuitsEventTicker, null, Placement.DEFAULT, null, Constants.KEY_EVENT_TICKER_JOINS_QUITS); + URPanels.addToPanel(this, showJoinsQuitsMainWindow, null, Placement.DEFAULT, null, Constants.KEY_MAIN_WINDOW_JOINS_QUITS); + URPanels.addToPanel(this, logChannelText, null, Placement.DEFAULT, null, Constants.KEY_LOG_CHANNEL_ACTIVITY); + URPanels.addToPanel(this, logServerActivity, null, Placement.DEFAULT, null, Constants.KEY_LOG_SERVER_ACTIVITY); + URPanels.addToPanel(this, logClientText, null, Placement.DEFAULT, null, Constants.KEY_LOG_CLIENT_TEXT); + URPanels.addToPanel(this, limitServerLines, null, Placement.DEFAULT, null, Constants.KEY_LIMIT_SERVER_LINES); + URPanels.addToPanel(this, limitServerLinesCount, null, Placement.RIGHT, null, Constants.KEY_LIMIT_SERVER_LINES_COUNT); + URPanels.addToPanel(this, limitChannelLines, null, Placement.DEFAULT, null, Constants.KEY_LIMIT_CHANNEL_LINES); + URPanels.addToPanel(this, limitChannelLinesCount, null, Placement.RIGHT, null, Constants.KEY_LIMIT_CHANNEL_LINES_COUNT); + URPanels.addToPanel(this, enableTimeStamps, null, Placement.DEFAULT, null, Constants.KEY_TIME_STAMPS); + + // Turn on labels at major tick mark. + eventTickerDelay.setMajorTickSpacing(10); + eventTickerDelay.setMinorTickSpacing(1); + eventTickerDelay.setPaintTicks(true); + + eventTickerDelay.setPaintLabels(true); + // eventTickerDelay.setMaximumSize(new Dimension(400, 40)); + + eventTickerDelay.setToolTipText("Event Ticker movement delay (Lower is faster)"); + + // interfacePanel.add(eventTickerLabel); + URPanels.addToPanel(this, eventTickerDelay, "Event Ticker Delay", Placement.DEFAULT, null, Constants.KEY_EVENT_TICKER_DELAY); + + showTabIcons.addActionListener(e -> { + for (int i = 0; i < DriverGUI.gui.tabbedPane.getTabCount(); i++) + { + ImageIcon setIcon = null; + + if (DriverGUI.gui.tabbedPane.getComponentAt(i) instanceof IRCRoomBase) + { + IRCRoomBase room = (IRCRoomBase) DriverGUI.gui.tabbedPane.getComponentAt(i); + setIcon = room.icon; + DriverGUI.gui.tabbedPane.setIconAt(i, showTabIcons.isSelected() ? setIcon : null); + } + + } + }); + } + + public int getLimitServerLinesCount () + { + try + { + return Integer.parseInt(limitServerLinesCount.getText()); + } catch (Exception e) + { + // Was an error, default to 1000 + return DEFAULT_LINES_LIMIT; + } + } + + public int getEventTickerDelay () + { + return eventTickerDelay.getValue(); + } + + public void enableLimitChannelLines (boolean enable) + { + limitChannelLines.setSelected(enable); + } + + public boolean getLimitChannelLines () + { + return limitChannelLines.isSelected(); + } + + public void setLimitChannelLinesCount (int limit) + { + limitChannelLinesCount.setText(Integer.toString(limit)); + } + + public void setLimitServerLinesCount (int limit) + { + limitServerLinesCount.setText(Integer.toString(limit)); + } + + public int getLimitChannelLinesCount () + { + try + { + return Integer.parseInt(limitChannelLinesCount.getText()); + } catch (Exception e) + { + // Was an error, set to default + return DEFAULT_LINES_LIMIT; + } + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#saveChannelHistory() + */ + public Boolean saveChannelHistory () + { + return logChannelText.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#saveServerHistory() + */ + public Boolean saveServerHistory () + { + return logServerActivity.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isShowingEventTicker() + */ + public Boolean isShowingEventTicker () + { + return showEventTicker.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isShowingUsersList() + */ + public Boolean isShowingUsersList () + { + return showUsersList.isSelected(); + } + + public Boolean isClickableLinksEnabled () + { + return enableClickableLinks.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isJoinsQuitsTickerEnabled() + */ + public Boolean isJoinsQuitsTickerEnabled () + { + return showJoinsQuitsEventTicker.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isJoinsQuitsMainEnabled() + */ + public Boolean isJoinsQuitsMainEnabled () + { + return showJoinsQuitsMainWindow.isSelected(); + } + + public void setJoinsQuitsMain (boolean enable) + { + showJoinsQuitsMainWindow.setSelected(enable); + } + + public void setJoinsQuitsEventTicker (boolean enable) + { + showJoinsQuitsEventTicker.setSelected(enable); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isChannelHistoryEnabled() + */ + public Boolean isChannelHistoryEnabled () + { + return logChannelText.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isLimitedServerActivity() + */ + public Boolean isLimitedServerActivity () + { + return limitServerLines.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isLimitedChannelActivity() + */ + public Boolean isLimitedChannelActivity () + { + return limitChannelLines.isSelected(); + } + + /* + * (non-Javadoc) + * + * @see urChatBasic.frontend.UserGUIBase#isTimeStampsEnabled() + */ + public Boolean isTimeStampsEnabled () + { + return enableTimeStamps.isSelected(); + } + + public Boolean isClientHistoryEnabled () + { + return logClientText.isSelected(); + + } +} diff --git a/src/urChatBasic/frontend/components/MainOptionsPanel.java b/src/urChatBasic/frontend/panels/MainOptionsPanel.java similarity index 91% rename from src/urChatBasic/frontend/components/MainOptionsPanel.java rename to src/urChatBasic/frontend/panels/MainOptionsPanel.java index 1ba24a0..ed490c5 100644 --- a/src/urChatBasic/frontend/components/MainOptionsPanel.java +++ b/src/urChatBasic/frontend/panels/MainOptionsPanel.java @@ -1,4 +1,4 @@ -package urChatBasic.frontend.components; +package urChatBasic.frontend.panels; import java.awt.BorderLayout; import java.awt.CardLayout; @@ -13,8 +13,9 @@ import javax.swing.event.ListSelectionListener; import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.base.Constants.Placement; -import urChatBasic.frontend.panels.UROptionsPanel; -import urChatBasic.frontend.utils.Panels; +import urChatBasic.frontend.components.ProfilePicker; +import urChatBasic.frontend.components.URVersionLabel; +import urChatBasic.frontend.utils.URPanels; public class MainOptionsPanel extends JPanel { @@ -63,11 +64,11 @@ public MainOptionsPanel () extrasPanel.setBackground(Color.green); // Extras panel is below the options list, and just contains the profile switcher and the version // label - Panels.addToPanel(extrasPanel, urVersionLabel, null, Placement.BOTTOM, null); + URPanels.addToPanel(extrasPanel, urVersionLabel, null, Placement.BOTTOM, null, null); profilePicker = new ProfilePicker(URProfilesUtil.getActiveProfileName(), true); - Panels.addToPanel(extrasPanel, profilePicker, "Active Profile", Placement.TOP, null); + URPanels.addToPanel(extrasPanel, profilePicker, "Active Profile", Placement.TOP, null, null); // extrasPanel.add(urVersionLabel, BorderLayout.SOUTH); } diff --git a/src/urChatBasic/frontend/components/ProfilePanel.java b/src/urChatBasic/frontend/panels/ProfilePanel.java similarity index 93% rename from src/urChatBasic/frontend/components/ProfilePanel.java rename to src/urChatBasic/frontend/panels/ProfilePanel.java index d39fab7..5385065 100644 --- a/src/urChatBasic/frontend/components/ProfilePanel.java +++ b/src/urChatBasic/frontend/panels/ProfilePanel.java @@ -1,4 +1,4 @@ -package urChatBasic.frontend.components; +package urChatBasic.frontend.panels; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -26,8 +26,7 @@ import urChatBasic.frontend.UserGUI; import urChatBasic.frontend.dialogs.MessageDialog; import urChatBasic.frontend.dialogs.YesNoDialog; -import urChatBasic.frontend.panels.UROptionsPanel; -import urChatBasic.frontend.utils.Panels; +import urChatBasic.frontend.utils.URPanels; public class ProfilePanel extends UROptionsPanel { @@ -56,11 +55,11 @@ public ProfilePanel (MainOptionsPanel optionsPanel) loadProfiles(); }); - Panels.addToPanel(this, profileScroller, "Available Profiles", Placement.DEFAULT, Size.CUSTOM.customSize(200, 200)); - Panels.addToPanel(this, cloneProfile, null, Placement.DEFAULT, null); - Panels.addToPanel(this, createProfile, null, Placement.RIGHT, null); + URPanels.addToPanel(this, profileScroller, "Available Profiles", Placement.DEFAULT, Size.CUSTOM.customSize(200, 200), null); + URPanels.addToPanel(this, cloneProfile, null, Placement.DEFAULT, null, null); + URPanels.addToPanel(this, createProfile, null, Placement.RIGHT, null, null); - Panels.addToPanel(this, profileName, "Selected Profile", Placement.DEFAULT, Size.SMALL); + URPanels.addToPanel(this, profileName, "Selected Profile", Placement.DEFAULT, Size.SMALL, null); setAsDefault.addActionListener(new ActionListener() { @@ -76,7 +75,7 @@ public void actionPerformed (ActionEvent arg0) listSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); listSelectionModel.addListSelectionListener(new ProfilesListSelectionHandler()); - Panels.addToPanel(this, setAsDefault, "Set as default", Placement.DEFAULT, null); + URPanels.addToPanel(this, setAsDefault, "Set as default", Placement.DEFAULT, null, null); // Add KeyListener to the table for key events profilesTable.addKeyListener(new KeyAdapter() diff --git a/src/urChatBasic/frontend/panels/UROptionsPanel.java b/src/urChatBasic/frontend/panels/UROptionsPanel.java index 35fa584..1f1e40b 100644 --- a/src/urChatBasic/frontend/panels/UROptionsPanel.java +++ b/src/urChatBasic/frontend/panels/UROptionsPanel.java @@ -6,7 +6,9 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.EventListenerList; -import urChatBasic.frontend.components.MainOptionsPanel; +import urChatBasic.backend.utils.URProfilesUtil; +import urChatBasic.base.Constants.EventType; +import urChatBasic.frontend.utils.URPanels; public class UROptionsPanel extends JPanel { @@ -26,6 +28,10 @@ public UROptionsPanel (String displayName, MainOptionsPanel optionsPanel, Option panelDisplayName = displayName; panelScroller = new JScrollPane(this); optionsPanel.addToOptions(displayName, this, preferredIndex); + + URProfilesUtil.addListener(EventType.CHANGE, e -> { + URPanels.getPreferences(this); + }); } @Override @@ -49,6 +55,16 @@ public void addHideListener (ActionListener actionListener) hideListenerList.add(ActionListener.class, actionListener); } + public void getPreferences () + { + URPanels.getPreferences(this); + } + + public void putPreferences () + { + URPanels.putPreferences(this); + } + /** * Fire the appropriate listener list. isShowing will fire the displayListenerList, else * hideListenerList diff --git a/src/urChatBasic/frontend/utils/Panels.java b/src/urChatBasic/frontend/utils/Panels.java deleted file mode 100644 index 7c47857..0000000 --- a/src/urChatBasic/frontend/utils/Panels.java +++ /dev/null @@ -1,171 +0,0 @@ -package urChatBasic.frontend.utils; - -import java.awt.*; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SpringLayout; -import urChatBasic.base.Constants.Placement; -import urChatBasic.base.Constants.Size; - -public class Panels -{ - - public static void addToPanel (JPanel targetPanel, Component newComponent, String label, Placement alignment, - Size targetSize) - { - Class layoutClass = targetPanel.getLayout().getClass(); - - if (layoutClass == BorderLayout.class) - { - addToBorderPanel(targetPanel, newComponent, label, alignment, targetSize); - } else - { - if (targetPanel.getLayout().getClass() != SpringLayout.class) - targetPanel.setLayout(new SpringLayout()); - - addToSpringPanel(targetPanel, newComponent, label, alignment, targetSize); - } - } - - private static void addToSpringPanel (JPanel targetPanel, Component newComponent, String label, Placement alignment, - Size targetSize) - { - boolean labelAdded = false; - int topSpacing = 6; - int leftSpacing = 6; - final int TOP_ALIGNED = 0; - final int LEFT_ALIGNED = 0; - - // Only add it now if the label would be "next" in the components list - if (null != label && !label.isBlank() && alignment == Placement.DEFAULT || alignment == Placement.BOTTOM) - { - Panels.addToPanel(targetPanel, new JLabel(label + ":"), null, alignment, targetSize); - // There is a label, so we want the added component to be aligned with the label - topSpacing = 0; - labelAdded = true; - } - - if (targetPanel.getLayout().getClass() != SpringLayout.class) - { - targetPanel.setLayout(new SpringLayout()); - } - - SpringLayout layout = (SpringLayout) targetPanel.getLayout(); - Component[] components = targetPanel.getComponents(); - - if (components.length > 0) - { - // Add newComponent to the targetPanel - targetPanel.add(newComponent); - - - // Used for Top Alignment - Component previousTopComponent = components[components.length - 1]; - - // Used for Left Alignment (default aligned with the previous component) - Component previousLeftComponent = previousTopComponent; - - // Default puts the curent component left aligned and below the previous component - String newComponentTopAlign = SpringLayout.NORTH; - String previousTopAlign = SpringLayout.SOUTH; - String newComponentLeftAlign = SpringLayout.WEST; - String previousLeftAlign = SpringLayout.WEST; - - // Set constraints for newComponent - switch (alignment) - { - case RIGHT: - // attach the new component inline and to the right of the previous - topSpacing = 0; - newComponentTopAlign = SpringLayout.NORTH; - previousTopAlign = SpringLayout.NORTH; - newComponentLeftAlign = SpringLayout.WEST; - previousLeftAlign = SpringLayout.EAST; - break; - case TOP: - // attach the new component inline and to the right of the previous - topSpacing = 0; - newComponentTopAlign = SpringLayout.SOUTH; - previousTopAlign = SpringLayout.NORTH; - newComponentLeftAlign = SpringLayout.WEST; - previousLeftAlign = SpringLayout.WEST; - break; - default: - // Aligned with the first component - previousLeftComponent = components[0]; - newComponentTopAlign = SpringLayout.NORTH; - previousTopAlign = SpringLayout.SOUTH; - newComponentLeftAlign = SpringLayout.WEST; - previousLeftAlign = SpringLayout.WEST; - break; - } - - layout.putConstraint(newComponentTopAlign, newComponent, topSpacing, previousTopAlign, - previousTopComponent); - layout.putConstraint(newComponentLeftAlign, newComponent, LEFT_ALIGNED, previousLeftAlign, - previousLeftComponent); - - // Add the label above the newComponent, then reorder the newComponent to be the next logical - // component - if (null != label && !label.isBlank() && !labelAdded) - { - Panels.addToPanel(targetPanel, new JLabel(label + ":"), null, Placement.TOP, targetSize); - targetPanel.setComponentZOrder(newComponent, targetPanel.getComponentZOrder(newComponent) + 1); - } - - if (null != targetSize) - { - if(newComponent instanceof JTextField) - ((JTextField) newComponent).setColumns(12); - else if(targetSize == Size.CUSTOM) - newComponent.setPreferredSize(targetSize.getDimension()); - } - - } else - { - // If it's the first component, align it against the targetPanel - targetPanel.add(newComponent); - - // Set constraints for newComponent when it's the first component - layout.putConstraint(SpringLayout.NORTH, newComponent, topSpacing * 2, SpringLayout.NORTH, targetPanel); - layout.putConstraint(SpringLayout.WEST, newComponent, leftSpacing * 2, SpringLayout.WEST, targetPanel); - - if (null != targetSize && newComponent instanceof JTextField) - ((JTextField) newComponent).setColumns(12); - } - } - - private static void addToBorderPanel (JPanel targetPanel, Component newComponent, String label, Placement alignment, - Size targetSize) - { - if (null != label && !label.isBlank()) - { - JPanel newPanelWithLabel = new JPanel(new BorderLayout()); - Panels.addToPanel(newPanelWithLabel, new JLabel(label + ":"), null, Placement.TOP, targetSize); - Panels.addToPanel(newPanelWithLabel, newComponent, null, Placement.BOTTOM, targetSize); - newComponent = newPanelWithLabel; - } - - switch (alignment) - { - case BOTTOM: - targetPanel.add(newComponent, BorderLayout.SOUTH); - break; - case TOP: - targetPanel.add(newComponent, BorderLayout.NORTH); - break; - default: - targetPanel.add(newComponent); - break; - } - - if (null != targetSize && newComponent instanceof JTextField) - ((JTextField) newComponent).setColumns(12); - - // layout.putConstraint(newComponentTopAlign, newComponent, topSpacing, previousTopAlign, - // previousTopComponent); - // layout.putConstraint(newComponentLeftAlign, newComponent, LEFT_ALIGNED, previousLeftAlign, - // previousLeftComponent); - } -} diff --git a/src/urChatBasic/frontend/utils/URPanels.java b/src/urChatBasic/frontend/utils/URPanels.java new file mode 100644 index 0000000..15f3a45 --- /dev/null +++ b/src/urChatBasic/frontend/utils/URPanels.java @@ -0,0 +1,394 @@ +package urChatBasic.frontend.utils; + +import java.awt.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.prefs.Preferences; +import java.util.stream.Collectors; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JSlider; +import javax.swing.JTextField; +import javax.swing.SpringLayout; +import urChatBasic.backend.utils.URPreferencesUtil; +import urChatBasic.backend.utils.URProfilesUtil; +import urChatBasic.base.Constants; +import urChatBasic.base.Constants.Placement; +import urChatBasic.base.Constants.Size; + +public class URPanels +{ + /** + * Used to keep track of keys associated with specific components + * JPanel, Component Hash Code, preferenceKey + */ + private static Map> keyComponentAssociations = new HashMap<>(); + + /** + * Used to keep track of newly created labels against components + */ + private static Map> componentLabelAssociations = new HashMap<>(); + + public static Component addToPanel (JPanel targetPanel, Component newComponent, String label, Placement alignment, + Size targetSize, String preferenceKey) + { + // TODO: add a visibility listener somehow for when a component is hidden, it's associated label is also hidden + + Class layoutClass = targetPanel.getLayout().getClass(); + + if (layoutClass == BorderLayout.class) + { + addToBorderPanel(targetPanel, newComponent, label, alignment, targetSize); + } else + { + if (targetPanel.getLayout().getClass() != SpringLayout.class) + targetPanel.setLayout(new SpringLayout()); + + addToSpringPanel(targetPanel, newComponent, label, alignment, targetSize); + } + + addKeyAssociation(targetPanel, newComponent, preferenceKey); + + return newComponent; + } + + public static void addKeyAssociation (JPanel targetPanel, Component targetComponent, String preferenceKey) + { + if(keyComponentAssociations.get(targetPanel) == null) + keyComponentAssociations.put(targetPanel, new HashMap<>()); + + if(preferenceKey != null && !preferenceKey.isBlank()) + keyComponentAssociations.get(targetPanel).put(targetComponent.hashCode(), preferenceKey); + } + + public static void addLabelAssociation (JPanel targetPanel, Component targetComponent, JLabel targetLabel) + { + if(componentLabelAssociations.get(targetPanel.toString()) == null) + componentLabelAssociations.put(targetPanel.toString(), new HashMap<>()); + + if(targetComponent != null && targetLabel != null) + componentLabelAssociations.get(targetPanel.toString()).put(targetComponent.hashCode(), targetLabel.hashCode()); + } + + /** + * Get component that is associated with a preference key. + * @param preferenceKey + * @return + */ + public static Object getKeyComponentValue (String preferenceKey) + { + for (JPanel jPanel : keyComponentAssociations.keySet()) + { + for (Entry keyComponents : keyComponentAssociations.get(jPanel).entrySet()) + { + if (keyComponents.getValue().equals(preferenceKey)) + { + for (Component panelComponent : jPanel.getComponents()) + { + if (panelComponent.hashCode() == keyComponents.getKey()) + { + if (panelComponent instanceof JCheckBox) + { + return ((JCheckBox) panelComponent).isSelected(); + } else if (panelComponent instanceof JTextField || panelComponent instanceof JPasswordField) + { + return ((JTextField) panelComponent).getText(); + } else if (panelComponent instanceof JSlider) + { + return ((JSlider) panelComponent).getValue(); + } else if (panelComponent instanceof JComboBox) + { + return ((JComboBox) panelComponent).getSelectedItem(); + } + } + } + } + } + } + + return null; + } + + /** + * Sets values on the interface components based on their associated Key and it's Default value. For the currently active Profile. + * @param targetPanel + */ + public static void getPreferences (JPanel targetPanel) + { + Preferences settingsPath = URProfilesUtil.getActiveProfilePath(); + + Map panelSettings = keyComponentAssociations.get(targetPanel); + Map panelComponents = Arrays.stream(targetPanel.getComponents()) + .collect(Collectors.toMap(Component::hashCode, component -> component, (v1, v2)-> v2)); + + if(panelSettings != null) + for (Integer componentHashcode : panelSettings.keySet()) + { + String componentKeyString = panelSettings.get(componentHashcode); + + + // No association, skip. + if(componentKeyString == null) + continue; + + Component targetComponent = panelComponents.get(componentHashcode); + + if(targetComponent instanceof JCheckBox) + { + ((JCheckBox) targetComponent).setSelected((boolean) URPreferencesUtil.getPref(componentKeyString, Constants.ConfigKeys.getDefault(componentKeyString), settingsPath)); + } else if(targetComponent instanceof JTextField || targetComponent instanceof JPasswordField) + { + ((JTextField) targetComponent).setText((String) URPreferencesUtil.getPref(componentKeyString, Constants.ConfigKeys.getDefault(componentKeyString), settingsPath)); + } else if(targetComponent instanceof JSlider) + { + ((JSlider) targetComponent).setValue((Integer) URPreferencesUtil.getPref(componentKeyString, Constants.ConfigKeys.getDefault(componentKeyString), settingsPath)); + } else if(targetComponent instanceof JComboBox) + { + ((JComboBox) targetComponent).setSelectedItem((String) URPreferencesUtil.getPref(componentKeyString, Constants.ConfigKeys.getDefault(componentKeyString), settingsPath)); + } else { + Constants.LOGGER.error("Getting values for component type [" + targetComponent.getClass().toString() + "] has not been configured!"); + } + } + } + + /** + * Saves the preferences to the settingsPath of the currently active profile. + * @param targetPanel + */ + public static void putPreferences (JPanel targetPanel) + { + Preferences settingsPath = URProfilesUtil.getActiveProfilePath(); + + Map panelSettings = keyComponentAssociations.get(targetPanel); + Map panelComponents = Arrays.stream(targetPanel.getComponents()) + .collect(Collectors.toMap(Component::hashCode, component -> component, (v1, v2)-> v2)); + + for (Integer componentHashcode : panelSettings.keySet()) + { + String componentKeyString = panelSettings.get(componentHashcode); + + // No association, skip. + if(componentKeyString == null) + continue; + + Component targetComponent = panelComponents.get(componentHashcode); + + if(targetComponent instanceof JCheckBox) + { + URPreferencesUtil.putPref(componentKeyString, ((JCheckBox) targetComponent).isSelected(), settingsPath); + } else if(targetComponent instanceof JTextField) + { + URPreferencesUtil.putPref(componentKeyString, ((JTextField) targetComponent).getText(), settingsPath); + } else if(targetComponent instanceof JSlider) + { + URPreferencesUtil.putPref(componentKeyString, ((JSlider) targetComponent).getValue(), settingsPath); + } else if(targetComponent instanceof JPasswordField) + { + String passwordString = ""; + passwordString = new String(((JPasswordField) targetComponent).getPassword()); + URPreferencesUtil.putPref(componentKeyString, passwordString, settingsPath); + } else if(targetComponent instanceof JComboBox) { + URPreferencesUtil.putPref(componentKeyString, ((JComboBox) targetComponent).getSelectedItem(), settingsPath); + } else { + Constants.LOGGER.error("Saving values for component type [" + targetComponent.getClass().toString() + "] has not been configured!"); + } + } + } + + private static void addToSpringPanel (JPanel targetPanel, Component newComponent, String label, Placement placement, + Size targetSize) + { + boolean labelAdded = false; + int topSpacing = 6; + int leftSpacing = 6; + final int TOP_ALIGNED = 0; + final int LEFT_ALIGNED = 0; + + // Only add it now if the label would be "next" in the components list + if (null != label && !label.isBlank() && placement == Placement.DEFAULT) + { + // Add the label, alignment should be the same, + JLabel newLabel = (JLabel) URPanels.addToPanel(targetPanel, new JLabel(label + ":"), null, Placement.DEFAULT, null, null); + + addLabelAssociation(targetPanel, newComponent, newLabel); + + // There is a label, so we want the added component to be aligned with the label + topSpacing = 0; + labelAdded = true; + } + + if (targetPanel.getLayout().getClass() != SpringLayout.class) + { + targetPanel.setLayout(new SpringLayout()); + } + + SpringLayout layout = (SpringLayout) targetPanel.getLayout(); + Component[] components = targetPanel.getComponents(); + + if (components.length > 0) + { + // Add newComponent to the targetPanel + targetPanel.add(newComponent); + + + // Used for Top Alignment + Component previousTopComponent = components[components.length - 1]; + + // Used for Left Alignment (default aligned with the previous component) + Component previousLeftComponent = previousTopComponent; + + // Default puts the curent component left aligned and below the previous component + String newComponentTopAlign = SpringLayout.NORTH; + String previousTopAlign = SpringLayout.SOUTH; + String newComponentLeftAlign = SpringLayout.WEST; + String previousLeftAlign = SpringLayout.WEST; + + // Set constraints for newComponent + switch (placement) + { + case RIGHT: + // attach the new component inline and to the right of the previous + topSpacing = 0; + newComponentTopAlign = SpringLayout.NORTH; + previousTopAlign = SpringLayout.NORTH; + newComponentLeftAlign = SpringLayout.WEST; + previousLeftAlign = SpringLayout.EAST; + break; + case TOP: + // attach the new component inline and to the right of the previous + topSpacing = 0; + newComponentTopAlign = SpringLayout.SOUTH; + previousTopAlign = SpringLayout.NORTH; + newComponentLeftAlign = SpringLayout.WEST; + previousLeftAlign = SpringLayout.WEST; + break; + default: + // Aligned with the first component + previousLeftComponent = components[0]; + newComponentTopAlign = SpringLayout.NORTH; + previousTopAlign = SpringLayout.SOUTH; + newComponentLeftAlign = SpringLayout.WEST; + previousLeftAlign = SpringLayout.WEST; + break; + } + + layout.putConstraint(newComponentTopAlign, newComponent, topSpacing, previousTopAlign, + previousTopComponent); + layout.putConstraint(newComponentLeftAlign, newComponent, LEFT_ALIGNED, previousLeftAlign, + previousLeftComponent); + + JLabel newLabel = null; + // Add the label above the newComponent, then reorder the newComponent to be the next logical + // component + if (label != null && !label.isBlank() && !labelAdded) + { + newLabel = (JLabel) URPanels.addToPanel(targetPanel, new JLabel(label + ":"), null, Placement.TOP, targetSize, null); + targetPanel.setComponentZOrder(newComponent, targetPanel.getComponentZOrder(newComponent) + 1); + + addLabelAssociation(targetPanel, newComponent, newLabel); + } + + // components = targetPanel.getComponents(); + + if (null != targetSize) + { + targetSize.setComponentSize(newComponent); + } + else if(newComponent instanceof JCheckBox && placement == Placement.RIGHT) + { + layout.putConstraint(SpringLayout.EAST, newComponent, 0, SpringLayout.EAST, newLabel); + layout.putConstraint(SpringLayout.SOUTH, newComponent, 0, SpringLayout.SOUTH, previousLeftComponent); + } + + } else + { + // If it's the first component, align it against the targetPanel + targetPanel.add(newComponent); + + // Set constraints for newComponent when it's the first component + layout.putConstraint(SpringLayout.NORTH, newComponent, topSpacing * 2, SpringLayout.NORTH, targetPanel); + layout.putConstraint(SpringLayout.WEST, newComponent, leftSpacing * 2, SpringLayout.WEST, targetPanel); + + if (null != targetSize) + targetSize.setComponentSize(newComponent); + } + } + + private static void addToBorderPanel (JPanel targetPanel, Component newComponent, String label, Placement placement, + Size targetSize) + { + if (null != label && !label.isBlank()) + { + JPanel newPanelWithLabel = new JPanel(new BorderLayout()); + JLabel newLabel = (JLabel) URPanels.addToPanel(newPanelWithLabel, new JLabel(label + ":"), null, Placement.TOP, targetSize, null); + + addLabelAssociation(targetPanel, newComponent, newLabel); + + URPanels.addToPanel(newPanelWithLabel, newComponent, null, Placement.BOTTOM, targetSize, null); + newComponent = newPanelWithLabel; + } + + switch (placement) + { + case BOTTOM: + targetPanel.add(newComponent, BorderLayout.SOUTH); + break; + case TOP: + targetPanel.add(newComponent, BorderLayout.NORTH); + break; + default: + targetPanel.add(newComponent); + break; + } + + if (null != targetSize) + targetSize.setComponentSize(newComponent); + + // layout.putConstraint(newComponentTopAlign, newComponent, topSpacing, previousTopAlign, + // previousTopComponent); + // layout.putConstraint(newComponentLeftAlign, newComponent, LEFT_ALIGNED, previousLeftAlign, + // previousLeftComponent); + } + + public static JLabel getLabelForComponent (JPanel targetPanel, Component targetComponent) + { + Component[] components = targetPanel.getComponents(); + + + // First check the component-label associations. + if(componentLabelAssociations.get(targetPanel.toString()) != null) + { + if(componentLabelAssociations.get(targetPanel.toString()).get(targetComponent.hashCode()) != null) + { + int labelHashCode = componentLabelAssociations.get(targetPanel.toString()).get(targetComponent.hashCode()); + + for (Component component : components) { + if(component.hashCode() == labelHashCode && component instanceof JLabel) + return (JLabel) component; + } + } + } + + + // otherwise, just iterate over the components and find the closest Jlabel + int componentIndex = -1; + + for (int i = 0; i < components.length; i++) { + if(components[i] == targetComponent) + componentIndex = i; + } + + for (int x = componentIndex; x <= 0; x--) { + if(components[x] instanceof JLabel) + return (JLabel) components[x]; + } + + return null; + } +} diff --git a/tests/backend/MessageHandlerTests.java b/tests/backend/MessageHandlerTests.java index 5ba3acc..f4f4014 100644 --- a/tests/backend/MessageHandlerTests.java +++ b/tests/backend/MessageHandlerTests.java @@ -19,11 +19,14 @@ import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.base.Constants; import urChatBasic.base.IRCRoomBase; +import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypes; import urChatBasic.frontend.DriverGUI; import urChatBasic.frontend.IRCPrivate; import urChatBasic.frontend.IRCServer; import urChatBasic.frontend.IRCUser; import urChatBasic.frontend.UserGUI; +import urChatBasic.frontend.panels.InterfacePanel; import utils.TestDriverGUI; @@ -45,7 +48,7 @@ public void setUp() throws Exception testDriver = new TestDriverGUI(); testGUI = DriverGUI.gui; testServer = new IRCServer("testServer", "testUser", "testUser", "testPassword", "1337", true, "testProxy", - "1234", true); + "1234", ProxyTypes.NONE.getType(), CapabilityTypes.NONE.getType()); testUser = new IRCUser(testServer, "testUser"); testServer.addToPrivateRooms(testUser); testPrivChannel = testServer.getCreatedPrivateRoom(testUser.toString()); @@ -139,8 +142,7 @@ public void sendActionMessageChannel() } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } Reporter.log("This test won't run unless the dependant method is included in the test and passed."); @@ -155,8 +157,7 @@ public void sendPrivateMessageMessageUser() testConnection.sendClientText(rawMessage, "otheruser"); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } @@ -170,8 +171,7 @@ public void sendActionMessageUser() testConnection.sendClientText(rawMessage, "otheruser"); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } @@ -218,15 +218,15 @@ public void testQuitServer() String rawMessage = "ERROR :\"Goodbye cruel world\""; Message testMessage = testHandler.new Message(rawMessage); - assertEquals(MessageHandler.DisconnectMessage.class, testMessage.getMessageBase().getClass()); + assertEquals(MessageHandler.DisconnectErrorMessage.class, testMessage.getMessageBase().getClass()); } @Test(groups = {"Test #005"}) public void testChannelLineLimit() throws BadLocationException, InterruptedException { - testGUI.setLimitChannelLines(10); - testGUI.setJoinsQuitsMain(false); - int channelLinesLimit = testGUI.getLimitChannelLinesCount(); + ((InterfacePanel) testGUI.interfacePanel).setLimitChannelLinesCount(10); + ((InterfacePanel) testGUI.interfacePanel).setJoinsQuitsMain(false); + int channelLinesLimit = ((InterfacePanel) testGUI.interfacePanel).getLimitChannelLinesCount(); String channelMessage = ":" + testUser + "!~" + testUser + "@urchatclient PRIVMSG "+PUB_CHANNEL_NAME+" :line # "; @@ -268,9 +268,9 @@ public void testChannelLineLimit() throws BadLocationException, InterruptedExcep @Test(groups = {"Test #005"}, description = "Test Description") public void testServerLineLimit() throws BadLocationException, InterruptedException { - testGUI.setLimitServerLines(10); - testGUI.setJoinsQuitsMain(false); - int serverLinesLimit = testGUI.getLimitServerLinesCount(); + ((InterfacePanel) testGUI.interfacePanel).setLimitServerLinesCount(10); + ((InterfacePanel) testGUI.interfacePanel).setJoinsQuitsMain(false); + int serverLinesLimit = ((InterfacePanel) testGUI.interfacePanel).getLimitServerLinesCount(); String serverMessage = ":" + testServer.getName() + " 001 " + testUser + " :line # "; diff --git a/tests/backend/ProfileTests.java b/tests/backend/ProfileTests.java index a438484..12c3d08 100644 --- a/tests/backend/ProfileTests.java +++ b/tests/backend/ProfileTests.java @@ -51,7 +51,8 @@ public void createdTestProfileTest () @Test public void deleteTestProfileTest () { - URProfilesUtil.createProfile(testDriver.getTestProfileName()); + if(!URProfilesUtil.profileExists(testDriver.getTestProfileName())) + URProfilesUtil.createProfile(testDriver.getTestProfileName()); URProfilesUtil.setActiveProfileName(testDriver.getTestProfileName()); assertTrue(URProfilesUtil.getActiveProfileName().equals(testDriver.getTestProfileName())); // Delete the active profile @@ -112,8 +113,7 @@ public void cloneProfileTest () throws BackingStoreException } } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Constants.LOGGER.warn(e.getLocalizedMessage(), e); } } diff --git a/tests/frontend/LineFormatterTests.java b/tests/frontend/LineFormatterTests.java index c33ef94..b28144c 100644 --- a/tests/frontend/LineFormatterTests.java +++ b/tests/frontend/LineFormatterTests.java @@ -6,6 +6,8 @@ import java.awt.event.MouseListener; import java.awt.geom.Rectangle2D; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -15,6 +17,8 @@ import urChatBasic.backend.MessageHandler.Message; import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.base.IRCRoomBase; +import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypes; import urChatBasic.frontend.DriverGUI; import urChatBasic.frontend.IRCServer; import urChatBasic.frontend.IRCUser; @@ -27,7 +31,7 @@ public class LineFormatterTests IRCServer testServer; TestDriverGUI testDriver; UserGUI testGUI; - IRCRoomBase testPrivChannel; + // IRCRoomBase testPrivChannel; final String PUB_CHANNEL_NAME = "#someChannel"; IRCRoomBase testPubChannel; IRCUser testUser; @@ -39,7 +43,7 @@ public void setUp () throws Exception testDriver = new TestDriverGUI(); TestDriverGUI.startTestGUI(DriverGUI.gui); testGUI = DriverGUI.gui; - testServer = new IRCServer("testServer", "testUser", "testUser", "testPassword", "1337", true, "testProxy", "1234", true); + testServer = new IRCServer("testServer", "testUser", "testUser", "testPassword", "1337", true, "testProxy", "1234", ProxyTypes.NONE.getType(), CapabilityTypes.NONE.getType()); testUser = new IRCUser(testServer, "testUser"); testServer.addToCreatedRooms(PUB_CHANNEL_NAME, false); testPubChannel = testServer.getCreatedChannel(PUB_CHANNEL_NAME); @@ -50,10 +54,7 @@ public void setUp () throws Exception @AfterClass(alwaysRun = true) public void tearDown () throws Exception { - // Reporter.log("Deleting testing profile.", true); testServer.quitRooms(); - // URProfilesUtil.getActiveProfilePath().sync(); - // URProfilesUtil.getActiveProfilePath().sync(); URProfilesUtil.deleteProfile(testDriver.getTestProfileName()); TestDriverGUI.closeWindow(); } @@ -72,12 +73,34 @@ public void rightClickOnNickTest () throws BadLocationException, InterruptedExce TimeUnit.SECONDS.sleep(1); } - testGUI.tabbedPane.setSelectedComponent(testPubChannel); + testGUI.tabbedPane.setSelectedIndex(1); assertEquals(" Welcome to somechannel!", testPubChannel.getLineFormatter().getLineAtPosition(9).split("] ")[1].trim()); testPubChannel.getChannelTextPane().setCaretPosition(9); // Right click on someuser - Rectangle2D coords = testPubChannel.getChannelTextPane().modelToView2D(testPubChannel.getChannelTextPane().getCaretPosition()); + final Rectangle2D[] coords = new Rectangle2D[1]; + AtomicBoolean canContinue = new AtomicBoolean(false); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + try + { + coords[0] = testPubChannel.getChannelTextPane().modelToView2D(testPubChannel.getChannelTextPane().getCaretPosition()); + canContinue.set(true); + } catch (BadLocationException e) + { + fail(); + } + } + }); + + + while(!canContinue.get()) + { + TimeUnit.SECONDS.sleep(1); + } // Right-Click mouse event at the x-y coords of the caret in the text pane MouseEvent event = new MouseEvent( @@ -85,8 +108,8 @@ public void rightClickOnNickTest () throws BadLocationException, InterruptedExce MouseEvent.BUTTON3, System.currentTimeMillis(), MouseEvent.BUTTON3_DOWN_MASK, - (int) coords.getX(), - (int) coords.getY(), + (int) coords[0].getX(), + (int) coords[0].getY(), 1, false ); diff --git a/tests/utils/TestDriverGUI.java b/tests/utils/TestDriverGUI.java index 481d213..328c50c 100644 --- a/tests/utils/TestDriverGUI.java +++ b/tests/utils/TestDriverGUI.java @@ -87,15 +87,13 @@ public static void startTestGUI(UserGUI gui) throws InterruptedException SwingUtilities.invokeLater(gui); - Constants.LOGGER.log(Level.INFO, "Started"); + Constants.LOGGER.info( "Started"); frame.setVisible(false); } public static void closeWindow() { - for (Handler tempHandler : Constants.LOGGER.getHandlers()) - tempHandler.close(); WindowEvent closingEvent = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING); Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent); // frame.dispose();