mirror of https://github.com/zlatinb/muwire
Avatars in chat, multi-line paste support
parent
9b931dbdb4
commit
27b734bc40
1
TODO.md
1
TODO.md
|
@ -38,7 +38,6 @@
|
||||||
|Downloads queue with priorities | N/A | Core, GUI | Medium |
|
|Downloads queue with priorities | N/A | Core, GUI | Medium |
|
||||||
|Remote queuing of uploads | N/A | Core, Network, GUI | Medium |
|
|Remote queuing of uploads | N/A | Core, Network, GUI | Medium |
|
||||||
|Incomplete file handling | 2 | Core, Portable | Low |
|
|Incomplete file handling | 2 | Core, Portable | Low |
|
||||||
|Chat - break up lines on CR/LF | N/A | GUI | Low |
|
|
||||||
|Chat - enforce # in room names | N/A | GUI | Low |
|
|Chat - enforce # in room names | N/A | GUI | Low |
|
||||||
|Chat - jump from notification window to room | N/A | GUI | Optional |
|
|Chat - jump from notification window to room | N/A | GUI | Optional |
|
||||||
|Chat - emoji support | 113 | GUI | Low |
|
|Chat - emoji support | 113 | GUI | Low |
|
||||||
|
|
|
@ -61,14 +61,7 @@ class ChatRoomController {
|
||||||
long now = System.currentTimeMillis()
|
long now = System.currentTimeMillis()
|
||||||
|
|
||||||
if (command.action == ChatAction.SAY && command.payload.length() > 0) {
|
if (command.action == ChatAction.SAY && command.payload.length() > 0) {
|
||||||
String header = DataHelper.formatTime(now) + " <" + model.core.me.getHumanReadableName() + ">"
|
view.appendSay(command.payload, model.buildChatPOP(model.core.me), now)
|
||||||
StyledDocument sd = view.roomTextArea.getStyledDocument()
|
|
||||||
sd.insertString(sd.getEndPosition().getOffset() - 1, header, sd.getStyle("italic"))
|
|
||||||
sd.insertString(sd.getEndPosition().getOffset() - 1, " ", sd.getStyle("regular"))
|
|
||||||
sd.insertString(sd.getEndPosition().getOffset() - 1, command.payload, sd.getStyle("regular"))
|
|
||||||
sd.insertString(sd.getEndPosition().getOffset() - 1, "\n", sd.getStyle("regular"))
|
|
||||||
|
|
||||||
trimLines()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.action == ChatAction.JOIN && model.console) {
|
if (command.action == ChatAction.JOIN && model.console) {
|
||||||
|
@ -208,8 +201,7 @@ class ChatRoomController {
|
||||||
|
|
||||||
private void processSay(ChatMessageEvent e, String text) {
|
private void processSay(ChatMessageEvent e, String text) {
|
||||||
runInsideUIAsync {
|
runInsideUIAsync {
|
||||||
view.appendSay(text, e.sender, e.timestamp)
|
view.appendSay(text, model.buildChatPOP(e.sender), e.timestamp)
|
||||||
trimLines()
|
|
||||||
if (!model.console)
|
if (!model.console)
|
||||||
view.chatNotificator.onMessage(mvcGroup.mvcId)
|
view.chatNotificator.onMessage(mvcGroup.mvcId)
|
||||||
}
|
}
|
||||||
|
@ -266,7 +258,7 @@ class ChatRoomController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trimLines() {
|
void trimLines() {
|
||||||
if (model.settings.maxChatLines < 0)
|
if (model.settings.maxChatLines < 0)
|
||||||
return
|
return
|
||||||
while(view.getLineCount() > model.settings.maxChatLines)
|
while(view.getLineCount() > model.settings.maxChatLines)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.muwire.gui
|
package com.muwire.gui
|
||||||
|
|
||||||
import com.muwire.core.trust.TrustLevel
|
import com.muwire.core.trust.TrustLevel
|
||||||
|
import com.muwire.gui.chat.ChatEntry
|
||||||
|
import com.muwire.gui.chat.ChatTextField
|
||||||
|
import com.muwire.gui.contacts.POPLabel
|
||||||
import com.muwire.gui.profile.PersonaOrProfile
|
import com.muwire.gui.profile.PersonaOrProfile
|
||||||
import com.muwire.gui.profile.PersonaOrProfileCellRenderer
|
import com.muwire.gui.profile.PersonaOrProfileCellRenderer
|
||||||
import com.muwire.gui.profile.PersonaOrProfileComparator
|
import com.muwire.gui.profile.PersonaOrProfileComparator
|
||||||
|
@ -8,6 +11,11 @@ import griffon.core.GriffonApplication
|
||||||
import griffon.core.artifact.GriffonView
|
import griffon.core.artifact.GriffonView
|
||||||
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.swing.BorderFactory
|
||||||
|
import javax.swing.JLabel
|
||||||
|
import javax.swing.JScrollPane
|
||||||
|
import javax.swing.border.Border
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
import static com.muwire.gui.Translator.trans
|
import static com.muwire.gui.Translator.trans
|
||||||
import griffon.inject.MVCMember
|
import griffon.inject.MVCMember
|
||||||
|
@ -52,15 +60,21 @@ class ChatRoomView {
|
||||||
|
|
||||||
def pane
|
def pane
|
||||||
def parent
|
def parent
|
||||||
def sayField
|
ChatTextField sayField
|
||||||
JTextPane roomTextArea
|
JTextPane roomTextArea
|
||||||
def textScrollPane
|
def textScrollPane
|
||||||
def membersTable
|
def membersTable
|
||||||
def lastMembersTableSortEvent
|
def lastMembersTableSortEvent
|
||||||
|
UISettings settings
|
||||||
|
|
||||||
|
private static final SimpleDateFormat SDF = new SimpleDateFormat("dd/MM hh:mm:ss")
|
||||||
void initUI() {
|
void initUI() {
|
||||||
|
settings = application.context.get("ui-settings")
|
||||||
int rowHeight = application.context.get("row-height")
|
int rowHeight = application.context.get("row-height")
|
||||||
def parentModel = mvcGroup.parentGroup.model
|
def parentModel = mvcGroup.parentGroup.model
|
||||||
|
|
||||||
|
sayField = new ChatTextField()
|
||||||
|
|
||||||
if (model.console || model.privateChat) {
|
if (model.console || model.privateChat) {
|
||||||
pane = builder.panel {
|
pane = builder.panel {
|
||||||
borderLayout()
|
borderLayout()
|
||||||
|
@ -73,7 +87,9 @@ class ChatRoomView {
|
||||||
panel(constraints : BorderLayout.SOUTH) {
|
panel(constraints : BorderLayout.SOUTH) {
|
||||||
borderLayout()
|
borderLayout()
|
||||||
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
|
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
|
||||||
sayField = textField(enabled : bind {parentModel.sayActionEnabled}, actionPerformed : {controller.say()}, constraints : BorderLayout.CENTER)
|
scrollPane(verticalScrollBarPolicy: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, constraints: BorderLayout.CENTER) {
|
||||||
|
widget(sayField, enabled: bind { parentModel.sayActionEnabled }, actionPerformed: { controller.say() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,7 +121,9 @@ class ChatRoomView {
|
||||||
panel(constraints : BorderLayout.SOUTH) {
|
panel(constraints : BorderLayout.SOUTH) {
|
||||||
borderLayout()
|
borderLayout()
|
||||||
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
|
label(text : trans("SAY_SOMETHING_HERE") + ": ", constraints : BorderLayout.WEST)
|
||||||
sayField = textField(enabled : bind {parentModel.sayActionEnabled}, actionPerformed : {controller.say()}, constraints : BorderLayout.CENTER)
|
scrollPane(verticalScrollBarPolicy: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, constraints: BorderLayout.CENTER) {
|
||||||
|
widget(sayField, enabled: bind { parentModel.sayActionEnabled }, actionPerformed: { controller.say() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -222,12 +240,26 @@ class ChatRoomView {
|
||||||
doc.insertString(doc.getEndPosition().getOffset() - 1, gray, doc.getStyle("gray"))
|
doc.insertString(doc.getEndPosition().getOffset() - 1, gray, doc.getStyle("gray"))
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendSay(String text, Persona sender, long timestamp) {
|
void appendSay(String text, PersonaOrProfile sender, long timestamp) {
|
||||||
StyledDocument doc = roomTextArea.getStyledDocument()
|
StyledDocument doc = roomTextArea.getStyledDocument()
|
||||||
String header = DataHelper.formatTime(timestamp) + " <" + sender.getHumanReadableName() + "> "
|
def label = new DateLabel(timestamp)
|
||||||
doc.insertString(doc.getEndPosition().getOffset() - 1, header, doc.getStyle("italic"))
|
def style = doc.addStyle("newStyle", null)
|
||||||
doc.insertString(doc.getEndPosition().getOffset() - 1, text, doc.getStyle("regular"))
|
StyleConstants.setComponent(style, label)
|
||||||
|
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
|
||||||
|
|
||||||
|
Border border = BorderFactory.createEmptyBorder(0, 5, 0, 5)
|
||||||
|
label = new POPLabel(sender, settings, border, JLabel.TOP)
|
||||||
|
label.setAlignmentY(0f)
|
||||||
|
style = doc.addStyle("newStyle", null)
|
||||||
|
StyleConstants.setComponent(style, label)
|
||||||
|
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
|
||||||
|
|
||||||
|
def textField = new ChatEntry("$text")
|
||||||
|
style = doc.addStyle("newStyle", null)
|
||||||
|
StyleConstants.setComponent(style, textField)
|
||||||
|
doc.insertString(doc.getEndPosition().getOffset() - 1, " ", style)
|
||||||
doc.insertString(doc.getEndPosition().getOffset() - 1, "\n", doc.getStyle("regular"))
|
doc.insertString(doc.getEndPosition().getOffset() - 1, "\n", doc.getStyle("regular"))
|
||||||
|
controller.trimLines()
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLineCount() {
|
int getLineCount() {
|
||||||
|
@ -240,4 +272,12 @@ class ChatRoomView {
|
||||||
Element element = doc.getParagraphElement(0)
|
Element element = doc.getParagraphElement(0)
|
||||||
doc.remove(0, element.getEndOffset())
|
doc.remove(0, element.getEndOffset())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DateLabel extends JLabel {
|
||||||
|
DateLabel(long now) {
|
||||||
|
setAlignmentY(0f)
|
||||||
|
String text = SDF.format(new Date(now))
|
||||||
|
setText(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.muwire.gui.chat
|
||||||
|
|
||||||
|
import javax.swing.JTextArea
|
||||||
|
import javax.swing.JTextField
|
||||||
|
|
||||||
|
class ChatEntry extends JTextArea {
|
||||||
|
|
||||||
|
ChatEntry(String text) {
|
||||||
|
setEditable(false)
|
||||||
|
setLineWrap(true)
|
||||||
|
setWrapStyleWord(true)
|
||||||
|
setColumns(countRows(text))
|
||||||
|
setText(text)
|
||||||
|
setAlignmentY(0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int countRows(String text) {
|
||||||
|
int rv = 0
|
||||||
|
char newLine = "\n".toCharacter()
|
||||||
|
for (int i = 0; i < text.length(); i++) {
|
||||||
|
char c = text.charAt(i)
|
||||||
|
if (c == newLine)
|
||||||
|
rv++
|
||||||
|
}
|
||||||
|
rv
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.muwire.gui.chat
|
||||||
|
|
||||||
|
import javax.swing.JTextField
|
||||||
|
import javax.swing.text.AttributeSet
|
||||||
|
import javax.swing.text.BadLocationException
|
||||||
|
import javax.swing.text.Document
|
||||||
|
import javax.swing.text.PlainDocument
|
||||||
|
|
||||||
|
class ChatTextField extends JTextField {
|
||||||
|
ChatTextField() {
|
||||||
|
setEditable(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Document createDefaultModel() {
|
||||||
|
return new ChatDocument()
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ChatDocument extends PlainDocument {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
|
||||||
|
println "inserting string $str"
|
||||||
|
getDocumentProperties().put("filterNewlines", false)
|
||||||
|
super.insertString(offs, str, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getText(int offset, int length) throws BadLocationException {
|
||||||
|
String rv = super.getText(offset, length)
|
||||||
|
println "getting string $rv"
|
||||||
|
return rv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,11 +15,19 @@ class POPLabel extends JLabel {
|
||||||
private final UISettings settings
|
private final UISettings settings
|
||||||
|
|
||||||
POPLabel(PersonaOrProfile personaOrProfile, UISettings settings) {
|
POPLabel(PersonaOrProfile personaOrProfile, UISettings settings) {
|
||||||
|
this(personaOrProfile, settings,
|
||||||
|
BorderFactory.createEmptyBorder(2, 2, 2, 2),
|
||||||
|
JLabel.CENTER)
|
||||||
|
}
|
||||||
|
|
||||||
|
POPLabel(PersonaOrProfile personaOrProfile, UISettings settings,
|
||||||
|
Border border, int verticalAllignment) {
|
||||||
super()
|
super()
|
||||||
|
setVerticalAlignment(verticalAllignment)
|
||||||
this.personaOrProfile = personaOrProfile
|
this.personaOrProfile = personaOrProfile
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
|
|
||||||
Border border = BorderFactory.createEmptyBorder(2, 2, 2, 2)
|
if (border != null)
|
||||||
setBorder(border)
|
setBorder(border)
|
||||||
|
|
||||||
MWProfileHeader header = personaOrProfile.getHeader()
|
MWProfileHeader header = personaOrProfile.getHeader()
|
||||||
|
|
Loading…
Reference in New Issue