2
0

Support for deleting sites from the Java GUI.

This commit is contained in:
Maarten Billemont 2015-04-03 12:12:12 -04:00
parent d05c5eedd8
commit 5f0367ad29
7 changed files with 85 additions and 40 deletions

3
.idea/encodings.xml Normal file → Executable file
View File

@ -7,4 +7,5 @@
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-gui" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-gui" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-model" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-model" charset="UTF-8" />
</component> </component>
</project> </project>

View File

@ -41,4 +41,8 @@ public class IncognitoUser extends User {
@Override @Override
public void addSite(final Site site) { public void addSite(final Site site) {
} }
@Override
public void deleteSite(Site site) {
}
} }

View File

@ -16,6 +16,10 @@ public class ModelSite extends Site {
this.model = result.getSite(); this.model = result.getSite();
} }
public MPSite getModel() {
return model;
}
public String getSiteName() { public String getSiteName() {
return model.getSiteName(); return model.getSiteName();
} }

View File

@ -42,7 +42,7 @@ public class ModelUser extends User {
} }
public void setAvatar(final int avatar) { public void setAvatar(final int avatar) {
model.setAvatar( avatar % Res.avatars() ); model.setAvatar(avatar % Res.avatars());
MPUserFileManager.get().save(); MPUserFileManager.get().save();
} }
@ -67,8 +67,8 @@ public class ModelUser extends User {
return FluentIterable.from( model.findSitesByName( query ) ).transform( new Function<MPSiteResult, Site>() { return FluentIterable.from( model.findSitesByName( query ) ).transform( new Function<MPSiteResult, Site>() {
@Nullable @Nullable
@Override @Override
public Site apply(@Nullable final MPSiteResult result) { public Site apply(@Nullable final MPSiteResult site) {
return new ModelSite( Preconditions.checkNotNull( result ) ); return new ModelSite( Preconditions.checkNotNull( site ) );
} }
} ); } );
} }
@ -80,6 +80,14 @@ public class ModelUser extends User {
MPUserFileManager.get().save(); MPUserFileManager.get().save();
} }
@Override
public void deleteSite(Site site) {
if (site instanceof ModelSite) {
model.deleteSite(((ModelSite) site).getModel());
MPUserFileManager.get().save();
}
}
public boolean keySaved() { public boolean keySaved() {
// TODO // TODO
return false; return false;

View File

@ -1,9 +1,13 @@
package com.lyndir.masterpassword.gui; package com.lyndir.masterpassword.gui;
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
import static com.lyndir.lhunath.opal.system.util.StringUtils.*; import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.*; import com.google.common.util.concurrent.*;
import com.lyndir.lhunath.opal.system.util.NNSupplier;
import com.lyndir.lhunath.opal.system.util.PredicateNN;
import com.lyndir.masterpassword.*; import com.lyndir.masterpassword.*;
import com.lyndir.masterpassword.gui.util.Components; import com.lyndir.masterpassword.gui.util.Components;
import java.awt.*; import java.awt.*;
@ -24,7 +28,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
private final User user; private final User user;
private final Components.GradientPanel root; private final Components.GradientPanel root;
private final JTextField siteNameField; private final JTextField siteNameField;
private final JButton siteAddButton; private final JButton siteActionButton;
private final JComboBox<MPSiteType> siteTypeField; private final JComboBox<MPSiteType> siteTypeField;
private final JComboBox<MasterKey.Version> siteVersionField; private final JComboBox<MasterKey.Version> siteVersionField;
private final JSpinner siteCounterField; private final JSpinner siteCounterField;
@ -33,8 +37,10 @@ public class PasswordFrame extends JFrame implements DocumentListener {
private final JCheckBox maskPasswordField; private final JCheckBox maskPasswordField;
private final char passwordEchoChar; private final char passwordEchoChar;
private final Font passwordEchoFont; private final Font passwordEchoFont;
private boolean updatingUI;
@Nullable
private Site currentSite; private Site currentSite;
private boolean updatingUI;
public PasswordFrame(User user) public PasswordFrame(User user)
throws HeadlessException { throws HeadlessException {
@ -58,45 +64,48 @@ public class PasswordFrame extends JFrame implements DocumentListener {
sitePanel.add( Components.stud() ); sitePanel.add( Components.stud() );
// Site Name // Site Name
sitePanel.add( Components.label( "Site Name:" ) ); sitePanel.add(Components.label("Site Name:"));
JComponent siteControls = Components.boxLayout( BoxLayout.LINE_AXIS, // JComponent siteControls = Components.boxLayout( BoxLayout.LINE_AXIS, //
siteNameField = Components.textField(), Components.stud(), siteNameField = Components.textField(), Components.stud(),
siteAddButton = Components.button( "Add Site" ) ); siteActionButton = Components.button( "Add Site" ) );
siteNameField.getDocument().addDocumentListener( this ); siteNameField.getDocument().addDocumentListener(this);
siteNameField.addActionListener( new ActionListener() { siteNameField.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(final ActionEvent e) { public void actionPerformed(final ActionEvent e) {
Futures.addCallback( updatePassword(), new FutureCallback<String>() { Futures.addCallback(updatePassword(true), new FutureCallback<String>() {
@Override @Override
public void onSuccess(@Nullable final String sitePassword) { public void onSuccess(@Nullable final String sitePassword) {
StringSelection clipboardContents = new StringSelection( sitePassword ); StringSelection clipboardContents = new StringSelection(sitePassword);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents( clipboardContents, null ); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboardContents, null);
SwingUtilities.invokeLater( new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
passwordField.setText( null ); passwordField.setText(null);
siteNameField.setText( null ); siteNameField.setText(null);
dispatchEvent( new WindowEvent( PasswordFrame.this, WindowEvent.WINDOW_CLOSING ) ); dispatchEvent(new WindowEvent(PasswordFrame.this, WindowEvent.WINDOW_CLOSING));
} }
} ); });
} }
@Override @Override
public void onFailure(final Throwable t) { public void onFailure(final Throwable t) {
} }
} ); });
} }
} ); });
siteAddButton.setVisible( false ); siteActionButton.addActionListener(new ActionListener() {
siteAddButton.addActionListener( new ActionListener() {
@Override @Override
public void actionPerformed(final ActionEvent e) { public void actionPerformed(final ActionEvent e) {
PasswordFrame.this.user.addSite( currentSite ); if (currentSite instanceof ModelSite)
siteAddButton.setVisible( false ); PasswordFrame.this.user.deleteSite(currentSite);
else
PasswordFrame.this.user.addSite(currentSite);
updatePassword(true);
} }
} ); });
sitePanel.add( siteControls ); sitePanel.add( siteControls );
sitePanel.add( Components.stud() ); sitePanel.add( Components.stud() );
@ -115,7 +124,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
siteTypeField.addItemListener( new ItemListener() { siteTypeField.addItemListener( new ItemListener() {
@Override @Override
public void itemStateChanged(final ItemEvent e) { public void itemStateChanged(final ItemEvent e) {
updatePassword(); updatePassword(true);
} }
} ); } );
@ -125,7 +134,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
siteVersionField.addItemListener( new ItemListener() { siteVersionField.addItemListener( new ItemListener() {
@Override @Override
public void itemStateChanged(final ItemEvent e) { public void itemStateChanged(final ItemEvent e) {
updatePassword(); updatePassword(true);
} }
} ); } );
@ -134,7 +143,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
siteCounterField.addChangeListener( new ChangeListener() { siteCounterField.addChangeListener( new ChangeListener() {
@Override @Override
public void stateChanged(final ChangeEvent e) { public void stateChanged(final ChangeEvent e) {
updatePassword(); updatePassword(true);
} }
} ); } );
@ -186,25 +195,33 @@ public class PasswordFrame extends JFrame implements DocumentListener {
} }
@Nonnull @Nonnull
private ListenableFuture<String> updatePassword() { private ListenableFuture<String> updatePassword(boolean allowNameCompletion) {
final String siteNameQuery = siteNameField.getText(); final String siteNameQuery = siteNameField.getText();
if (updatingUI) if (updatingUI)
return Futures.immediateCancelledFuture(); return Futures.immediateCancelledFuture();
if (siteNameQuery == null || siteNameQuery.isEmpty() || !user.isKeyAvailable()) { if (siteNameQuery == null || siteNameQuery.isEmpty() || !user.isKeyAvailable()) {
siteActionButton.setVisible(false);
tipLabel.setText( null ); tipLabel.setText( null );
passwordField.setText( null ); passwordField.setText( null );
return Futures.immediateCancelledFuture(); return Futures.immediateCancelledFuture();
} }
final MPSiteType siteType = siteTypeField.getModel().getElementAt( siteTypeField.getSelectedIndex() ); final MPSiteType siteType = siteTypeField.getModel().getElementAt(siteTypeField.getSelectedIndex());
final MasterKey.Version siteVersion = siteVersionField.getItemAt( siteVersionField.getSelectedIndex() ); final MasterKey.Version siteVersion = siteVersionField.getItemAt(siteVersionField.getSelectedIndex());
final int siteCounter = (Integer) siteCounterField.getValue(); final int siteCounter = (Integer) siteCounterField.getValue();
final Site site = currentSite != null && currentSite.getSiteName().equals( siteNameQuery )? currentSite
: Iterables.getFirst( user.findSitesByName( siteNameQuery ), Iterable<Site> siteResults = user.findSitesByName(siteNameQuery);
new IncognitoSite( siteNameQuery, siteType, siteCounter, siteVersion ) ); if (!allowNameCompletion)
assert site != null; siteResults = FluentIterable.from(siteResults).filter(new PredicateNN<Site>() {
if (site == currentSite) { @Override
public boolean apply(Site input) {
return siteNameQuery.equals(input.getSiteName());
}
});
final Site site = Iterables.getFirst(siteResults,
new IncognitoSite(siteNameQuery, siteType, siteCounter, siteVersion) );
if (currentSite != null && site.getSiteName().equals(currentSite.getSiteName())) {
site.setSiteType( siteType ); site.setSiteType( siteType );
site.setAlgorithmVersion( siteVersion ); site.setAlgorithmVersion( siteVersion );
site.setSiteCounter( siteCounter ); site.setSiteCounter( siteCounter );
@ -226,8 +243,12 @@ public class PasswordFrame extends JFrame implements DocumentListener {
public void run() { public void run() {
updatingUI = true; updatingUI = true;
currentSite = site; currentSite = site;
siteAddButton.setVisible( user instanceof ModelUser && !(currentSite instanceof ModelSite) ); siteActionButton.setVisible(user instanceof ModelUser);
siteTypeField.setSelectedItem( currentSite.getSiteType() ); if (currentSite instanceof ModelSite)
siteActionButton.setText("Delete Site");
else
siteActionButton.setText("Add Site");
siteTypeField.setSelectedItem(currentSite.getSiteType());
siteVersionField.setSelectedItem( currentSite.getAlgorithmVersion() ); siteVersionField.setSelectedItem( currentSite.getAlgorithmVersion() );
siteCounterField.setValue( currentSite.getSiteCounter() ); siteCounterField.setValue( currentSite.getSiteCounter() );
siteNameField.setText( currentSite.getSiteName() ); siteNameField.setText( currentSite.getSiteName() );
@ -251,15 +272,16 @@ public class PasswordFrame extends JFrame implements DocumentListener {
@Override @Override
public void insertUpdate(final DocumentEvent e) { public void insertUpdate(final DocumentEvent e) {
updatePassword(); updatePassword(true);
} }
@Override @Override
public void removeUpdate(final DocumentEvent e) { public void removeUpdate(final DocumentEvent e) {
updatePassword(false);
} }
@Override @Override
public void changedUpdate(final DocumentEvent e) { public void changedUpdate(final DocumentEvent e) {
updatePassword(); updatePassword(true);
} }
} }

View File

@ -62,6 +62,8 @@ public abstract class User {
public abstract void addSite(final Site site); public abstract void addSite(final Site site);
public abstract void deleteSite(final Site site);
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
return this == obj || obj instanceof User && Objects.equals( getFullName(), ((User) obj).getFullName() ); return this == obj || obj instanceof User && Objects.equals( getFullName(), ((User) obj).getFullName() );

View File

@ -59,6 +59,10 @@ public class MPUser implements Comparable<MPUser> {
sites.add( site ); sites.add( site );
} }
public void deleteSite(final MPSite site) {
sites.remove( site );
}
public String getFullName() { public String getFullName() {
return fullName; return fullName;
} }