Identicon support and UI improvements.
This commit is contained in:
parent
400ebe59db
commit
16cdcda94b
@ -27,6 +27,7 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
|
|||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,6 +84,10 @@ public class MPIdenticon {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHTML() {
|
||||||
|
return strf( "<span style='color: %s'>%s</span>", color.getCSS(), text );
|
||||||
|
}
|
||||||
|
|
||||||
public Color getColor() {
|
public Color getColor() {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
@ -94,6 +99,15 @@ public class MPIdenticon {
|
|||||||
BLUE,
|
BLUE,
|
||||||
MAGENTA,
|
MAGENTA,
|
||||||
CYAN,
|
CYAN,
|
||||||
MONO
|
MONO {
|
||||||
|
@Override
|
||||||
|
public String getCSS() {
|
||||||
|
return "inherit";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public String getCSS() {
|
||||||
|
return name().toLowerCase( Locale.ROOT );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,20 +180,20 @@ public abstract class Res {
|
|||||||
|
|
||||||
public static class Fonts {
|
public static class Fonts {
|
||||||
|
|
||||||
public Font emoticonsFont() {
|
public Font emoticonsFont(final float size) {
|
||||||
return emoticonsRegular();
|
return emoticonsRegular().deriveFont( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font controlFont() {
|
public Font controlFont(final float size) {
|
||||||
return exoRegular();
|
return exoRegular().deriveFont( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font valueFont() {
|
public Font valueFont(final float size) {
|
||||||
return sourceSansProRegular();
|
return sourceSansProRegular().deriveFont( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font bigValueFont() {
|
public Font bigValueFont(final float size) {
|
||||||
return sourceSansProBlack();
|
return sourceSansProBlack().deriveFont( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font emoticonsRegular() {
|
public Font emoticonsRegular() {
|
||||||
@ -268,12 +268,17 @@ public abstract class Res {
|
|||||||
|
|
||||||
public static class Colors {
|
public static class Colors {
|
||||||
|
|
||||||
|
private final Color transparent = new Color( 0, 0, 0, 0 );
|
||||||
private final Color frameBg = Color.decode( "#5A5D6B" );
|
private final Color frameBg = Color.decode( "#5A5D6B" );
|
||||||
private final Color controlBg = SystemColor.window;
|
private final Color controlBg = SystemColor.window;
|
||||||
private final Color controlBorder = Color.decode( "#BFBFBF" );
|
private final Color controlBorder = Color.decode( "#BFBFBF" );
|
||||||
private final Color highlightFg = SystemColor.controlHighlight;
|
private final Color highlightFg = SystemColor.controlHighlight;
|
||||||
private final Color errorFg = Color.decode( "#FF3333" );
|
private final Color errorFg = Color.decode( "#FF3333" );
|
||||||
|
|
||||||
|
public Color transparent() {
|
||||||
|
return transparent;
|
||||||
|
}
|
||||||
|
|
||||||
public Color frameBg() {
|
public Color frameBg() {
|
||||||
return frameBg;
|
return frameBg;
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,20 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lhunath, 2018-07-19
|
* @author lhunath, 2018-07-19
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class CollectionListModel<E> extends AbstractListModel<E> implements ComboBoxModel<E> {
|
public class CollectionListModel<E> extends AbstractListModel<E> implements ComboBoxModel<E>, ListSelectionListener {
|
||||||
|
|
||||||
private final List<E> model = new LinkedList<>();
|
private final List<E> model = new LinkedList<>();
|
||||||
@Nullable
|
@Nullable
|
||||||
private E selectedItem;
|
private E selectedItem;
|
||||||
|
private JList<E> list;
|
||||||
|
|
||||||
public CollectionListModel() {
|
public CollectionListModel() {
|
||||||
}
|
}
|
||||||
@ -77,6 +80,10 @@ public class CollectionListModel<E> extends AbstractListModel<E> implements Comb
|
|||||||
if (!Objects.equals( selectedItem, newSelectedItem ) && model.contains( newSelectedItem )) {
|
if (!Objects.equals( selectedItem, newSelectedItem ) && model.contains( newSelectedItem )) {
|
||||||
selectedItem = (E) newSelectedItem;
|
selectedItem = (E) newSelectedItem;
|
||||||
fireContentsChanged( this, -1, -1 );
|
fireContentsChanged( this, -1, -1 );
|
||||||
|
|
||||||
|
//noinspection ObjectEquality
|
||||||
|
if ((list != null) && (list.getModel() == this))
|
||||||
|
list.setSelectedValue( selectedItem, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,4 +92,21 @@ public class CollectionListModel<E> extends AbstractListModel<E> implements Comb
|
|||||||
public synchronized E getSelectedItem() {
|
public synchronized E getSelectedItem() {
|
||||||
return selectedItem;
|
return selectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void registerList(final JList<E> list) {
|
||||||
|
// TODO: This class should probably implement ListSelectionModel instead.
|
||||||
|
if (this.list != null)
|
||||||
|
this.list.removeListSelectionListener( this );
|
||||||
|
|
||||||
|
this.list = list;
|
||||||
|
this.list.addListSelectionListener( this );
|
||||||
|
this.list.setModel( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void valueChanged(final ListSelectionEvent event) {
|
||||||
|
//noinspection ObjectEquality
|
||||||
|
if ((event.getSource() == list) && (list.getModel() == this))
|
||||||
|
selectedItem = list.getSelectedValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,10 @@ import javax.swing.border.CompoundBorder;
|
|||||||
*/
|
*/
|
||||||
public abstract class Components {
|
public abstract class Components {
|
||||||
|
|
||||||
private static final float HEADING_TEXT_SIZE = 19f;
|
public static final float TEXT_SIZE_HEADING = 19f;
|
||||||
private static final float CONTROL_TEXT_SIZE = 13f;
|
public static final float TEXT_SIZE_CONTROL = 13f;
|
||||||
|
public static final int SIZE_MARGIN = 20;
|
||||||
|
public static final int SIZE_PADDING = 8;
|
||||||
|
|
||||||
public static GradientPanel boxPanel(final int axis, final Component... components) {
|
public static GradientPanel boxPanel(final int axis, final Component... components) {
|
||||||
GradientPanel container = gradientPanel( null, null );
|
GradientPanel container = gradientPanel( null, null );
|
||||||
@ -77,7 +79,7 @@ public abstract class Components {
|
|||||||
{
|
{
|
||||||
setBorder( BorderFactory.createCompoundBorder( BorderFactory.createLineBorder( Res.colors().controlBorder(), 1, true ),
|
setBorder( BorderFactory.createCompoundBorder( BorderFactory.createLineBorder( Res.colors().controlBorder(), 1, true ),
|
||||||
BorderFactory.createEmptyBorder( 4, 4, 4, 4 ) ) );
|
BorderFactory.createEmptyBorder( 4, 4, 4, 4 ) ) );
|
||||||
setFont( Res.fonts().valueFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().valueFont( TEXT_SIZE_CONTROL ) );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
setAlignmentY( BOTTOM_ALIGNMENT );
|
setAlignmentY( BOTTOM_ALIGNMENT );
|
||||||
}
|
}
|
||||||
@ -108,7 +110,7 @@ public abstract class Components {
|
|||||||
public static <E> JList<E> list(final ListModel<E> model, final Function<E, String> valueTransformer) {
|
public static <E> JList<E> list(final ListModel<E> model, final Function<E, String> valueTransformer) {
|
||||||
return new JList<E>( model ) {
|
return new JList<E>( model ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().valueFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().valueFont( TEXT_SIZE_CONTROL ) );
|
||||||
setBorder( BorderFactory.createEmptyBorder( 4, 0, 4, 0 ) );
|
setBorder( BorderFactory.createEmptyBorder( 4, 0, 4, 0 ) );
|
||||||
setCellRenderer( new DefaultListCellRenderer() {
|
setCellRenderer( new DefaultListCellRenderer() {
|
||||||
{
|
{
|
||||||
@ -147,7 +149,7 @@ public abstract class Components {
|
|||||||
public static JButton button(final String label) {
|
public static JButton button(final String label) {
|
||||||
return new JButton( label ) {
|
return new JButton( label ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().controlFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().controlFont( TEXT_SIZE_CONTROL ) );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
setAlignmentY( BOTTOM_ALIGNMENT );
|
setAlignmentY( BOTTOM_ALIGNMENT );
|
||||||
}
|
}
|
||||||
@ -160,7 +162,7 @@ public abstract class Components {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Component strut() {
|
public static Component strut() {
|
||||||
return strut( 8 );
|
return strut( SIZE_PADDING );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Component strut(final int size) {
|
public static Component strut(final int size) {
|
||||||
@ -172,6 +174,18 @@ public abstract class Components {
|
|||||||
return rigidArea;
|
return rigidArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int margin() {
|
||||||
|
return SIZE_MARGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Border marginBorder() {
|
||||||
|
return marginBorder( margin() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Border marginBorder(final int size) {
|
||||||
|
return BorderFactory.createEmptyBorder( size, size, size, size );
|
||||||
|
}
|
||||||
|
|
||||||
public static JSpinner spinner(final SpinnerModel model) {
|
public static JSpinner spinner(final SpinnerModel model) {
|
||||||
return new JSpinner( model ) {
|
return new JSpinner( model ) {
|
||||||
{
|
{
|
||||||
@ -191,6 +205,14 @@ public abstract class Components {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JLabel heading() {
|
||||||
|
return heading( " " );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JLabel heading(final int horizontalAlignment) {
|
||||||
|
return heading( " ", horizontalAlignment );
|
||||||
|
}
|
||||||
|
|
||||||
public static JLabel heading(@Nullable final String heading) {
|
public static JLabel heading(@Nullable final String heading) {
|
||||||
return heading( heading, SwingConstants.CENTER );
|
return heading( heading, SwingConstants.CENTER );
|
||||||
}
|
}
|
||||||
@ -207,7 +229,7 @@ public abstract class Components {
|
|||||||
public static JLabel heading(@Nullable final String heading, final int horizontalAlignment) {
|
public static JLabel heading(@Nullable final String heading, final int horizontalAlignment) {
|
||||||
return new JLabel( heading, horizontalAlignment ) {
|
return new JLabel( heading, horizontalAlignment ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().controlFont().deriveFont( Font.BOLD, HEADING_TEXT_SIZE ) );
|
setFont( Res.fonts().controlFont( TEXT_SIZE_HEADING ).deriveFont( Font.BOLD ) );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
setAlignmentY( BOTTOM_ALIGNMENT );
|
setAlignmentY( BOTTOM_ALIGNMENT );
|
||||||
}
|
}
|
||||||
@ -219,6 +241,14 @@ public abstract class Components {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JLabel label() {
|
||||||
|
return label( " " );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JLabel label(final int horizontalAlignment) {
|
||||||
|
return label( " ", horizontalAlignment );
|
||||||
|
}
|
||||||
|
|
||||||
public static JLabel label(@Nullable final String label) {
|
public static JLabel label(@Nullable final String label) {
|
||||||
return label( label, SwingConstants.LEADING );
|
return label( label, SwingConstants.LEADING );
|
||||||
}
|
}
|
||||||
@ -235,7 +265,7 @@ public abstract class Components {
|
|||||||
public static JLabel label(@Nullable final String label, final int horizontalAlignment) {
|
public static JLabel label(@Nullable final String label, final int horizontalAlignment) {
|
||||||
return new JLabel( label, horizontalAlignment ) {
|
return new JLabel( label, horizontalAlignment ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().controlFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().controlFont( TEXT_SIZE_CONTROL ) );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
setAlignmentY( BOTTOM_ALIGNMENT );
|
setAlignmentY( BOTTOM_ALIGNMENT );
|
||||||
}
|
}
|
||||||
@ -250,7 +280,7 @@ public abstract class Components {
|
|||||||
public static JCheckBox checkBox(final String label) {
|
public static JCheckBox checkBox(final String label) {
|
||||||
return new JCheckBox( label ) {
|
return new JCheckBox( label ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().controlFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().controlFont( TEXT_SIZE_CONTROL ) );
|
||||||
setBackground( null );
|
setBackground( null );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
setAlignmentY( BOTTOM_ALIGNMENT );
|
setAlignmentY( BOTTOM_ALIGNMENT );
|
||||||
@ -266,7 +296,7 @@ public abstract class Components {
|
|||||||
public static <E> JComboBox<E> comboBox(final ComboBoxModel<E> model, final Function<E, String> valueTransformer) {
|
public static <E> JComboBox<E> comboBox(final ComboBoxModel<E> model, final Function<E, String> valueTransformer) {
|
||||||
return new JComboBox<E>( model ) {
|
return new JComboBox<E>( model ) {
|
||||||
{
|
{
|
||||||
setFont( Res.fonts().valueFont().deriveFont( CONTROL_TEXT_SIZE ) );
|
setFont( Res.fonts().valueFont( TEXT_SIZE_CONTROL ) );
|
||||||
setBorder( BorderFactory.createEmptyBorder( 4, 0, 4, 0 ) );
|
setBorder( BorderFactory.createEmptyBorder( 4, 0, 4, 0 ) );
|
||||||
setRenderer( new DefaultListCellRenderer() {
|
setRenderer( new DefaultListCellRenderer() {
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ public class FilesPanel extends JPanel implements ItemListener {
|
|||||||
|
|
||||||
protected FilesPanel() {
|
protected FilesPanel() {
|
||||||
setOpaque( false );
|
setOpaque( false );
|
||||||
setBackground( new Color( 0, 0, 0, 0 ) );
|
setBackground( Res.colors().transparent() );
|
||||||
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
|
|
||||||
// -
|
// -
|
||||||
@ -46,9 +46,6 @@ public class FilesPanel extends JPanel implements ItemListener {
|
|||||||
// User Selection
|
// User Selection
|
||||||
add( userField );
|
add( userField );
|
||||||
userField.addItemListener( this );
|
userField.addItemListener( this );
|
||||||
|
|
||||||
// -
|
|
||||||
add( Box.createVerticalGlue() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
|
@ -1,9 +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.masterpassword.gui.Res;
|
import com.lyndir.masterpassword.gui.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.model.MPUser;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.ComponentListener;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
@ -11,21 +14,24 @@ import javax.swing.*;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2018-07-14
|
* @author lhunath, 2018-07-14
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("MagicNumber")
|
@SuppressWarnings("serial")
|
||||||
public class MasterPasswordFrame extends JFrame implements FilesPanel.Listener {
|
public class MasterPasswordFrame extends JFrame implements FilesPanel.Listener, ComponentListener {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.get( MasterPasswordFrame.class );
|
||||||
|
|
||||||
@SuppressWarnings("FieldCanBeLocal")
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private final Components.GradientPanel root;
|
private final Components.GradientPanel root;
|
||||||
private final FilesPanel filesPanel = new FilesPanel();
|
private final FilesPanel filesPanel = new FilesPanel();
|
||||||
private final UserPanel userPanel = new UserPanel();
|
private final UserPanel userPanel = new UserPanel();
|
||||||
|
|
||||||
|
@SuppressWarnings("MagicNumber")
|
||||||
public MasterPasswordFrame() {
|
public MasterPasswordFrame() {
|
||||||
super( "Master Password" );
|
super( "Master Password" );
|
||||||
|
|
||||||
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
||||||
setContentPane( root = Components.gradientPanel( Res.colors().frameBg(), new FlowLayout() ) );
|
setContentPane( root = Components.gradientPanel( Res.colors().frameBg(), new FlowLayout() ) );
|
||||||
root.setLayout( new BoxLayout( root, BoxLayout.PAGE_AXIS ) );
|
root.setLayout( new BoxLayout( root, BoxLayout.PAGE_AXIS ) );
|
||||||
root.setBorder( BorderFactory.createEmptyBorder( 20, 20, 20, 20 ) );
|
root.setBorder( Components.marginBorder() );
|
||||||
|
|
||||||
root.add( filesPanel );
|
root.add( filesPanel );
|
||||||
root.add( new JSeparator( SwingConstants.HORIZONTAL ) );
|
root.add( new JSeparator( SwingConstants.HORIZONTAL ) );
|
||||||
@ -35,7 +41,8 @@ public class MasterPasswordFrame extends JFrame implements FilesPanel.Listener {
|
|||||||
filesPanel.addListener( this );
|
filesPanel.addListener( this );
|
||||||
filesPanel.reload();
|
filesPanel.reload();
|
||||||
|
|
||||||
setMinimumSize( new Dimension( 640, 480 ) );
|
addComponentListener(this );
|
||||||
|
setPreferredSize( new Dimension( 640, 480 ) );
|
||||||
pack();
|
pack();
|
||||||
|
|
||||||
setLocationByPlatform( true );
|
setLocationByPlatform( true );
|
||||||
@ -46,4 +53,21 @@ public class MasterPasswordFrame extends JFrame implements FilesPanel.Listener {
|
|||||||
public void onUserSelected(@Nullable final MPUser<?> selectedUser) {
|
public void onUserSelected(@Nullable final MPUser<?> selectedUser) {
|
||||||
userPanel.setUser( selectedUser );
|
userPanel.setUser( selectedUser );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentResized(final ComponentEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentMoved(final ComponentEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentShown(final ComponentEvent e) {
|
||||||
|
userPanel.transferFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentHidden(final ComponentEvent e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ import java.awt.datatransfer.StringSelection;
|
|||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -34,8 +36,9 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
private MPUser<?> user;
|
private MPUser<?> user;
|
||||||
|
|
||||||
public UserPanel() {
|
public UserPanel() {
|
||||||
super( new BorderLayout( 20, 20 ), null );
|
super( new BorderLayout( Components.margin(), Components.margin() ), null );
|
||||||
setBorder( BorderFactory.createEmptyBorder( 20, 20, 20, 20 ) );
|
setBorder( Components.marginBorder() );
|
||||||
|
setUser( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUser(@Nullable final MPUser<?> user) {
|
public void setUser(@Nullable final MPUser<?> user) {
|
||||||
@ -61,6 +64,7 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
}
|
}
|
||||||
|
|
||||||
revalidate();
|
revalidate();
|
||||||
|
transferFocus();
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +92,16 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
|
|
||||||
private static final class AuthenticateUserPanel extends JPanel implements ActionListener, DocumentListener {
|
private static 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 JPasswordField masterPasswordField = Components.passwordField();
|
private final JPasswordField masterPasswordField = Components.passwordField();
|
||||||
private final JLabel errorLabel = Components.label( null );
|
private final JLabel errorLabel = Components.label();
|
||||||
|
private final JLabel identiconLabel = Components.label( SwingConstants.CENTER );
|
||||||
|
|
||||||
|
private Future<?> identiconJob;
|
||||||
|
|
||||||
private AuthenticateUserPanel(@Nonnull final MPUser<?> user) {
|
private AuthenticateUserPanel(@Nonnull final MPUser<?> user) {
|
||||||
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
@ -110,39 +119,72 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
add( errorLabel );
|
add( errorLabel );
|
||||||
errorLabel.setForeground( Res.colors().errorFg() );
|
errorLabel.setForeground( Res.colors().errorFg() );
|
||||||
|
|
||||||
add( Box.createGlue() );
|
add( Components.strut() );
|
||||||
|
add( identiconLabel );
|
||||||
|
identiconLabel.setFont( Res.fonts().emoticonsFont( Components.TEXT_SIZE_CONTROL ) );
|
||||||
|
|
||||||
Res.ui( false, masterPasswordField::requestFocusInWindow );
|
add( Box.createGlue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent event) {
|
public void actionPerformed(final ActionEvent event) {
|
||||||
try {
|
updateIdenticon();
|
||||||
user.authenticate( masterPasswordField.getPassword() );
|
|
||||||
}
|
char[] masterPassword = masterPasswordField.getPassword();
|
||||||
catch (final MPIncorrectMasterPasswordException e) {
|
Res.job( () -> {
|
||||||
logger.wrn( e, "During user authentication for: %s", user );
|
try {
|
||||||
errorLabel.setText( e.getLocalizedMessage() );
|
user.authenticate( masterPassword );
|
||||||
}
|
}
|
||||||
catch (final MPAlgorithmException e) {
|
catch (final MPIncorrectMasterPasswordException e) {
|
||||||
logger.err( e, "During user authentication for: %s", user );
|
logger.wrn( e, "During user authentication for: %s", user );
|
||||||
errorLabel.setText( e.getLocalizedMessage() );
|
errorLabel.setText( e.getLocalizedMessage() );
|
||||||
}
|
}
|
||||||
|
catch (final MPAlgorithmException e) {
|
||||||
|
logger.err( e, "During user authentication for: %s", user );
|
||||||
|
errorLabel.setText( e.getLocalizedMessage() );
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insertUpdate(final DocumentEvent event) {
|
public void insertUpdate(final DocumentEvent event) {
|
||||||
errorLabel.setText( null );
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeUpdate(final DocumentEvent event) {
|
public void removeUpdate(final DocumentEvent event) {
|
||||||
errorLabel.setText( null );
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changedUpdate(final DocumentEvent event) {
|
public void changedUpdate(final DocumentEvent event) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void update() {
|
||||||
errorLabel.setText( null );
|
errorLabel.setText( null );
|
||||||
|
|
||||||
|
if (identiconJob != null)
|
||||||
|
identiconJob.cancel( true );
|
||||||
|
|
||||||
|
identiconJob = Res.job( this::updateIdenticon, 100 + random.nextInt( 100 ), TimeUnit.MILLISECONDS );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIdenticon() {
|
||||||
|
char[] masterPassword = masterPasswordField.getPassword();
|
||||||
|
MPIdenticon identicon = ((masterPassword != null) && (masterPassword.length > 0))?
|
||||||
|
new MPIdenticon( user.getFullName(), masterPassword ): null;
|
||||||
|
|
||||||
|
Res.ui( () -> {
|
||||||
|
if (identicon != null) {
|
||||||
|
identiconLabel.setForeground(
|
||||||
|
Res.colors().fromIdenticonColor( identicon.getColor(), Res.Colors.BackgroundMode.LIGHT ) );
|
||||||
|
identiconLabel.setText( identicon.getText() );
|
||||||
|
} else {
|
||||||
|
identiconLabel.setForeground( null );
|
||||||
|
identiconLabel.setText( " " );
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,11 +192,13 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
private static final class AuthenticatedUserPanel extends JPanel implements ActionListener, DocumentListener, ListSelectionListener,
|
private static final class AuthenticatedUserPanel extends JPanel implements ActionListener, DocumentListener, ListSelectionListener,
|
||||||
KeyListener {
|
KeyListener {
|
||||||
|
|
||||||
|
public static final int SIZE_RESULT = 48;
|
||||||
|
|
||||||
@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 JLabel queryLabel = Components.label( " " );
|
private final JLabel queryLabel = Components.label();
|
||||||
private final JTextField queryField = Components.textField();
|
private final JTextField queryField = Components.textField();
|
||||||
private final CollectionListModel<MPSite<?>> sitesModel = new CollectionListModel<>();
|
private final CollectionListModel<MPSite<?>> sitesModel = new CollectionListModel<>();
|
||||||
private final JList<MPSite<?>> sitesList = Components.list( sitesModel,
|
private final JList<MPSite<?>> sitesList = Components.list( sitesModel,
|
||||||
@ -172,7 +216,7 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
add( passwordLabel );
|
add( passwordLabel );
|
||||||
add( passwordField );
|
add( passwordField );
|
||||||
passwordField.setForeground( Res.colors().highlightFg() );
|
passwordField.setForeground( Res.colors().highlightFg() );
|
||||||
passwordField.setFont( Res.fonts().bigValueFont().deriveFont( Font.BOLD, 48 ) );
|
passwordField.setFont( Res.fonts().bigValueFont( SIZE_RESULT ) );
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
add( Components.strut() );
|
add( Components.strut() );
|
||||||
|
|
||||||
@ -182,12 +226,12 @@ public class UserPanel extends Components.GradientPanel implements MPUser.Listen
|
|||||||
queryField.addActionListener( this );
|
queryField.addActionListener( this );
|
||||||
queryField.addKeyListener( this );
|
queryField.addKeyListener( this );
|
||||||
queryField.getDocument().addDocumentListener( this );
|
queryField.getDocument().addDocumentListener( this );
|
||||||
|
queryField.requestFocusInWindow();
|
||||||
add( Components.strut() );
|
add( Components.strut() );
|
||||||
add( Components.scrollPane( sitesList ) );
|
add( Components.scrollPane( sitesList ) );
|
||||||
|
sitesModel.registerList( sitesList );
|
||||||
sitesList.addListSelectionListener( this );
|
sitesList.addListSelectionListener( this );
|
||||||
add( Box.createGlue() );
|
add( Box.createGlue() );
|
||||||
|
|
||||||
Res.ui( false, queryField::requestFocusInWindow );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user