简体   繁体   中英

Custom draggable layout manager

I am implementing a widget board for controlling numerous widgets (extending JComponents) which must implement several featrues: resizable, draggable, closeable etc...

Null (or absolute) layout came to my mind because all other native Layout managers do not support the desired features (dragging a component and placing it on a specific position). But as we all know, using absolute manager is not even not recommended, but also forbidden in Netbeans RCP. So I am trying to implement my own layout manager which would be as close to absolute layout as possible and provide some additional features.

Here is the code of my layout prototype

public class WidgetLayout implements LayoutManager, java.io.Serializable {

    private boolean usePreferredSize;

    /**
     * Convenience constructor
     */
    public WidgetLayout() {
        this(true);
    }

    /**
     * Create a DragLayout and indicate how the component size is determined.
     *
     * @param usePreferred size see setPreferredSize() for values.
     */
    public WidgetLayout(boolean usePreferredSize) {
        setUsePreferredSize(usePreferredSize);
    }

    /**
     * Set the use preferred size property
     *
     * @param usePreferredSize when true, use the preferred size of the
     * component in layout calculations. When false, use the size of the
     * component, unless the size is 0, in which case use the preferred size as
     * a default.
     */
    public void setUsePreferredSize(boolean usePreferredSize) {
        this.usePreferredSize = usePreferredSize;
    }

    /**
     * Get the use Preferred Size property
     *
     * @return the use preferred size property
     */
    public boolean isUsePreferredSize() {
        return usePreferredSize;
    }

    /**
     * Adds the specified component with the specified name to the layout.
     *
     * @param name the name of the component
     * @param comp the component to be added
     */
    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    /**
     * Removes the specified component from the layout.
     *
     * @param comp the component to be removed
     */
    @Override
    public void removeLayoutComponent(Component component) {
    }

    /**
     * Determine the preferred size on the Container
     *
     * @param   parent the container in which to do the layout
     * @return the preferred dimensions to lay out the subcomponents of the
     * specified container
     */
    @Override
    public Dimension preferredLayoutSize(Container parent) {
        synchronized (parent.getTreeLock()) {
            return getLayoutSize(parent);
        }
    }

    /**
     * Determine the minimum size on the Container
     *
     * @param   target the container in which to do the layout
     * @return  the minimum dimensions needed to lay out the subcomponents of the
     * specified container
     */
    @Override
    public Dimension minimumLayoutSize(Container parent) {
        synchronized (parent.getTreeLock()) {
            return preferredLayoutSize(parent);
        }
    }

    /**
     * Lays out the specified container using this layout.
     *
     * @param   target the container in which to do the layout
     */
    @Override
    public void layoutContainer(Container parent) {
    }

    /*
     *  The calculation for minimum/preferred size is the same.
     *
     *  @param   parent  the container in which to do the layout
     */
    private Dimension getLayoutSize(Container parent) {
        Insets parentInsets = parent.getInsets();
        int x = parentInsets.left;
        int y = parentInsets.top;
        int width = 0;
        int height = 0;

        //  Get extreme values of the components on the container.
        //  The x/y values represent the starting point relative to the
        //  top/left of the container. The width/height values represent
        //  the bottom/right value within the container.
        for (Component component : parent.getComponents()) {
            if (component.isVisible()) {
                Point p = component.getLocation();
                Dimension d = component.getSize();
                x = Math.min(x, p.x);
                y = Math.min(y, p.y);
                width = Math.max(width, p.x + d.width);
                height = Math.max(height, p.y + d.height);
            }
        }

        Dimension d = new Dimension(width, height);

        return d;

    }

    /**
     * Returns the string representation of this column layout's values.
     *
     * @return  a string representation of this layout
     */
    @Override
    public String toString() {
        return "["
                + getClass().getName()
                + "]";
    }

}

It sort of works, but I have a problem with other components in my RCP application that surrounds this one.

There is a JPanel with this layout inside a TopComponent. return parent.getParent().getParent().getSize(); ensures that this panel has the same size as the topComponent istself (it is the only component there, it works as a canvas or a board). But when I want to increase size of the Explorer, for example, I cant. I can only make the board with my layout bigger, but not smaller. I think I know the reason (the panel with my layout has set preferred size as high as possible) but I am not sure how to correct this. Any tips?

EDIT: what I need is for this layout to has the same size as the TopComponent but the TopComponent should have the ability to increase and decrease its size...

EDIT2: Problem solved. I based some of the functions on DragLayout and now it behaves as an AbsoluteLayout but does not move other components when its size changes (unless the whole component above it changes size) - see the code above.

Also, the trick is to place the component implementing this layout inside some layout which does not force newly created components on the middle of the container, so I put this one into a GridLayout(1, 1) , which fill the whole component by default :-)

Solved - see question EDIT. I will leave the question here, perhaps someone could make use of it when implementing absolute layout-like layout manager...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM