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

com.alee.extended.tab.PaneData 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.tab;

import com.alee.laf.button.WebButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.menu.WebPopupMenu;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.splitpane.WebSplitPane;
import com.alee.laf.tabbedpane.TabbedPaneStyle;
import com.alee.laf.tabbedpane.WebTabbedPane;
import com.alee.managers.focus.DefaultFocusTracker;
import com.alee.managers.focus.FocusManager;
import com.alee.managers.hotkey.Hotkey;
import com.alee.managers.hotkey.HotkeyManager;
import com.alee.managers.hotkey.HotkeyRunnable;
import com.alee.managers.language.LM;
import com.alee.utils.CollectionUtils;
import com.alee.utils.SwingUtils;
import com.alee.utils.swing.Customizer;
import com.alee.utils.swing.menu.PopupMenuGenerator;

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

/**
 * Data for single tabbed pane within document pane.
 * It basically contains tabbed pane and opened documents list.
 *
 * @author Mikle Garin
 * @see How to use WebDocumentPane
 * @see com.alee.extended.tab.WebDocumentPane
 */

public final class PaneData implements StructureData, SwingConstants
{
    /**
     * Close icons.
     */
    private static final ImageIcon closeTabIcon = new ImageIcon ( PaneData.class.getResource ( "icons/close.png" ) );
    private static final ImageIcon closeTabRolloverIcon = new ImageIcon ( PaneData.class.getResource ( "icons/close-rollover.png" ) );

    /**
     * Actual tabbed pane component.
     */
    protected final WebTabbedPane tabbedPane;

    /**
     * Pane focus tracker.
     */
    protected final DefaultFocusTracker focusTracker;

    /**
     * Pane documents.
     */
    protected List data = new ArrayList ();

    /**
     * Constructs new PaneData for the specified WebDocumentPane.
     *
     * @param documentPane parent WebDocumentPane
     */
    public PaneData ( final WebDocumentPane documentPane )
    {
        super ();

        // Creating tabbed pane
        tabbedPane = new WebTabbedPane ( TabbedPaneStyle.attached );
        tabbedPane.putClientProperty ( WebDocumentPane.DATA_KEY, this );

        // Customizing tabbed pane
        updateTabbedPaneCustomizer ( documentPane );

        // Some hotkeys
        HotkeyManager.registerHotkey ( tabbedPane, tabbedPane, Hotkey.CTRL_W, new HotkeyRunnable ()
        {
            @Override
            public void run ( final KeyEvent e )
            {
                closeSelected ();
            }
        } );

        // Tab drag
        DocumentDragHandler.install ( this );

        // Tab menu
        tabbedPane.addMouseListener ( new MouseAdapter ()
        {
            @Override
            public void mousePressed ( final MouseEvent e )
            {
                if ( SwingUtils.isMiddleMouseButton ( e ) )
                {
                    if ( getDocumentPane ().isCloseable () )
                    {
                        final int index = tabbedPane.getTabAt ( e.getPoint () );
                        if ( index != -1 )
                        {
                            final T document = get ( index );
                            if ( document.isCloseable () )
                            {
                                close ( document );
                            }
                        }
                    }
                }
                else if ( SwingUtils.isPopupTrigger ( e ) )
                {
                    // Checking that menu is enabled
                    final WebDocumentPane documentPane = getDocumentPane ();
                    if ( !documentPane.isTabMenuEnabled () )
                    {
                        return;
                    }

                    // Checking that user actually clicked on a tab
                    final int index = tabbedPane.getTabAt ( e.getPoint () );
                    if ( index == -1 )
                    {
                        return;
                    }

                    // Variables
                    final T document = get ( index );
                    final boolean csb = documentPane.isCloseable () && document.isCloseable ();
                    final boolean spb = data.size () > 1 && documentPane.isSplitEnabled ();
                    final boolean spl = tabbedPane.getParent () instanceof WebSplitPane;

                    // Creating popup menu
                    final PopupMenuGenerator pmg = new PopupMenuGenerator ( "document-pane-menu" );
                    pmg.setIconSettings ( PaneData.class, "icons/menu/", ".png" );
                    pmg.setLanguagePrefix ( "weblaf.ex.docpane" );
                    pmg.addItem ( "close", "close", Hotkey.CTRL_W, csb, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            close ( get ( index ) );
                        }
                    } );
                    pmg.addSeparator ();
                    pmg.addItem ( "left", "left", spb, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            split ( document, LEFT );
                        }
                    } );
                    pmg.addItem ( "right", "right", spb, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            split ( document, RIGHT );
                        }
                    } );
                    pmg.addItem ( "top", "top", spb, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            split ( document, TOP );
                        }
                    } );
                    pmg.addItem ( "bottom", "bottom", spb, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            split ( document, BOTTOM );
                        }
                    } );
                    pmg.addSeparator ();
                    pmg.addItem ( "rotate", "rotate", spl, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            rotate ();
                        }
                    } );
                    pmg.addItem ( "unsplit", "unsplit", spl, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            merge ();
                        }
                    } );
                    pmg.addItem ( "unsplit", "unsplitall", spl, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            mergeAll ();
                        }
                    } );

                    // Displaying popup menu
                    final WebPopupMenu menu = pmg.getPopupMenu ();
                    final Dimension mps = menu.getPreferredSize ();
                    final Rectangle bounds = tabbedPane.getBoundsAt ( index );
                    menu.show ( tabbedPane, bounds.x + bounds.width / 2 - mps.width / 2,
                            bounds.y + bounds.height - menu.getShadeWidth () + 5 );
                }
            }
        } );

        // Adding focus tracker
        focusTracker = new DefaultFocusTracker ( true )
        {
            @Override
            public void focusChanged ( final boolean focused )
            {
                if ( focused )
                {
                    activate ();
                }
            }
        };
        FocusManager.addFocusTracker ( tabbedPane, focusTracker );
    }

    /**
     * Updates tabbed pane customizer.
     *
     * @param documentPane parent WebDocumentPane
     */
    protected void updateTabbedPaneCustomizer ( final WebDocumentPane documentPane )
    {
        final Customizer customizer = documentPane.getTabbedPaneCustomizer ();
        if ( customizer != null )
        {
            customizer.customize ( tabbedPane );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component getComponent ()
    {
        return getTabbedPane ();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PaneData findClosestPane ()
    {
        return this;
    }

    /**
     * Returns parent WebDocumentPane.
     *
     * @return parent WebDocumentPane
     */
    public WebDocumentPane getDocumentPane ()
    {
        return SwingUtils.getFirstParent ( tabbedPane, WebDocumentPane.class );
    }

    /**
     * Returns actual tabbed pane component.
     *
     * @return actual tabbed pane component
     */
    public WebTabbedPane getTabbedPane ()
    {
        return tabbedPane;
    }

    /**
     * Returns pane documents.
     *
     * @return pane documents
     */
    public List getData ()
    {
        return data;
    }

    /**
     * Returns pane documents count.
     *
     * @return pane documents count
     */
    public int count ()
    {
        return data.size ();
    }

    /**
     * Returns whether specified document is in this pane or not.
     *
     * @param document document to look for
     * @return true if specified document is in this pane, false otherwise
     */
    public boolean contains ( final T document )
    {
        return contains ( document.getId () );
    }

    /**
     * Returns whether document with the specified ID is in this pane or not.
     *
     * @param documentId ID of the document to look for
     * @return true if document with the specified ID is in this pane, false otherwise
     */
    public boolean contains ( final String documentId )
    {
        for ( final T document : data )
        {
            if ( document.getId ().equals ( documentId ) )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Adds new document into this pane.
     *
     * @param document document to add
     */
    public void add ( final T document )
    {
        add ( document, -1 );
    }

    /**
     * Adds new document into this pane at the specified index.
     *
     * @param document document to add
     * @param index    index to add at
     */
    public void add ( final T document, final int index )
    {
        final int i = index != -1 ? index : tabbedPane.getTabCount ();
        data.add ( i, document );
        tabbedPane.insertTab ( "", document.getIcon (), document.getComponent (), null, i );
        tabbedPane.setBackgroundAt ( i, document.getBackground () );
        tabbedPane.setTabComponentAt ( i, createTabComponent ( document ) );
    }

    /**
     * Returns new tab component.
     *
     * @param document document to create tab component for
     * @return new tab component
     */
    protected JComponent createTabComponent ( final T document )
    {
        final WebPanel tabPanel = new WebPanel ( new BorderLayout ( 2, 0 ) );
        tabPanel.setOpaque ( false );

        // Creating title component
        final String title = document.getTitle ();
        if ( title != null )
        {
            if ( LM.contains ( title ) )
            {
                // Tab with translated title and icon
                tabPanel.add ( WebLabel.createTranslatedLabel ( document.getIcon (), title ), BorderLayout.CENTER );
            }
            else
            {
                // Tab with simple title and icon
                tabPanel.add ( new WebLabel ( title, document.getIcon () ), BorderLayout.CENTER );
            }
        }
        else
        {
            // Tab with icon only
            tabPanel.add ( new WebLabel ( document.getIcon () ), BorderLayout.CENTER );
        }

        if ( getDocumentPane ().isCloseable () && document.isCloseable () )
        {
            final WebButton closeButton = new WebButton ( closeTabIcon, closeTabRolloverIcon );
            closeButton.setUndecorated ( true );
            closeButton.setFocusable ( false );
            closeButton.addActionListener ( new ActionListener ()
            {
                @Override
                public void actionPerformed ( final ActionEvent e )
                {
                    close ( document );
                }
            } );
            tabPanel.add ( closeButton, BorderLayout.LINE_END );
        }

        return tabPanel;
    }

    /**
     * Opens document in this pane.
     * Unlike add method this one informs listeners about opened document.
     *
     * @param document document to open
     */
    public void open ( final T document )
    {
        // Opening document
        add ( document );

        // Informing listeners about document open event
        getDocumentPane ().fireDocumentOpened ( document, this, indexOf ( document ) );
    }

    /**
     * Returns pane document at the specified index.
     *
     * @param index document index
     * @return pane document at the specified index
     */
    public T get ( final int index )
    {
        return data.get ( index );
    }

    /**
     * Returns pane document with the specified ID.
     *
     * @param id document ID
     * @return pane document with the specified ID
     */
    public T get ( final String id )
    {
        for ( final T document : data )
        {
            if ( document.getId ().equals ( id ) )
            {
                return document;
            }
        }
        return null;
    }

    /**
     * Returns pane's selected document.
     *
     * @return pane's selected document
     */
    public T getSelected ()
    {
        final int index = tabbedPane.getSelectedIndex ();
        return index != -1 ? data.get ( index ) : null;
    }

    /**
     * Sets pane's selected document ID.
     *
     * @param id ID of the document to select
     */
    public void setSelected ( final String id )
    {
        setSelected ( indexOf ( id ) );
    }

    /**
     * Sets selected document.
     *
     * @param document document to select
     */
    public void setSelected ( final T document )
    {
        setSelected ( indexOf ( document ) );
    }

    /**
     * Sets selected document index.
     *
     * @param index index of the document to select
     */
    public void setSelected ( final int index )
    {
        tabbedPane.setSelectedIndex ( index );
    }

    /**
     * Returns index of the document with the specified ID.
     *
     * @param id document ID
     * @return index of the document with the specified ID
     */
    public int indexOf ( final String id )
    {
        return indexOf ( get ( id ) );
    }

    /**
     * Returns index of the specified document.
     *
     * @param document document
     * @return index of the specified document
     */
    public int indexOf ( final T document )
    {
        return data.indexOf ( document );
    }

    /**
     * Closes document at the specified index in the active pane.
     *
     * @param index index of the document to close
     */
    public boolean remove ( final int index )
    {
        return remove ( get ( index ) );
    }

    /**
     * Closes document with the specified ID.
     *
     * @param id ID of the document to close
     */
    public boolean remove ( final String id )
    {
        return remove ( get ( id ) );
    }

    /**
     * Closes the specified document.
     *
     * @param document document to close
     */
    public boolean remove ( final T document )
    {
        if ( document != null )
        {
            final int index = indexOf ( document );
            if ( index != -1 )
            {
                tabbedPane.remove ( index );
                data.remove ( document );
                return true;
            }
        }
        return false;
    }

    /**
     * Closes all document in this group.
     */
    public void closeAll ()
    {
        for ( final T document : CollectionUtils.copy ( data ) )
        {
            close ( document );
        }
    }

    /**
     * Closes document at the specified index in the active pane.
     *
     * @param index index of the document to close
     */
    public boolean close ( final int index )
    {
        return close ( get ( index ) );
    }

    /**
     * Closes document with the specified ID.
     *
     * @param id ID of the document to close
     */
    public boolean close ( final String id )
    {
        return close ( get ( id ) );
    }

    /**
     * Closes the specified document.
     *
     * @param document document to close
     */
    public boolean close ( final T document )
    {
        if ( document != null )
        {
            final WebDocumentPane documentPane = getDocumentPane ();
            final int index = indexOf ( document );

            // Informing listeners about document closing event
            if ( documentPane.fireDocumentClosing ( document, this, index ) )
            {
                // Closing document and fixing view
                final boolean removed = remove ( document );
                mergeIfEmpty ();

                // Informing listeners about document close event
                documentPane.fireDocumentClosed ( document, this, index );

                return removed;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    /**
     * Closes selected document.
     */
    public void closeSelected ()
    {
        final T selected = getSelected ();
        if ( selected != null )
        {
            close ( selected );
        }
    }

    /**
     * Activates this pane within WebDocumentPane.
     */
    public void activate ()
    {
        final WebDocumentPane pane = getDocumentPane ();
        if ( pane != null )
        {
            pane.activate ( PaneData.this );
        }
    }

    /**
     * Splits the specified document into a separate pane.
     *
     * @param document  document to split
     * @param direction split direction
     */
    public void split ( final T document, final int direction )
    {
        final WebDocumentPane pane = getDocumentPane ();
        if ( pane != null )
        {
            pane.split ( PaneData.this, document, direction );
        }
    }

    /**
     * Merges this pane with its neighbour if it is empty.
     */
    public void mergeIfEmpty ()
    {
        if ( count () == 0 )
        {
            merge ();
        }
    }

    /**
     * Changes parent split orientation if this pane is located within a split.
     */
    public void rotate ()
    {
        final Container parent = tabbedPane.getParent ();
        if ( parent instanceof WebSplitPane )
        {
            final SplitData splitData = WebDocumentPane.getData ( ( WebSplitPane ) parent );
            splitData.changeSplitOrientation ();
        }
    }

    /**
     * Merges this pane with its neighbour.
     */
    public void merge ()
    {
        final WebDocumentPane documentPane = getDocumentPane ();
        if ( documentPane != null )
        {
            documentPane.merge ( this );
        }
    }

    /**
     * Merges all panes within WebDocumentPane.
     */
    public void mergeAll ()
    {
        final WebDocumentPane pane = getDocumentPane ();
        if ( pane != null )
        {
            pane.merge ( pane.getStructureRoot () );
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy