All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alee.extended.dock.WebDockableFrame Maven / Gradle / Ivy

There is a newer version: 1.2.14
Show newest version
/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WebLookAndFeel library.  If not, see .
 */

package com.alee.extended.dock;

import com.alee.api.Identifiable;
import com.alee.api.annotations.NotNull;
import com.alee.api.annotations.Nullable;
import com.alee.api.data.CompassDirection;
import com.alee.api.jdk.Objects;
import com.alee.extended.WebContainer;
import com.alee.managers.style.StyleId;
import com.alee.managers.style.StyleManager;
import com.alee.painter.decoration.Stateful;
import com.alee.utils.CollectionUtils;

import javax.swing.*;
import java.awt.*;
import java.util.List;

/**
 * Frame element for {@link WebDockablePane}.
 * It can have its own content which can be easily moved within dockable pane or even outside of its bounds.
 * Frame usually take side space within dockable pane and its center area is taken by some custom content.
 *
 * This component should never be used with a non-Web UIs as it might cause an unexpected behavior.
 * You could still use that component even if WebLaF is not your application LaF as this component will use Web-UI in any case.
 *
 * @author Mikle Garin
 * @see How to use WebDockablePane
 * @see DockableFrameDescriptor
 * @see WDockableFrameUI
 * @see WebDockableFrameUI
 * @see IDockableFramePainter
 * @see DockablePanePainter
 * @see WebContainer
 */
public class WebDockableFrame extends WebContainer implements Identifiable, Stateful
{
    /**
     * Component properties.
     */
    public static final String FRAME_ID_PROPERTY = "frameId";
    public static final String STATE_PROPERTY = "state";
    public static final String MAXIMIZED_PROPERTY = "maximized";
    public static final String RESTORE_STATE_PROPERTY = "restoreState";
    public static final String DRAGGABLE_PROPERTY = "draggable";
    public static final String FLOATABLE_PROPERTY = "floatable";
    public static final String MAXIMIZABLE_PROPERTY = "maximizable";
    public static final String CLOSABLE_PROPERTY = "closable";
    public static final String ICON_PROPERTY = "icon";
    public static final String TITLE_PROPERTY = "title";
    public static final String POSITION_PROPERTY = "position";
    public static final String DOCKABLE_PANE_PROPERTY = "dockablePane";

    /**
     * Frame ID unique within its dockable pane.
     * It is used to connect frame with its position data inside dockable pane model.
     */
    protected String frameId;

    /**
     * Current frame state.
     */
    protected DockableFrameState state;

    /**
     * Whether or not frame is maximized.
     */
    protected boolean maximized;

    /**
     * State to restore frame into from {@link com.alee.extended.dock.DockableFrameState#minimized}.
     */
    protected DockableFrameState restoreState;

    /**
     * Position of this frame on dockable pane.
     * This value will only be used if dockable pane didn't save any position for this frame yet.
     */
    protected CompassDirection position;

    /**
     * Frame icon.
     */
    protected Icon icon;

    /**
     * Frame title.
     */
    protected String title;

    /**
     * Whether or not frame can be dragged.
     */
    protected boolean draggable;

    /**
     * Whether or not frame can be separated into floating window from the UI.
     * You can still float the frame from the code even if this setting is set to {@code false}.
     */
    protected boolean floatable;

    /**
     * Whether or not frame can be maximized.
     * It can only be maximized when it is in {@link com.alee.extended.dock.DockableFrameState#docked} or
     * {@link com.alee.extended.dock.DockableFrameState#floating} states.
     */
    protected boolean maximizable;

    /**
     * Whether or not frame can be closed from the UI.
     * You can still close the frame from the code even if this setting is set to {@code false}.
     */
    protected boolean closable;

    /**
     * Dockable pane this frame is added into.
     */
    protected WebDockablePane dockablePane;

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param frameId unique frame ID
     * @param title   frame title
     */
    public WebDockableFrame ( final String frameId, final String title )
    {
        this ( StyleId.auto, frameId, title );
    }

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param frameId unique frame ID
     * @param icon    frame icon
     */
    public WebDockableFrame ( final String frameId, final Icon icon )
    {
        this ( StyleId.auto, frameId, icon );
    }

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param frameId unique frame ID
     * @param icon    frame icon
     * @param title   frame title
     */
    public WebDockableFrame ( final String frameId, final Icon icon, final String title )
    {
        this ( StyleId.auto, frameId, icon, title );
    }

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param id      style ID
     * @param frameId unique frame ID
     * @param title   frame title
     */
    public WebDockableFrame ( final StyleId id, final String frameId, final String title )
    {
        this ( id, frameId, null, title );
    }

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param id      style ID
     * @param frameId unique frame ID
     * @param icon    frame icon
     */
    public WebDockableFrame ( final StyleId id, final String frameId, final Icon icon )
    {
        this ( id, frameId, icon, "" );
    }

    /**
     * Constructs new {@link com.alee.extended.dock.WebDockableFrame}.
     *
     * @param id      style ID
     * @param frameId unique frame ID
     * @param icon    frame icon
     * @param title   frame title
     */
    public WebDockableFrame ( final StyleId id, final String frameId, final Icon icon, final String title )
    {
        super ();
        setId ( frameId );
        setIcon ( icon );
        setTitle ( title );
        updateUI ();
        setStyleId ( id );
    }

    @Override
    public StyleId getDefaultStyleId ()
    {
        return StyleId.dockableframe;
    }

    @NotNull
    @Override
    public String getId ()
    {
        return frameId;
    }

    /**
     * Sets frame ID unique within its dockable pane.
     *
     * @param id frame ID unique within its dockable pane
     * @return this frame
     */
    public WebDockableFrame setId ( final String id )
    {
        if ( Objects.notEquals ( this.frameId, id ) )
        {
            final String old = this.frameId;
            this.frameId = id;
            firePropertyChange ( FRAME_ID_PROPERTY, old, id );
        }
        return this;
    }

    @Nullable
    @Override
    public List getStates ()
    {
        return CollectionUtils.asList ( getState ().name () );
    }

    /**
     * Returns current frame state.
     *
     * @return current frame state
     */
    public DockableFrameState getState ()
    {
        return state;
    }

    /**
     * Sets frame state.
     *
     * @param state frame state
     * @return this frame
     */
    public WebDockableFrame setState ( final DockableFrameState state )
    {
        if ( this.state != state )
        {
            final DockableFrameState old = this.state;
            this.state = state;
            firePropertyChange ( STATE_PROPERTY, old, state );
        }
        return this;
    }

    /**
     * Returns whether or not frame is maximized.
     *
     * @return true if frame is maximized, false otherwise
     */
    public boolean isMaximized ()
    {
        return maximized;
    }

    /**
     * Sets whether or not frame is maximized.
     *
     * @param maximized whether or not frame is maximized
     * @return this frame
     */
    public WebDockableFrame setMaximized ( final boolean maximized )
    {
        if ( Objects.notEquals ( this.maximized, maximized ) )
        {
            final boolean old = this.maximized;
            this.maximized = maximized;
            firePropertyChange ( MAXIMIZED_PROPERTY, old, maximized );
        }
        return this;
    }

    /**
     * Returns state to restore frame into from {@link com.alee.extended.dock.DockableFrameState#minimized}.
     *
     * @return state to restore frame into from {@link com.alee.extended.dock.DockableFrameState#minimized}
     */
    public DockableFrameState getRestoreState ()
    {
        return restoreState;
    }

    /**
     * Sets state to restore frame into from {@link com.alee.extended.dock.DockableFrameState#minimized}.
     *
     * @param state state to restore frame into from {@link com.alee.extended.dock.DockableFrameState#minimized}
     * @return this frame
     */
    public WebDockableFrame setRestoreState ( final DockableFrameState state )
    {
        if ( this.restoreState != state )
        {
            final DockableFrameState old = this.restoreState;
            this.restoreState = state;
            firePropertyChange ( RESTORE_STATE_PROPERTY, old, state );
        }
        return this;
    }

    /**
     * Returns position of this frame on dockable pane.
     *
     * @return position of this frame on dockable pane
     */
    public CompassDirection getPosition ()
    {
        return position;
    }

    /**
     * Sets position of this frame on dockable pane.
     *
     * @param position position of this frame on dockable pane
     * @return this frame
     */
    public WebDockableFrame setPosition ( final CompassDirection position )
    {
        if ( this.position != position )
        {
            final CompassDirection old = this.position;
            this.position = position;
            firePropertyChange ( POSITION_PROPERTY, old, position );
        }
        return this;
    }

    /**
     * Returns frame icon.
     *
     * @return frame icon
     */
    public Icon getIcon ()
    {
        return icon;
    }

    /**
     * Sets frame icon.
     *
     * @param icon frame icon
     * @return this frame
     */
    public WebDockableFrame setIcon ( final Icon icon )
    {
        if ( this.icon != icon )
        {
            final Icon old = this.icon;
            this.icon = icon;
            firePropertyChange ( ICON_PROPERTY, old, icon );
        }
        return this;
    }

    /**
     * Returns frame title.
     *
     * @return frame title
     */
    public String getTitle ()
    {
        return title;
    }

    /**
     * Sets frame title.
     *
     * @param title frame title
     * @return this frame
     */
    public WebDockableFrame setTitle ( final String title )
    {
        if ( Objects.notEquals ( this.title, title ) )
        {
            final String old = this.title;
            this.title = title;
            firePropertyChange ( TITLE_PROPERTY, old, title );
        }
        return this;
    }

    /**
     * Returns whether or not frame can be dragged.
     *
     * @return true if frame can be dragged, false otherwise
     */
    public boolean isDraggable ()
    {
        return draggable;
    }

    /**
     * Sets whether or not frame can be dragged.
     *
     * @param draggable whether or not frame can be dragged
     * @return this frame
     */
    public WebDockableFrame setDraggable ( final boolean draggable )
    {
        if ( this.draggable != draggable )
        {
            final boolean old = this.draggable;
            this.draggable = draggable;
            firePropertyChange ( DRAGGABLE_PROPERTY, old, draggable );
        }
        return this;
    }

    /**
     * Returns whether or not frame can be separated into floating window from the UI.
     *
     * @return true if frame can be separated into floating window from the UI, false otherwise
     */
    public boolean isFloatable ()
    {
        return floatable;
    }

    /**
     * Sets whether or not frame can be separated into floating window from the UI.
     *
     * @param floatable whether or not frame can be separated into floating window from the UI
     * @return this frame
     */
    public WebDockableFrame setFloatable ( final boolean floatable )
    {
        if ( this.floatable != floatable )
        {
            final boolean old = this.floatable;
            this.floatable = floatable;
            firePropertyChange ( FLOATABLE_PROPERTY, old, floatable );
        }
        return this;
    }

    /**
     * Returns whether or not frame can be maximized.
     *
     * @return true if frame can be maximized, false otherwise
     */
    public boolean isMaximizable ()
    {
        return maximizable;
    }

    /**
     * Sets whether or not frame can be maximized.
     *
     * @param maximizable whether or not frame can be maximized
     * @return this frame
     */
    public WebDockableFrame setMaximizable ( final boolean maximizable )
    {
        if ( this.maximizable != maximizable )
        {
            final boolean old = this.maximizable;
            this.maximizable = maximizable;
            firePropertyChange ( MAXIMIZABLE_PROPERTY, old, maximizable );
        }
        return this;
    }

    /**
     * Returns whether or not frame can be closed from the UI.
     *
     * @return true if frame can be closed from the UI, false otherwise
     */
    public boolean isClosable ()
    {
        return closable;
    }

    /**
     * Sets whether or not frame can be closed from the UI.
     *
     * @param closable whether or not frame can be closed from the UI
     * @return this frame
     */
    public WebDockableFrame setClosable ( final boolean closable )
    {
        if ( this.closable != closable )
        {
            final boolean old = this.closable;
            this.closable = closable;
            firePropertyChange ( CLOSABLE_PROPERTY, old, closable );
        }
        return this;
    }

    /**
     * Returns dockable pane this frame is added into.
     *
     * @return dockable pane this frame is added into
     */
    public WebDockablePane getDockablePane ()
    {
        return dockablePane;
    }

    /**
     * Sets dockable pane this frame is added into.
     *
     * @param dockablePane dockable pane this frame is added into
     * @return this frame
     */
    protected WebDockableFrame setDockablePane ( final WebDockablePane dockablePane )
    {
        if ( this.dockablePane != dockablePane )
        {
            final WebDockablePane old = this.dockablePane;
            this.dockablePane = dockablePane;
            firePropertyChange ( DOCKABLE_PANE_PROPERTY, old, dockablePane );
        }
        return this;
    }

    /**
     * Returns sidebar button for this frame.
     *
     * @return sidebar button for this frame
     */
    public JComponent getSidebarButton ()
    {
        return getUI ().getSidebarButton ();
    }

    /**
     * Returns whether or not sidebar button is currently visible.
     *
     * @return true if sidebar button is currently visible, false otherwise
     */
    public boolean isSidebarButtonVisible ()
    {
        final WebDockablePane dockablePane = getDockablePane ();
        if ( dockablePane != null )
        {
            switch ( dockablePane.getSidebarVisibility () )
            {
                case never:
                    return false;

                case minimized:
                    return isMinimized () || isPreview ();

                case anyMinimized:
                    if ( !isClosed () )
                    {
                        for ( final WebDockableFrame frame : dockablePane.getFrames ( getPosition () ) )
                        {
                            if ( frame.isMinimized () || frame.isPreview () )
                            {
                                return true;
                            }
                        }
                    }
                    return false;

                case always:
                    return isOpened ();
            }
        }
        return false;
    }

    /**
     * Returns whether or not frame is closed.
     *
     * @return true if frame is closed, false otherwise
     */
    public boolean isClosed ()
    {
        return state == DockableFrameState.closed;
    }

    /**
     * Returns whether or not frame is opened.
     *
     * @return true if frame is opened, false otherwise
     */
    public boolean isOpened ()
    {
        return state != DockableFrameState.closed;
    }

    /**
     * Returns whether or not frame is minimized.
     *
     * @return true if frame is minimized, false otherwise
     */
    public boolean isMinimized ()
    {
        return state == DockableFrameState.minimized;
    }

    /**
     * Returns whether or not frame is in preview state.
     *
     * @return true if frame is in preview state, false otherwise
     */
    public boolean isPreview ()
    {
        return state == DockableFrameState.preview;
    }

    /**
     * Returns whether or not frame is docked.
     *
     * @return true if frame is docked, false otherwise
     */
    public boolean isDocked ()
    {
        return state == DockableFrameState.docked;
    }

    /**
     * Returns whether or not frame is floating.
     *
     * @return true if frame is floating, false otherwise
     */
    public boolean isFloating ()
    {
        return state == DockableFrameState.floating;
    }

    /**
     * Hides this dockable frame, only its sidebar button will be visible.
     * If {@link #maximized} was {@code true} it will be switched to {@code false}.
     *
     * @return this frame
     */
    public WebDockableFrame minimize ()
    {
        return setState ( DockableFrameState.minimized );
    }

    /**
     * Docks this dockable frame to its last position on the pane.
     *
     * @return this frame
     */
    public WebDockableFrame dock ()
    {
        return setState ( DockableFrameState.docked );
    }

    /**
     * Displays frame preview on top of other pane elements, sidebar button will still be kept visible.
     *
     * @return this frame
     */
    public WebDockableFrame preview ()
    {
        return setState ( DockableFrameState.preview );
    }

    /**
     * Displays frame on a separate non-modal dialog window attached to dockable frame window.
     *
     * @return this frame
     */
    public WebDockableFrame detach ()
    {
        return setState ( DockableFrameState.floating );
    }

    /**
     * Maximizes dockable frame.
     * Frame will be made
     */
    public void maximize ()
    {
        if ( !isMaximized () )
        {
            // Restoring frame state if needed
            if ( !isDocked () && !isFloating () )
            {
                restore ();
            }

            // Maximize frame
            setMaximized ( true );
        }
        else
        {
            // Restore frame size
            setMaximized ( false );
        }
    }

    /**
     * Restores either docked or floating state of this dockable frame.
     *
     * @return this frame
     */
    public WebDockableFrame restore ()
    {
        return setState ( getRestoreState () );
    }

    /**
     * Closes this dockable frame.
     *
     * @return this frame
     */
    public WebDockableFrame close ()
    {
        return setState ( DockableFrameState.closed );
    }

    /**
     * Adds new {@link com.alee.extended.dock.DockableFrameListener}.
     *
     * @param listener {@link com.alee.extended.dock.DockableFrameListener} to add
     */
    public void addFrameListener ( final DockableFrameListener listener )
    {
        listenerList.add ( DockableFrameListener.class, listener );
    }

    /**
     * Removes specified {@link com.alee.extended.dock.DockableFrameListener}.
     *
     * @param listener {@link com.alee.extended.dock.DockableFrameListener} to remove
     */
    public void removeFrameListener ( final DockableFrameListener listener )
    {
        listenerList.remove ( DockableFrameListener.class, listener );
    }

    /**
     * Informs listeners about frame being added.
     */
    public void fireFrameAdded ()
    {
        for ( final DockableFrameListener listener : listenerList.getListeners ( DockableFrameListener.class ) )
        {
            listener.frameAdded ( this, dockablePane );
        }
    }

    /**
     * Informs listeners about frame state change.
     *
     * @param oldState previous frame state
     * @param newState current frame state
     */
    public void fireFrameStateChanged ( final DockableFrameState oldState, final DockableFrameState newState )
    {
        for ( final DockableFrameListener listener : listenerList.getListeners ( DockableFrameListener.class ) )
        {
            listener.frameStateChanged ( this, oldState, newState );
        }
    }

    /**
     * Informs listeners about frame being moved.
     *
     * @param position current frame position relative to content
     */
    public void fireFrameMoved ( final CompassDirection position )
    {
        for ( final DockableFrameListener listener : listenerList.getListeners ( DockableFrameListener.class ) )
        {
            listener.frameMoved ( this, position );
        }
    }

    /**
     * Informs listeners about frame being removed.
     */
    public void fireFrameRemoved ()
    {
        for ( final DockableFrameListener listener : listenerList.getListeners ( DockableFrameListener.class ) )
        {
            listener.frameRemoved ( this, dockablePane );
        }
    }

    @Override
    public void applyComponentOrientation ( final ComponentOrientation orientation )
    {
        super.applyComponentOrientation ( orientation );
        getSidebarButton ().applyComponentOrientation ( orientation );
    }

    /**
     * Returns the look and feel (LaF) object that renders this component.
     *
     * @return the {@link WDockableFrameUI} object that renders this component
     */
    public WDockableFrameUI getUI ()
    {
        return ( WDockableFrameUI ) ui;
    }

    /**
     * Sets the LaF object that renders this component.
     *
     * @param ui {@link WDockableFrameUI}
     */
    public void setUI ( final WDockableFrameUI ui )
    {
        super.setUI ( ui );
    }

    @Override
    public void updateUI ()
    {
        StyleManager.getDescriptor ( this ).updateUI ( this );
    }

    @NotNull
    @Override
    public String getUIClassID ()
    {
        return StyleManager.getDescriptor ( this ).getUIClassId ();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy