/*
 * Copyright (c) 2005-2007 Laf-Widget Kirill Grouchnikov. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 *  o Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 *     
 *  o Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution. 
 *     
 *  o Neither the name of Laf-Widget Kirill Grouchnikov nor the names of 
 *    its contributors may be used to endorse or promote products derived 
 *    from this software without specific prior written permission. 
 *     
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
package org.jvnet.lafwidget;

import javax.swing.JComponent;

/**
 * Interface for LAF widgets (behavioural traits).
 * 
 * @author Kirill Grouchnikov
 */
public interface LafWidget {
	/**
	 * <p>
	 * Client property name for specifying that the editable combobox can accept
	 * only entries from the model. This property can be set either on a single
	 * combobox or globally on {@link UIManager}. The value in both cases
	 * should be either {@link Boolean#TRUE} or {@link Boolean#FALSE}.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of editable combobox that accepts model-entries only:
	 * </p>
	 * 
	 * <code>
	 * final JComboBox comboCompletionModelOnlyTest = new JComboBox(<br>
	 * &nbsp;&nbsp;new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });<br>
	 * comboCompletionModelOnlyTest.setEditable(true);<br>
	 * comboCompletionModelOnlyTest.putClientProperty(<br>
	 * &nbsp;&nbsp;LafWidget.COMBO_BOX_USE_MODEL_ONLY, Boolean.TRUE);
	 * </code>
	 */
	public final static String COMBO_BOX_USE_MODEL_ONLY = "lafwidgets.comboboxUseModelOnly";

	/**
	 * <p>
	 * Client property name for specifying that the editable combobox has no
	 * auto completion. This property can be set either on a single combobox or
	 * globally on {@link UIManager}. The value in both cases should be either
	 * {@link Boolean#TRUE} or {@link Boolean#FALSE}. By default, all editable
	 * comboboxes have auto-completion.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of editable combobox that has no auto-completion:
	 * </p>
	 * 
	 * <code>
	 * final JComboBox comboNoAutoCompletion = new JComboBox(<br>
	 * &nbsp;&nbsp;new Object[] { "Ester", "Jordi", "Jordina", "Jorge", "Sergi" });<br>
	 * comboCompletionModelOnlyTest.setEditable(true);<br>
	 * comboCompletionModelOnlyTest.putClientProperty(<br>
	 * &nbsp;&nbsp;LafWidget.COMBO_BOX_NO_AUTOCOMPLETION, Boolean.TRUE);
	 * </code>
	 */
	public final static String COMBO_BOX_NO_AUTOCOMPLETION = "lafwidgets.comboboxNoAutoCompletion";

	/**
	 * <p>
	 * Client property name for specifying the preview painter for tabbed pane.
	 * This property can be set either on a single tabbed pane or globally on
	 * {@link UIManager}. The value in both cases should be an instance of
	 * {@link TabPreviewPainter}. Default implementation of this
	 * {@link DefaultTabPreviewPainter}. Tabbed panes that have associated
	 * preview painters (set either on tabbed pane itself or globally on
	 * {@link UIManager}, have two widgets installed:
	 * </p>
	 * <ul>
	 * <li>Tab overview dialog from {@link TabOverviewDialogWidget}.</li>
	 * <li>Tab hover preview from {@link TabHoverPreviewWidget}.</li>
	 * </ul>
	 * 
	 * <p>
	 * Here is an example of tabbed pane with default tab preview painter
	 * installed:
	 * </p>
	 * 
	 * <code>
	 * &nbsp;&nbsp;JTabbedPane jtp = new JTabbedPane();<br>
	 * &nbsp;&nbsp;jtp.putClientProperty(LafWidget.TABBED_PANE_PREVIEW_PAINTER,<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;new DefaultTabPreviewPainter());
	 * </code>
	 */
	public final static String TABBED_PANE_PREVIEW_PAINTER = "lafwidgets.tabbedpanePreviewPainter";

	/**
	 * <p>
	 * Client property name for specifying the preview painter for a component.
	 * This property can be set either on a component or globally on
	 * {@link UIManager}. The value in both cases should be an instance of
	 * {@link PreviewPainter}. Default implementation is available in the
	 * {@link DefaultPreviewPainter}.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of a scroll pane with default preview painter
	 * installed on the internal component:
	 * </p>
	 * 
	 * <code>
	 * JPanel myPanel = new JPanel();<br>
	 * myPanel.putClientProperty(LafWidget.PANE_PREVIEW_PAINTER,<br>
	 * &nbsp;&nbsp;new DefaultPreviewPainter());<br>
	 * JScrollPane jsp = new JScrollPane(myPanel);
	 * </code>
	 */
	public final static String COMPONENT_PREVIEW_PAINTER = "lafwidgets.componentPreviewPainter";

	/**
	 * <p>
	 * Client property name for specifying the kind of animation on various
	 * components. The value should be one of {@link LafConstants.AnimationKind}
	 * enum. This property can be set either on component or globally on
	 * {@link UIManager}.
	 * </p>
	 * 
	 * <p>
	 * In order to compute the animation kind for some component, the
	 * component's hierarchy is traversed bottom up. The first component that
	 * has this property set, defines the animation kind. Finally, if neither
	 * component not its ancestors define this property, the global setting on
	 * {@link UIManager} is checked. If there is no global setting, the default
	 * {@link LafConstants.AnimationKind#REGULAR} is taken. Here is an example:
	 * </p>
	 * 
	 * <p>
	 * <code>
	 * &nbsp;&nbsp;JPanel panel = new JPanel();<br>
	 * &nbsp;&nbsp;panel.putClientProperty(LafWidget.ANIMATION_KIND, AnimationKind.SLOW);<br>
	 * &nbsp;&nbsp;JButton b1 = new JButton("button1");<br>
	 * &nbsp;&nbsp;JButton b2 = new JButton("button2");<br>
	 * &nbsp;&nbsp;b2.putClientProperty(LafWidget.ANIMATION_KIND, AnimationKind.FAST);
	 * </code>
	 * </p>
	 * 
	 * <p>
	 * In the example above, <b>b2</b> will have fast animation, and <b>b1</b>
	 * will have slow animation ("inherited" from the parent <b>panel</b>).
	 * </p>
	 */
	public final static String ANIMATION_KIND = "lafwidgets.animationKind";

	/**
	 * <p>
	 * Client property name for specifying password strength checker for a
	 * password field. The value should be an instance of
	 * {@link PasswordStrengthChecker}, otherwise will be ignored. This
	 * property must be set on a specific {@link JPasswordField}. Here is an
	 * example:
	 * </p>
	 * 
	 * <code>
	 * &nbsp;&nbsp;JPasswordField jpf = new JPasswordField("password", 10);<br>
	 * &nbsp;&nbsp;jpf.putClientProperty(LafWidget.PASSWORD_STRENGTH_CHECKER,<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;new PasswordStrengthChecker() {<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public PasswordStrength getStrength(char[] password) {<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (password == null)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return PasswordStrength.WEAK;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int length = password.length;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (length < 3)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return PasswordStrength.WEAK;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (length < 6)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return PasswordStrength.MEDIUM;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return PasswordStrength.STRONG;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
	 * <br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;public String getDescription(PasswordStrength strength) {<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strength == PasswordStrength.WEAK)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "&lt;html&gt;This password is &lt;b&gt;way&lt;/b&gt; too weak&lt;/html&gt;";<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strength == PasswordStrength.MEDIUM)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "&lt;html&gt;Come on, you can do&lt;br&gt; a little better than that&lt;/html&gt;";<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strength == PasswordStrength.STRONG)<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "OK";<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;<br>
	 * &nbsp;&nbsp;&nbsp;&nbsp;}<br>
	 * &nbsp;&nbsp;});
	 * </code>
	 */
	public final static String PASSWORD_STRENGTH_CHECKER = "lafwidgets.passwordStrengthChecker";

	/**
	 * <p>
	 * Client property name for specifying that the text component contents
	 * should be selected on focus gain. This property can be set either on a
	 * single text component or globally on {@link UIManager}. The value in
	 * both cases should be either {@link Boolean#TRUE} or {@link Boolean#FALSE}.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of globally set property (all text components that
	 * don't specify {@link Boolean#FALSE} as a client property will have the
	 * "select all on focus gain" behaviour):
	 * </p>
	 * 
	 * <code>
	 * &nbsp;&nbsp;UIManager.put(LafWidget.TEXT_SELECT_ON_FOCUS, Boolean.TRUE);
	 * </code>
	 */
	public final static String TEXT_SELECT_ON_FOCUS = "lafwidgets.textSelectAllOnFocus";

	/**
	 * <p>
	 * Client property name for specifying that the text component contents
	 * should flip selection on ESCAPE key press. This property can be set
	 * either on a single text component or globally on {@link UIManager}. The
	 * value in both cases should be either {@link Boolean#TRUE} or
	 * {@link Boolean#FALSE}.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of globally set property (all text components that
	 * don't specify {@link Boolean#FALSE} as a client property will have the
	 * "flip select on escape" behaviour):
	 * </p>
	 * 
	 * <code>
	 * &nbsp;&nbsp;UIManager.put(LafWidget.TEXT_FLIP_SELECT_ON_ESCAPE, Boolean.TRUE);
	 * </code>
	 */
	public final static String TEXT_FLIP_SELECT_ON_ESCAPE = "lafwidgets.textFlipSelectOnEscape";

	/**
	 * <p>
	 * Client property name for specifying that the text component should have
	 * the edit context menu (with Cut / Copy / Paste / ... menu items). This
	 * property can be set either on a single text component or globally on
	 * {@link UIManager}. The value in both cases should be either
	 * {@link Boolean#TRUE} or {@link Boolean#FALSE}.
	 * </p>
	 * 
	 * <p>
	 * Here is an example of globally set property (all text components that
	 * don't specify {@link Boolean#FALSE} as a client property will have the
	 * the edit context menu):
	 * </p>
	 * 
	 * <code>
	 * &nbsp;&nbsp;UIManager.put(LafWidget.TEXT_EDIT_CONTEXT_MENU, Boolean.TRUE);
	 * </code>
	 */
	public final static String TEXT_EDIT_CONTEXT_MENU = "lafwidgets.textEditContextMenu";

	/**
	 * Client property name for specifying that the tree component should have
	 * automatic drag and drop support. This property can be set either on a
	 * single text component or globally on {@link UIManager}. The value in
	 * both cases should be either {@link Boolean#TRUE} or {@link Boolean#FALSE}.<br>
	 * <br>
	 * Here is an example of globally set property (all trees that don't specify
	 * {@link Boolean#FALSE} as a client property will have the automatic drag
	 * and drop support): <br>
	 * <br>
	 * <code>
	 * &nbsp;&nbsp;UIManager.put(LafWidget.TREE_AUTO_DND_SUPPORT, Boolean.TRUE);
	 * </code>
	 */
	public final static String TREE_AUTO_DND_SUPPORT = "lafwidgets.treeAutoDnDSupport";

	/**
	 * Associates a component with <code>this</code> widget.
	 * 
	 * @param jcomp
	 *            Component.
	 */
	public void setComponent(JComponent jcomp);

	/**
	 * Returns indication whether <code>this</code> widget requires custom LAF
	 * support. Some widgets such as {@link TabOverviewDialogWidget} or
	 * {@link TabHoverPreviewWidget} require custom implementation based on the
	 * internals of the specific LAF. Relevant functions in the base
	 * {@link LafWidgetSupport} support throw
	 * {@link UnsupportedOperationException}.
	 * 
	 * @return <code>true</code> if <code>this</code> widget requires custom
	 *         LAF support, <code>false</code> otherwise.
	 */
	public boolean requiresCustomLafSupport();

	/**
	 * Installs UI on the associated component.
	 */
	public void installUI();

	/**
	 * Installs default settings for the associated component.
	 */
	public void installDefaults();

	/**
	 * Installs listeners for the associated component.
	 */
	public void installListeners();

	/**
	 * Installs components for the associated component.
	 */
	public void installComponents();

	/**
	 * Uninstalls UI on the associated component.
	 */
	public void uninstallUI();

	/**
	 * Uninstalls default settings for the associated component.
	 */
	public void uninstallDefaults();

	/**
	 * Uninstalls listeners for the associated component.
	 */
	public void uninstallListeners();

	/**
	 * Uninstalls components for the associated component.
	 */
	public void uninstallComponents();
}
