~~NOTRANS~~
~~Title: Replace the Login dialog~~
It's possible to customize the standard login dialog a little bit as described in [[vaadin:customize_login|this article]].
If you want full control of the login dialog, it's better to replace the dialog with a custom one. In our example, we'll create a login dialog with additional buttons to do custom authentication steps, e.g.
{{:vaadin:login_custom.png?nolink|}}
If you use the **standard application layout**, do following:
In your web.xml (WebContent/WEB-INF directory), search:
  main
  com.sibvisions.apps.projx.ProjX
and replace it with:
  main
  com.sibvisions.apps.customlogin.MyCustomApplication
If you use the **corporation application layout**, do following:
In your web.xml (WebContent/WEB-INF directory), search:
com.sibvisions.rad.ui.vaadin.server.VaadinServlet
and add the following:
  Application.Login.corporation.classname
  com.sibvisions.apps.customlogin.MyCustomLogin
Finally, let us create the source files (in //src.server// folder):
  * com.sibvisions.apps.customlogin.**MyCustomApplication** (only for standard layout mode, but also works in corporation mode)
  * com.sibvisions.apps.customlogin.**MyCustomLogin**
The Application simply creates the login, e.g.:
package com.sibvisions.apps.customlogin;
import jvx.rad.application.genui.UILauncher;
import com.sibvisions.apps.projx.ILogin;
import com.sibvisions.apps.projx.ProjX;
public class MyCustomApplication extends ProjX 
{
    public MyCustomApplication(UILauncher pLauncher) throws Throwable 
    {
        super(pLauncher);
    }
  
    @Override
    protected ILogin createLogin() throws Throwable
    {
        if (getLauncher().isWebEnvironment())
  {
      return new MyCustomLogin(); 
  }
    
  return super.createLogin();
    }
}
We'll use our custom login, only in web environment. This is all.
The login class contains a little bit more code:
package com.sibvisions.apps.customlogin;
import jvx.rad.genui.component.UIButton;
import jvx.rad.genui.container.UIPanel;
import jvx.rad.genui.layout.UIFormLayout;
import jvx.rad.ui.Style;
import com.sibvisions.apps.vaadin.web.WebLogin;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
public class MyCustomLogin extends WebLogin
{
    private UIPanel panCustomButtons;
    
    @Override
    protected void createLogin()
    {
        super.createLogin();
        updateUI();
    }
    
    @Override
    protected void handleLoginError(Throwable pException)
    {
        super.handleLoginError(pException);
        
        //important, because the error area will be added dynamically
        updateUI();
    }
    
    private void updateUI()
    {
        if (!isChangePassword())
        {
            CssLayout cssl = (CssLayout)getInfoLabel().getParent().getParent();
            //cleanup
            if (panCustomButtons != null)
            {
                cssl.removeComponent((Component)panCustomButtons.getResource());
            }
            else
            {
                UIFormLayout flCustomButtons = new UIFormLayout();
                //flCustomButtons.setHorizontalAlignment(IAlignmentConstants.ALIGN_CENTER);
                flCustomButtons.setMargins(10, 18, 5, 18);
                flCustomButtons.setHorizontalGap(10);
                
                panCustomButtons = new UIPanel(flCustomButtons);
                
                UIButton butISA = new UIButton("ISA");
                butSAM.eventAction().addListener(this, "doISA");
                Style.addStyleNames(butISA, "default", "isa");
                UIButton butSAM = new UIButton("SAM");
                butSAM.eventAction().addListener(this, "doSAM");
                Style.addStyleNames(butSAM, "default", "sam");
                panCustomButtons.add(butISA, flCustomButtons.getConstraints(0, 0));
                panCustomButtons.add(butSAM, flCustomButtons.getConstraints(1, 0));
            }
            
            //always above the "error area"
            cssl.addComponent((Component)panCustomButtons.getResource(), 2);
        }
    }
    
    public void doISA() throws Throwable
    {
      ((RemoteApplication)getApplication()).showInformation(null, "ISA pressed!");
    }    
    public void doSAM() throws Throwable
    {
      ((RemoteApplication)getApplication()).showInformation(null, "SAM pressed!");
    }    
}
Our code adds two new buttons and adds shows an information if one of the two buttons were pressed.
The stylesheet definition for the new buttons are:
.loginwindow .default.v-button.isa
{
  background: red;
  border-color: darkred;
}
.loginwindow .default.v-button.isa.v-pressed,
.loginwindow .default.v-button.isa:active
{
  background: red;
  border-color: darkred;
}
.loginwindow .default.v-button.isa:focus
{
  border-color: darkred;  
  box-shadow: 0 0 4px darkred;
}
.v-button.isa:focus:after 
{
    border-color: darkred;
    box-shadow: none;
}
.loginwindow .default.v-button.sam
{
  background: green;
  border-color: darkgreen;
}
.loginwindow .default.v-button.sam.v-pressed,
.loginwindow .default.v-button.sam:active
{
  background: green;
  border-color: dargreen;
}
.loginwindow .default.v-button.sam:focus
{
  border-color: darkgreen;  
  box-shadow: 0 0 4px darkgreen;
}
.v-button.sam:focus:after 
{
    border-color: darkgren;
    box-shadow: none;
}
If you want to create a complete new layout for the login dialog, simply write your own code in **createLogin** method and don't call **super.createLogin()**.
The **createLogin** method of WebLogin:
protected void createLogin()
{
    sNewPassword = null;
    sConfirmPassword = null;
    
    boolean bChangePwd = isChangePassword();
    
    cslayLoginPanel = new CssLayout();
    cslayLoginPanel.addStyleName("login-panel");
    cslayLoginPanel.setSizeFull();
    
    layoutMode = getLayoutMode();
    
    boolean bMini = layoutMode == LayoutMode.Mini;
    
    if (bMini)
    {
        winLogin.addStyleName("small");
        
        cslayLoginPanel.addStyleName("small");
    }
    else
    {
        winLogin.removeStyleName("small");
    }
    
    //----------------------------------------------------------------------------
    // Header
    //----------------------------------------------------------------------------
    
        lblTitle = new Label();
        lblTitle.setSizeUndefined();
        lblTitle.addStyleName("welcome");
    
        lblInfo = new Label();
        lblInfo.setSizeUndefined();
        lblInfo.addStyleName("info");
        
        lblError = new Label();
        lblError.setSizeUndefined();
        lblError.addStyleName("welcomerror");
        
    VerticalLayout vlayLabels = new VerticalLayout();
    vlayLabels.setSpacing(false);
    vlayLabels.setWidth("100%");
    vlayLabels.setSizeUndefined();
    vlayLabels.setMargin(true);
    vlayLabels.addStyleName("labels");
    vlayLabels.addComponent(lblTitle);
    vlayLabels.addComponent(lblError);
    
    if (!bMini)
    {
        vlayLabels.addComponent(lblInfo);
    }
    //----------------------------------------------------------------------------
    // Username and Password
    //----------------------------------------------------------------------------
    AbstractOrderedLayout aolFields;
    
    if (bMini)
    {
        aolFields = new VerticalLayout();
    }
    else
    {
        aolFields = new HorizontalLayout();
    }
    
    aolFields.setSpacing(true);
    aolFields.setMargin(true);
    aolFields.addStyleName("fields");
        tfUserName = new TextField(projx.translate("Username"));
        tfUserName.setIcon(VaadinIcons.USER);
        tfUserName.setId("UserName");
        tfUserName.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
        
        if (sUserName != null)
        {
            tfUserName.setValue(sUserName);
        }
        pfPassword = new PasswordField();
        if (bChangePwd)
        {
            pfPassword.setIcon(VaadinIcons.UNLOCK);
        }
        else
        {
            pfPassword.setIcon(VaadinIcons.LOCK);
        }
        
        pfPassword.setId("Password");
        pfPassword.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
        
        if (sPassword != null)
        {
            pfPassword.setValue(sPassword);
        }
    
        butLogin = new Button();
        butLogin.addStyleName("default");
        butLogin.addStyleName("ok");
        butLogin.setId("OK");
        
        if (bChangePwd)    
        {
            butLogin.setCaption(projx.translate("Change"));
        }
        else
        {
            butLogin.setCaption(projx.translate("Login"));
        }
    aolFields.addComponent(tfUserName);
    aolFields.addComponent(pfPassword);
            
    if (sUserName == null)
    {
        tfUserName.focus();
    }
    else
    {
        pfPassword.focus();
    }
    
    //----------------------------------------------------------------------------
    // New Password and Confirm Password
    //----------------------------------------------------------------------------
    
    AbstractOrderedLayout aolPasswordFields;
    if (bChangePwd)
    {
        lblTitle.setValue(projx.translate(CHANGE_PASSWORD));
        
        pfPassword.setCaption(projx.translate("Old Password"));
        if (bMini)
        {
            aolPasswordFields = new VerticalLayout();
        }
        else
        {
            aolPasswordFields = new HorizontalLayout();
        }
        
        aolPasswordFields.setSpacing(true);
        aolPasswordFields.setMargin(true);
        aolPasswordFields.addStyleName("fields");
        aolPasswordFields.addStyleName("passwordfields");
        
        pfNewPassword = new PasswordField(projx.translate("New Password"));
        pfNewPassword.setId("PasswordNew");
        pfNewPassword.setIcon(VaadinIcons.LOCK);
        pfNewPassword.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
        
        
        if (sNewPassword != null)
        {
            pfNewPassword.setValue(sNewPassword);
        }
        
        pfPassword.focus();
        pfConfirmPassword = new PasswordField(projx.translate("Confirm Password"));
        pfConfirmPassword.setId("PasswordConfirm");
        pfConfirmPassword.setIcon(VaadinIcons.LOCK);
        pfConfirmPassword.addStyleName(ValoTheme.TEXTFIELD_INLINE_ICON);
        
        AbstractOrderedLayout aolButtons;
        
        if (bMini)
        {
            aolButtons = new HorizontalLayout();
            aolButtons.addStyleName("nopadding");
            aolButtons.setSpacing(true);
            aolButtons.setMargin(false);
            aolButtons.setSizeFull();
        }
        else
        {
            aolButtons = aolPasswordFields;
        }
        
        butCancel = new Button(projx.translate("Cancel"));
        butCancel.addStyleName("default");
        butCancel.addStyleName("cancel");
        butCancel.setId("Cancel");
        
        aolPasswordFields.addComponent(pfNewPassword);
        aolPasswordFields.addComponent(pfConfirmPassword);
        aolButtons.addComponent(butLogin);
        aolButtons.setComponentAlignment(butLogin, Alignment.BOTTOM_LEFT);
        Label lblOr = new Label(projx.translate("or"), ContentMode.HTML);
        lblOr.addStyleName("or");
        
        if (!bMini)
        {
            aolButtons.addComponent(lblOr);
            aolButtons.setComponentAlignment(lblOr, Alignment.BOTTOM_LEFT);
        }
        
        aolButtons.addComponent(butCancel);
        
        if (bMini)
        {
            aolButtons.setComponentAlignment(butCancel, Alignment.BOTTOM_RIGHT);
        }
        else
        {
            aolButtons.setComponentAlignment(butCancel, Alignment.BOTTOM_LEFT);
        }
        if (aolButtons != aolPasswordFields)
        {
            aolPasswordFields.addComponent(aolButtons);
        }
        
        if (projx.isConnected())
        {
            lblInfo.setValue(projx.translate("Please enter and confirm the new password."));
            
            tfUserName.setEnabled(false);
        }
        else
        {
            if (projx.isForceChangePassword())
            {
                lblInfo.setValue(projx.translate("Please enter and confirm the new password."));
                
                tfUserName.setEnabled(false);
                pfPassword.setEnabled(false);
            }
            else
            {
                lblInfo.setValue(projx.translate("Please enter your username and passwords."));
            }
        }
        
        ShortcutListener sclEsc = new ShortcutListener(projx.translate("Cancel"), KeyCode.ESCAPE, null) 
        {
            public void handleAction(Object pSender, Object pTarget) 
            {
                doCancel();
            }
        };
        
        butCancel.addClickListener(new ClickListener() 
        {
            public void buttonClick(ClickEvent event) 
            {
                doCancel();
            }
        });
        
        butLogin.addShortcutListener(sclEsc);
    }
    else
    {
        pfPassword.setCaption(projx.translate("Password"));
        
        lblTitle.setValue(projx.translate(WELCOME));
        lblInfo.setValue(projx.translate("Please enter your username and password."));
        
        pfNewPassword = null;
        pfConfirmPassword = null;
        
        aolFields.addComponent(butLogin);
        aolFields.setComponentAlignment(butLogin, Alignment.BOTTOM_LEFT);
        
        aolPasswordFields = null;
    }
    
    //----------------------------------------------------------------------------
    // ALL together
    //----------------------------------------------------------------------------
    
    cslayLoginPanel.addComponent(vlayLabels);
    cslayLoginPanel.addComponent(aolFields);
    if (aolPasswordFields != null)
    {
        cslayLoginPanel.addComponent(aolPasswordFields);
    }
    
    ((CssLayout)winLogin.getContent()).addComponent(cslayLoginPanel);
    
    //----------------------------------------------------------------------------
    // Event handling
    //----------------------------------------------------------------------------
    
    ShortcutListener sclEnter = new ShortcutListener(projx.translate("Login"), KeyCode.ENTER, null) 
    {
        public void handleAction(Object pSender, Object pTarget) 
        {
            doOk();
        }
    };
    butLogin.addClickListener(new ClickListener() 
    {
        public void buttonClick(ClickEvent event) 
        {
            doOk();
        }
    });
    butLogin.addShortcutListener(sclEnter);
    
    updateError();
}