diff --git a/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy b/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy index 45e0fc0b..8bf449a6 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/ChatRoomController.groovy @@ -44,7 +44,7 @@ class ChatRoomController { @ControllerAction void say() { - String words = view.sayField.text + String words = view.sayField.getFinalText() view.sayField.setText(null) ChatCommand command diff --git a/gui/src/main/groovy/com/muwire/gui/chat/ChatEntry.groovy b/gui/src/main/groovy/com/muwire/gui/chat/ChatEntry.groovy index e7dbe345..c4a80314 100644 --- a/gui/src/main/groovy/com/muwire/gui/chat/ChatEntry.groovy +++ b/gui/src/main/groovy/com/muwire/gui/chat/ChatEntry.groovy @@ -6,7 +6,10 @@ import com.muwire.gui.contacts.POPLabel import com.muwire.gui.profile.PersonaOrProfile import com.muwire.gui.profile.ProfileConstants +import javax.swing.BorderFactory +import javax.swing.JLabel import javax.swing.JTextPane +import javax.swing.border.Border import javax.swing.text.Document import javax.swing.text.SimpleAttributeSet import javax.swing.text.StyleConstants @@ -153,9 +156,9 @@ class ChatEntry extends JTextPane { void render() { StyledDocument document = getStyledDocument() - - def popLabel = new POPLabel(personaOrProfile, settings) - popLabel.setMaximumSize([200, ProfileConstants.MAX_THUMBNAIL_SIZE] as Dimension) + + Border border = BorderFactory.createEtchedBorder() + def popLabel = new POPLabel(personaOrProfile, settings, border, JLabel.TOP) def style = document.addStyle("newStyle", null) StyleConstants.setComponent(style, popLabel) document.insertString(document.getEndPosition().getOffset() - 1, diff --git a/gui/src/main/groovy/com/muwire/gui/chat/ChatEntryPane.groovy b/gui/src/main/groovy/com/muwire/gui/chat/ChatEntryPane.groovy index a9f9d1b4..06b0b678 100644 --- a/gui/src/main/groovy/com/muwire/gui/chat/ChatEntryPane.groovy +++ b/gui/src/main/groovy/com/muwire/gui/chat/ChatEntryPane.groovy @@ -8,6 +8,7 @@ import com.muwire.gui.profile.ProfileConstants import sun.swing.UIAction import javax.swing.* +import javax.swing.border.Border import javax.swing.event.MenuKeyEvent import javax.swing.event.MenuKeyListener import javax.swing.text.* @@ -21,6 +22,7 @@ import java.util.stream.Collectors class ChatEntryPane extends JTextPane { private static final char AT = "@".toCharacter() + private static final char SPACE = " ".toCharacter() private static final char BACKSPACE = (char)8 private static final int ENTER = 10 @@ -179,20 +181,50 @@ class ChatEntryPane extends JTextPane { setSelectionEnd(position) replaceSelection("") - final String name = personaOrProfile.getPersona().getHumanReadableName() + + Border border = BorderFactory.createEtchedBorder() + def popLabel = new POPLabel(personaOrProfile, settings, border, JLabel.TOP) StyledDocument document = getStyledDocument() - def popLabel = new POPLabel(personaOrProfile, settings) - popLabel.setMaximumSize([200, ProfileConstants.MAX_THUMBNAIL_SIZE] as Dimension) Style style = document.addStyle("newStyle", null) StyleConstants.setComponent(style, popLabel) - document.insertString(startPosition, name, style) + document.insertString(startPosition, " ", style) popupMenu?.setVisible(false) popupMenu = null } } + String getFinalText() { + String currentText = getText() + StringBuilder sb = new StringBuilder() + for (int i = 0; i < currentText.length(); i ++) { + final char c = currentText.charAt(i) + if ( c != SPACE) { + sb.append(c) + continue + } + def component = getComponentForPosition(i) + if (component == null) { + sb.append(c) + continue + } + POPLabel label = (POPLabel) component + sb.append(label.personaOrProfile.getPersona().getHumanReadableName()) + } + sb.toString() + } + + private boolean isInComponent(int position) { + getComponentForPosition(position) != null + } + + private Object getComponentForPosition(int position) { + StyledDocument document = getStyledDocument() + Element element = document.getCharacterElement(position) + element.getAttributes().getAttribute(StyleConstants.ComponentAttribute) + } + private class ForwardingAction extends UIAction { private final Action delegate private final boolean forward, modifying @@ -229,12 +261,6 @@ class ChatEntryPane extends JTextPane { } } } - - private boolean isInComponent(int position) { - StyledDocument document = getStyledDocument() - Element element = document.getCharacterElement(position) - return element.getAttributes().getAttribute(StyleConstants.ComponentAttribute) != null - } } private static class NullAction extends UIAction { diff --git a/gui/src/main/groovy/com/muwire/gui/contacts/POPLabel.groovy b/gui/src/main/groovy/com/muwire/gui/contacts/POPLabel.groovy index 34831539..98a368be 100644 --- a/gui/src/main/groovy/com/muwire/gui/contacts/POPLabel.groovy +++ b/gui/src/main/groovy/com/muwire/gui/contacts/POPLabel.groovy @@ -5,11 +5,16 @@ import com.muwire.gui.HTMLSanitizer import com.muwire.gui.PersonaCellRenderer import com.muwire.gui.UISettings import com.muwire.gui.profile.PersonaOrProfile +import com.muwire.gui.profile.ProfileConstants import javax.swing.BorderFactory import javax.swing.JComponent import javax.swing.JLabel import javax.swing.border.Border +import java.awt.Dimension +import java.awt.Font +import java.awt.FontMetrics +import java.awt.Insets import static com.muwire.gui.Translator.trans @@ -20,31 +25,49 @@ class POPLabel extends JLabel { POPLabel(PersonaOrProfile personaOrProfile, UISettings settings) { this(personaOrProfile, settings, BorderFactory.createEmptyBorder(2, 2, 2, 2), - JLabel.CENTER) + CENTER) } POPLabel(PersonaOrProfile personaOrProfile, UISettings settings, Border border, int verticalAllignment) { super() + setMinimumSize([0, 0] as Dimension) setVerticalAlignment(verticalAllignment) this.personaOrProfile = personaOrProfile this.settings = settings + int preferredX = 0, preferredY = 0 + + preferredY = settings.getFontSize() if (border != null) setBorder(border) MWProfileHeader header = personaOrProfile.getHeader() if (settings.personaRendererAvatars) { setIcon(personaOrProfile.getThumbnail()) + preferredY = Math.max(preferredY, ProfileConstants.MAX_THUMBNAIL_SIZE) + preferredX = ProfileConstants.MAX_THUMBNAIL_SIZE } - String text + String text, visibleText if (settings.personaRendererIds) { text = "${PersonaCellRenderer.htmlize(personaOrProfile.getPersona())}" - } else + visibleText = personaOrProfile.getPersona().getHumanReadableName() + } else { text = PersonaCellRenderer.justName(personaOrProfile.getPersona()) + visibleText = text + } setText(text) + FontMetrics fontMetrics = getFontMetrics(getFont()) + for (int i = 0; i < visibleText.length(); i++) + preferredX += fontMetrics.charWidth(text.charAt(i)) + + preferredX += getIconTextGap() + Insets insets = border.getBorderInsets(this) + preferredX += insets.left + preferredX += insets.right + if (personaOrProfile.getTitle() != null) { if (settings.personaRendererIds) setToolTipText(personaOrProfile.getTitle()) @@ -55,5 +78,7 @@ class POPLabel extends JLabel { } } else setToolTipText(trans("NO_PROFILE")) + + setMaximumSize([preferredX, preferredY] as Dimension) } }