/**
* L2FProd.com Common Components 7.3 License.
*
* Copyright 2005-2007 L2FProd.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.l2fprod.common.swing;
import com.l2fprod.common.swing.TipModel.Tip;
import com.l2fprod.common.swing.plaf.JTipOfTheDayAddon;
import com.l2fprod.common.swing.plaf.LookAndFeelAddons;
import com.l2fprod.common.swing.plaf.TipOfTheDayUI;
import com.l2fprod.common.swing.tips.DefaultTipModel;
import javax.swing.*;
import java.awt.*;
import java.util.prefs.Preferences;
/**
* Provides the "Tip of The Day" pane and dialog.<br>
* Tips are retrieved from the {@link com.l2fprod.common.swing.TipModel}. In
* the most common usage, a tip (as returned by
* {@link com.l2fprod.common.swing.TipModel.Tip#getTip()}) is just a
* <code>String</code>. However, the return type of this method is actually
* <code>Object</code>. Its interpretation depends on its type:
* <dl compact>
* <dt>Component
* <dd>The <code>Component</code> is displayed in the dialog.
* <dt>Icon
* <dd>The <code>Icon</code> is wrapped in a <code>JLabel</code> and
* displayed in the dialog.
* <dt>others
* <dd>The object is converted to a <code>String</code> by calling its
* <code>toString</code> method. The result is wrapped in a
* <code>JEditorPane</code> or <code>JTextArea</code> and displayed.
* </dl>
*
* @author Frederic Lavigne
*/
public class JTipOfTheDay extends JComponent {
public final static String uiClassID = "l2fprod/TipOfTheDayUI";
// ensure at least the default ui is registered
static {
LookAndFeelAddons.contribute(new JTipOfTheDayAddon());
}
/**
* Key used to store the status of the "Show tip on startup" checkbox"
*/
public static final String PREFERENCE_KEY = "ShowTipOnStartup";
/**
* Used when generating PropertyChangeEvents for the "currentTip" property
*/
public static final String CURRENT_TIP_CHANGED_KEY = "currentTip";
private TipModel model;
private int currentTip = 0;
public JTipOfTheDay() {
this(new DefaultTipModel(new Tip[0]));
}
public JTipOfTheDay(TipModel model) {
this.model = model;
updateUI();
}
/**
* Notification from the <code>UIManager</code> that the L&F has changed.
* Replaces the current UI object with the latest version from the
* <code>UIManager</code>.
*
* @see javax.swing.JComponent#updateUI
*/
public void updateUI() {
setUI((TipOfTheDayUI) LookAndFeelAddons.getUI(this, TipOfTheDayUI.class));
}
/**
* Sets the L&F object that renders this component.
*
* @param ui the <code>TipOfTheDayUI</code> L&F object
* @beaninfo bound: true hidden: true description: The UI object that
* implements the taskpane group's LookAndFeel.
* @see javax.swing.UIDefaults#getUI
*/
public void setUI(TipOfTheDayUI ui) {
super.setUI(ui);
}
/**
* Gets the UI object which implements the L&F for this component.
*
* @return the TipOfTheDayUI object that implements the TipOfTheDayUI L&F
*/
public TipOfTheDayUI getUI() {
return (TipOfTheDayUI) ui;
}
/**
* Returns the name of the L&F class that renders this component.
*
* @return the string {@link #uiClassID}
* @see javax.swing.JComponent#getUIClassID
* @see javax.swing.UIDefaults#getUI
*/
public String getUIClassID() {
return uiClassID;
}
public TipModel getModel() {
return model;
}
public void setModel(TipModel model) {
TipModel old = this.model;
this.model = model;
firePropertyChange("model", old, model);
}
public int getCurrentTip() {
return currentTip;
}
/**
* Sets the index of the tip to show
*
* @param currentTip
* @throw IllegalArgumentException if currentTip is not within the bounds [0,
* getModel().getTipCount()[.
*/
public void setCurrentTip(int currentTip) {
if (currentTip < 0 || currentTip >= getModel().getTipCount()) {
throw new IllegalArgumentException("Current tip must be within the bounds [0, " + getModel().getTipCount() + "[");
}
int oldTip = this.currentTip;
this.currentTip = currentTip;
firePropertyChange(CURRENT_TIP_CHANGED_KEY, oldTip, currentTip);
}
/**
* Shows the next tip in the list. It cycles the tip list.
*/
public void nextTip() {
int count = getModel().getTipCount();
if (count == 0) { return; }
int nextTip = currentTip + 1;
if (nextTip >= count) {
nextTip = 0;
}
setCurrentTip(nextTip);
}
/**
* Shows the previous tip in the list. It cycles the tip list.
*/
public void previousTip() {
int count = getModel().getTipCount();
if (count == 0) { return; }
int previousTip = currentTip - 1;
if (previousTip < 0) {
previousTip = count - 1;
}
setCurrentTip(previousTip);
}
/**
* Pops up a "Tip of the day" dialog.
*
* @param parentComponent
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public void showDialog(Component parentComponent) throws HeadlessException {
showDialog(parentComponent, (ShowOnStartupChoice) null);
}
/**
* Pops up a "Tip of the day" dialog. Additionally, it saves the state of the
* "Show tips on startup" checkbox in a key named "ShowTipOnStartup" in the
* given Preferences.
*
* @param parentComponent
* @param showOnStartupPref
* @return true if the user chooses to see the tips again, false otherwise.
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
* @throws IllegalArgumentException if showOnStartupPref is null
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public boolean showDialog(Component parentComponent, Preferences showOnStartupPref) throws HeadlessException {
return showDialog(parentComponent, showOnStartupPref, false);
}
/**
* Pops up a "Tip of the day" dialog. Additionally, it saves the state of the
* "Show tips on startup" checkbox in a key named "ShowTipOnStartup" in the
* given Preferences.
*
* @param parentComponent
* @param showOnStartupPref
* @param force if true, the dialog is displayed even if the Preferences is set to
* hide the dialog
* @return true if the user chooses to see the tips again, false
* otherwise.
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
* @throws IllegalArgumentException if showOnStartupPref is null
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public boolean showDialog(Component parentComponent, final Preferences showOnStartupPref, boolean force) throws HeadlessException {
if (showOnStartupPref == null) {
throw new IllegalArgumentException("Preferences can not be null");
}
ShowOnStartupChoice store = new ShowOnStartupChoice() {
public boolean isShowingOnStartup() {
return showOnStartupPref.getBoolean(PREFERENCE_KEY, true);
}
public void setShowingOnStartup(boolean showOnStartup) {
// only save the choice if it is negative
if (!showOnStartup) {
showOnStartupPref.putBoolean(PREFERENCE_KEY, showOnStartup);
}
}
};
return showDialog(parentComponent, store, force);
}
/**
* Pops up a "Tip of the day" dialog.
* <p/>
* If <code>choice</code> is not null, the method first checks if
* {@link ShowOnStartupChoice#isShowingOnStartup()} is true before showing the
* dialog.
* <p/>
* Additionally, it saves the state of the "Show tips on startup" checkbox
* using the given {@link ShowOnStartupChoice} object.
*
* @param parentComponent
* @param choice
* @return true if the user chooses to not the tips again, false otherwise.
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public boolean showDialog(Component parentComponent, ShowOnStartupChoice choice) {
return showDialog(parentComponent, choice, false);
}
/**
* Pops up a "Tip of the day" dialog.
* <p/>
* If <code>choice</code> is not null, the method first checks if
* <code>force</code> is true or if
* {@link ShowOnStartupChoice#isShowingOnStartup()} is true before showing the
* dialog.
* <p/>
* Additionally, it saves the state of the "Show tips on startup" checkbox
* using the given {@link ShowOnStartupChoice} object.
*
* @param parentComponent
* @param choice
* @param force if true, the dialog is displayed even if
* {@link ShowOnStartupChoice#isShowingOnStartup()} is false
* @return true if the user chooses to see the tips again, false otherwise.
* @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public boolean showDialog(Component parentComponent, ShowOnStartupChoice choice, boolean force) {
if (choice == null) {
JDialog dialog = createDialog(parentComponent, choice);
dialog.setVisible(true);
dialog.dispose();
return true;
} else if (force || choice.isShowingOnStartup()) {
JDialog dialog = createDialog(parentComponent, choice);
dialog.setVisible(true);
dialog.dispose();
return choice.isShowingOnStartup();
} else {
return false;
}
}
/**
* @param showOnStartupPref
* @return true if the key named "ShowTipOnStartup" is not set to false
*/
public static boolean isShowingOnStartup(Preferences showOnStartupPref) {
return showOnStartupPref.getBoolean(PREFERENCE_KEY, true);
}
/**
* Removes the value set for "ShowTipOnStartup" in the given Preferences to
* ensure the dialog shown by a later call to
* {@link #showDialog(Component, Preferences)} will be visible to the user.
*
* @param showOnStartupPref
*/
public static void forceShowOnStartup(Preferences showOnStartupPref) {
showOnStartupPref.remove(PREFERENCE_KEY);
}
/**
* Calls
* {@link TipOfTheDayUI#createDialog(Component, JTipOfTheDay.ShowOnStartupChoice)}
*
* @param parentComponent
* @param choice
* @return a JDialog to show this TipOfTheDay pane
*/
protected JDialog createDialog(Component parentComponent, ShowOnStartupChoice choice) {
return getUI().createDialog(parentComponent, choice);
}
/**
* Used in conjunction with the
* {@link JTipOfTheDay#showDialog(Component, ShowOnStartupChoice)} to save the
* "Show tips on startup" choice.
*/
public static interface ShowOnStartupChoice {
void setShowingOnStartup(boolean showOnStartup);
boolean isShowingOnStartup();
}
}