mirror of https://github.com/zlatinb/muwire
new contact selector
parent
56f83c8078
commit
53206b3b84
|
@ -669,7 +669,7 @@ FOLDER_CONFIRM_DELETE=This folder is not empty. Are you sure you want to delete
|
|||
## New message window
|
||||
UNREAD=Unread
|
||||
RECIPIENTS=Recipients
|
||||
RECIPIENTS_TITLE=Drag and drop contacts from your contact list
|
||||
RECIPIENTS_TITLE=You can drag and drop contacts from your contact list here
|
||||
SEND=Send
|
||||
MESSAGE_VERB=Message
|
||||
MESSAGE_NOUN=Message
|
||||
|
@ -681,6 +681,9 @@ SUBJECT_TOO_LONG_BODY=Your subject is {0} characters. The maximum length is {1}
|
|||
NO_RECIPIENTS=No Recipients
|
||||
NO_RECIPIENTS_BODY=Please add at least one recipient.
|
||||
|
||||
## Contact chooser
|
||||
CONTACT_CHOOSER_SELECT_CONTACT=Select Contact
|
||||
|
||||
## Add Contact dialog
|
||||
ADD_CONTACT_SPECIFIC=Add Contact
|
||||
ADD_CONTACT_TITLE=Add a new contact
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import com.muwire.core.Core
|
||||
import com.muwire.core.Persona
|
||||
import griffon.core.artifact.GriffonModel
|
||||
import griffon.inject.MVCMember
|
||||
|
@ -9,5 +10,6 @@ import javax.annotation.Nonnull
|
|||
|
||||
@ArtifactProviderFor(GriffonModel)
|
||||
class ContactSelectorModel {
|
||||
Core core
|
||||
Set<Persona> contacts
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ class NewMessageView {
|
|||
|
||||
def params = [:]
|
||||
params.contacts = model.recipients
|
||||
params.core = model.core
|
||||
contactSelector = mvcGroup.createMVCGroup("contact-selector", UUID.randomUUID().toString(), params)
|
||||
|
||||
window = builder.frame(visible : false, locationRelativeTo : mainFrame,
|
||||
|
|
|
@ -43,6 +43,7 @@ class WatchedDirectoryView {
|
|||
mainFrame = application.windowManager.findWindow("main-frame")
|
||||
|
||||
def params = [:]
|
||||
params.core = model.core
|
||||
params.contacts = model.allowedContacts
|
||||
contactSelector = mvcGroup.createMVCGroup("contact-selector", UUID.randomUUID().toString(), params)
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ import javax.swing.border.TitledBorder
|
|||
import java.awt.BorderLayout
|
||||
import java.awt.datatransfer.DataFlavor
|
||||
import java.awt.datatransfer.Transferable
|
||||
import java.awt.event.ItemEvent
|
||||
import java.awt.event.ItemListener
|
||||
import java.awt.event.KeyAdapter
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
|
||||
|
@ -39,23 +43,37 @@ class ContactSelectorView {
|
|||
|
||||
DefaultListModel contactsModel
|
||||
JList contactsList
|
||||
ContactChooser contactChooser
|
||||
ContactChooserModel contactChooserModel
|
||||
|
||||
JPanel component
|
||||
|
||||
private UISettings settings
|
||||
|
||||
private Contact lastSelectedContact
|
||||
|
||||
void initUI() {
|
||||
settings = application.context.get("ui-settings")
|
||||
|
||||
contactsModel = new DefaultListModel()
|
||||
model.contacts.each {
|
||||
contactsModel.addElement(new Contact(it))
|
||||
contactsModel.addElement(new Contact(it, settings))
|
||||
}
|
||||
contactsList = new JList(contactsModel)
|
||||
contactsList.setVisibleRowCount(2)
|
||||
|
||||
component = builder.panel(border : builder.titledBorder(title : trans("RECIPIENTS_TITLE"),
|
||||
border : builder.etchedBorder(), titlePosition : TitledBorder.TOP)) {
|
||||
contactChooserModel= new ContactChooserModel(model.core.trustService.getGood().values())
|
||||
contactChooser = new ContactChooser(settings, contactChooserModel)
|
||||
|
||||
component = builder.panel {
|
||||
borderLayout()
|
||||
scrollPane(constraints : BorderLayout.CENTER) {
|
||||
scrollPane(constraints : BorderLayout.CENTER, border : builder.titledBorder(title : trans("RECIPIENTS_TITLE"),
|
||||
border : builder.etchedBorder(), titlePosition : TitledBorder.TOP)) {
|
||||
widget(contactsList)
|
||||
}
|
||||
widget(contactChooser, constraints: BorderLayout.SOUTH,
|
||||
border : builder.titledBorder(title : trans("CONTACT_CHOOSER_SELECT_CONTACT"),
|
||||
border : builder.etchedBorder(), titlePosition : TitledBorder.TOP))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +97,34 @@ class ContactSelectorView {
|
|||
contactsMenu.show(e.getComponent(), e.getX(), e.getY())
|
||||
}
|
||||
})
|
||||
|
||||
contactChooser.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() != ItemEvent.SELECTED)
|
||||
return
|
||||
Object item = e.getItem()
|
||||
if (item == null || item instanceof String)
|
||||
return
|
||||
ContactChooserPOP ccp = (ContactChooserPOP) item
|
||||
if (ccp.getPersona() == null)
|
||||
return
|
||||
|
||||
lastSelectedContact = new Contact(ccp.getPersona(), settings)
|
||||
}
|
||||
})
|
||||
|
||||
contactChooser.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() != KeyEvent.VK_ENTER)
|
||||
return
|
||||
if (lastSelectedContact != null) {
|
||||
if (model.contacts.add(lastSelectedContact.persona))
|
||||
contactsModel << lastSelectedContact
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
void removeSelectedContacts() {
|
||||
|
@ -110,7 +156,7 @@ class ContactSelectorView {
|
|||
|
||||
items.each {
|
||||
if (model.contacts.add(it))
|
||||
contactsModel.insertElementAt(new Contact(it),0)
|
||||
contactsModel.insertElementAt(new Contact(it, settings),0)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -119,8 +165,9 @@ class ContactSelectorView {
|
|||
private static class Contact {
|
||||
private final UISettings settings
|
||||
private final Persona persona
|
||||
Contact(Persona persona) {
|
||||
Contact(Persona persona, UISettings settings) {
|
||||
this.persona = persona
|
||||
this.settings = settings
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import com.muwire.gui.UISettings
|
||||
import com.muwire.gui.profile.PersonaOrProfileCellRenderer
|
||||
|
||||
import javax.swing.JComboBox
|
||||
import javax.swing.JTextField
|
||||
|
||||
class ContactChooser extends JComboBox{
|
||||
ContactChooser(UISettings settings, ContactChooserModel model) {
|
||||
super()
|
||||
setEditable(true)
|
||||
setModel(model)
|
||||
setEditor(new ContactChooserEditor(model, this))
|
||||
setRenderer(new PersonaOrProfileListCellRenderer(settings))
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import javax.swing.SwingUtilities
|
||||
import javax.swing.event.DocumentEvent
|
||||
import javax.swing.event.DocumentListener
|
||||
import javax.swing.plaf.basic.BasicComboBoxEditor
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.ActionListener
|
||||
import java.awt.event.KeyAdapter
|
||||
import java.awt.event.KeyEvent
|
||||
|
||||
class ContactChooserEditor extends BasicComboBoxEditor{
|
||||
|
||||
private final ContactChooserModel model
|
||||
private final ContactChooser field
|
||||
|
||||
ContactChooserEditor(ContactChooserModel model, ContactChooser field) {
|
||||
super()
|
||||
this.model = model
|
||||
this.field = field
|
||||
|
||||
editor.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
void keyPressed(KeyEvent e) {
|
||||
int keyCode = e.getKeyCode()
|
||||
if (keyCode == KeyEvent.VK_ENTER)
|
||||
editor.setText("")
|
||||
else if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) {
|
||||
return
|
||||
} else {
|
||||
SwingUtilities.invokeLater {
|
||||
field.hidePopup()
|
||||
if (model.onKeyStroke(editor.text))
|
||||
field.showPopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public void setItem(Object o) {
|
||||
if (o == null || o instanceof ContactChooserPOP)
|
||||
super.setItem(o)
|
||||
else
|
||||
editor.setText("")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import com.muwire.core.trust.TrustService
|
||||
import com.muwire.core.trust.TrustService.TrustEntry
|
||||
import com.muwire.gui.profile.PersonaOrProfile
|
||||
import com.muwire.gui.profile.PersonaOrProfileComparator
|
||||
import com.muwire.gui.profile.TrustPOP
|
||||
|
||||
import javax.swing.ComboBoxModel
|
||||
import javax.swing.DefaultComboBoxModel
|
||||
import javax.swing.DefaultListModel
|
||||
import javax.swing.MutableComboBoxModel
|
||||
|
||||
class ContactChooserModel extends DefaultComboBoxModel implements MutableComboBoxModel {
|
||||
private final List<PersonaOrProfile> allObjects
|
||||
private final Comparator<PersonaOrProfile> popComparator = new PersonaOrProfileComparator()
|
||||
PersonaOrProfile selectedPOP
|
||||
|
||||
ContactChooserModel(Collection<TrustEntry> entries) {
|
||||
allObjects = entries.collect {new ContactChooserPOP(it)}
|
||||
addAll(allObjects)
|
||||
}
|
||||
|
||||
boolean onKeyStroke(String selected) {
|
||||
|
||||
if (selected == null || selected.length() == 0) {
|
||||
removeAllElements()
|
||||
addAll(allObjects)
|
||||
return true
|
||||
}
|
||||
|
||||
removeAllElements()
|
||||
setSelectedItem(new ContactChooserPOP(selected))
|
||||
|
||||
List<PersonaOrProfile> matches = []
|
||||
for(PersonaOrProfile pop : allObjects) {
|
||||
if (justName(pop).containsIgnoreCase(selected))
|
||||
matches << pop
|
||||
}
|
||||
if (matches.isEmpty())
|
||||
return false
|
||||
|
||||
Collections.sort(matches, popComparator)
|
||||
addAll(matches)
|
||||
true
|
||||
}
|
||||
|
||||
private static String justName(PersonaOrProfile pop) {
|
||||
String name = pop.getPersona().getHumanReadableName()
|
||||
name.substring(0, name.indexOf("@")).toLowerCase()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anObject) {
|
||||
if (anObject instanceof String) {
|
||||
if (anObject == selectedPOP?.getPersona()?.getHumanReadableName())
|
||||
super.setSelectedItem(selectedPOP)
|
||||
return
|
||||
}
|
||||
if (anObject == null)
|
||||
selectedPOP = null
|
||||
else {
|
||||
if (!(anObject instanceof ContactChooserPOP))
|
||||
throw new Exception("invalid type $anObject")
|
||||
|
||||
ContactChooserPOP ccp = (ContactChooserPOP) anObject
|
||||
if (ccp.getPersona() != null)
|
||||
selectedPOP = ccp
|
||||
}
|
||||
super.setSelectedItem(anObject)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import com.muwire.core.Persona
|
||||
import com.muwire.core.profile.MWProfile
|
||||
import com.muwire.core.profile.MWProfileHeader
|
||||
import com.muwire.core.trust.TrustService.TrustEntry
|
||||
import com.muwire.gui.profile.PersonaOrProfile
|
||||
import com.muwire.gui.profile.ThumbnailIcon
|
||||
|
||||
import javax.swing.Icon
|
||||
|
||||
class ContactChooserPOP implements PersonaOrProfile {
|
||||
private final TrustEntry trustEntry
|
||||
private final String text
|
||||
private Icon icon
|
||||
|
||||
ContactChooserPOP(TrustEntry trustEntry) {
|
||||
this.trustEntry = trustEntry
|
||||
this.text = null
|
||||
}
|
||||
|
||||
ContactChooserPOP(String text) {
|
||||
this.text = text
|
||||
this.trustEntry = null
|
||||
}
|
||||
|
||||
Persona getPersona() {
|
||||
trustEntry?.getPersona()
|
||||
}
|
||||
|
||||
@Override
|
||||
Icon getThumbnail() {
|
||||
MWProfileHeader header = getHeader()
|
||||
if (header == null)
|
||||
return null
|
||||
if (icon == null)
|
||||
icon = new ThumbnailIcon(header.getThumbNail())
|
||||
return icon
|
||||
}
|
||||
|
||||
@Override
|
||||
MWProfileHeader getHeader() {
|
||||
trustEntry.getProfileHeader()
|
||||
}
|
||||
|
||||
@Override
|
||||
MWProfile getProfile() {
|
||||
trustEntry.getProfile()
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof ContactChooserPOP))
|
||||
return false
|
||||
ContactChooserPOP other = (ContactChooserPOP)o
|
||||
Objects.equals(text, other.text) &&
|
||||
Objects.equals(trustEntry, other.trustEntry)
|
||||
}
|
||||
|
||||
String toString() {
|
||||
if (text != null)
|
||||
return text
|
||||
else
|
||||
return getPersona().getHumanReadableName()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.muwire.gui.contacts
|
||||
|
||||
import com.muwire.gui.PersonaCellRenderer
|
||||
import com.muwire.gui.UISettings
|
||||
import com.muwire.gui.profile.PersonaOrProfile
|
||||
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JList
|
||||
import javax.swing.ListCellRenderer
|
||||
import java.awt.Component
|
||||
|
||||
import static com.muwire.gui.Translator.trans
|
||||
|
||||
class PersonaOrProfileListCellRenderer implements ListCellRenderer<PersonaOrProfile>{
|
||||
|
||||
private final UISettings settings
|
||||
|
||||
PersonaOrProfileListCellRenderer(UISettings settings) {
|
||||
this.settings = settings
|
||||
}
|
||||
|
||||
@Override
|
||||
Component getListCellRendererComponent(JList<? extends PersonaOrProfile> list, PersonaOrProfile value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
JLabel rv = new JLabel()
|
||||
String text
|
||||
if (settings.personaRendererIds)
|
||||
text = "<html>" + PersonaCellRenderer.htmlize(value.getPersona()) + "</html>"
|
||||
else
|
||||
text = PersonaCellRenderer.justName(value.getPersona())
|
||||
|
||||
rv.setText(text)
|
||||
|
||||
if (value.getThumbnail() != null)
|
||||
rv.setIcon(value.getThumbnail())
|
||||
else
|
||||
rv.setIcon(null)
|
||||
|
||||
if (value.getTitle() != null)
|
||||
rv.setToolTipText(value.getTitle())
|
||||
else
|
||||
rv.setToolTipText(trans("NO_PROFILE"))
|
||||
|
||||
if (!isSelected) {
|
||||
rv.setForeground(list.getForeground())
|
||||
rv.setBackground(list.getBackground())
|
||||
} else {
|
||||
rv.setForeground(list.getSelectionForeground())
|
||||
rv.setBackground(list.getSelectionBackground())
|
||||
}
|
||||
rv
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue