com.alee.extended.panel.WebCollapsiblePane Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weblaf-ui Show documentation
Show all versions of weblaf-ui Show documentation
WebLaf is a Java Swing Look and Feel and extended components library for cross-platform applications
/*
* 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.panel;
import com.alee.extended.icon.OrientedIcon;
import com.alee.global.StyleConstants;
import com.alee.laf.WebLookAndFeel;
import com.alee.laf.button.WebButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.panel.WebPanel;
import com.alee.managers.hotkey.Hotkey;
import com.alee.managers.language.LanguageManager;
import com.alee.managers.language.LanguageMethods;
import com.alee.managers.language.updaters.LanguageUpdater;
import com.alee.managers.settings.DefaultValue;
import com.alee.managers.settings.SettingsManager;
import com.alee.managers.settings.SettingsMethods;
import com.alee.managers.settings.SettingsProcessor;
import com.alee.managers.style.ChildStyleId;
import com.alee.managers.style.ShapeProvider;
import com.alee.managers.style.StyleId;
import com.alee.painter.decoration.DecorationState;
import com.alee.painter.decoration.DecorationUtils;
import com.alee.painter.decoration.Stateful;
import com.alee.managers.style.Bounds;
import com.alee.painter.decoration.states.BoxOrientation;
import com.alee.utils.CollectionUtils;
import com.alee.utils.ImageUtils;
import com.alee.utils.swing.DataProvider;
import com.alee.utils.swing.WebTimer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
/**
* This extended components allows you to quickly create and manipulate a collapsible pane.
* Pane title, content and style can be modified in any way you like.
*
* @author Mikle Garin
*/
public class WebCollapsiblePane extends WebPanel implements SwingConstants, ShapeProvider, LanguageMethods, SettingsMethods
{
/**
* todo 1. Create CollapsiblePaneUI and its implementation
* todo 2. Move implementation into UI and painter
*/
/**
* Collapsed state icon.
*/
public static ImageIcon EXPAND_ICON = new ImageIcon ( WebCollapsiblePane.class.getResource ( "icons/arrow.png" ) );
/**
* Expanded state icon.
*/
public static ImageIcon COLLAPSE_ICON = ImageUtils.rotateImage180 ( EXPAND_ICON );
/**
* Whether animate transition between states or not.
*/
protected Boolean animate;
/**
* Collapsed state icon.
*/
protected ImageIcon expandIcon;
/**
* Expanded state icon.
*/
protected ImageIcon collapseIcon;
/**
* Whether rotate state icon according to title pane position or not.
*/
protected Boolean rotateStateIcon;
/**
* Whether display state icon in title pane or not.
*/
protected Boolean showStateIcon;
/**
* State icon position in title pane.
*/
protected int stateIconPosition;
/**
* Title pane position in collapsible pane.
*/
protected int titlePanePosition;
/**
* Collapsible pane listeners.
*/
protected List listeners = new ArrayList ( 1 );
/**
* Cached collapsed state icon.
*/
protected ImageIcon cachedExpandIcon = null;
/**
* Cached disabled collapsed state icon.
*/
protected ImageIcon cachedDisabledExpandIcon = null;
/**
* Cached expanded state icon.
*/
protected ImageIcon cachedCollapseIcon = null;
/**
* Cached disabled expanded state icon.
*/
protected ImageIcon cachedDisabledCollapseIcon = null;
/**
* Handler that dynamically enable and disable collapsible pane state changes by providing according boolean value.
*/
protected DataProvider stateChangeHandler = null;
/**
* Whether collapsible pane is expanded or not.
*/
protected boolean expanded = true;
/**
* Current collapsible pane transition progress.
* When pane is fully expanded this variable becomes 1f.
* When pane is fully collapsed this variable becomes 0f.
*/
protected float transitionProgress = 1f;
/**
* Collapsible pane expand and collapse speed.
*/
protected float expandSpeed = 0.1f;
/**
* State change animation timer.
*/
protected WebTimer animator = null;
/**
* Whether custom title component is set or not.
*/
protected boolean customTitle = false;
/**
* Header panel.
*/
protected HeaderPanel headerPanel;
/**
* Title component.
*/
protected Component titleComponent;
/**
* State change button.
*/
protected WebButton expandButton;
/**
* Content panel.
*/
protected WebPanel contentPanel;
/**
* Collapsible pane content.
*/
protected Component content = null;
/**
* Constructs empty collapsible pane.
*/
public WebCollapsiblePane ()
{
this ( StyleId.collapsiblepane, "" );
}
/**
* Constructs empty collapsible pane with specified title text.
*
* @param title collapsible pane title text
*/
public WebCollapsiblePane ( final String title )
{
this ( StyleId.collapsiblepane, null, title );
}
/**
* Constructs empty collapsible pane with specified title icon and text.
*
* @param icon collapsible pane title icon
* @param title collapsible pane title text
*/
public WebCollapsiblePane ( final ImageIcon icon, final String title )
{
this ( StyleId.collapsiblepane, icon, title, null );
}
/**
* Constructs collapsible pane with specified content.
*
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final Component content )
{
this ( StyleId.collapsiblepane, null, "", content );
}
/**
* Constructs collapsible pane with specified title text and content.
*
* @param title collapsible pane title text
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final String title, final Component content )
{
this ( StyleId.collapsiblepane, null, title, content );
}
/**
* Constructs collapsible pane with specified title icon, text and content.
*
* @param icon collapsible pane title icon
* @param title collapsible pane title text
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final Icon icon, final String title, final Component content )
{
this ( StyleId.collapsiblepane, icon, title, content );
}
/**
* Constructs empty collapsible pane.
*
* @param id style ID
*/
public WebCollapsiblePane ( final StyleId id )
{
this ( id, "" );
}
/**
* Constructs empty collapsible pane with specified title text.
*
* @param id style ID
* @param title collapsible pane title text
*/
public WebCollapsiblePane ( final StyleId id, final String title )
{
this ( id, null, title );
}
/**
* Constructs empty collapsible pane with specified title icon and text.
*
* @param id style ID
* @param icon collapsible pane title icon
* @param title collapsible pane title text
*/
public WebCollapsiblePane ( final StyleId id, final ImageIcon icon, final String title )
{
this ( id, icon, title, null );
}
/**
* Constructs collapsible pane with specified content.
*
* @param id style ID
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final StyleId id, final Component content )
{
this ( id, null, "", content );
}
/**
* Constructs collapsible pane with specified title text and content.
*
* @param id style ID
* @param title collapsible pane title text
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final StyleId id, final String title, final Component content )
{
this ( id, null, title, content );
}
/**
* Constructs collapsible pane with specified title icon, text and content.
*
* @param id style ID
* @param icon collapsible pane title icon
* @param title collapsible pane title text
* @param content collapsible pane content
*/
public WebCollapsiblePane ( final StyleId id, final Icon icon, final String title, final Component content )
{
super ( id, new BorderLayout ( 0, 0 ) );
this.content = content;
// todo Handle enable/disable
// putClientProperty ( SwingUtils.HANDLES_ENABLE_STATE, true );
// Header
headerPanel = new HeaderPanel ();
headerPanel.addMouseListener ( new MouseAdapter ()
{
@Override
public void mouseReleased ( final MouseEvent e )
{
if ( SwingUtilities.isLeftMouseButton ( e ) && Bounds.margin.of ( WebCollapsiblePane.this ).contains ( e.getPoint () ) )
{
invertExpandState ();
takeFocus ();
}
}
} );
headerPanel.addKeyListener ( new KeyAdapter ()
{
@Override
public void keyReleased ( final KeyEvent e )
{
if ( Hotkey.ENTER.isTriggered ( e ) || Hotkey.SPACE.isTriggered ( e ) )
{
invertExpandState ();
}
}
} );
updateHeaderPosition ();
updateDefaultTitleComponent ( icon, title );
expandButton = new WebButton ( StyleId.collapsiblepaneExpandButton.at ( this ), getCollapseIcon () );
expandButton.addActionListener ( new ActionListener ()
{
@Override
public void actionPerformed ( final ActionEvent e )
{
invertExpandState ();
takeFocus ();
}
} );
setStateIcons ();
updateStateIconPosition ();
// Content
contentPanel = new WebPanel ( StyleId.collapsiblepaneContentPanel.at ( this ), new BorderLayout ( 0, 0 ) )
{
@Override
public Dimension getPreferredSize ()
{
final Dimension ps = super.getPreferredSize ();
if ( titlePanePosition == TOP || titlePanePosition == BOTTOM )
{
if ( WebCollapsiblePane.this.content != null )
{
final Insets insets = getInsets ();
ps.width = insets.left + WebCollapsiblePane.this.content.getPreferredSize ().width + insets.right;
}
if ( transitionProgress < 1f )
{
ps.height = Math.round ( ps.height * transitionProgress );
}
}
else
{
if ( WebCollapsiblePane.this.content != null )
{
final Insets insets = getInsets ();
ps.height = insets.top + WebCollapsiblePane.this.content.getPreferredSize ().height + insets.bottom;
}
if ( transitionProgress < 1f )
{
ps.width = Math.round ( ps.width * transitionProgress );
}
}
return ps;
}
};
add ( contentPanel, BorderLayout.CENTER );
if ( this.content != null )
{
contentPanel.add ( this.content, BorderLayout.CENTER );
}
addPropertyChangeListener ( WebLookAndFeel.COMPONENT_ORIENTATION_PROPERTY, new PropertyChangeListener ()
{
@Override
public void propertyChange ( final PropertyChangeEvent evt )
{
updateStateIcons ();
}
} );
}
/**
* Transfers application focus to this collapsible pane.
*/
protected void takeFocus ()
{
if ( isShowing () && isEnabled () )
{
if ( isFocusable () )
{
requestFocusInWindow ();
}
else
{
transferFocus ();
}
}
}
/**
* Updates default title component.
*/
protected void updateDefaultTitleComponent ()
{
updateDefaultTitleComponent ( getIcon (), getTitle () );
}
/**
* Updates default title component with the specified title icon and text.
*
* @param icon collapsible pane title icon
* @param title collapsible pane title text
*/
protected void updateDefaultTitleComponent ( final Icon icon, final String title )
{
if ( headerPanel != null && !customTitle )
{
if ( titleComponent != null )
{
headerPanel.remove ( titleComponent );
}
titleComponent = createDefaultTitleComponent ( icon, title );
headerPanel.add ( titleComponent, BorderLayout.CENTER );
}
}
/**
* Updates header panel position.
*/
protected void updateHeaderPosition ()
{
if ( headerPanel != null )
{
if ( titlePanePosition == TOP )
{
add ( headerPanel, BorderLayout.NORTH );
}
else if ( titlePanePosition == BOTTOM )
{
add ( headerPanel, BorderLayout.SOUTH );
}
else if ( titlePanePosition == LEFT )
{
add ( headerPanel, BorderLayout.LINE_START );
}
else if ( titlePanePosition == RIGHT )
{
add ( headerPanel, BorderLayout.LINE_END );
}
headerPanel.updateDecoration ();
revalidate ();
}
}
/**
* Updates state icon position.
*/
protected void updateStateIconPosition ()
{
if ( headerPanel != null && expandButton != null )
{
if ( showStateIcon )
{
if ( titlePanePosition == TOP || titlePanePosition == BOTTOM )
{
headerPanel.add ( expandButton, stateIconPosition == RIGHT ? BorderLayout.LINE_END : BorderLayout.LINE_START );
}
else if ( titlePanePosition == LEFT )
{
headerPanel.add ( expandButton, stateIconPosition == RIGHT ? BorderLayout.PAGE_START : BorderLayout.PAGE_END );
}
else if ( titlePanePosition == RIGHT )
{
headerPanel.add ( expandButton, stateIconPosition == RIGHT ? BorderLayout.PAGE_END : BorderLayout.PAGE_START );
}
}
else
{
headerPanel.remove ( expandButton );
}
headerPanel.revalidate ();
}
}
/**
* Returns new default title component with specified icon and text.
*
* @param title collapsible pane title text
* @param icon collapsible pane title icon
* @return new default title component with specified icon and text
*/
protected JComponent createDefaultTitleComponent ( final Icon icon, final String title )
{
// todo RTL orientation support
final ChildStyleId id;
switch ( titlePanePosition )
{
case TOP:
id = StyleId.collapsiblepaneTopTitleLabel;
break;
case LEFT:
id = StyleId.collapsiblepaneLeftTitleLabel;
break;
case BOTTOM:
id = StyleId.collapsiblepaneBottomTitleLabel;
break;
case RIGHT:
id = StyleId.collapsiblepaneRightTitleLabel;
break;
default:
throw new IllegalArgumentException ( "Unknown title pane position specified" );
}
return new WebLabel ( id.at ( this ), title, icon, WebLabel.LEADING );
}
/**
* Returns handler that dynamically enable and disable collapsible pane state changes by providing according boolean value.
*
* @return state change handler
*/
public DataProvider getStateChangeHandler ()
{
return stateChangeHandler;
}
/**
* Sets handler that dynamically enable and disable collapsible pane state changes by providing according boolean value.
*
* @param stateChangeHandler new state change handler
*/
public void setStateChangeHandler ( final DataProvider stateChangeHandler )
{
this.stateChangeHandler = stateChangeHandler;
}
/**
* Returns whether collapsible pane state change is enabled or not.
*
* @return true if collapsible pane state change is enabled, false otherwise
*/
public boolean isStateChangeEnabled ()
{
return stateChangeHandler == null || stateChangeHandler.provide ();
}
/**
* Returns whether collapsible pane is performing animated transition at the moment or not.
*
* @return true if collapsible pane is performing animated transition at the moment, false otherwise
*/
public boolean isAnimating ()
{
return animator != null && animator.isRunning ();
}
/**
* Changes expanded state to opposite and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @return true if operation succeed, false otherwise
*/
public boolean invertExpandState ()
{
return invertExpandState ( animate );
}
/**
* Changes expanded state to opposite and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @param animate whether animate state change transition or not
* @return true if operation succeed, false otherwise
*/
public boolean invertExpandState ( final boolean animate )
{
return setExpanded ( !isExpanded (), animate );
}
/**
* Returns whether this collapsible pane is expanded or not.
*
* @return true if this collapsible pane is expanded, false otherwise
*/
public boolean isExpanded ()
{
return expanded;
}
/**
* Changes expanded state to specified one and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @param expanded whether collapsible pane should be expanded or collapsed
* @return true if operation succeed, false otherwise
*/
public boolean setExpanded ( final boolean expanded )
{
return setExpanded ( expanded, isShowing () && animate );
}
/**
* Changes expanded state to specified one and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @param expanded whether collapsible pane should be expanded or collapsed
* @param animate whether animate state change transition or not
* @return true if operation succeed, false otherwise
*/
public boolean setExpanded ( final boolean expanded, final boolean animate )
{
if ( isEnabled () )
{
if ( expanded )
{
return expand ( animate );
}
else
{
return collapse ( animate );
}
}
return false;
}
/**
* Changes expanded state to collapsed and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @return true if operation succeed, false otherwise
*/
public boolean collapse ()
{
return collapse ( animate );
}
/**
* Changes expanded state to collapsed and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @param animate whether animate state change transition or not
* @return true if operation succeed, false otherwise
*/
public boolean collapse ( final boolean animate )
{
if ( !expanded || !isStateChangeEnabled () )
{
return false;
}
stopAnimation ();
expanded = false;
setStateIcons ();
fireCollapsing ();
if ( animate && isShowing () )
{
animator = new WebTimer ( "WebCollapsiblePane.collapseTimer", StyleConstants.fps48, new ActionListener ()
{
@Override
public void actionPerformed ( final ActionEvent e )
{
if ( transitionProgress > 0f )
{
transitionProgress = Math.max ( 0f, transitionProgress - expandSpeed );
revalidate ();
}
else
{
transitionProgress = 0f;
finishCollapseAction ();
animator.stop ();
}
}
} );
animator.start ();
}
else
{
transitionProgress = 0f;
finishCollapseAction ();
}
return true;
}
/**
* Finishes collapse action.
*/
protected void finishCollapseAction ()
{
// Updating header style
if ( headerPanel != null )
{
headerPanel.updateDecoration ();
}
// Hide content
if ( content != null )
{
content.setVisible ( false );
}
// Update collapsible pane
revalidate ();
repaint ();
// Inform about event
fireCollapsed ();
}
/**
* Changes expanded state to expanded and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @return true if operation succeed, false otherwise
*/
public boolean expand ()
{
return expand ( animate );
}
/**
* Changes expanded state to expanded and returns whether operation succeed or not.
* Operation might fail in case state change is disabled for some reason.
*
* @param animate whether animate state change transition or not
* @return true if operation succeed, false otherwise
*/
public boolean expand ( final boolean animate )
{
if ( expanded || !isStateChangeEnabled () )
{
return false;
}
stopAnimation ();
expanded = true;
setStateIcons ();
// Updating header style
if ( headerPanel != null )
{
headerPanel.updateDecoration ();
}
// Show content
if ( content != null )
{
content.setVisible ( true );
}
fireExpanding ();
if ( animate && isShowing () )
{
animator = new WebTimer ( "WebCollapsiblePane.expandTimer", StyleConstants.fps48, new ActionListener ()
{
@Override
public void actionPerformed ( final ActionEvent e )
{
if ( transitionProgress < 1f )
{
transitionProgress = Math.min ( 1f, transitionProgress + expandSpeed );
revalidate ();
}
else
{
transitionProgress = 1f;
finishExpandAction ();
animator.stop ();
}
}
} );
animator.start ();
}
else
{
transitionProgress = 1f;
finishExpandAction ();
}
return true;
}
/**
* Finishes expand action.
*/
protected void finishExpandAction ()
{
// Update collapsible pane
revalidate ();
repaint ();
// Inform about event
fireExpanded ();
}
/**
* Stops state transition animation.
*/
protected void stopAnimation ()
{
if ( animator != null && animator.isRunning () )
{
animator.stop ();
}
}
/**
* Returns title pane position in collapsible pane.
*
* @return title pane position in collapsible pane
*/
public int getTitlePanePosition ()
{
return titlePanePosition;
}
/**
* Sets title pane position in collapsible pane.
*
* @param titlePanePosition new title pane position in collapsible pane
*/
public void setTitlePanePosition ( final int titlePanePosition )
{
this.titlePanePosition = titlePanePosition;
updateDefaultTitleComponent ();
updateHeaderPosition ();
updateStateIcons ();
updateStateIconPosition ();
}
/**
* Returns whether animate transition between states or not.
*
* @return true if animate transition between states, false otherwise
*/
public boolean isAnimate ()
{
return animate;
}
/**
* Sets whether animate transition between states or not
*
* @param animate whether animate transition between states or not
*/
public void setAnimate ( final boolean animate )
{
this.animate = animate;
}
/**
* Returns default title component icon.
*
* @return default title component icon
*/
public Icon getIcon ()
{
return customTitle ? null : titleComponent != null ? ( ( WebLabel ) titleComponent ).getIcon () : null;
}
/**
* Sets default title component icon.
*
* @param icon new default title component icon
*/
public void setIcon ( final Icon icon )
{
if ( !customTitle )
{
( ( WebLabel ) titleComponent ).setIcon ( icon );
}
}
/**
* Returns default title component text.
*
* @return default title component text
*/
public String getTitle ()
{
return customTitle ? null : titleComponent != null ? ( ( WebLabel ) titleComponent ).getText () : null;
}
/**
* Sets default title component text.
*
* @param title new default title component text
*/
public void setTitle ( final String title )
{
if ( !customTitle )
{
( ( WebLabel ) titleComponent ).setText ( title );
}
}
/**
* Sets default title component text alignment.
*
* @param alignment new default title component text alignment
*/
public void setTitleAlignment ( final int alignment )
{
if ( !customTitle )
{
( ( WebLabel ) titleComponent ).setHorizontalAlignment ( alignment );
}
}
/**
* Returns expanded state icon.
*
* @return expanded state icon
*/
public ImageIcon getCollapseIcon ()
{
return collapseIcon != null ? collapseIcon : COLLAPSE_ICON;
}
/**
* Sets expanded state icon.
*
* @param collapseIcon new expanded state icon
*/
public void setCollapseIcon ( final ImageIcon collapseIcon )
{
this.collapseIcon = collapseIcon;
clearCachedCollapseIcons ();
setStateIcons ();
}
/**
* Returns collapsed state icon.
*
* @return collapsed state icon
*/
public ImageIcon getExpandIcon ()
{
return expandIcon != null ? expandIcon : EXPAND_ICON;
}
/**
* Sets collapsed state icon.
*
* @param expandIcon new collapsed state icon
*/
public void setExpandIcon ( final ImageIcon expandIcon )
{
this.expandIcon = expandIcon;
clearCachedExpandIcons ();
setStateIcons ();
}
/**
* Returns whether rotate state icon according to title pane position or not.
*
* @return true if stat icon must be rotated according to title pane position, false otherwise
*/
public boolean isRotateStateIcon ()
{
return rotateStateIcon;
}
/**
* Sets whether rotate state icon according to title pane position or not.
*
* @param rotateStateIcon whether rotate state icon according to title pane position or not
*/
public void setRotateStateIcon ( final boolean rotateStateIcon )
{
this.rotateStateIcon = rotateStateIcon;
updateStateIcons ();
}
/**
* Returns whether display state icon in title pane or not.
*
* @return true if state icon must be displayed in title pane, false otherwise
*/
public boolean isShowStateIcon ()
{
return showStateIcon;
}
/**
* Sets whether display state icon in title pane or not.
*
* @param showStateIcon whether display state icon in title pane or not
*/
public void setShowStateIcon ( final boolean showStateIcon )
{
this.showStateIcon = showStateIcon;
updateStateIconPosition ();
}
/**
* Returns state icon position in title pane.
*
* @return state icon position in title pane
*/
public int getStateIconPosition ()
{
return stateIconPosition;
}
/**
* Sets state icon position in title pane.
*
* @param stateIconPosition new state icon position in title pane
*/
public void setStateIconPosition ( final int stateIconPosition )
{
this.stateIconPosition = stateIconPosition;
updateStateIconPosition ();
}
/**
* Updates state icons.
*/
protected void updateStateIcons ()
{
clearCachedCollapseIcons ();
clearCachedExpandIcons ();
setStateIcons ();
}
/**
* Installs state icons into state change button.
*/
protected void setStateIcons ()
{
if ( expandButton != null )
{
if ( expanded )
{
expandButton.setIcon ( getCachedCollapseIcon () );
expandButton.setDisabledIcon ( getCachedDisabledCollapseIcon () );
}
else
{
expandButton.setIcon ( getCachedExpandIcon () );
expandButton.setDisabledIcon ( getCachedDisabledExpandIcon () );
}
}
}
/**
* Clears cached expanded state icons.
*/
protected void clearCachedCollapseIcons ()
{
cachedCollapseIcon = null;
cachedDisabledCollapseIcon = null;
}
/**
* Returns cached expanded state icon.
*
* @return cached expanded state icon
*/
protected ImageIcon getCachedCollapseIcon ()
{
if ( cachedCollapseIcon == null )
{
// todo Proper icon for RTL
// boolean ltr = getComponentOrientation ().isLeftToRight ();
if ( !rotateStateIcon || titlePanePosition == TOP || titlePanePosition == BOTTOM )
{
cachedCollapseIcon = new OrientedIcon ( getCollapseIcon () );
}
else if ( titlePanePosition == LEFT )
{
cachedCollapseIcon = ImageUtils.rotateImage90CCW ( getCollapseIcon () );
}
else if ( titlePanePosition == RIGHT )
{
cachedCollapseIcon = ImageUtils.rotateImage90CW ( getCollapseIcon () );
}
}
return cachedCollapseIcon;
}
/**
* Returns cached disabled expanded state icon.
*
* @return cached disabled expanded state icon
*/
protected ImageIcon getCachedDisabledCollapseIcon ()
{
if ( cachedDisabledCollapseIcon == null )
{
cachedDisabledCollapseIcon = ImageUtils.createDisabledCopy ( getCachedCollapseIcon () );
}
return cachedDisabledCollapseIcon;
}
/**
* Clears cached collapsed state icons.
*/
protected void clearCachedExpandIcons ()
{
cachedExpandIcon = null;
cachedDisabledExpandIcon = null;
}
/**
* Returns cached collapsed state icon.
*
* @return cached collapsed state icon
*/
protected ImageIcon getCachedExpandIcon ()
{
if ( cachedExpandIcon == null )
{
final boolean ltr = getComponentOrientation ().isLeftToRight ();
if ( !rotateStateIcon || titlePanePosition == TOP || titlePanePosition == BOTTOM )
{
cachedExpandIcon = getExpandIcon ();
}
else if ( ltr ? titlePanePosition == LEFT : titlePanePosition == RIGHT )
{
cachedExpandIcon = ImageUtils.rotateImage90CCW ( getExpandIcon () );
}
else if ( ltr ? titlePanePosition == RIGHT : titlePanePosition == LEFT )
{
cachedExpandIcon = ImageUtils.rotateImage90CW ( getExpandIcon () );
}
}
return cachedExpandIcon;
}
/**
* Returns cached disabled collapsed state icon.
*
* @return cached disabled collapsed state icon
*/
protected ImageIcon getCachedDisabledExpandIcon ()
{
if ( cachedDisabledExpandIcon == null )
{
cachedDisabledExpandIcon = ImageUtils.createDisabledCopy ( getCachedExpandIcon () );
}
return cachedDisabledExpandIcon;
}
/**
* Returns header panel.
*
* @return header panel
*/
public WebPanel getHeaderPanel ()
{
return headerPanel;
}
/**
* Returns state change button.
*
* @return state change button
*/
public WebButton getExpandButton ()
{
return expandButton;
}
/**
* Returns title component.
*
* @return title component
*/
public Component getTitleComponent ()
{
return titleComponent;
}
/**
* Sets custom title component.
*
* @param titleComponent new custom title component
*/
public void setTitleComponent ( final Component titleComponent )
{
if ( this.titleComponent != null )
{
headerPanel.remove ( this.titleComponent );
}
if ( titleComponent != null )
{
headerPanel.add ( titleComponent, BorderLayout.CENTER );
}
this.titleComponent = titleComponent;
this.customTitle = true;
}
/**
* Returns collapsible pane content.
*
* @return collapsible pane content
*/
public Component getContent ()
{
return content;
}
/**
* Sets collapsible pane content.
*
* @param content new collapsible pane content
*/
public void setContent ( final Component content )
{
if ( this.content != null )
{
contentPanel.remove ( this.content );
}
this.content = content;
content.setVisible ( transitionProgress > 0f );
contentPanel.add ( content, BorderLayout.CENTER );
revalidate ();
}
/**
* Returns collapsible pane listeners.
*
* @return collapsible pane listeners
*/
public List getCollapsiblePaneListeners ()
{
return CollectionUtils.copy ( listeners );
}
/**
* Sets collapsible pane listeners.
*
* @param listeners new collapsible pane listeners
*/
public void setCollapsiblePaneListeners ( final List listeners )
{
this.listeners = listeners;
}
/**
* Adds collapsible pane listener.
*
* @param listener collapsible pane listener to add
*/
public void addCollapsiblePaneListener ( final CollapsiblePaneListener listener )
{
listeners.add ( listener );
}
/**
* Removes collapsible pane listener.
*
* @param listener collapsible pane listener to remove
*/
public void removeCollapsiblePaneListener ( final CollapsiblePaneListener listener )
{
listeners.remove ( listener );
}
/**
* Notifies when collapsible pane starts to expand.
*/
public void fireExpanding ()
{
for ( final CollapsiblePaneListener listener : CollectionUtils.copy ( listeners ) )
{
listener.expanding ( this );
}
}
/**
* Notifies when collapsible pane finished expanding.
*/
public void fireExpanded ()
{
for ( final CollapsiblePaneListener listener : CollectionUtils.copy ( listeners ) )
{
listener.expanded ( this );
}
}
/**
* Notifies when collapsible pane starts to collapse.
*/
public void fireCollapsing ()
{
for ( final CollapsiblePaneListener listener : CollectionUtils.copy ( listeners ) )
{
listener.collapsing ( this );
}
}
/**
* Notifies when collapsible pane finished collapsing.
*/
public void fireCollapsed ()
{
for ( final CollapsiblePaneListener listener : CollectionUtils.copy ( listeners ) )
{
listener.collapsed ( this );
}
}
/**
* Returns current collapsible pane transition progress.
* Returns 1f when pane is fully expanded and 0f when pane is fully collapsed.
*
* @return current collapsible pane transition progress
*/
public float getTransitionProgress ()
{
return transitionProgress;
}
/**
* Returns preferred size without taking collapsible pane content into account.
*
* @return preferred size without taking collapsible pane content into account
*/
public Dimension getBasePreferredSize ()
{
final Dimension ps = getPreferredSize ();
if ( content == null || transitionProgress <= 0 )
{
return ps;
}
else
{
final Dimension cps = content.getPreferredSize ();
if ( titlePanePosition == TOP || titlePanePosition == BOTTOM )
{
return new Dimension ( ps.width, ps.height - Math.round ( cps.height * transitionProgress ) );
}
else
{
return new Dimension ( ps.width - Math.round ( cps.width * transitionProgress ), ps.height );
}
}
}
@Override
public void setLanguage ( final String key, final Object... data )
{
LanguageManager.registerComponent ( this, key, data );
}
@Override
public void updateLanguage ( final Object... data )
{
LanguageManager.updateComponent ( this, data );
}
@Override
public void updateLanguage ( final String key, final Object... data )
{
LanguageManager.updateComponent ( this, key, data );
}
@Override
public void removeLanguage ()
{
LanguageManager.unregisterComponent ( this );
}
@Override
public boolean isLanguageSet ()
{
return LanguageManager.isRegisteredComponent ( this );
}
@Override
public void setLanguageUpdater ( final LanguageUpdater updater )
{
LanguageManager.registerLanguageUpdater ( this, updater );
}
@Override
public void removeLanguageUpdater ()
{
LanguageManager.unregisterLanguageUpdater ( this );
}
@Override
public void registerSettings ( final String key )
{
SettingsManager.registerComponent ( this, key );
}
@Override
public void registerSettings ( final String key, final Class defaultValueClass )
{
SettingsManager.registerComponent ( this, key, defaultValueClass );
}
@Override
public void registerSettings ( final String key, final Object defaultValue )
{
SettingsManager.registerComponent ( this, key, defaultValue );
}
@Override
public void registerSettings ( final String group, final String key )
{
SettingsManager.registerComponent ( this, group, key );
}
@Override
public void registerSettings ( final String group, final String key, final Class defaultValueClass )
{
SettingsManager.registerComponent ( this, group, key, defaultValueClass );
}
@Override
public void registerSettings ( final String group, final String key, final Object defaultValue )
{
SettingsManager.registerComponent ( this, group, key, defaultValue );
}
@Override
public void registerSettings ( final String key, final boolean loadInitialSettings, final boolean applySettingsChanges )
{
SettingsManager.registerComponent ( this, key, loadInitialSettings, applySettingsChanges );
}
@Override
public void registerSettings ( final String key, final Class defaultValueClass,
final boolean loadInitialSettings, final boolean applySettingsChanges )
{
SettingsManager.registerComponent ( this, key, defaultValueClass, loadInitialSettings, applySettingsChanges );
}
@Override
public void registerSettings ( final String key, final Object defaultValue, final boolean loadInitialSettings,
final boolean applySettingsChanges )
{
SettingsManager.registerComponent ( this, key, defaultValue, loadInitialSettings, applySettingsChanges );
}
@Override
public void registerSettings ( final String group, final String key, final Class defaultValueClass,
final boolean loadInitialSettings, final boolean applySettingsChanges )
{
SettingsManager.registerComponent ( this, group, key, defaultValueClass, loadInitialSettings, applySettingsChanges );
}
@Override
public void registerSettings ( final String group, final String key, final Object defaultValue, final boolean loadInitialSettings,
final boolean applySettingsChanges )
{
SettingsManager.registerComponent ( this, group, key, defaultValue, loadInitialSettings, applySettingsChanges );
}
@Override
public void registerSettings ( final SettingsProcessor settingsProcessor )
{
SettingsManager.registerComponent ( this, settingsProcessor );
}
@Override
public void unregisterSettings ()
{
SettingsManager.unregisterComponent ( this );
}
@Override
public void loadSettings ()
{
SettingsManager.loadComponentSettings ( this );
}
@Override
public void saveSettings ()
{
SettingsManager.saveComponentSettings ( this );
}
/**
* Custom header panel.
*/
public class HeaderPanel extends WebPanel implements Stateful
{
/**
* Constructs new header panel.
*/
public HeaderPanel ()
{
super ( StyleId.collapsiblepaneHeaderPanel.at ( WebCollapsiblePane.this ), new BorderLayout () );
}
@Override
public List getStates ()
{
final String state = isExpanded () || getTransitionProgress () > 0f ? DecorationState.expanded : DecorationState.collapsed;
final String position = BoxOrientation.get ( getTitlePanePosition () ).name ();
return CollectionUtils.asList ( state, position );
}
/**
* Force decoration updates.
*/
public void updateDecoration ()
{
DecorationUtils.fireStatesChanged ( this );
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy