/**
*
* Copyright
* 2009-2015 Jayway Products AB
* 2016-2017 Föreningen Sambruk
*
* Licensed under AGPL, Version 3.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/agpl.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package se.streamsource.streamflow.client.ui.workspace.cases.contacts;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.jdesktop.application.Action;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.swingx.util.WindowUtils;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.property.Property;
import org.qi4j.api.structure.Module;
import org.qi4j.api.value.ValueBuilder;
import org.restlet.resource.ResourceException;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactAddressDTO;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactDTO;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactEmailDTO;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactPhoneDTO;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactPreference;
import se.streamsource.streamflow.api.workspace.cases.contact.ContactsDTO;
import se.streamsource.streamflow.client.ui.workspace.WorkspaceResources;
import se.streamsource.streamflow.client.ui.workspace.cases.CaseResources;
import se.streamsource.streamflow.client.util.CommandTask;
import se.streamsource.streamflow.client.util.StateBinder;
import se.streamsource.streamflow.client.util.StreamflowButton;
import se.streamsource.streamflow.client.util.ValueBinder;
import se.streamsource.streamflow.client.util.dialog.DialogService;
import se.streamsource.streamflow.client.util.i18n;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import static se.streamsource.streamflow.client.util.BindingFormBuilder.Fields.*;
/**
* JAVADOC
*/
public class ContactView
extends JPanel
implements Observer
{
@Service
DialogService dialogs;
@Structure
Module module;
private StateBinder contactBinder;
private StateBinder phoneNumberBinder;
private StateBinder emailBinder;
private StateBinder addressBinder;
ContactModel model;
private CardLayout layout = new CardLayout();
public JPanel form;
private JTextField defaultFocusField;
private JTextField addressField;
private StreetAddressSuggestTextField suggestAddress;
private JTextField zipField = (JTextField) TEXTFIELD.newField();
private JTextField cityField = (JTextField) TEXTFIELD.newField();
private JTextField regionField = (JTextField) TEXTFIELD.newField();
private JTextField countryField = (JTextField) TEXTFIELD.newField();
private JTextField phoneField = (JTextField) TEXTFIELD.newField();
private JTextField emailField = (JTextField) TEXTFIELD.newField();
private JTextField contactIdField = (JTextField) TEXTFIELD.newField();
private JTextField companyField = (JTextField) TEXTFIELD.newField();
private JComboBox contactPreferenceField = (JComboBox) COMBOBOX.newField();
// do this out of the state binder otherwise the translation is hard
private JLabel contactPreferenceLabel = new JLabel( );
private ApplicationContext context;
private JPanel lookupPanel;
private ValueBinder viewBinder;
private ValueBinder phoneViewBinder;
private ValueBinder addressViewBinder;
private ValueBinder emailViewBinder;
private StreetAddressSuggestModel suggestModel;
public ContactView(@Service ApplicationContext appContext, @Structure Module module)
{
setLayout(layout);
context = appContext;
setActionMap(context.getActionMap(this));
add(new JLabel(), "EMPTY");
DefaultComboBoxModel contactPreferenceModel = new DefaultComboBoxModel();
for (ContactPreference preference : ContactPreference.values())
{
contactPreferenceModel.addElement( preference );
}
contactPreferenceField.setModel( contactPreferenceModel );
contactPreferenceField.setSelectedIndex( 0 );
contactPreferenceField.setRenderer( new ListCellRenderer()
{
public Component getListCellRendererComponent( JList jList, Object o, int i, boolean b, boolean b1 )
{
JLabel comp = new JLabel( "null" );
if (o instanceof ContactPreference)
{
if (((ContactPreference) o) == ContactPreference.none )
{
comp = new JLabel( " " );
} else
{
comp = new JLabel( i18n.text( WorkspaceResources.valueOf( ((ContactPreference) o).name() ) ) );
}
}
comp.setBorder( BorderFactory.createEmptyBorder( 2, 4, 2, 0 ) );
return comp;
}
});
viewBinder = module.objectBuilderFactory().newObject(ValueBinder.class);
phoneViewBinder = module.objectBuilderFactory().newObject(ValueBinder.class);
addressViewBinder = module.objectBuilderFactory().newObject(ValueBinder.class);
emailViewBinder = module.objectBuilderFactory().newObject(ValueBinder.class);
suggestModel = new StreetAddressSuggestModel();
suggestAddress = new StreetAddressSuggestTextField( suggestModel, cityField, addressViewBinder );
addressField = suggestAddress.getTextField();
// Edit panel
{
FormLayout formLayout = new FormLayout(
"right:70dlu, 5dlu, 150dlu:grow",
"pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, 5dlu, top:70dlu:grow, pref, pref");
this.setBorder(Borders.createEmptyBorder("2dlu, 2dlu, 2dlu, 2dlu"));
form = new JPanel();
JScrollPane scrollPane = new JScrollPane(form);
scrollPane.getVerticalScrollBar().setUnitIncrement(30);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
DefaultFormBuilder builder = new DefaultFormBuilder(formLayout, form);
contactBinder = module.objectBuilderFactory().newObject(StateBinder.class);
contactBinder.setResourceMap(context.getResourceMap(getClass()));
ContactDTO template = contactBinder.bindingTemplate(ContactDTO.class);
phoneNumberBinder = module.objectBuilderFactory().newObject(StateBinder.class);
phoneNumberBinder.setResourceMap(context.getResourceMap(getClass()));
ContactPhoneDTO phoneTemplate = phoneNumberBinder.bindingTemplate(ContactPhoneDTO.class);
addressBinder = module.objectBuilderFactory().newObject(StateBinder.class);
addressBinder.setResourceMap(context.getResourceMap(getClass()));
ContactAddressDTO addressTemplate = addressBinder.bindingTemplate(ContactAddressDTO.class);
emailBinder = module.objectBuilderFactory().newObject(StateBinder.class);
emailBinder.setResourceMap(context.getResourceMap(getClass()));
ContactEmailDTO emailTemplate = emailBinder.bindingTemplate(ContactEmailDTO.class);
builder.add(new StreamflowButton(getActionMap().get("view")));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.name_label));
builder.nextColumn(2);
builder.add(contactBinder.bind(defaultFocusField = (JTextField) TEXTFIELD.newField(), template.name()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.phone_label));
builder.nextColumn(2);
builder.add(phoneNumberBinder.bind(phoneField, phoneTemplate.phoneNumber()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.address_label));
builder.nextColumn(2);
builder.add( suggestAddress);
builder.nextLine();
builder.add(createLabel(WorkspaceResources.zip_label));
builder.nextColumn(2);
builder.add(addressBinder.bind(zipField, addressTemplate.zipCode()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.city_label));
builder.nextColumn(2);
builder.add(addressBinder.bind(cityField, addressTemplate.city()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.region_label));
builder.nextColumn(2);
builder.add(addressBinder.bind(regionField, addressTemplate.region()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.country_label));
builder.nextColumn(2);
builder.add(addressBinder.bind(countryField, addressTemplate.country()));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.email_label));
builder.nextColumn( 2 );
builder.add( emailBinder.bind( emailField, emailTemplate.emailAddress() ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.contact_id_label ) );
builder.nextColumn( 2 );
builder.add( contactBinder.bind( contactIdField, template.contactId() ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.company_label ) );
builder.nextColumn( 2 );
builder.add( contactBinder.bind( companyField, template.company() ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.contact_preference_label ) );
builder.nextColumn( 2 );
builder.add( contactBinder.bind( contactPreferenceField, template.contactPreference() ),
new CellConstraints( 3, 12, 1, 1, CellConstraints.LEFT, CellConstraints.TOP, new Insets(
5, 0, 0, 0 ) ) );
builder.nextLine(2);
builder.add(createLabel(WorkspaceResources.note_label));
builder.nextColumn(2);
builder.add(contactBinder.bind(TEXTAREA.newField(), template.note()));
builder.nextLine(2);
builder.nextColumn(2);
lookupPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
lookupPanel.add(new StreamflowButton(getActionMap().get("lookupContact")));
builder.add(lookupPanel);
contactBinder.addObserver(this);
phoneNumberBinder.addObserver(this);
addressBinder.addObserver(this);
emailBinder.addObserver(this);
add(scrollPane, "EDIT");
}
// View panel
{
FormLayout formLayout = new FormLayout(
"right:70dlu, 5dlu, 150dlu:grow",
"pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, pref, 5dlu, top:70dlu:grow, pref, pref");
this.setBorder(Borders.createEmptyBorder("2dlu, 2dlu, 2dlu, 2dlu"));
form = new JPanel();
JScrollPane scrollPane = new JScrollPane(form);
scrollPane.getVerticalScrollBar().setUnitIncrement(30);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
DefaultFormBuilder builder = new DefaultFormBuilder(formLayout, form);
builder.add(new StreamflowButton(getActionMap().get("edit")));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.name_label));
builder.nextColumn(2);
builder.add(viewBinder.bind("name", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.phone_label));
builder.nextColumn(2);
builder.add(phoneViewBinder.bind("phoneNumber", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.address_label));
builder.nextColumn(2);
builder.add(addressViewBinder.bind("address", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.zip_label));
builder.nextColumn(2);
builder.add(addressViewBinder.bind("zipCode", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.city_label));
builder.nextColumn(2);
builder.add(addressViewBinder.bind("city", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.region_label));
builder.nextColumn(2);
builder.add(addressViewBinder.bind("region", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.country_label));
builder.nextColumn(2);
builder.add(addressViewBinder.bind("country", visibleIfNotEmpty(new JLabel("!"))));
builder.nextLine();
builder.add(createLabel(WorkspaceResources.email_label));
builder.nextColumn( 2 );
builder.add( emailViewBinder.bind( "emailAddress", visibleIfNotEmpty( new JLabel( "!" ) ) ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.contact_id_label ) );
builder.nextColumn( 2 );
builder.add( viewBinder.bind( "contactId", visibleIfNotEmpty( new JLabel( "!" ) ) ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.company_label ) );
builder.nextColumn( 2 );
builder.add( viewBinder.bind( "company", visibleIfNotEmpty( new JLabel( "!" ) ) ) );
builder.nextLine();
builder.add( createLabel( WorkspaceResources.contact_preference_label ) );
builder.nextColumn( 2 );
builder.add( contactPreferenceLabel );
builder.nextLine(2);
builder.add(createLabel(WorkspaceResources.note_label));
builder.nextColumn(2);
builder.add(viewBinder.bind("note", visibleIfNotEmpty(new JLabel("!"))));
add(scrollPane, "VIEW");
}
}
private JLabel createLabel(Enum key)
{
JLabel label = new JLabel(i18n.text(key));
label.setForeground(Color.gray);
return label;
}
public void setModel(ContactModel model )
{
this.model = model;
if (model != null)
{
updateFromModel( model );
javax.swing.Action action = getActionMap().get("lookupContact");
action.setEnabled(model.isContactLookupEnabled());
lookupPanel.setVisible(action.isEnabled());
// TODO do a better way of checking if the contact is empty
if (model.getContact().toJSON().equals("{\"addresses\":[{\"address\":\"\",\"city\":\"\",\"contactType\":\"HOME\",\"country\":\"\",\"region\":\"\",\"zipCode\":\"\"}],\"company\":\"\",\"contactId\":\"\",\"contactPreference\":\"none\",\"emailAddresses\":[{\"contactType\":\"HOME\",\"emailAddress\":\"\"}],\"isCompany\":false,\"name\":\"\",\"note\":\"\",\"phoneNumbers\":[{\"contactType\":\"HOME\",\"phoneNumber\":\"\"}],\"picture\":\"\"}"))
{
layout.show(this, "EDIT");
} else
{
layout.show(this, "VIEW");
}
} else
{
layout.show(this, "EMPTY");
}
}
public void updateFromModel( ContactModel model )
{
handleContactPreference();
suggestModel.setContactModel( model );
contactBinder.updateWith(model.getContact());
phoneNumberBinder.updateWith(model.getPhoneNumber());
addressBinder.updateWith(model.getAddress());
suggestAddress.getTextField().setText( model.getAddress().address() != null ? model.getAddress().address().get() : "" );
emailBinder.updateWith(model.getEmailAddress());
viewBinder.update( model.getContact() );
phoneViewBinder.update(model.getPhoneNumber());
addressViewBinder.update(model.getAddress());
emailViewBinder.update(model.getEmailAddress());
}
public void update(Observable observable, Object arg)
{
final Property property = (Property) arg;
new CommandTask()
{
@Override
public void command()
throws Exception
{
String propertyName = property.qualifiedName().name();
if (propertyName.equals("name"))
{
model.changeName((String) property.get());
} else if (propertyName.equals("note"))
{
model.changeNote((String) property.get());
} else if (propertyName.equals("company"))
{
model.changeCompany((String) property.get());
} else if (propertyName.equals("phoneNumber"))
{
model.changePhoneNumber((String) property.get());
} else if (propertyName.equals("address"))
{
model.changeAddress((String) property.get());
} else if (propertyName.equals("zipCode"))
{
model.changeZipCode((String) property.get());
} else if (propertyName.equals("city"))
{
model.changeCity((String) property.get());
} else if (propertyName.equals("region"))
{
model.changeRegion((String) property.get());
} else if (propertyName.equals("country"))
{
model.changeCountry((String) property.get());
} else if (propertyName.equals("emailAddress"))
{
model.changeEmailAddress((String) property.get());
} else if (propertyName.equals("contactId"))
{
model.changeContactId((String) property.get());
} else if (propertyName.equals( "contactPreference" ))
{
if ( property.get() instanceof ContactPreference )
{
model.changeContactPreference( (ContactPreference) property.get() );
} else
{
model.changeContactPreference( null );
}
}
}
}.execute();
}
@Action
public void edit()
{
layout.show(this, "EDIT");
}
@Action
public void view()
{
setModel(model);
layout.show(this, "VIEW");
}
@Action
public void lookupContact()
{
try
{
ContactDTO query = createContactQuery();
ContactDTO emptyCriteria = module.valueBuilderFactory().newValueBuilder(ContactDTO.class).newInstance();
if (emptyCriteria.equals(query))
{
String msg = i18n.text(CaseResources.could_not_find_search_criteria);
dialogs.showMessageDialog(this, msg, "Info");
} else
{
ContactsDTO contacts = model.searchContacts(query);
if (contacts.contacts().get().isEmpty())
{
String msg = i18n.text(CaseResources.could_not_find_contacts);
dialogs.showMessageDialog(this, msg, "Info");
} else
{
ContactLookupResultDialog dialog = module.objectBuilderFactory().newObjectBuilder(ContactLookupResultDialog.class).use(
contacts.contacts().get()).newInstance();
dialogs.showOkCancelHelpDialog(WindowUtils.findWindow(this), dialog, i18n.text(WorkspaceResources.contacts_tab));
ContactDTO contactValue = dialog.getSelectedContact();
if (contactValue != null)
{
if (defaultFocusField.getText().equals("") && !contactValue.name().get().equals(""))
{
model.changeName(contactValue.name().get());
defaultFocusField.setText(contactValue.name().get());
}
for (ContactPhoneDTO contactPhoneDTO : contactValue.phoneNumbers().get())
{
if (!contactPhoneDTO.phoneNumber().get().equals("") && model.getPhoneNumber().phoneNumber().get().equals(""))
{
model.changePhoneNumber(contactPhoneDTO.phoneNumber().get());
phoneField.setText(contactPhoneDTO.phoneNumber().get());
}
}
List<ContactAddressDTO> addressDTOs = contactValue.addresses().get();
for (ContactAddressDTO addressDTO : addressDTOs)
{
if (!addressDTO.address().get().equals("") && model.getAddress().address().get().equals(""))
{
model.changeAddress(addressDTO.address().get());
addressField.setText(addressDTO.address().get());
}
}
List<ContactEmailDTO> emailDTOs = contactValue.emailAddresses().get();
for (ContactEmailDTO emailDTO : emailDTOs)
{
if (!emailDTO.emailAddress().get().equals("") && model.getEmailAddress().emailAddress().get().equals(""))
{
model.changeEmailAddress(emailDTO.emailAddress().get());
emailField.setText(emailDTO.emailAddress().get());
}
}
if (contactIdField.getText().equals("") && !contactValue.contactId().get().equals(""))
{
model.changeContactId(contactValue.contactId().get());
contactIdField.setText(contactValue.contactId().get());
}
if (companyField.getText().equals("") && !contactValue.company().get().equals(""))
{
model.changeCompany(contactValue.company().get());
companyField.setText(contactValue.company().get());
}
}
}
}
} catch (ResourceException e)
{
e.printStackTrace();
}
}
private ContactDTO createContactQuery()
{
ValueBuilder<ContactDTO> contactBuilder = module.valueBuilderFactory().newValueBuilder(ContactDTO.class);
if (!defaultFocusField.getText().isEmpty())
{
contactBuilder.prototype().name().set(defaultFocusField.getText());
}
if (!phoneField.getText().isEmpty())
{
ValueBuilder<ContactPhoneDTO> builder = module.valueBuilderFactory().newValueBuilder(ContactPhoneDTO.class);
builder.prototype().phoneNumber().set(phoneField.getText());
contactBuilder.prototype().phoneNumbers().get().add(builder.newInstance());
}
if (!addressField.getText().isEmpty())
{
ValueBuilder<ContactAddressDTO> builder = module.valueBuilderFactory().newValueBuilder(ContactAddressDTO.class);
builder.prototype().address().set(addressField.getText());
contactBuilder.prototype().addresses().get().add(builder.newInstance());
}
if (!emailField.getText().isEmpty())
{
ValueBuilder<ContactEmailDTO> builder = module.valueBuilderFactory().newValueBuilder(ContactEmailDTO.class);
builder.prototype().emailAddress().set(emailField.getText());
contactBuilder.prototype().emailAddresses().get().add(builder.newInstance());
}
if (!contactIdField.getText().isEmpty())
{
contactBuilder.prototype().contactId().set(contactIdField.getText());
}
if (!companyField.getText().isEmpty())
{
contactBuilder.prototype().contactId().set(contactIdField.getText());
}
return contactBuilder.newInstance();
}
private void handleContactPreference()
{
ContactPreference val = model.getContact().contactPreference().get();
if ( val == null )
{
model.getContact().contactPreference().set( ContactPreference.none );
val = model.getContact().contactPreference().get();
}
if ( val == ContactPreference.none )
{
contactPreferenceLabel.setVisible( false );
} else
{
contactPreferenceLabel.setVisible( true );
contactPreferenceLabel.setText( i18n.text( WorkspaceResources.valueOf( val.name() ) ) );
}
alignSibling( contactPreferenceLabel );
}
private JLabel visibleIfNotEmpty(final JLabel label)
{
label.addPropertyChangeListener("text", new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent evt)
{
label.setVisible(!evt.getNewValue().equals(""));
alignSibling( label );
}
});
return label;
}
private void alignSibling( JLabel label )
{
Container container = label.getParent();
for (int i = 0; i < container.getComponents().length; i++)
{
Component component = container.getComponents()[i];
if (component == label)
{
JLabel labelForLabel = (JLabel) container.getComponent(i - 1);
labelForLabel.setVisible(label.isVisible());
}
}
}
public void setFocusOnName()
{
defaultFocusField.requestFocusInWindow();
}
}