Adding and deleting users and sites.
This commit is contained in:
parent
8cd9755616
commit
7455fba55e
@ -83,6 +83,10 @@ public abstract class Components {
|
|||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GradientPanel panel(@Nullable final LayoutManager layout) {
|
||||||
|
return panel( layout, null );
|
||||||
|
}
|
||||||
|
|
||||||
public static GradientPanel panel(@Nullable final LayoutManager layout, @Nullable final Color color) {
|
public static GradientPanel panel(@Nullable final LayoutManager layout, @Nullable final Color color) {
|
||||||
return new GradientPanel( layout, color );
|
return new GradientPanel( layout, color );
|
||||||
}
|
}
|
||||||
@ -223,6 +227,11 @@ public abstract class Components {
|
|||||||
if (actionListener != null)
|
if (actionListener != null)
|
||||||
actionListener.actionPerformed( e );
|
actionListener.actionPerformed( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return actionListener != null;
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +242,11 @@ public abstract class Components {
|
|||||||
if (actionListener != null)
|
if (actionListener != null)
|
||||||
actionListener.actionPerformed( e );
|
actionListener.actionPerformed( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return actionListener != null;
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
iconButton.setFocusable( false );
|
iconButton.setFocusable( false );
|
||||||
|
|
||||||
@ -441,6 +455,9 @@ public abstract class Components {
|
|||||||
|
|
||||||
public GradientPanel(@Nullable final LayoutManager layout, @Nullable final Color gradientColor) {
|
public GradientPanel(@Nullable final LayoutManager layout, @Nullable final Color gradientColor) {
|
||||||
super( layout );
|
super( layout );
|
||||||
|
if (getLayout() == null)
|
||||||
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
|
|
||||||
setGradientColor( gradientColor );
|
setGradientColor( gradientColor );
|
||||||
setBackground( null );
|
setBackground( null );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
@ -459,7 +476,7 @@ public abstract class Components {
|
|||||||
@Override
|
@Override
|
||||||
public void setBackground(@Nullable final Color bg) {
|
public void setBackground(@Nullable final Color bg) {
|
||||||
super.setBackground( bg );
|
super.setBackground( bg );
|
||||||
updatePaint();
|
setOpaque( bg != null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -469,8 +486,6 @@ public abstract class Components {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updatePaint() {
|
private void updatePaint() {
|
||||||
setOpaque( (getGradientColor() != null) || (getBackground() != null) );
|
|
||||||
|
|
||||||
if (gradientColor == null) {
|
if (gradientColor == null) {
|
||||||
paint = null;
|
paint = null;
|
||||||
return;
|
return;
|
||||||
|
@ -128,6 +128,10 @@ public abstract class Res {
|
|||||||
return icon( "media/icon_user.png" );
|
return icon( "media/icon_user.png" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Icon lock() {
|
||||||
|
return icon( "media/icon_lock.png" );
|
||||||
|
}
|
||||||
|
|
||||||
public Icon settings() {
|
public Icon settings() {
|
||||||
return icon( "media/icon_settings.png" );
|
return icon( "media/icon_settings.png" );
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ package com.lyndir.masterpassword.gui.view;
|
|||||||
|
|
||||||
import static com.lyndir.masterpassword.util.Utilities.*;
|
import static com.lyndir.masterpassword.util.Utilities.*;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.lyndir.masterpassword.gui.util.Res;
|
import com.lyndir.masterpassword.gui.util.Res;
|
||||||
import com.lyndir.masterpassword.gui.util.CollectionListModel;
|
import com.lyndir.masterpassword.gui.util.CollectionListModel;
|
||||||
import com.lyndir.masterpassword.gui.util.Components;
|
import com.lyndir.masterpassword.gui.util.Components;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
import com.lyndir.masterpassword.model.MPUser;
|
||||||
|
import com.lyndir.masterpassword.model.impl.MPFileUser;
|
||||||
import com.lyndir.masterpassword.model.impl.MPFileUserManager;
|
import com.lyndir.masterpassword.model.impl.MPFileUserManager;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -18,7 +20,7 @@ import javax.swing.*;
|
|||||||
* @author lhunath, 2018-07-14
|
* @author lhunath, 2018-07-14
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class FilesPanel extends JPanel {
|
public class FilesPanel extends JPanel implements MPFileUserManager.Listener {
|
||||||
|
|
||||||
private final Collection<Listener> listeners = new CopyOnWriteArraySet<>();
|
private final Collection<Listener> listeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
@ -48,11 +50,8 @@ public class FilesPanel extends JPanel {
|
|||||||
|
|
||||||
// User Selection
|
// User Selection
|
||||||
add( userField );
|
add( userField );
|
||||||
}
|
|
||||||
|
|
||||||
public void reload() {
|
MPFileUserManager.get().addListener( this );
|
||||||
// TODO: Should we use a listener here instead?
|
|
||||||
usersModel.set( MPFileUserManager.get().reload() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addListener(final Listener listener) {
|
public boolean addListener(final Listener listener) {
|
||||||
@ -75,6 +74,11 @@ public class FilesPanel extends JPanel {
|
|||||||
listener.onUserSelected( user );
|
listener.onUserSelected( user );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFilesUpdated(final ImmutableSortedSet<MPFileUser> files) {
|
||||||
|
usersModel.set( files );
|
||||||
|
}
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
|
|
||||||
void onUserSelected(@Nullable MPUser<?> user);
|
void onUserSelected(@Nullable MPUser<?> user);
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package com.lyndir.masterpassword.gui.view;
|
package com.lyndir.masterpassword.gui.view;
|
||||||
|
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.masterpassword.gui.util.Res;
|
|
||||||
import com.lyndir.masterpassword.gui.util.Components;
|
import com.lyndir.masterpassword.gui.util.Components;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
import com.lyndir.masterpassword.gui.util.Res;
|
||||||
|
import com.lyndir.masterpassword.model.impl.MPFileUserManager;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.BevelBorder;
|
import javax.swing.border.BevelBorder;
|
||||||
|
|
||||||
@ -16,57 +15,48 @@ import javax.swing.border.BevelBorder;
|
|||||||
* @author lhunath, 2018-07-14
|
* @author lhunath, 2018-07-14
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class MasterPasswordFrame extends JFrame implements FilesPanel.Listener, ComponentListener {
|
public class MasterPasswordFrame extends JFrame {
|
||||||
|
|
||||||
private static final Logger logger = Logger.get( MasterPasswordFrame.class );
|
private static final Logger logger = Logger.get( MasterPasswordFrame.class );
|
||||||
|
|
||||||
@SuppressWarnings("FieldCanBeLocal")
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private final Components.GradientPanel root;
|
private final Components.GradientPanel root = Components.borderPanel( Res.colors().frameBg(), BoxLayout.PAGE_AXIS );
|
||||||
private final FilesPanel filesPanel = new FilesPanel();
|
private final FilesPanel filesPanel = new FilesPanel();
|
||||||
private final UserPanel userPanel = new UserPanel();
|
private final JPanel userPanel = Components.panel( new BorderLayout( 0, 0 ) );
|
||||||
|
private final UserContentPanel userContent = new UserContentPanel();
|
||||||
|
|
||||||
@SuppressWarnings("MagicNumber")
|
@SuppressWarnings("MagicNumber")
|
||||||
public MasterPasswordFrame() {
|
public MasterPasswordFrame() {
|
||||||
super( "Master Password" );
|
super( "Master Password" );
|
||||||
|
|
||||||
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
setContentPane( root );
|
||||||
setContentPane( root = Components.borderPanel( Res.colors().frameBg(), BoxLayout.PAGE_AXIS ) );
|
|
||||||
root.add( filesPanel );
|
root.add( filesPanel );
|
||||||
root.add( Components.strut() );
|
root.add( Components.strut() );
|
||||||
root.add( Components.borderPanel(
|
root.add( userPanel );
|
||||||
|
|
||||||
|
userPanel.add( userContent.getUserToolbar(), BorderLayout.LINE_START );
|
||||||
|
userPanel.add( userContent.getSiteToolbar(), BorderLayout.LINE_END );
|
||||||
|
userPanel.add( Components.borderPanel(
|
||||||
BorderFactory.createBevelBorder( BevelBorder.RAISED, Res.colors().controlBorder(), Res.colors().frameBg() ),
|
BorderFactory.createBevelBorder( BevelBorder.RAISED, Res.colors().controlBorder(), Res.colors().frameBg() ),
|
||||||
Res.colors().controlBg(), BoxLayout.PAGE_AXIS, userPanel ) );
|
Res.colors().controlBg(), BoxLayout.PAGE_AXIS, userContent ), BorderLayout.CENTER );
|
||||||
|
|
||||||
filesPanel.addListener( this );
|
filesPanel.addListener( userContent );
|
||||||
filesPanel.reload();
|
|
||||||
|
|
||||||
addComponentListener( this );
|
addComponentListener( new ComponentHandler() );
|
||||||
setPreferredSize( new Dimension( 640, 480 ) );
|
setPreferredSize( new Dimension( 800, 560 ) );
|
||||||
|
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
||||||
pack();
|
pack();
|
||||||
|
|
||||||
setLocationRelativeTo( null );
|
setLocationRelativeTo( null );
|
||||||
setLocationByPlatform( true );
|
setLocationByPlatform( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private class ComponentHandler extends ComponentAdapter {
|
||||||
public void onUserSelected(@Nullable final MPUser<?> user) {
|
|
||||||
userPanel.setUser( user );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentResized(final ComponentEvent e) {
|
public void componentShown(final ComponentEvent e) {
|
||||||
}
|
MPFileUserManager.get().reload();
|
||||||
|
userContent.transferFocus();
|
||||||
@Override
|
}
|
||||||
public void componentMoved(final ComponentEvent e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void componentShown(final ComponentEvent e) {
|
|
||||||
userPanel.transferFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void componentHidden(final ComponentEvent e) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@ import com.lyndir.masterpassword.*;
|
|||||||
import com.lyndir.masterpassword.gui.model.MPNewSite;
|
import com.lyndir.masterpassword.gui.model.MPNewSite;
|
||||||
import com.lyndir.masterpassword.gui.util.*;
|
import com.lyndir.masterpassword.gui.util.*;
|
||||||
import com.lyndir.masterpassword.model.*;
|
import com.lyndir.masterpassword.model.*;
|
||||||
import com.lyndir.masterpassword.model.impl.MPFileSite;
|
import com.lyndir.masterpassword.model.impl.*;
|
||||||
import com.lyndir.masterpassword.model.impl.MPFileUser;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
@ -32,44 +31,38 @@ import javax.swing.event.DocumentListener;
|
|||||||
* @author lhunath, 2018-07-14
|
* @author lhunath, 2018-07-14
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("SerializableStoresNonSerializable")
|
@SuppressWarnings("SerializableStoresNonSerializable")
|
||||||
public class UserPanel extends Components.GradientPanel implements MPUser.Listener {
|
public class UserContentPanel extends JPanel implements FilesPanel.Listener, MPUser.Listener {
|
||||||
|
|
||||||
private static final Logger logger = Logger.get( UserPanel.class );
|
private static final Random random = new Random();
|
||||||
|
private static final Logger logger = Logger.get( UserContentPanel.class );
|
||||||
|
private static final JButton iconButton = Components.button( Res.icons().user(), null );
|
||||||
|
|
||||||
|
private final JPanel userToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
||||||
|
private final JPanel siteToolbar = Components.panel( BoxLayout.PAGE_AXIS );
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private MPUser<?> user;
|
private MPUser<?> listeningUser;
|
||||||
|
|
||||||
public UserPanel() {
|
public UserContentPanel() {
|
||||||
super( new BorderLayout( Components.margin(), Components.margin() ), null );
|
userToolbar.setPreferredSize( iconButton.getPreferredSize() );
|
||||||
|
siteToolbar.setPreferredSize( iconButton.getPreferredSize() );
|
||||||
|
|
||||||
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
setBorder( Components.marginBorder() );
|
setBorder( Components.marginBorder() );
|
||||||
setUser( null );
|
setUser( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUser(@Nullable final MPUser<?> user) {
|
protected JComponent getUserToolbar() {
|
||||||
if ((this.user != null) && !Objects.equals( this.user, user ))
|
return userToolbar;
|
||||||
this.user.removeListener( this );
|
}
|
||||||
|
|
||||||
this.user = user;
|
protected JComponent getSiteToolbar() {
|
||||||
|
return siteToolbar;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.user != null)
|
@Override
|
||||||
this.user.addListener( this );
|
public void onUserSelected(@Nullable final MPUser<?> user) {
|
||||||
|
setUser( user );
|
||||||
Res.ui( () -> {
|
|
||||||
removeAll();
|
|
||||||
if (this.user == null)
|
|
||||||
add( new NoUserPanel(), BorderLayout.CENTER );
|
|
||||||
|
|
||||||
else {
|
|
||||||
if (!this.user.isMasterKeyAvailable())
|
|
||||||
add( new AuthenticateUserPanel( this.user ), BorderLayout.CENTER );
|
|
||||||
|
|
||||||
else
|
|
||||||
add( new AuthenticatedUserPanel( this.user ), BorderLayout.CENTER );
|
|
||||||
}
|
|
||||||
|
|
||||||
revalidate();
|
|
||||||
transferFocus();
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,7 +75,40 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
setUser( user );
|
setUser( user );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class NoUserPanel extends JPanel {
|
@Override
|
||||||
|
public void onUserInvalidated(final MPUser<?> user) {
|
||||||
|
setUser( user );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUser(@Nullable final MPUser<?> user) {
|
||||||
|
Res.ui( () -> {
|
||||||
|
if (listeningUser != null)
|
||||||
|
listeningUser.removeListener( this );
|
||||||
|
listeningUser = user;
|
||||||
|
|
||||||
|
userToolbar.removeAll();
|
||||||
|
siteToolbar.removeAll();
|
||||||
|
removeAll();
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
add( new NoUserPanel() );
|
||||||
|
|
||||||
|
else {
|
||||||
|
user.addListener( this );
|
||||||
|
|
||||||
|
if (!user.isMasterKeyAvailable())
|
||||||
|
add( new AuthenticateUserPanel( user ) );
|
||||||
|
|
||||||
|
else
|
||||||
|
add( new AuthenticatedUserPanel( user ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidate();
|
||||||
|
transferFocus();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class NoUserPanel extends JPanel {
|
||||||
|
|
||||||
private NoUserPanel() {
|
private NoUserPanel() {
|
||||||
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
@ -94,13 +120,14 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final class AuthenticateUserPanel extends JPanel implements ActionListener, DocumentListener {
|
private final class AuthenticateUserPanel extends JPanel implements ActionListener, DocumentListener {
|
||||||
|
|
||||||
private static final Random random = new Random();
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final MPUser<?> user;
|
private final MPUser<?> user;
|
||||||
|
|
||||||
|
private final JButton addButton = Components.button( Res.icons().add(), event -> addUser() );
|
||||||
|
private final JButton deleteButton = Components.button( Res.icons().delete(), event -> deleteUser() );
|
||||||
|
|
||||||
private final JPasswordField masterPasswordField = Components.passwordField();
|
private final JPasswordField masterPasswordField = Components.passwordField();
|
||||||
private final JLabel errorLabel = Components.label();
|
private final JLabel errorLabel = Components.label();
|
||||||
private final JLabel identiconLabel = Components.label( SwingConstants.CENTER );
|
private final JLabel identiconLabel = Components.label( SwingConstants.CENTER );
|
||||||
@ -112,7 +139,14 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
|
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
||||||
|
userToolbar.add( addButton );
|
||||||
|
userToolbar.add( deleteButton );
|
||||||
|
|
||||||
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
|
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
|
||||||
|
add( Components.strut() );
|
||||||
|
|
||||||
|
add( identiconLabel );
|
||||||
|
identiconLabel.setFont( Res.fonts().emoticonsFont( Components.TEXT_SIZE_CONTROL ) );
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
|
|
||||||
add( Components.label( "Master Password:" ) );
|
add( Components.label( "Master Password:" ) );
|
||||||
@ -122,14 +156,31 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
masterPasswordField.getDocument().addDocumentListener( this );
|
masterPasswordField.getDocument().addDocumentListener( this );
|
||||||
add( errorLabel );
|
add( errorLabel );
|
||||||
errorLabel.setForeground( Res.colors().errorFg() );
|
errorLabel.setForeground( Res.colors().errorFg() );
|
||||||
|
|
||||||
add( Components.strut() );
|
|
||||||
add( identiconLabel );
|
|
||||||
identiconLabel.setFont( Res.fonts().emoticonsFont( Components.TEXT_SIZE_CONTROL ) );
|
|
||||||
|
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addUser() {
|
||||||
|
Object fullName = JOptionPane.showInputDialog(
|
||||||
|
this, strf( "<html>Enter your full legal name:</html>" ), "Add User",
|
||||||
|
JOptionPane.QUESTION_MESSAGE, null, null, "Robert Lee Mitchell" );
|
||||||
|
if (fullName == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setUser( MPFileUserManager.get().add( fullName.toString() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteUser() {
|
||||||
|
MPFileUser fileUser = (user instanceof MPFileUser)? (MPFileUser) user: null;
|
||||||
|
if (fileUser == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(
|
||||||
|
this, strf( "<html>Delete the user <strong>%s</strong>?<br><br><em>%s</em></html>",
|
||||||
|
fileUser.getFullName(), fileUser.getFile().getName() ),
|
||||||
|
"Delete User", JOptionPane.YES_NO_OPTION ))
|
||||||
|
MPFileUserManager.get().delete( fileUser );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent event) {
|
public void actionPerformed(final ActionEvent event) {
|
||||||
updateIdenticon();
|
updateIdenticon();
|
||||||
@ -193,21 +244,25 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final class AuthenticatedUserPanel extends JPanel implements KeyListener {
|
private final class AuthenticatedUserPanel extends JPanel implements KeyListener {
|
||||||
|
|
||||||
public static final int SIZE_RESULT = 48;
|
public static final int SIZE_RESULT = 48;
|
||||||
|
|
||||||
|
private final JButton userButton = Components.button( Res.icons().user(), event -> showUserPreferences() );
|
||||||
|
private final JButton logoutButton = Components.button( Res.icons().lock(), event -> logoutUser() );
|
||||||
|
private final JButton settingsButton = Components.button( Res.icons().settings(), event -> showSiteSettings() );
|
||||||
|
private final JButton questionsButton = Components.button( Res.icons().question(), null );
|
||||||
|
private final JButton deleteButton = Components.button( Res.icons().delete(), event -> deleteSite() );
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final MPUser<?> user;
|
private final MPUser<?> user;
|
||||||
private final JLabel passwordLabel = Components.label( SwingConstants.CENTER );
|
private final JLabel passwordLabel = Components.label( SwingConstants.CENTER );
|
||||||
private final JLabel passwordField = Components.heading( SwingConstants.CENTER );
|
private final JLabel passwordField = Components.heading( SwingConstants.CENTER );
|
||||||
private final JButton passwordButton =
|
private final JLabel queryLabel = Components.label();
|
||||||
Components.button( Res.icons().settings(), event -> showSiteSettings() );
|
private final JTextField queryField = Components.textField( null, this::updateSites );
|
||||||
private final JLabel queryLabel = Components.label();
|
private final CollectionListModel<MPSite<?>> sitesModel =
|
||||||
private final JTextField queryField = Components.textField( null, this::updateSites );
|
|
||||||
private final CollectionListModel<MPSite<?>> sitesModel =
|
|
||||||
new CollectionListModel<MPSite<?>>().selection( this::showSiteResult );
|
new CollectionListModel<MPSite<?>>().selection( this::showSiteResult );
|
||||||
private final JList<MPSite<?>> sitesList =
|
private final JList<MPSite<?>> sitesList =
|
||||||
Components.list( sitesModel, this::getSiteDescription );
|
Components.list( sitesModel, this::getSiteDescription );
|
||||||
|
|
||||||
private Future<?> updateSitesJob;
|
private Future<?> updateSitesJob;
|
||||||
@ -217,23 +272,20 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
|
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
||||||
add( Components.panel(
|
userToolbar.add( userButton );
|
||||||
Components.heading( user.getFullName(), SwingConstants.CENTER ),
|
userToolbar.add( logoutButton );
|
||||||
Components.panel(
|
|
||||||
BoxLayout.LINE_AXIS,
|
siteToolbar.add( settingsButton );
|
||||||
Box.createGlue(),
|
siteToolbar.add( questionsButton );
|
||||||
Components.button( Res.icons().user(), event -> showUserPreferences() ) ) ) );
|
siteToolbar.add( deleteButton );
|
||||||
|
settingsButton.setEnabled( false );
|
||||||
|
|
||||||
|
add( Components.heading( user.getFullName(), SwingConstants.CENTER ) );
|
||||||
|
|
||||||
add( passwordLabel );
|
add( passwordLabel );
|
||||||
add( Components.panel(
|
add( passwordField );
|
||||||
passwordField,
|
|
||||||
Components.panel(
|
|
||||||
BoxLayout.LINE_AXIS,
|
|
||||||
Box.createGlue(),
|
|
||||||
passwordButton ) ) );
|
|
||||||
passwordField.setForeground( Res.colors().highlightFg() );
|
passwordField.setForeground( Res.colors().highlightFg() );
|
||||||
passwordField.setFont( Res.fonts().bigValueFont( SIZE_RESULT ) );
|
passwordField.setFont( Res.fonts().bigValueFont( SIZE_RESULT ) );
|
||||||
passwordButton.setVisible( false );
|
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
add( Components.strut() );
|
add( Components.strut() );
|
||||||
|
|
||||||
@ -269,13 +321,16 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showSiteSettings() {
|
public void logoutUser() {
|
||||||
ImmutableList.Builder<Component> components = ImmutableList.builder();
|
user.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showSiteSettings() {
|
||||||
MPSite<?> site = sitesModel.getSelectedItem();
|
MPSite<?> site = sitesModel.getSelectedItem();
|
||||||
if (site == null)
|
if (site == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ImmutableList.Builder<Component> components = ImmutableList.builder();
|
||||||
components.add( Components.label( "Algorithm:" ),
|
components.add( Components.label( "Algorithm:" ),
|
||||||
Components.comboBox( MPAlgorithm.Version.values(), MPAlgorithm.Version::name,
|
Components.comboBox( MPAlgorithm.Version.values(), MPAlgorithm.Version::name,
|
||||||
site.getAlgorithm().version(),
|
site.getAlgorithm().version(),
|
||||||
@ -306,6 +361,14 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteSite() {
|
||||||
|
MPSite<?> site = sitesModel.getSelectedItem();
|
||||||
|
if (site == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
user.deleteSite( site );
|
||||||
|
}
|
||||||
|
|
||||||
private String getSiteDescription(@Nonnull final MPSite<?> site) {
|
private String getSiteDescription(@Nonnull final MPSite<?> site) {
|
||||||
if (site instanceof MPNewSite)
|
if (site instanceof MPNewSite)
|
||||||
return strf( "<html><strong>%s</strong> <Add new site></html>", queryField.getText() );
|
return strf( "<html><strong>%s</strong> <Add new site></html>", queryField.getText() );
|
||||||
@ -334,7 +397,7 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
MPSite<?> site = sitesModel.getSelectedItem();
|
MPSite<?> site = sitesModel.getSelectedItem();
|
||||||
if (site instanceof MPNewSite) {
|
if (site instanceof MPNewSite) {
|
||||||
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(
|
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(
|
||||||
this, strf( "<html>Remember the site [<strong>%s</strong>]?</html>", site.getSiteName() ),
|
this, strf( "<html>Remember the site <strong>%s</strong>?</html>", site.getSiteName() ),
|
||||||
"New Site", JOptionPane.YES_NO_OPTION )) {
|
"New Site", JOptionPane.YES_NO_OPTION )) {
|
||||||
sitesModel.setSelectedItem( user.addSite( site.getSiteName() ) );
|
sitesModel.setSelectedItem( user.addSite( site.getSiteName() ) );
|
||||||
useSite();
|
useSite();
|
||||||
@ -370,7 +433,7 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
Res.ui( () -> {
|
Res.ui( () -> {
|
||||||
passwordLabel.setText( " " );
|
passwordLabel.setText( " " );
|
||||||
passwordField.setText( " " );
|
passwordField.setText( " " );
|
||||||
passwordButton.setVisible( false );
|
settingsButton.setEnabled( false );
|
||||||
} );
|
} );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -384,7 +447,7 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
Res.ui( () -> {
|
Res.ui( () -> {
|
||||||
passwordLabel.setText( strf( "Your password for %s:", site.getSiteName() ) );
|
passwordLabel.setText( strf( "Your password for %s:", site.getSiteName() ) );
|
||||||
passwordField.setText( result );
|
passwordField.setText( result );
|
||||||
passwordButton.setVisible( true );
|
settingsButton.setEnabled( true );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
catch (final MPKeyUnavailableException | MPAlgorithmException e) {
|
catch (final MPKeyUnavailableException | MPAlgorithmException e) {
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
@ -94,9 +94,9 @@ public interface MPSite<Q extends MPQuestion> extends Comparable<MPSite<?>> {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
MPUser<?> getUser();
|
MPUser<?> getUser();
|
||||||
|
|
||||||
void addQuestion(Q question);
|
boolean addQuestion(Q question);
|
||||||
|
|
||||||
void deleteQuestion(Q question);
|
boolean deleteQuestion(Q question);
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
Collection<Q> getQuestions();
|
Collection<Q> getQuestions();
|
||||||
|
@ -77,6 +77,8 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
|
|||||||
void authenticate(MPMasterKey masterKey)
|
void authenticate(MPMasterKey masterKey)
|
||||||
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException;
|
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException;
|
||||||
|
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
boolean isMasterKeyAvailable();
|
boolean isMasterKeyAvailable();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@ -90,7 +92,7 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
S addSite(S site);
|
S addSite(S site);
|
||||||
|
|
||||||
void deleteSite(S site);
|
boolean deleteSite(MPSite<?> site);
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
Collection<S> getSites();
|
Collection<S> getSites();
|
||||||
@ -107,5 +109,7 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
|
|||||||
void onUserUpdated(MPUser<?> user);
|
void onUserUpdated(MPUser<?> user);
|
||||||
|
|
||||||
void onUserAuthenticated(MPUser<?> user);
|
void onUserAuthenticated(MPUser<?> user);
|
||||||
|
|
||||||
|
void onUserInvalidated(MPUser<?> user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,10 @@ public abstract class MPBasicQuestion extends Changeable implements MPQuestion {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setType(final MPResultType type) {
|
public void setType(final MPResultType type) {
|
||||||
this.type = type;
|
if (Objects.equals(this.type, type))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +73,10 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||||
this.algorithm = algorithm;
|
if (Objects.equals(this.algorithm, algorithm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.algorithm = algorithm;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,8 +88,10 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCounter(final UnsignedInteger counter) {
|
public void setCounter(final UnsignedInteger counter) {
|
||||||
this.counter = counter;
|
if (Objects.equals(this.counter, counter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.counter = counter;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +103,10 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setResultType(final MPResultType resultType) {
|
public void setResultType(final MPResultType resultType) {
|
||||||
this.resultType = resultType;
|
if (Objects.equals(this.resultType, resultType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.resultType = resultType;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +118,10 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLoginType(@Nullable final MPResultType loginType) {
|
public void setLoginType(@Nullable final MPResultType loginType) {
|
||||||
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
if (Objects.equals(this.loginType, loginType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.loginType = ifNotNullElse( loginType, getAlgorithm().mpw_default_login_type() );
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,17 +160,21 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addQuestion(final Q question) {
|
public boolean addQuestion(final Q question) {
|
||||||
questions.add( question );
|
if (!questions.add( question ))
|
||||||
|
return false;
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteQuestion(final Q question) {
|
public boolean deleteQuestion(final Q question) {
|
||||||
questions.remove( question );
|
if (!questions.remove( question ))
|
||||||
|
return false;
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -25,8 +25,7 @@ import com.google.common.collect.ImmutableSortedSet;
|
|||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
import com.lyndir.masterpassword.model.*;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -66,8 +65,10 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAvatar(final int avatar) {
|
public void setAvatar(final int avatar) {
|
||||||
this.avatar = avatar;
|
if (Objects.equals(this.avatar, avatar))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.avatar = avatar;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +86,10 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAlgorithm(final MPAlgorithm algorithm) {
|
public void setAlgorithm(final MPAlgorithm algorithm) {
|
||||||
this.algorithm = algorithm;
|
if (Objects.equals(this.algorithm, algorithm))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.algorithm = algorithm;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +139,17 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
|
|||||||
listener.onUserAuthenticated( this );
|
listener.onUserAuthenticated( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidate() {
|
||||||
|
if (masterKey == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.masterKey = null;
|
||||||
|
|
||||||
|
for (final Listener listener : listeners)
|
||||||
|
listener.onUserInvalidated( this );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMasterKeyAvailable() {
|
public boolean isMasterKeyAvailable() {
|
||||||
return masterKey != null;
|
return masterKey != null;
|
||||||
@ -151,6 +165,7 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
|
|||||||
return masterKey;
|
return masterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public S addSite(final S site) {
|
public S addSite(final S site) {
|
||||||
sites.put( site.getSiteName(), site );
|
sites.put( site.getSiteName(), site );
|
||||||
@ -160,10 +175,12 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> extends Changeabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteSite(final S site) {
|
public boolean deleteSite(final MPSite<?> site) {
|
||||||
sites.values().remove( site );
|
if (!sites.values().remove( site ))
|
||||||
|
return false;
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -21,6 +21,7 @@ package com.lyndir.masterpassword.model.impl;
|
|||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
import com.lyndir.masterpassword.model.MPSite;
|
import com.lyndir.masterpassword.model.MPSite;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.joda.time.Instant;
|
import org.joda.time.Instant;
|
||||||
@ -75,8 +76,10 @@ public class MPFileSite extends MPBasicSite<MPFileUser, MPFileQuestion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setUrl(@Nullable final String url) {
|
public void setUrl(@Nullable final String url) {
|
||||||
this.url = url;
|
if (Objects.equals( this.url, url))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +95,6 @@ public class MPFileSite extends MPBasicSite<MPFileUser, MPFileQuestion> {
|
|||||||
uses++;
|
uses++;
|
||||||
lastUsed = new Instant();
|
lastUsed = new Instant();
|
||||||
getUser().use();
|
getUser().use();
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
|||||||
import com.lyndir.masterpassword.model.MPUser;
|
import com.lyndir.masterpassword.model.MPUser;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.joda.time.Instant;
|
import org.joda.time.Instant;
|
||||||
@ -98,8 +99,10 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setFormat(final MPMarshalFormat format) {
|
public void setFormat(final MPMarshalFormat format) {
|
||||||
this.format = format;
|
if (Objects.equals(this.format, format))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.format = format;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +111,10 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setContentMode(final MPMarshaller.ContentMode contentMode) {
|
public void setContentMode(final MPMarshaller.ContentMode contentMode) {
|
||||||
this.contentMode = contentMode;
|
if (Objects.equals(this.contentMode, contentMode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.contentMode = contentMode;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +123,10 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultType(final MPResultType defaultType) {
|
public void setDefaultType(final MPResultType defaultType) {
|
||||||
this.defaultType = defaultType;
|
if (Objects.equals(this.defaultType, defaultType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.defaultType = defaultType;
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +136,6 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
|
|
||||||
public void use() {
|
public void use() {
|
||||||
lastUsed = new Instant();
|
lastUsed = new Instant();
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +165,6 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
|
|
||||||
if (keyID == null) {
|
if (keyID == null) {
|
||||||
keyID = masterKey.getKeyID( getAlgorithm() );
|
keyID = masterKey.getKeyID( getAlgorithm() );
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
|
|||||||
import com.lyndir.masterpassword.model.MPConstants;
|
import com.lyndir.masterpassword.model.MPConstants;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,6 +52,7 @@ public class MPFileUserManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Collection<Listener> listeners = new CopyOnWriteArraySet<>();
|
||||||
private final Map<String, MPFileUser> userByName = new HashMap<>();
|
private final Map<String, MPFileUser> userByName = new HashMap<>();
|
||||||
private final File path;
|
private final File path;
|
||||||
|
|
||||||
@ -67,13 +68,13 @@ public class MPFileUserManager {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImmutableSortedSet<MPFileUser> reload() {
|
public void reload() {
|
||||||
userByName.clear();
|
userByName.clear();
|
||||||
|
|
||||||
File[] pathFiles;
|
File[] pathFiles;
|
||||||
if ((!path.exists() && !path.mkdirs()) || ((pathFiles = path.listFiles()) == null)) {
|
if ((!path.exists() && !path.mkdirs()) || ((pathFiles = path.listFiles()) == null)) {
|
||||||
logger.err( "Couldn't create directory for user files: %s", path );
|
logger.err( "Couldn't create directory for user files: %s", path );
|
||||||
return getFiles();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final File file : pathFiles)
|
for (final File file : pathFiles)
|
||||||
@ -90,12 +91,14 @@ public class MPFileUserManager {
|
|||||||
logger.err( e, "Couldn't read user from: %s", file );
|
logger.err( e, "Couldn't read user from: %s", file );
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFiles();
|
fireUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MPFileUser add(final String fullName) {
|
public MPFileUser add(final String fullName) {
|
||||||
MPFileUser user = new MPFileUser( fullName );
|
MPFileUser user = new MPFileUser( fullName );
|
||||||
userByName.put( user.getFullName(), user );
|
userByName.put( user.getFullName(), user );
|
||||||
|
fireUpdated();
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +107,8 @@ public class MPFileUserManager {
|
|||||||
File userFile = user.getFile();
|
File userFile = user.getFile();
|
||||||
if (userFile.exists() && !userFile.delete())
|
if (userFile.exists() && !userFile.delete())
|
||||||
logger.err( "Couldn't delete file: %s", userFile );
|
logger.err( "Couldn't delete file: %s", userFile );
|
||||||
else
|
else if (userByName.values().remove( user ))
|
||||||
userByName.values().remove( user );
|
fireUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getPath() {
|
public File getPath() {
|
||||||
@ -115,4 +118,27 @@ public class MPFileUserManager {
|
|||||||
public ImmutableSortedSet<MPFileUser> getFiles() {
|
public ImmutableSortedSet<MPFileUser> getFiles() {
|
||||||
return ImmutableSortedSet.copyOf( userByName.values() );
|
return ImmutableSortedSet.copyOf( userByName.values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean addListener(final Listener listener) {
|
||||||
|
return listeners.add( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeListener(final Listener listener) {
|
||||||
|
return listeners.remove( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireUpdated() {
|
||||||
|
if (listeners.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImmutableSortedSet<MPFileUser> files = getFiles();
|
||||||
|
|
||||||
|
for (final Listener listener : listeners)
|
||||||
|
listener.onFilesUpdated( files );
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
|
||||||
|
void onFilesUpdated(ImmutableSortedSet<MPFileUser> files);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user