001: /**
002: * L2FProd.com Common Components 7.3 License.
003: *
004: * Copyright 2005-2007 L2FProd.com
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package com.l2fprod.common.swing;
018:
019: import com.l2fprod.common.swing.TipModel.Tip;
020: import com.l2fprod.common.swing.plaf.JTipOfTheDayAddon;
021: import com.l2fprod.common.swing.plaf.LookAndFeelAddons;
022: import com.l2fprod.common.swing.plaf.TipOfTheDayUI;
023: import com.l2fprod.common.swing.tips.DefaultTipModel;
024:
025: import java.awt.Component;
026: import java.awt.HeadlessException;
027: import java.util.prefs.Preferences;
028:
029: import javax.swing.JComponent;
030: import javax.swing.JDialog;
031:
032: /**
033: * Provides the "Tip of The Day" pane and dialog.<br>
034: * Tips are retrieved from the {@link com.l2fprod.common.swing.TipModel}. In
035: * the most common usage, a tip (as returned by
036: * {@link com.l2fprod.common.swing.TipModel.Tip#getTip()}) is just a
037: * <code>String</code>. However, the return type of this method is actually
038: * <code>Object</code>. Its interpretation depends on its type:
039: * <dl compact>
040: * <dt>Component
041: * <dd>The <code>Component</code> is displayed in the dialog.
042: * <dt>Icon
043: * <dd>The <code>Icon</code> is wrapped in a <code>JLabel</code> and
044: * displayed in the dialog.
045: * <dt>others
046: * <dd>The object is converted to a <code>String</code> by calling its
047: * <code>toString</code> method. The result is wrapped in a
048: * <code>JEditorPane</code> or <code>JTextArea</code> and displayed.
049: * </dl>
050: *
051: * @author Frederic Lavigne
052: */
053: public class JTipOfTheDay extends JComponent {
054:
055: public final static String uiClassID = "l2fprod/TipOfTheDayUI";
056:
057: // ensure at least the default ui is registered
058: static {
059: LookAndFeelAddons.contribute(new JTipOfTheDayAddon());
060: }
061:
062: /**
063: * Key used to store the status of the "Show tip on startup" checkbox"
064: */
065: public static final String PREFERENCE_KEY = "ShowTipOnStartup";
066:
067: /**
068: * Used when generating PropertyChangeEvents for the "currentTip" property
069: */
070: public static final String CURRENT_TIP_CHANGED_KEY = "currentTip";
071:
072: private TipModel model;
073: private int currentTip = 0;
074:
075: public JTipOfTheDay() {
076: this (new DefaultTipModel(new Tip[0]));
077: }
078:
079: public JTipOfTheDay(TipModel model) {
080: this .model = model;
081: updateUI();
082: }
083:
084: /**
085: * Notification from the <code>UIManager</code> that the L&F has changed.
086: * Replaces the current UI object with the latest version from the
087: * <code>UIManager</code>.
088: *
089: * @see javax.swing.JComponent#updateUI
090: */
091: public void updateUI() {
092: setUI((TipOfTheDayUI) LookAndFeelAddons.getUI(this ,
093: TipOfTheDayUI.class));
094: }
095:
096: /**
097: * Sets the L&F object that renders this component.
098: *
099: * @param ui
100: * the <code>TipOfTheDayUI</code> L&F object
101: * @see javax.swing.UIDefaults#getUI
102: *
103: * @beaninfo bound: true hidden: true description: The UI object that
104: * implements the taskpane group's LookAndFeel.
105: */
106: public void setUI(TipOfTheDayUI ui) {
107: super .setUI(ui);
108: }
109:
110: /**
111: * Gets the UI object which implements the L&F for this component.
112: *
113: * @return the TipOfTheDayUI object that implements the TipOfTheDayUI L&F
114: */
115: public TipOfTheDayUI getUI() {
116: return (TipOfTheDayUI) ui;
117: }
118:
119: /**
120: * Returns the name of the L&F class that renders this component.
121: *
122: * @return the string {@link #uiClassID}
123: * @see javax.swing.JComponent#getUIClassID
124: * @see javax.swing.UIDefaults#getUI
125: */
126: public String getUIClassID() {
127: return uiClassID;
128: }
129:
130: public TipModel getModel() {
131: return model;
132: }
133:
134: public void setModel(TipModel model) {
135: TipModel old = this .model;
136: this .model = model;
137: firePropertyChange("model", old, model);
138: }
139:
140: public int getCurrentTip() {
141: return currentTip;
142: }
143:
144: /**
145: * Sets the index of the tip to show
146: *
147: * @param currentTip
148: * @throw IllegalArgumentException if currentTip is not within the bounds [0,
149: * getModel().getTipCount()[.
150: */
151: public void setCurrentTip(int currentTip) {
152: if (currentTip < 0 || currentTip >= getModel().getTipCount()) {
153: throw new IllegalArgumentException(
154: "Current tip must be within the bounds [0, "
155: + getModel().getTipCount() + "[");
156: }
157:
158: int oldTip = this .currentTip;
159: this .currentTip = currentTip;
160: firePropertyChange(CURRENT_TIP_CHANGED_KEY, oldTip, currentTip);
161: }
162:
163: /**
164: * Shows the next tip in the list. It cycles the tip list.
165: */
166: public void nextTip() {
167: int count = getModel().getTipCount();
168: if (count == 0) {
169: return;
170: }
171:
172: int nextTip = currentTip + 1;
173: if (nextTip >= count) {
174: nextTip = 0;
175: }
176: setCurrentTip(nextTip);
177: }
178:
179: /**
180: * Shows the previous tip in the list. It cycles the tip list.
181: */
182: public void previousTip() {
183: int count = getModel().getTipCount();
184: if (count == 0) {
185: return;
186: }
187:
188: int previousTip = currentTip - 1;
189: if (previousTip < 0) {
190: previousTip = count - 1;
191: }
192: setCurrentTip(previousTip);
193: }
194:
195: /**
196: * Pops up a "Tip of the day" dialog.
197: *
198: * @param parentComponent
199: * @exception HeadlessException
200: * if GraphicsEnvironment.isHeadless() returns true.
201: * @see java.awt.GraphicsEnvironment#isHeadless
202: */
203: public void showDialog(Component parentComponent)
204: throws HeadlessException {
205: showDialog(parentComponent, (ShowOnStartupChoice) null);
206: }
207:
208: /**
209: * Pops up a "Tip of the day" dialog. Additionally, it saves the state of the
210: * "Show tips on startup" checkbox in a key named "ShowTipOnStartup" in the
211: * given Preferences.
212: *
213: * @param parentComponent
214: * @param showOnStartupPref
215: * @exception HeadlessException
216: * if GraphicsEnvironment.isHeadless() returns true.
217: * @throws IllegalArgumentException
218: * if showOnStartupPref is null
219: * @see java.awt.GraphicsEnvironment#isHeadless
220: * @return true if the user chooses to see the tips again, false otherwise.
221: */
222: public boolean showDialog(Component parentComponent,
223: Preferences showOnStartupPref) throws HeadlessException {
224: return showDialog(parentComponent, showOnStartupPref, false);
225: }
226:
227: /**
228: * Pops up a "Tip of the day" dialog. Additionally, it saves the state of the
229: * "Show tips on startup" checkbox in a key named "ShowTipOnStartup" in the
230: * given Preferences.
231: *
232: * @param parentComponent
233: * @param showOnStartupPref
234: * @param force
235: * if true, the dialog is displayed even if the Preferences is set to
236: * hide the dialog
237: * @exception HeadlessException
238: * if GraphicsEnvironment.isHeadless() returns true.
239: * @throws IllegalArgumentException
240: * if showOnStartupPref is null
241: * @see java.awt.GraphicsEnvironment#isHeadless
242: * @return true if the user chooses to see the tips again, false
243: * otherwise.
244: */
245: public boolean showDialog(Component parentComponent,
246: final Preferences showOnStartupPref, boolean force)
247: throws HeadlessException {
248: if (showOnStartupPref == null) {
249: throw new IllegalArgumentException(
250: "Preferences can not be null");
251: }
252:
253: ShowOnStartupChoice store = new ShowOnStartupChoice() {
254: public boolean isShowingOnStartup() {
255: return showOnStartupPref.getBoolean(PREFERENCE_KEY,
256: true);
257: }
258:
259: public void setShowingOnStartup(boolean showOnStartup) {
260: // only save the choice if it is negative
261: if (!showOnStartup) {
262: showOnStartupPref.putBoolean(PREFERENCE_KEY,
263: showOnStartup);
264: }
265: }
266: };
267: return showDialog(parentComponent, store, force);
268: }
269:
270: /**
271: * Pops up a "Tip of the day" dialog.
272: *
273: * If <code>choice</code> is not null, the method first checks if
274: * {@link ShowOnStartupChoice#isShowingOnStartup()} is true before showing the
275: * dialog.
276: *
277: * Additionally, it saves the state of the "Show tips on startup" checkbox
278: * using the given {@link ShowOnStartupChoice} object.
279: *
280: * @param parentComponent
281: * @param choice
282: * @exception HeadlessException
283: * if GraphicsEnvironment.isHeadless() returns true.
284: * @see java.awt.GraphicsEnvironment#isHeadless
285: * @return true if the user chooses to not the tips again, false otherwise.
286: */
287: public boolean showDialog(Component parentComponent,
288: ShowOnStartupChoice choice) {
289: return showDialog(parentComponent, choice, false);
290: }
291:
292: /**
293: * Pops up a "Tip of the day" dialog.
294: *
295: * If <code>choice</code> is not null, the method first checks if
296: * <code>force</code> is true or if
297: * {@link ShowOnStartupChoice#isShowingOnStartup()} is true before showing the
298: * dialog.
299: *
300: * Additionally, it saves the state of the "Show tips on startup" checkbox
301: * using the given {@link ShowOnStartupChoice} object.
302: *
303: * @param parentComponent
304: * @param choice
305: * @param force
306: * if true, the dialog is displayed even if
307: * {@link ShowOnStartupChoice#isShowingOnStartup()} is false
308: * @exception HeadlessException
309: * if GraphicsEnvironment.isHeadless() returns true.
310: * @see java.awt.GraphicsEnvironment#isHeadless
311: * @return true if the user chooses to see the tips again, false otherwise.
312: */
313: public boolean showDialog(Component parentComponent,
314: ShowOnStartupChoice choice, boolean force) {
315: if (choice == null) {
316: JDialog dialog = createDialog(parentComponent, choice);
317: dialog.setVisible(true);
318: dialog.dispose();
319: return true;
320: } else if (force || choice.isShowingOnStartup()) {
321: JDialog dialog = createDialog(parentComponent, choice);
322: dialog.setVisible(true);
323: dialog.dispose();
324: return choice.isShowingOnStartup();
325: } else {
326: return false;
327: }
328: }
329:
330: /**
331: * @param showOnStartupPref
332: * @return true if the key named "ShowTipOnStartup" is not set to false
333: */
334: public static boolean isShowingOnStartup(
335: Preferences showOnStartupPref) {
336: return showOnStartupPref.getBoolean(PREFERENCE_KEY, true);
337: }
338:
339: /**
340: * Removes the value set for "ShowTipOnStartup" in the given Preferences to
341: * ensure the dialog shown by a later call to
342: * {@link #showDialog(Component, Preferences)} will be visible to the user.
343: *
344: * @param showOnStartupPref
345: */
346: public static void forceShowOnStartup(Preferences showOnStartupPref) {
347: showOnStartupPref.remove(PREFERENCE_KEY);
348: }
349:
350: /**
351: * Calls
352: * {@link TipOfTheDayUI#createDialog(Component, JTipOfTheDay.ShowOnStartupChoice)}
353: *
354: * @param parentComponent
355: * @param choice
356: * @return a JDialog to show this TipOfTheDay pane
357: */
358: protected JDialog createDialog(Component parentComponent,
359: ShowOnStartupChoice choice) {
360: return getUI().createDialog(parentComponent, choice);
361: }
362:
363: /**
364: * Used in conjunction with the
365: * {@link JTipOfTheDay#showDialog(Component, ShowOnStartupChoice)} to save the
366: * "Show tips on startup" choice.
367: */
368: public static interface ShowOnStartupChoice {
369: void setShowingOnStartup(boolean showOnStartup);
370:
371: boolean isShowingOnStartup();
372: }
373:
374: }
|