Proportial Layout - Does not fit when created, only after some ui event

Hi Folks. I’m in troble with a proportial layout design.

This is the root component hierarchy:

  • VerticalLayout - 100% x 100%.
    - HorizontalLayout (width 100%, height undefined, 0 expand)
    - Panel (Width 100%, Height 100%, 1.0 expand)
    - Horizontal Layout (Width 100%, Height undefined, 0 expand).

When UI is displayed at first time, I have a small margin at bottom and right (about 8px). If I drag the window, the layout is fixed. How can I search for the cause?
I’ve attached my UI Source, and screenshots.

@org.springframework.stereotype.Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class EmbeddedNotesViewImpl implements EmbeddedNotesView {

    private static final long serialVersionUID = 1L;
    
    private VerticalLayout mainLayout;
    private VerticalLayout notesContainer;
    private TextArea newNoteEditor;
    private Button saveButton;
    
    // Search
    private UsuarioDTOSearchField userField;
    private TextField contentField;
    private DateField createdBeforeField;
    private DateField createdAfterField;
    private Button filterButton;
    private PopupView filterPopup;
    
    private PaginationComponent paginator;
    private Label totalNotesLabel;
    
    private UsuarioService usuarioService;
    
    private Map<String, Resource> avatarCache = new HashMap<>();
    
    @Autowired
    public void setUsuarioService(UsuarioService usuarioService) {
        this.usuarioService = usuarioService;
    }

    @PostConstruct
    private void draw() {
        mainLayout = new VerticalLayout();
        mainLayout.setWidth("100%");
        mainLayout.setHeight("100%");
        
        drawNewNote();
        drawNotesLayout();
        drawFilterLayout();
        drawPaginator();
    }
    
    private void drawPaginator() {
        HorizontalLayout headerLayout = new HorizontalLayout();
        headerLayout.setWidth("100%");
        headerLayout.addStyleName(VitruvioTheme.LAYOUT_PANEL_CAPTION);
        headerLayout.addStyleName(VitruvioTheme.NO_BORDER_BOTTOM);
        headerLayout.addStyleName(VitruvioTheme.BORDER_TOP_TINY);
        
        totalNotesLabel = new Label();
        totalNotesLabel.addStyleName(VitruvioTheme.LABEL_NO_MARGIN);
        totalNotesLabel.addStyleName(VitruvioTheme.LABEL_COLORED);
        totalNotesLabel.setWidthUndefined();
        headerLayout.addComponent(totalNotesLabel);
        headerLayout.setExpandRatio(totalNotesLabel, 0.3f);
        
        
        paginator = new PaginationComponent();
        headerLayout.addComponent(paginator);
        headerLayout.setComponentAlignment(paginator, Alignment.BOTTOM_CENTER);
        headerLayout.setExpandRatio(paginator, 1.0f);
        
        CssLayout container = new CssLayout();
        headerLayout.addComponent(container);
        headerLayout.setComponentAlignment(container, Alignment.BOTTOM_RIGHT);
        headerLayout.setExpandRatio(container, 0.3f);
        
        Button popupButton = new Button("Filtrar");
        popupButton.setIcon(FontAwesome.FILTER);
        popupButton.addStyleName(VitruvioTheme.BUTTON_BORDERLESS);
        popupButton.addStyleName(VitruvioTheme.BUTTON_BORDERLESS_COLORED);
        popupButton.addClickListener(new Button.ClickListener() {
            private static final long serialVersionUID = 1L;
            @Override
            public void buttonClick(ClickEvent event) {
                filterPopup.setPopupVisible(!filterPopup.isPopupVisible());
                contentField.focus();
            }
        });
        container.addComponents(filterPopup, popupButton);
        
        mainLayout.addComponent(headerLayout);
        mainLayout.setExpandRatio(headerLayout, 0.0f);
    }
    
    private void drawNewNote() {
        HorizontalLayout main = new HorizontalLayout();
        main.setWidth("100%");
        main.setSpacing(true);
        main.addStyleName(VitruvioTheme.LAYOUT_TINY_MARGIN);
        
        newNoteEditor = new TextArea();
        newNoteEditor.setInputPrompt("Digite uma nova anotação");
        newNoteEditor.setRows(3);
        newNoteEditor.addStyleName(VitruvioTheme.TEXTAREA_BORDERLESS);
        newNoteEditor.setWidth("100%");
        newNoteEditor.setNullRepresentation("");
        newNoteEditor.setNullSettingAllowed(true);
        main.addComponent(newNoteEditor);
        main.setExpandRatio(newNoteEditor, 1.0f);
            
        saveButton = new Button("Salvar");
        saveButton.setIcon(FontAwesome.SAVE);
        saveButton.addStyleName(VitruvioTheme.BUTTON_PRIMARY);
        saveButton.addStyleName(VitruvioTheme.BUTTON_ICON_ALIGN_TOP);
        saveButton.setHeight("100%");
        
        main.addComponent(saveButton);
        main.setExpandRatio(saveButton, 0.0f);
        
        mainLayout.addComponent(main);
        mainLayout.setExpandRatio(main, 0.0f);
    }
    
    private void drawNotesLayout() {
        notesContainer = new VerticalLayout();
        notesContainer.setWidth("100%");
        notesContainer.setSpacing(true);
        
        Panel notesPanel = new Panel(null, notesContainer);
        notesPanel.setWidth("100%");
        notesPanel.setHeight("100%");
        notesPanel.addStyleName(VitruvioTheme.PANEL_BORDERLESS);
        
        mainLayout.addComponent(notesPanel);
        mainLayout.setExpandRatio(notesPanel, 1.0f);
    }
    
    private void drawFilterLayout() {
        GridLayout filterLayout = new GridLayout(2, 4);
        filterLayout.addStyleName(VitruvioTheme.LAYOUT_TINY_MARGIN);
        filterLayout.setWidth("300px");
        filterLayout.setSpacing(true);
        
        filterPopup = new PopupView(null, filterLayout);
        filterPopup.setHideOnMouseOut(false);
        
        contentField = new TextField("Contendo o texto");
        contentField.setNullSettingAllowed(true);
        contentField.setNullRepresentation("");
        contentField.setWidth("100%");
        contentField.addStyleName(VitruvioTheme.TEXTFIELD_SMALL);
        
        filterLayout.addComponent(contentField, 0, 0, 1, 0);
        
        userField = ComponentFactory.createField(UsuarioDTOSearchField.class);
        userField.setCaption("Criado por");
        userField.setWidth("100%");
        filterLayout.addComponent(userField, 0, 1, 1, 1);
        
        createdAfterField = new DateField("A partir de");
        createdAfterField.setResolution(Resolution.MINUTE);
        createdAfterField.addStyleName(VitruvioTheme.DATEFIELD_SMALL);
        createdAfterField.setWidth("100%");
        filterLayout.addComponent(createdAfterField,0,2);
        
        createdBeforeField = new DateField("Até");
        createdBeforeField.setResolution(Resolution.MINUTE);
        createdBeforeField.addStyleName(VitruvioTheme.DATEFIELD_SMALL);
        createdBeforeField.setWidth("100%");
        filterLayout.addComponent(createdBeforeField,1,2);
        
        filterButton = new Button("Aplicar");
        filterButton.setWidth("100%");
        filterButton.addStyleName(VitruvioTheme.BUTTON_PRIMARY);
        filterButton.addClickListener(new Button.ClickListener() {
            private static final long serialVersionUID = 1L;
            @Override
            public void buttonClick(ClickEvent event) {
                filterPopup.setPopupVisible(false);
            }
        });
        filterLayout.addComponent(filterButton, 0, 3, 1, 3);
    }
    
    @Override
    public Component getViewComponent() {
        return mainLayout;
    }

    @Override
    public String getTitle() {
        return "Notas";
    }

    @Override
    public TextArea newNoteEditor() {
        return newNoteEditor;
    }

    @Override
    public Button saveButton() {
        return saveButton;
    }
    
    private Resource getAvatar(String login) {
        Resource r = avatarCache.get(login);
        if(r == null) {
            final ArquivoDTO dto = usuarioService.getFotoIcone(login);
            if(dto != null) {
                r = new StreamResource(new StreamResource.StreamSource() {
                    private static final long serialVersionUID = 1L;
                    @Override
                    public InputStream getStream() {
                        return dto.getStream();
                    }
                }, dto.getNome());
            } else {
                r = IconFactory.instance().getIconAsResource(Vitruvio.USER);
            }
            avatarCache.put(login, r);
        }
        return r;
    }

    @Override
    public void showNote(Nota note) {
        DateFormat df = new SimpleDateFormat("d/M/yy HH:mm");
        
        HorizontalLayout layout = new HorizontalLayout();
        layout.addStyleName(VitruvioTheme.LAYOUT_SMALL_MARGIN);
        layout.addStyleName(VitruvioTheme.BORDER_TOP_TINY);
        layout.setWidth("100%");
        
        CssLayout avatar = new CssLayout();
        avatar.setWidth("120px");
        avatar.addStyleName(VitruvioTheme.AVATAR);
        layout.addComponent(avatar);
        layout.setExpandRatio(avatar, 0.0f);
        
        Image image = new Image(null, getAvatar(note.getLogin()));
        avatar.addComponent(image);
        
        Label loginLabel = new Label(note.getLogin());
        loginLabel.setWidth("100%");
        loginLabel.addStyleName(VitruvioTheme.LABEL_COLORED);
        loginLabel.addStyleName(VitruvioTheme.LABEL_H3);
        avatar.addComponent(loginLabel);
        
        Label date = new Label(df.format(note.getDataCriacao()));
        //date.addStyleName(VitruvioTheme.LABEL_TINY);
        date.addStyleName(VitruvioTheme.LABEL_LIGHT);
        avatar.addComponent(date);
        
        Label noteLabel = new Label();
        noteLabel.setWidth("100%");
        noteLabel.addStyleName(VitruvioTheme.LAYOUT_TINY_MARGIN);
        noteLabel.setContentMode(ContentMode.HTML);
        noteLabel.addStyleName(VitruvioTheme.LABEL_NO_MARGIN);
        noteLabel.setValue(note.getNota());
        layout.addComponent(noteLabel);
        layout.setExpandRatio(noteLabel, 1.0f);

        notesContainer.addComponent(layout);
    }

    @Override
    public UsuarioDTOSearchField userField() {
        return userField;
    }

    @Override
    public TextField contentField() {
        return contentField;
    }

    @Override
    public DateField createdBeforeField() {
        return createdBeforeField;
    }

    @Override
    public DateField createdAfterField() {
        return createdAfterField;
    }

    @Override
    public void removeNotes() {
        notesContainer.removeAllComponents();
    }

    @Override
    public PaginationComponent paginator() {
        return paginator;
    }

    @Override
    public Button filterButton() {
        return filterButton;
    }

    @Override
    public Label totalOfNotesLabel() {
        return totalNotesLabel;
    }

}

26048.png
26049.png