com.haulmont.cuba.desktop.gui.components.DesktopScrollBoxLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.desktop.gui.components.DesktopScrollBoxLayout.java

Source

/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.haulmont.cuba.desktop.gui.components;

import com.haulmont.cuba.gui.ComponentsHelper;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.Component;
import org.apache.commons.lang.ObjectUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DesktopScrollBoxLayout extends DesktopAbstractComponent<JScrollPane>
        implements ScrollBoxLayout, AutoExpanding, DesktopContainer {

    protected List<Component> components = new ArrayList<>();
    protected Orientation orientation = Orientation.VERTICAL;
    protected ScrollBarPolicy scrollBarPolicy = ScrollBarPolicy.VERTICAL;
    protected DesktopAbstractBox content;

    protected boolean scheduledRepaint = false;

    public DesktopScrollBoxLayout() {
        impl = new JScrollPane();
        // by default it is turned off
        impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        impl.setBorder(null);

        content = new DesktopVBox();

        DesktopVBox contentPane = new DesktopVBox();
        contentPane.setContainer(this);
        contentPane.add(content);

        impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane));

        applyScrollBarPolicy(scrollBarPolicy);

        // support tables with 100% width like in web
        impl.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                adjustViewPreferredSize();
            }
        });

        setWidth("100%");
    }

    private void adjustViewPreferredSize() {
        JComponent view = DesktopComponentsHelper.getComposition(content);
        Dimension minimumSize = view.getMinimumSize();
        Dimension preferredSize = null;
        switch (scrollBarPolicy) {
        case VERTICAL:
            preferredSize = new Dimension(impl.getViewport().getWidth(), minimumSize.height);
            break;

        case HORIZONTAL:
            preferredSize = new Dimension(minimumSize.width, impl.getViewport().getHeight());
            break;

        case NONE:
            preferredSize = new Dimension(impl.getViewport().getWidth(), impl.getViewport().getHeight());
            break;

        case BOTH:
            preferredSize = new Dimension(minimumSize.width, minimumSize.height);
            break;
        }
        view.setPreferredSize(preferredSize);

        requestRepaint();
    }

    protected void requestRepaint() {
        if (!scheduledRepaint) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JComponent view = DesktopComponentsHelper.getComposition(content);

                    view.revalidate();
                    view.repaint();

                    scheduledRepaint = false;
                }
            });

            scheduledRepaint = true;
        }
    }

    @Override
    public void add(Component component) {
        add(component, getOwnComponents().size());
    }

    @Override
    public void add(Component component, int index) {
        if (component.getParent() != null && component.getParent() != this) {
            throw new IllegalStateException("Component already has parent");
        }

        DesktopAbstractBox newContent = null;
        if (orientation == Orientation.VERTICAL && !(content instanceof DesktopVBox)) {
            newContent = new DesktopVBox();
        } else if (orientation == Orientation.HORIZONTAL && !(content instanceof DesktopHBox)) {
            newContent = new DesktopHBox();
        }

        if (newContent != null) {
            content = newContent;

            DesktopVBox contentPane = new DesktopVBox();
            contentPane.add(content);
            contentPane.setContainer(this);

            impl.setViewportView(DesktopComponentsHelper.getComposition(contentPane));

            applyScrollBarPolicy(scrollBarPolicy);
        }

        content.add(component, index);

        if (frame != null) {
            if (component instanceof BelongToFrame && ((BelongToFrame) component).getFrame() == null) {
                ((BelongToFrame) component).setFrame(frame);
            } else {
                frame.registerComponent(component);
            }
        }

        if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) {
            ((DesktopAbstractComponent) component).setParentEnabled(false);
        }

        component.setParent(this);

        adjustViewPreferredSize();
    }

    @Override
    public int indexOf(Component component) {
        return ComponentsHelper.indexOf(components, component);
    }

    @Override
    public void remove(Component component) {
        components.remove(component);
        content.remove(component);

        if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) {
            ((DesktopAbstractComponent) component).setParentEnabled(true);
        }

        component.setParent(null);

        adjustViewPreferredSize();
    }

    @Override
    public void removeAll() {
        content.removeAll();

        List<Component> innerComponents = new ArrayList<>(components);
        components.clear();

        for (Component component : innerComponents) {
            if (component instanceof DesktopAbstractComponent && !isEnabledWithParent()) {
                ((DesktopAbstractComponent) component).setParentEnabled(true);
            }

            component.setParent(null);
        }

        adjustViewPreferredSize();
    }

    @Override
    public void setFrame(com.haulmont.cuba.gui.components.Frame frame) {
        super.setFrame(frame);

        if (frame != null) {
            for (Component childComponent : content.getOwnComponents()) {
                if (childComponent instanceof BelongToFrame
                        && ((BelongToFrame) childComponent).getFrame() == null) {
                    ((BelongToFrame) childComponent).setFrame(frame);
                }
            }
        }
    }

    @Override
    public Component getOwnComponent(String id) {
        return content.getOwnComponent(id);
    }

    @Nullable
    @Override
    public Component getComponent(String id) {
        return content.getComponent(id);
    }

    @Nonnull
    @Override
    public Component getComponentNN(String id) {
        Component component = getComponent(id);
        if (component == null) {
            throw new IllegalArgumentException(String.format("Not found component with id '%s'", id));
        }
        return component;
    }

    @Override
    public Collection<Component> getOwnComponents() {
        return content.getOwnComponents();
    }

    @Override
    public Collection<Component> getComponents() {
        return content.getComponents();
    }

    @Override
    public boolean expandsWidth() {
        return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsWidth();
    }

    @Override
    public boolean expandsHeight() {
        return !(content instanceof AutoExpanding) || ((AutoExpanding) content).expandsHeight();
    }

    @Override
    public Orientation getOrientation() {
        return orientation;
    }

    @Override
    public void setOrientation(Orientation orientation) {
        if (!ObjectUtils.equals(orientation, this.orientation)) {
            if (!components.isEmpty())
                throw new IllegalStateException(
                        "Unable to change scrollbox orientation after adding components to it");

            this.orientation = orientation;
        }
    }

    @Override
    public ScrollBarPolicy getScrollBarPolicy() {
        return scrollBarPolicy;
    }

    @Override
    public void setScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) {
        if (this.scrollBarPolicy != scrollBarPolicy) {
            applyScrollBarPolicy(scrollBarPolicy);
        }
        this.scrollBarPolicy = scrollBarPolicy;
    }

    private void applyScrollBarPolicy(ScrollBarPolicy scrollBarPolicy) {
        switch (scrollBarPolicy) {
        case BOTH:
            impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

            content.setWidth("-1px");
            content.setHeight("-1px");
            break;

        case HORIZONTAL:
            impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);

            content.setWidth("-1px");
            content.setHeight("100%");
            break;

        case VERTICAL:
            impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

            content.setWidth("100%");
            content.setHeight("-1px");
            break;

        case NONE:
            impl.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            impl.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);

            content.setWidth("100%");
            content.setHeight("100%");
            break;
        }
    }

    @Override
    public void setMargin(boolean enable) {
        content.setMargin(enable);
    }

    @Override
    public void setMargin(boolean topEnable, boolean rightEnable, boolean bottomEnable, boolean leftEnable) {
        content.setMargin(topEnable, rightEnable, bottomEnable, leftEnable);
    }

    @Override
    public void setSpacing(boolean enabled) {
        content.setSpacing(enabled);
    }

    @Override
    public void updateComponent(Component child) {
        adjustViewPreferredSize();
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (isEnabled() != enabled) {
            super.setEnabled(enabled);
        }
    }

    @Override
    public void updateEnabled() {
        super.updateEnabled();

        boolean resultEnabled = isEnabledWithParent();
        for (Component component : components) {
            if (component instanceof DesktopAbstractComponent) {
                ((DesktopAbstractComponent) component).setParentEnabled(resultEnabled);
            }
        }
    }
}