diff options
author | Yana Stamcheva <yana@jitsi.org> | 2008-07-11 07:26:28 +0000 |
---|---|---|
committer | Yana Stamcheva <yana@jitsi.org> | 2008-07-11 07:26:28 +0000 |
commit | 6fe16927f04d1e46880f44e0ba374d9ea6f038a5 (patch) | |
tree | 3086c4f37929376ed1a0b63bb5269553fc2b2e30 | |
parent | 11ecd5fae530e4df38ff00590fc0720beff54785 (diff) | |
download | jitsi-6fe16927f04d1e46880f44e0ba374d9ea6f038a5.zip jitsi-6fe16927f04d1e46880f44e0ba374d9ea6f038a5.tar.gz jitsi-6fe16927f04d1e46880f44e0ba374d9ea6f038a5.tar.bz2 |
Add formatting facilities in the gui and formatting support in ICQ, AIM.(Yahoo and SIP already support html content).
14 files changed, 638 insertions, 215 deletions
diff --git a/resources/images/impl/gui/buttons/textBold.png b/resources/images/impl/gui/buttons/textBold.png Binary files differindex 5817c1b..0530dfb 100644 --- a/resources/images/impl/gui/buttons/textBold.png +++ b/resources/images/impl/gui/buttons/textBold.png diff --git a/resources/images/impl/gui/buttons/textItalic.png b/resources/images/impl/gui/buttons/textItalic.png Binary files differindex 5c2c0d1..a2b082a 100644 --- a/resources/images/impl/gui/buttons/textItalic.png +++ b/resources/images/impl/gui/buttons/textItalic.png diff --git a/resources/images/impl/gui/buttons/textUnderlined.png b/resources/images/impl/gui/buttons/textUnderlined.png Binary files differindex 87acdae..f3171d6 100644 --- a/resources/images/impl/gui/buttons/textUnderlined.png +++ b/resources/images/impl/gui/buttons/textUnderlined.png diff --git a/resources/styles/defaultStyle.css b/resources/styles/defaultStyle.css index a9326a6..752d765 100644 --- a/resources/styles/defaultStyle.css +++ b/resources/styles/defaultStyle.css @@ -65,7 +65,7 @@ font-size:12; color:#000000 } -i +h7 { background-color:#FFF4AB }
\ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java index 91002fb..9f4ee5a 100755 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java @@ -569,7 +569,7 @@ public class ChatConversationPanel String matchGroup = m.group().trim(); - String replacement = endPlainTextTag + "<I>" + matchGroup + "</I>" + String replacement = endPlainTextTag + "<h7>" + matchGroup + "</h7>" + startPlainTextTag; m.appendReplacement(msgBuffer, GuiUtils diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java index a0d4f70..66d207b 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java @@ -50,13 +50,13 @@ public abstract class ChatPanel private JSplitPane messagePane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); - private ChatConversationPanel conversationPanel; + protected ChatConversationPanel conversationPanel; - private ChatWritePanel writeMessagePanel; + protected ChatWritePanel writeMessagePanel; - private ChatContactListPanel chatContactListPanel; + protected ChatContactListPanel chatContactListPanel; - private ChatSendPanel sendPanel; + protected ChatSendPanel sendPanel; private ChatWindow chatWindow; @@ -185,7 +185,7 @@ public abstract class ChatPanel * * @param text the text to send */ - protected abstract void sendMessage(String text); + protected abstract void sendMessage(); /** * This method should be implemented in case additional treatment is needed @@ -405,11 +405,21 @@ public abstract class ChatPanel { JEditorPane editorPane = getChatWritePanel().getEditorPane(); - if (editorPane.getText() == null - || editorPane.getText().equals("")) - return true; - else - return false; + Document doc = editorPane.getDocument(); + + try + { + String text = doc.getText(0, doc.getLength()); + + if (text == null || text.equals("")) + return true; + } + catch (BadLocationException e) + { + logger.error("Failed to obtain document text.", e); + } + + return false; } /** @@ -548,10 +558,9 @@ public abstract class ChatPanel * Refreshes write area editor pane. Deletes all existing text * content. */ - public void refreshWriteArea(){ - JEditorPane writeMsgPane = this.writeMessagePanel.getEditorPane(); - - writeMsgPane.setText(""); + public void refreshWriteArea() + { + this.writeMessagePanel.clearWriteArea(); } /** @@ -569,10 +578,17 @@ public abstract class ChatPanel * Returns the text contained in the write area editor. * @return The text contained in the write area editor. */ - public String getTextFromWriteArea(){ - JEditorPane editorPane = this.writeMessagePanel.getEditorPane(); - - return editorPane.getText(); + public String getTextFromWriteArea(String mimeType) + { + if (mimeType.equals( + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE)) + { + return writeMessagePanel.getText(); + } + else + { + return writeMessagePanel.getTextAsHtml(); + } } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java index 91d230f..366b7f3 100755 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java @@ -73,20 +73,14 @@ public class ChatSendPanel { if (!chatPanel.isWriteAreaEmpty()) { - final String text = chatPanel.getTextFromWriteArea(); - - chatPanel.refreshWriteArea(); - new Thread() { public void run() { - chatPanel.sendMessage(text); + chatPanel.sendMessage(); } }.start(); } - //make sure the focus goes back to the write area - chatPanel.requestFocusInWriteArea(); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java index e9e9475..dfcf116 100755 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java @@ -1,8 +1,7 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.gui.main.chat; @@ -13,28 +12,31 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; +import javax.swing.text.html.*; import javax.swing.undo.*; import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.i18n.*; import net.java.sip.communicator.impl.gui.lookandfeel.*; import net.java.sip.communicator.impl.gui.main.chat.menus.*; +import net.java.sip.communicator.impl.gui.main.chat.toolBars.*; import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; + /** * The <tt>ChatWritePanel</tt> is the panel, where user writes her messages. - * It is located at the bottom of the split in the <tt>ChatPanel</tt> and - * it contains an editor, where user writes the text. + * It is located at the bottom of the split in the <tt>ChatPanel</tt> and it + * contains an editor, where user writes the text. * * @author Yana Stamcheva */ public class ChatWritePanel - extends JScrollPane + extends JPanel implements UndoableEditListener, KeyListener, - MouseListener + MouseListener { private Logger logger = Logger.getLogger(ChatWritePanel.class); @@ -44,58 +46,72 @@ public class ChatWritePanel private ChatPanel chatPanel; - private Timer stoppedTypingTimer = new Timer(2 * 1000, - new Timer1ActionListener()); + private Timer stoppedTypingTimer = + new Timer(2 * 1000, new Timer1ActionListener()); private Timer typingTimer = new Timer(5 * 1000, new Timer2ActionListener()); private int typingState = -1; - private StyledEditorKit styledEditor = new StyledEditorKit(); - + private HTMLEditorKit htmlEditor = new HTMLEditorKit(); + private WritePanelRightButtonMenu rightButtonMenu; + + private EditTextToolBar editTextToolBar; + private JScrollPane scrollPane = new JScrollPane(); + + /** * Creates an instance of <tt>ChatWritePanel</tt>. + * * @param panel The parent <tt>ChatPanel</tt>. */ - public ChatWritePanel(ChatPanel panel) { + public ChatWritePanel(ChatPanel panel) + { - super(); + super(new BorderLayout()); this.chatPanel = panel; - - this.rightButtonMenu - = new WritePanelRightButtonMenu(chatPanel.getChatWindow()); - this.setHorizontalScrollBarPolicy( - JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + this.editTextToolBar = new EditTextToolBar(editorPane); + + this.add(editTextToolBar, BorderLayout.NORTH); + this.add(scrollPane, BorderLayout.CENTER); + + this.rightButtonMenu = + new WritePanelRightButtonMenu(chatPanel.getChatWindow()); + + this.scrollPane + .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + this.editorPane.setContentType("text/html"); this.editorPane.setFont(Constants.FONT); - - this.editorPane.setEditorKit(styledEditor); + this.editorPane.setCaretPosition(0); + this.editorPane.setEditorKit(htmlEditor); this.editorPane.getDocument().addUndoableEditListener(this); this.editorPane.addKeyListener(this); this.editorPane.addMouseListener(this); - - this.getViewport().add(editorPane, BorderLayout.CENTER); - this.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createEmptyBorder(3, 3, 3, 3), + this.scrollPane.getViewport().add(editorPane, BorderLayout.CENTER); + + this.scrollPane.setBorder(BorderFactory + .createCompoundBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3), SIPCommBorders.getBoldRoundBorder())); - - this.getVerticalScrollBar().setUnitIncrement(30); + + this.scrollPane.getVerticalScrollBar().setUnitIncrement(30); this.typingTimer.setRepeats(true); - - //initialize send command to Ctrl+Enter - ConfigurationService configService - = GuiActivator.getConfigurationService(); - - String messageCommand = configService.getString( - "net.java.sip.communicator.impl.gui.sendMessageCommand"); - - if(messageCommand == null || messageCommand.equalsIgnoreCase("enter")) + + // initialize send command to Ctrl+Enter + ConfigurationService configService = + GuiActivator.getConfigurationService(); + + String messageCommand = + configService + .getString("net.java.sip.communicator.impl.gui.sendMessageCommand"); + + if (messageCommand == null || messageCommand.equalsIgnoreCase("enter")) this.changeSendCommand(true); else this.changeSendCommand(false); @@ -103,48 +119,51 @@ public class ChatWritePanel /** * Returns the editor panel, contained in this <tt>ChatWritePanel</tt>. + * * @return The editor panel, contained in this <tt>ChatWritePanel</tt>. */ - public JEditorPane getEditorPane() { + public JEditorPane getEditorPane() + { return editorPane; } /** * Replaces the Ctrl+Enter send command with simple Enter. */ - public void changeSendCommand(boolean isEnter) + public void changeSendCommand(boolean isEnter) { this.editorPane.getActionMap().put("send", new SendMessageAction()); this.editorPane.getActionMap().put("newLine", new NewLineAction()); - + InputMap im = this.editorPane.getInputMap(); - - if(isEnter) { + + if (isEnter) + { im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "send"); - im.put(KeyStroke.getKeyStroke( - KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "newLine"); - im.put(KeyStroke.getKeyStroke( - KeyEvent.VK_ENTER, KeyEvent.SHIFT_DOWN_MASK), "newLine"); - - chatPanel.getChatSendPanel().getSendButton() - .setToolTipText("<html>" - + Messages.getI18NString("sendMessage").getText() - + " - Enter <br> " - + "Use Ctrl-Enter or Shift-Enter to make a new line" - + "</html>"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + KeyEvent.CTRL_DOWN_MASK), "newLine"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + KeyEvent.SHIFT_DOWN_MASK), "newLine"); + + chatPanel.getChatSendPanel().getSendButton().setToolTipText( + "<html>" + Messages.getI18NString("sendMessage").getText() + + " - Enter <br> " + + "Use Ctrl-Enter or Shift-Enter to make a new line" + + "</html>"); } - else { - im.put(KeyStroke.getKeyStroke( - KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "send"); - im.put(KeyStroke.getKeyStroke( - KeyEvent.VK_ENTER, 0), "newLine"); - + else + { + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + KeyEvent.CTRL_DOWN_MASK), "send"); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "newLine"); + chatPanel.getChatSendPanel().getSendButton() - .setToolTipText(Messages.getI18NString("sendMessage").getText() - + " Ctrl-Enter"); + .setToolTipText( + Messages.getI18NString("sendMessage").getText() + + " Ctrl-Enter"); } } - + /** * The <tt>SendMessageAction</tt> is an <tt>AbstractAction</tt> that * sends the text that is currently in the write message area. @@ -153,15 +172,15 @@ public class ChatWritePanel extends AbstractAction { public void actionPerformed(ActionEvent e) - { + { // chatPanel.stopTypingNotifications(); chatPanel.sendButtonDoClick(); } } - + /** - * The <tt>NewLineAction</tt> is an <tt>AbstractAction</tt> that - * types an enter in the write message area. + * The <tt>NewLineAction</tt> is an <tt>AbstractAction</tt> that types + * an enter in the write message area. */ private class NewLineAction extends AbstractAction @@ -169,32 +188,43 @@ public class ChatWritePanel public void actionPerformed(ActionEvent e) { int caretPosition = editorPane.getCaretPosition(); - String editorText = editorPane.getText(); - - editorPane.setText(editorText.substring(0, caretPosition) - + "\n" - + editorText.substring(caretPosition)); - + HTMLDocument doc = (HTMLDocument) editorPane.getDocument(); + + try + { + doc.insertString(caretPosition, "\n", null); + } + catch (BadLocationException e1) + { + logger.error("Could not insert <br> to the document.", e1); + } + editorPane.setCaretPosition(caretPosition + 1); } } - + /** - * Handles the <tt>UndoableEditEvent</tt>, by adding the content edit - * to the <tt>UndoManager</tt>. + * Handles the <tt>UndoableEditEvent</tt>, by adding the content edit to + * the <tt>UndoManager</tt>. + * * @param e The <tt>UndoableEditEvent</tt>. */ - public void undoableEditHappened(UndoableEditEvent e) { + public void undoableEditHappened(UndoableEditEvent e) + { this.undo.addEdit(e.getEdit()); } /** * Implements the undo operation. */ - private void undo() { - try { + private void undo() + { + try + { undo.undo(); - } catch (CannotUndoException e) { + } + catch (CannotUndoException e) + { logger.error("Unable to undo.", e); } } @@ -202,15 +232,20 @@ public class ChatWritePanel /** * Implements the redo operation. */ - private void redo() { - try { + private void redo() + { + try + { undo.redo(); - } catch (CannotRedoException e) { + } + catch (CannotRedoException e) + { logger.error("Unable to redo.", e); } } - public void keyTyped(KeyEvent e) { + public void keyTyped(KeyEvent e) + { } /** @@ -221,30 +256,30 @@ public class ChatWritePanel * Sends typing notifications when user types. */ public void keyPressed(KeyEvent e) - { + { if ((e.getModifiers() & KeyEvent.CTRL_MASK) == KeyEvent.CTRL_MASK - && (e.getKeyCode() == KeyEvent.VK_Z)) + && (e.getKeyCode() == KeyEvent.VK_Z)) { if (undo.canUndo()) undo(); } else if ((e.getModifiers() & KeyEvent.CTRL_MASK) == KeyEvent.CTRL_MASK - && (e.getKeyCode() == KeyEvent.VK_R)) + && (e.getKeyCode() == KeyEvent.VK_R)) { if (undo.canRedo()) redo(); } else if (ConfigurationManager.isSendTypingNotifications() - && e.getKeyCode() != KeyEvent.VK_ESCAPE) - { + && e.getKeyCode() != KeyEvent.VK_ESCAPE) + { if (typingState != OperationSetTypingNotifications.STATE_TYPING) - { - stoppedTypingTimer.setDelay(2 * 1000); + { + stoppedTypingTimer.setDelay(2 * 1000); typingState = OperationSetTypingNotifications.STATE_TYPING; int result = chatPanel.sendTypingNotification(typingState); - - if(result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) + + if (result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) typingTimer.start(); } @@ -256,25 +291,27 @@ public class ChatWritePanel } public void keyReleased(KeyEvent e) - {} + { + } /** * Listens for <code>stoppedTypingTimer</tt> events. */ - private class Timer1ActionListener implements ActionListener + private class Timer1ActionListener + implements ActionListener { public void actionPerformed(ActionEvent e) - { + { typingTimer.stop(); if (typingState == OperationSetTypingNotifications.STATE_TYPING) { try { typingState = OperationSetTypingNotifications.STATE_PAUSED; - + int result = chatPanel.sendTypingNotification(typingState); - - if(result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) + + if (result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) stoppedTypingTimer.setDelay(3 * 1000); } catch (Exception ex) @@ -282,8 +319,7 @@ public class ChatWritePanel logger.error("Failed to send typing notifications.", ex); } } - else if (typingState - == OperationSetTypingNotifications.STATE_PAUSED) + else if (typingState == OperationSetTypingNotifications.STATE_PAUSED) { stopTypingTimer(); } @@ -293,14 +329,15 @@ public class ChatWritePanel /** * Listens for <code>typingTimer</tt> events. */ - private class Timer2ActionListener implements ActionListener + private class Timer2ActionListener + implements ActionListener { public void actionPerformed(ActionEvent e) { if (typingState == OperationSetTypingNotifications.STATE_TYPING) - { - chatPanel.sendTypingNotification( - OperationSetTypingNotifications.STATE_TYPING); + { + chatPanel + .sendTypingNotification(OperationSetTypingNotifications.STATE_TYPING); } } } @@ -311,10 +348,10 @@ public class ChatWritePanel public void stopTypingTimer() { typingState = OperationSetTypingNotifications.STATE_STOPPED; - + int result = chatPanel.sendTypingNotification(typingState); - - if(result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) + + if (result == ChatPanel.TYPING_NOTIFICATION_SUCCESSFULLY_SENT) stoppedTypingTimer.stop(); } @@ -322,38 +359,126 @@ public class ChatWritePanel * Opens the <tt>WritePanelRightButtonMenu</tt> whe user clicks with the * right mouse button on the editor area. */ - public void mouseClicked(MouseEvent e) { + public void mouseClicked(MouseEvent e) + { if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0 - || (e.isControlDown() && !e.isMetaDown())) { + || (e.isControlDown() && !e.isMetaDown())) + { Point p = e.getPoint(); SwingUtilities.convertPointToScreen(p, e.getComponent()); - + rightButtonMenu.setInvoker(editorPane); rightButtonMenu.setLocation(p.x, p.y); rightButtonMenu.setVisible(true); } } - public void mousePressed(MouseEvent e) { + public void mousePressed(MouseEvent e) + { } - public void mouseReleased(MouseEvent e) { + public void mouseReleased(MouseEvent e) + { } - public void mouseEntered(MouseEvent e) { + public void mouseEntered(MouseEvent e) + { } - public void mouseExited(MouseEvent e) { + public void mouseExited(MouseEvent e) + { } /** * Returns the <tt>WritePanelRightButtonMenu</tt> opened in this panel. - * Used by the <tt>ChatWindow</tt>, when the ESC button is pressed, to check - * if there is an open menu, which should be closed. + * Used by the <tt>ChatWindow</tt>, when the ESC button is pressed, to + * check if there is an open menu, which should be closed. + * * @return the <tt>WritePanelRightButtonMenu</tt> opened in this panel */ public WritePanelRightButtonMenu getRightButtonMenu() { return rightButtonMenu; - } + } + + /** + * Returns the write area text as an html text. + * + * @return the write area text as an html text. + */ + public String getTextAsHtml() + { + String msgText = editorPane.getText(); + + String formattedString = extractFormattedText(msgText); + + return formattedString + .substring(0, formattedString.lastIndexOf("\n")); + } + + /** + * Returns the write area text as a plain text without any formatting. + * + * @return the write area text as a plain text without any formatting. + */ + public String getText() + { + try + { + Document doc = editorPane.getDocument(); + + return doc.getText(0, doc.getLength()); + } + catch (BadLocationException e) + { + logger.error("Could not obtain write area text.", e); + } + + return null; + } + + + /** + * Clears write message area. + */ + public void clearWriteArea() + { + try + { + this.editorPane.getDocument() + .remove(0, editorPane.getDocument().getLength()); + } + catch (BadLocationException e) + { + logger.error("Failed to obtain write panel document content.", e); + } + } + + /** + * Return all html paragraph content separated by <BR/> tags. + * + * @param msgText the html text. + * @return the string containing only paragraph content. + */ + private String extractFormattedText(String msgText) + { + int firstIndex = msgText.indexOf("<p"); + + if (firstIndex != -1) + { + int lastIndex = msgText.indexOf("</p>", firstIndex); + + if (lastIndex < 0) + lastIndex = msgText.length(); + + int firstTagClosureIndex = msgText.indexOf('>', firstIndex); + String pString = msgText + .substring(firstTagClosureIndex+1, lastIndex).trim(); + + return pString + "\n" + + extractFormattedText(msgText.substring(lastIndex+1)); + } + + return ""; + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/MenusPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/MenusPanel.java index 600f69d..e2ea81e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/MenusPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/MenusPanel.java @@ -26,8 +26,6 @@ public class MenusPanel { private MessageWindowMenuBar menuBar; - private EditTextToolBar editTextToolBar = new EditTextToolBar(); - private MainToolBar mainToolBar; private ChatWindow parentWindow; @@ -58,7 +56,6 @@ public class MenusPanel parentWindow.setJMenuBar(menuBar); this.add(mainToolBar, BorderLayout.CENTER); - // this.add(editTextToolBar); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatPanel.java index 95206cf..41624a4 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatPanel.java @@ -375,16 +375,19 @@ public class MetaContactChatPanel * appropriate operation set and sends the message, contained in the write * area, through it. */ - protected void sendMessage(String text) + protected void sendMessage() { if (sendSmsCheckBox.isSelected()) { - this.sendSmsMessage(text); + this.sendSmsMessage(); return; } - this.sendInstantMessage(text); + this.sendInstantMessage(); + + //make sure the focus goes back to the write area + this.requestFocusInWriteArea(); } /** @@ -456,7 +459,7 @@ public class MetaContactChatPanel } if (evt.getNewParent().equals(metaContact)) - { + { contactSelectorBox.addProtoContact(evt.getProtoContact()); } } @@ -765,8 +768,13 @@ public class MetaContactChatPanel { } - private void sendSmsMessage(String text) + private void sendSmsMessage() { + final String text = this.getTextFromWriteArea( + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + + this.refreshWriteArea(); + OperationSetSmsMessaging smsOpSet = null; /* Contact contact = null; @@ -888,7 +896,7 @@ public class MetaContactChatPanel smsDialog.setVisible(true); } - private void sendInstantMessage(String text) + private void sendInstantMessage() { Contact contact = (Contact) contactSelectorBox.getMenu() .getSelectedObject(); @@ -901,7 +909,27 @@ public class MetaContactChatPanel = (OperationSetTypingNotifications) contact.getProtocolProvider() .getOperationSet(OperationSetTypingNotifications.class); - Message msg = im.createMessage(text); + String htmlText = getTextFromWriteArea("text/html"); + String plainText = getTextFromWriteArea( + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + + System.out.println("HTML==========" + htmlText); + System.out.println("HTML==========" + plainText); + Message msg; + if (im.isContentTypeSupported("text/html") + && !htmlText.equals(plainText)) + { + msg = im.createMessage( htmlText.getBytes(), + "text/html", + "utf-8", + ""); + } + else + { + msg = im.createMessage(plainText); + } + + this.refreshWriteArea(); if (tn != null) { @@ -1066,4 +1094,19 @@ public class MetaContactChatPanel public void messageReceived(MessageReceivedEvent evt) {} } + + /** + * Returns the selected protocol contact. + * + * @return the selected protocol contact + */ + public Contact getSelectedProtocolContact() + { + return contactSelectorBox.getSelectedProtocolContact(); + } + + public ProtocolContactSelectorBox getProtocolContactSelectorBox() + { + return contactSelectorBox; + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatPanel.java index 25a141b..6fda8b3 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatPanel.java @@ -282,29 +282,31 @@ public class ConferenceChatPanel * <br> * Sends a message to the chat room. */ - protected void sendMessage(String text) + protected void sendMessage() { ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - Message msg = chatRoom.createMessage(text); - + + String msgText = this.getTextFromWriteArea( + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + Message msg = chatRoom.createMessage(msgText); + try - { + { chatRoom.sendMessage(msg); } catch (IllegalStateException ex) { logger.error("Failed to send message.", ex); - + this.refreshWriteArea(); - + this.processMessage( chatRoom.getName(), new Date(System.currentTimeMillis()), Constants.OUTGOING_MESSAGE, msg.getContent(), msg.getContentType()); - + this.processMessage( chatRoom.getName(), new Date(System.currentTimeMillis()), @@ -315,16 +317,16 @@ public class ConferenceChatPanel catch (Exception ex) { logger.error("Failed to send message.", ex); - + this.refreshWriteArea(); - + this.processMessage( chatRoom.getName(), new Date(System.currentTimeMillis()), Constants.OUTGOING_MESSAGE, msg.getContent(), msg.getContentType()); - + this.processMessage( chatRoom.getName(), new Date(System.currentTimeMillis()), diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/EditTextToolBar.java b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/EditTextToolBar.java index d8af76d..c2cb768 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/EditTextToolBar.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/EditTextToolBar.java @@ -1,61 +1,69 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.gui.main.chat.toolBars; import java.awt.*; +import java.awt.event.*; +import java.util.*; + import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.text.html.*; import net.java.sip.communicator.impl.gui.customcontrols.*; +import net.java.sip.communicator.impl.gui.main.chat.*; import net.java.sip.communicator.impl.gui.utils.*; /** - * The <tt>EditTextToolBar</tt> is a <tt>JToolBar</tt> which contains buttons - * for formatting a text, like make text in bold or italic, change the font, - * etc. It contains only <tt>MsgToolbarButton</tt>s, which have a specific - * background icon and rollover behaviour to differentiates them from normal - * buttons. - * + * The <tt>EditTextToolBar</tt> is a <tt>JToolBar</tt> which contains + * buttons for formatting a text, like make text in bold or italic, change the + * font, etc. It contains only <tt>MsgToolbarButton</tt>s, which have a + * specific background icon and rollover behaviour to differentiates them from + * normal buttons. + * * @author Yana Stamcheva */ -public class EditTextToolBar extends SIPCommToolBar { - - private SIPCommButton textBoldButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.TEXT_BOLD_BUTTON), ImageLoader - .getImage(ImageLoader.TEXT_BOLD_ROLLOVER_BUTTON)); +public class EditTextToolBar + extends SIPCommToolBar +{ + private JLabel colorLabel = new JLabel(); - private SIPCommButton textItalicButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.TEXT_ITALIC_BUTTON), ImageLoader - .getImage(ImageLoader.TEXT_ITALIC_ROLLOVER_BUTTON)); + private String[] fontSizeConstants = + new String[] + { "9", "10", "11", "12", "13", "14", "18", "24", "36", "48", "64", + "72", "96", "144", "288" }; - private SIPCommButton textUnderlinedButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.TEXT_UNDERLINED_BUTTON), ImageLoader - .getImage(ImageLoader.TEXT_UNDERLINED_ROLLOVER_BUTTON)); + private JComboBox fontSizeCombo = new JComboBox(fontSizeConstants); - private SIPCommButton alignLeftButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.ALIGN_LEFT_BUTTON), ImageLoader - .getImage(ImageLoader.ALIGN_LEFT_ROLLOVER_BUTTON)); + private JComboBox fontNameCombo; - private SIPCommButton alignRightButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.ALIGN_RIGHT_BUTTON), ImageLoader - .getImage(ImageLoader.ALIGN_RIGHT_ROLLOVER_BUTTON)); + private JEditorPane chatEditorPane; - private SIPCommButton alignCenterButton = new SIPCommButton(ImageLoader - .getImage(ImageLoader.ALIGN_CENTER_BUTTON), ImageLoader - .getImage(ImageLoader.ALIGN_CENTER_ROLLOVER_BUTTON)); + Action boldAction = new HTMLEditorKit.BoldAction(); - private JComboBox fontSizeCombo = new JComboBox(); + Action italicAction = new HTMLEditorKit.ItalicAction(); - private JComboBox fontNameCombo = new JComboBox(); + Action underlineAction = new HTMLEditorKit.UnderlineAction(); /** * Creates an instance and constructs the <tt>EditTextToolBar</tt>. */ - public EditTextToolBar() { + public EditTextToolBar(JEditorPane panel) + { + this.chatEditorPane = panel; + + this.fontNameCombo = new JComboBox(getSystemFontFamilies()); + this.fontSizeCombo.setEditable(true); + + fontNameCombo.setSelectedItem(ApplicationProperties + .getProperty("fontName")); + fontSizeCombo.setSelectedItem(ApplicationProperties + .getProperty("fontSize")); this.setRollover(true); this.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0)); @@ -63,9 +71,9 @@ public class EditTextToolBar extends SIPCommToolBar { this.fontSizeCombo.setPreferredSize(new Dimension(55, 21)); - this.add(textBoldButton); - this.add(textItalicButton); - this.add(textUnderlinedButton); + colorLabel.setPreferredSize(new Dimension(25, 25)); + + this.initToolbarButtons(); this.addSeparator(); @@ -74,8 +82,224 @@ public class EditTextToolBar extends SIPCommToolBar { this.addSeparator(); - this.add(alignLeftButton); - this.add(alignCenterButton); - this.add(alignRightButton); + this.add(colorLabel); + + fontNameCombo.addItemListener(new ItemListener() + { + public void itemStateChanged(ItemEvent evt) + { + String fontName = (String) evt.getItem(); + + ActionEvent actionEvent = + new ActionEvent(chatEditorPane, + ActionEvent.ACTION_PERFORMED, ""); + + Action action = + new HTMLEditorKit.FontFamilyAction(fontName, fontName); + + action.actionPerformed(actionEvent); + + chatEditorPane.requestFocus(); + } + }); + + fontSizeCombo.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + ActionEvent evt = + new ActionEvent(chatEditorPane, + ActionEvent.ACTION_PERFORMED, ""); + + String fontSizeString = + (String) fontSizeCombo.getSelectedItem(); + + Action action = + new HTMLEditorKit.FontSizeAction(fontSizeString, + new Integer(fontSizeString).intValue()); + + action.actionPerformed(evt); + + chatEditorPane.requestFocus(); + } + }); + + colorLabel.setOpaque(true); + colorLabel.setBackground(Color.BLACK); + colorLabel.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent arg0) + { + Color newColor = + JColorChooser.showDialog(new JColorChooser(), + "Choose a colour", colorLabel.getBackground()); + + colorLabel.setBackground(newColor); + + ActionEvent evt = + new ActionEvent(chatEditorPane, + ActionEvent.ACTION_PERFORMED, ""); + + Action action = + new HTMLEditorKit.ForegroundAction(new Integer(newColor + .getRGB()).toString(), newColor); + + action.actionPerformed(evt); + + chatEditorPane.requestFocus(); + } + }); + } + + private void initToolbarButtons() + { + JToggleButton boldButton = + initStyleToggleButton(boldAction, StyleConstants.Bold); + + boldButton.setIcon(new ImageIcon(ImageLoader + .getImage(ImageLoader.TEXT_BOLD_BUTTON))); + + this.add(boldButton); + + JToggleButton italicButton = + initStyleToggleButton(italicAction, StyleConstants.Italic); + + italicButton.setIcon(new ImageIcon(ImageLoader + .getImage(ImageLoader.TEXT_ITALIC_BUTTON))); + + this.add(italicButton); + + JToggleButton underlineButton = + initStyleToggleButton(underlineAction, StyleConstants.Underline); + + underlineButton.setIcon(new ImageIcon(ImageLoader + .getImage(ImageLoader.TEXT_UNDERLINED_BUTTON))); + + this.add(underlineButton); + + this.addBindings(); + } + + private JToggleButton initStyleToggleButton(final Action action, + final Object styleConstant) + { + final JToggleButton button = new JToggleButton(); + button.setPreferredSize(new Dimension(25, 25)); + + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + action.actionPerformed(e); + } + }); + + chatEditorPane.addCaretListener(new CaretListener() + { + public void caretUpdate(CaretEvent e) + { + selectButton(styleConstant, button); + } + }); + + chatEditorPane.addKeyListener(new KeyAdapter() + { + public void keyTyped(KeyEvent e) + { + button.setSelected(((HTMLEditorKit) chatEditorPane + .getEditorKit()).getInputAttributes().containsAttribute( + styleConstant, true)); + } + }); + chatEditorPane.addMouseListener(new MouseAdapter() + { + public void mouseClicked(MouseEvent e) + { + selectButton(styleConstant, button); + } + }); + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + chatEditorPane.requestFocus(); + } + }); + + return button; + } + + /** + * Selects or deselects the given toggle button depending on the given + * <tt>styleConstant</tt>. + * + * @param styleConstant + * @param button + */ + private void selectButton( final Object styleConstant, + final JToggleButton button) + + { + boolean selected = false; + + if (chatEditorPane.getSelectedText() == null) + { + int index = chatEditorPane.getCaretPosition(); + selected = + ((HTMLDocument) chatEditorPane.getDocument()) + .getCharacterElement(index - 1).getAttributes() + .containsAttribute(styleConstant, true); + } + else + { + for (int index = chatEditorPane.getSelectionStart(); + index < chatEditorPane.getSelectionEnd(); index++) + { + AttributeSet attributes = + ((HTMLDocument) chatEditorPane.getDocument()) + .getCharacterElement(index).getAttributes(); + + selected = + selected + || attributes.containsAttribute(styleConstant, true); + } + } + button.setSelected(selected); + } + + /** + * Adds key bindings for formatting actions. + */ + private void addBindings() + { + InputMap inputMap = chatEditorPane.getInputMap(); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, + Event.SHIFT_MASK), DefaultEditorKit.deletePrevCharAction); + + // styles + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_B, Event.CTRL_MASK), + "font-bold"); //$NON-NLS-1$ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Event.CTRL_MASK), + "font-bold"); //$NON-NLS-1$ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_I, Event.CTRL_MASK), + "font-italic"); //$NON-NLS-1$ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_K, Event.CTRL_MASK), + "font-italic"); //$NON-NLS-1$ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_U, Event.CTRL_MASK), + "font-underline"); //$NON-NLS-1$ + } + + /** + * Returns all supported local system font names. + * + * @return an array containing all supported local system font names. + */ + private String[] getSystemFontFamilies() + { + // Get all font family names + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + + return ge.getAvailableFontFamilyNames(); } } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPanel.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPanel.java index 047332f..4ba0da4 100755 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPanel.java @@ -403,7 +403,8 @@ public class ContactListPanel .getDestinationContact().getProtocolProvider(); logger.trace("MESSAGE DELIVERED: process message to chat for contact: " - + evt.getDestinationContact().getAddress()); + + evt.getDestinationContact().getAddress() + + " MESSAGE: " + msg.getContent()); chatPanel.processMessage(this.mainFrame .getAccount(protocolProvider), evt.getTimestamp(), diff --git a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java index d56fd74..494cf10 100644 --- a/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/icq/OperationSetBasicInstantMessagingIcqImpl.java @@ -100,6 +100,10 @@ public class OperationSetBasicInstantMessagingIcqImpl */ private final static long KEEPALIVE_WAIT = 20000l; //20 secs + private final String defaultHtmlStartTag = "<HTML><BODY>"; + + private final String defaultHtmlEndTag = "</BODY></HTML>"; + /** * The task sending packets */ @@ -176,8 +180,11 @@ public class OperationSetBasicInstantMessagingIcqImpl public Message createMessage(byte[] content, String contentType, String contentEncoding, String subject) { - return new MessageIcqImpl(new String(content), contentType - , contentEncoding, subject, null); + return new MessageIcqImpl( new String(content), + contentType, + contentEncoding, + subject, + null); } /** @@ -219,18 +226,26 @@ public class OperationSetBasicInstantMessagingIcqImpl getImConversation( new Screenname(to.getAddress())); + String messageContent = null; + if (message.getContentType().equals(CONTENT_TYPE_HTML) + && !message.getContent().startsWith(defaultHtmlStartTag)) + { + messageContent = defaultHtmlStartTag + + message.getContent() + + defaultHtmlEndTag; + } + else + messageContent = message.getContent(); + if (to.getPresenceStatus().isOnline()) { //do not add the conversation listener in here. we'll add it //inside the icbm listener - imConversation.sendMessage(new SimpleMessage(message.getContent())); + imConversation.sendMessage(new SimpleMessage(messageContent)); } else - imConversation.sendMessage(new SimpleMessage(message.getContent()) - , true); + imConversation.sendMessage(new SimpleMessage(messageContent), true); - //temporarily and uglity fire the sent event here. - /** @todo move elsewhaere */ MessageDeliveredEvent msgDeliveredEvt = new MessageDeliveredEvent( message, to, new Date()); @@ -388,7 +403,7 @@ public class OperationSetBasicInstantMessagingIcqImpl public boolean isContentTypeSupported(String contentType) { if(contentType.equals(DEFAULT_MIME_TYPE) || - (contentType.equals(CONTENT_TYPE_HTML) && !icqProvider.USING_ICQ) ) + (contentType.equals(CONTENT_TYPE_HTML))) return true; else return false; @@ -568,12 +583,18 @@ public class OperationSetBasicInstantMessagingIcqImpl return; } - Message newMessage = null; - - if(icqProvider.USING_ICQ) - newMessage = createMessage(msgBody); + String msgContent; + if (msgBody.startsWith(defaultHtmlStartTag)) + { + msgContent = msgBody.substring( + msgBody.indexOf(defaultHtmlStartTag) + + defaultHtmlStartTag.length(), + msgBody.indexOf(defaultHtmlEndTag)); + } else - newMessage = createMessage(msgBody.getBytes(), + msgContent = msgBody; + + Message newMessage = createMessage(msgContent.getBytes(), CONTENT_TYPE_HTML, DEFAULT_MIME_ENCODING, null); Contact sourceContact = |