001: package net.suberic.pooka.gui.crypto;
002:
003: import net.suberic.util.gui.*;
004: import net.suberic.util.VariableBundle;
005:
006: import javax.swing.*;
007: import java.awt.Color;
008:
009: import java.util.Hashtable;
010:
011: /**
012: * This defines a UI component which may be built dynamically using a
013: * set of properties in a VariableBundle, and then may have the Actions
014: * associated with the individual buttons/menu items/whatevers updated
015: * dynamically to reflect the new values.
016: *
017: * In general, the format for the properties which define a ConfigurableUI
018: * component are as follows:
019: *
020: * MenuBar=File:Edit:Mail:Window:Help
021: *
022: * MenuBar.File=NewFolder:NewMail:OpenFolder:OpenMessage:Close:SaveAs:Print:Exit
023: * MenuBar.File.Label=File
024: *
025: * MenuBar.File.NewFolder.Action=folder-new
026: * MenuBar.File.NewFolder.Image=images/New.gif
027: * MenuBar.File.NewFolder.KeyBinding=F
028: * MenuBar.File.NewFolder.Label=New Folder
029: *
030: * where MenuBar would be the name of the 'root' configuration property,
031: * 'MenuBar.File' is the first submenu, and 'MenuBar.File.NewFolder' is
032: * the first actual 'button' configured. On the NewFolder MenuItem, the
033: * 'Action' is the name of the Action which will be run, and is the
034: * central part of the configuration. The rest (Image, KeyBinding, and
035: * Label) just control how the item is displayed and invoked. The
036: * 'KeyBinding' and 'Label' items should probably be put in a localized
037: * file if you want to internationalize your application.
038: */
039:
040: public class CryptoButton extends JButton implements ConfigurableUI,
041: CryptoStatusDisplay {
042:
043: // the various icons
044: ImageIcon notEncryptedIcon;
045: ImageIcon uncheckedEncryptedIcon;
046: ImageIcon decryptedSuccessfullyIcon;
047: ImageIcon decryptedUnsuccessfullyIcon;
048: ImageIcon uncheckedSignedIcon;
049: ImageIcon signatureVerifiedIcon;
050: ImageIcon signatureBadIcon;
051: ImageIcon signatureFailedVerificationIcon;
052:
053: // the various status colors
054: Color signedEncryptedColor = Color.MAGENTA;
055: Color signedColor = Color.GREEN;
056: Color encryptedColor = Color.BLUE;
057: Color uncheckedColor = Color.YELLOW;
058: Color failedColor = Color.RED;
059:
060: // the current status
061: int currentCryptStatus = NOT_ENCRYPTED;
062: int currentSigStatus = NOT_SIGNED;
063:
064: Action currentAction = null;
065:
066: public CryptoButton() {
067: super ();
068: }
069:
070: /**
071: * This creates a new CryptoButton using the buttonID as the
072: * configuration key, and vars as the source for the values of all the
073: * properties.
074: *
075: * If buttonID doesn't exist in vars, then this returns an empty
076: * Button.
077: */
078: public CryptoButton(String buttonID, VariableBundle vars) {
079: super ();
080:
081: configureComponent(buttonID, vars);
082: }
083:
084: /**
085: * This configures the UI Component with the given ID and
086: * VariableBundle.
087: */
088: public void configureComponent(String key, VariableBundle vars) {
089:
090: loadIcons(key, vars);
091:
092: try {
093: this .setToolTipText(vars.getProperty(key + ".ToolTip"));
094: } catch (java.util.MissingResourceException mre) {
095: }
096:
097: String cmd = vars.getProperty(key + ".Action", key);
098:
099: setActionCommand(cmd);
100:
101: cryptoUpdated(NOT_SIGNED, NOT_ENCRYPTED);
102: }
103:
104: /**
105: * This loads all of the icons for this button.
106: */
107: public void loadIcons(String key, VariableBundle vars) {
108:
109: /*
110: * this is going to have several images:
111: * Unchecked Encrypted
112: * Decrypted Successfully
113: * Decrypted Unsuccessfully
114: * Unchecked Signed
115: * Signature verified
116: * Signature bad
117: * Signature failed verification
118: * ...and maybe more.
119: */
120:
121: try {
122: java.net.URL url = this .getClass().getResource(
123: vars.getProperty(key + ".notEncrypted.Image"));
124: if (url != null)
125: notEncryptedIcon = new ImageIcon(url);
126: } catch (java.util.MissingResourceException mre) {
127: return;
128: }
129:
130: try {
131: java.net.URL url = this .getClass()
132: .getResource(
133: vars.getProperty(key
134: + ".uncheckedEncrypted.Image"));
135: if (url != null)
136: uncheckedEncryptedIcon = new ImageIcon(url);
137: } catch (java.util.MissingResourceException mre) {
138: return;
139: }
140:
141: try {
142: java.net.URL url = this .getClass().getResource(
143: vars.getProperty(key
144: + ".decryptedSuccessfully.Image"));
145: if (url != null)
146: decryptedSuccessfullyIcon = new ImageIcon(url);
147: } catch (java.util.MissingResourceException mre) {
148: return;
149: }
150:
151: try {
152: java.net.URL url = this .getClass().getResource(
153: vars.getProperty(key
154: + ".decryptedUnsuccessfully.Image"));
155: if (url != null)
156: decryptedUnsuccessfullyIcon = new ImageIcon(url);
157: } catch (java.util.MissingResourceException mre) {
158: return;
159: }
160:
161: try {
162: java.net.URL url = this .getClass().getResource(
163: vars.getProperty(key + ".uncheckedSigned.Image"));
164: if (url != null)
165: uncheckedSignedIcon = new ImageIcon(url);
166: } catch (java.util.MissingResourceException mre) {
167: return;
168: }
169:
170: try {
171: java.net.URL url = this .getClass().getResource(
172: vars.getProperty(key + ".signatureVerified.Image"));
173: if (url != null)
174: signatureVerifiedIcon = new ImageIcon(url);
175: } catch (java.util.MissingResourceException mre) {
176: return;
177: }
178:
179: try {
180: java.net.URL url = this .getClass().getResource(
181: vars.getProperty(key + ".signatureBad.Image"));
182: if (url != null)
183: signatureBadIcon = new ImageIcon(url);
184: } catch (java.util.MissingResourceException mre) {
185: return;
186: }
187:
188: try {
189: java.net.URL url = this .getClass().getResource(
190: vars.getProperty(key
191: + ".signatureFailedVerification.Image"));
192: if (url != null)
193: signatureFailedVerificationIcon = new ImageIcon(url);
194: } catch (java.util.MissingResourceException mre) {
195: return;
196: }
197:
198: }
199:
200: /**
201: * This updates the Actions on the UI Component.
202: *
203: * The commands Hashtable is expected to be a table with the Action
204: * names as keys, and the Actions themselves as values.
205: */
206: public void setActive(Hashtable commands) {
207: if (currentAction != null) {
208: removeActionListener(currentAction);
209: }
210:
211: try {
212: currentAction = (Action) commands.get(getActionCommand());
213: } catch (ClassCastException cce) {
214: currentAction = null;
215: }
216:
217: if (currentAction != null) {
218: addActionListener(currentAction);
219: setEnabled(true);
220: } else {
221: setEnabled(false);
222: }
223: }
224:
225: /**
226: * This updates the Actions on the UI Component.
227: *
228: */
229: public void setActive(Action[] newActions) {
230: Hashtable tmpHash = new Hashtable();
231: if (newActions != null && newActions.length > 0) {
232: for (int i = 0; i < newActions.length; i++) {
233: String cmdName = (String) newActions[i]
234: .getValue(Action.NAME);
235: tmpHash.put(cmdName, newActions[i]);
236: }
237: }
238:
239: setActive(tmpHash);
240: }
241:
242: /**
243: * Updates the encryption information.
244: */
245: public void cryptoUpdated(
246: net.suberic.pooka.MessageCryptoInfo cryptoInfo) {
247:
248: try {
249: int sigStatus = NOT_SIGNED;
250: int cryptStatus = NOT_ENCRYPTED;
251:
252: if (cryptoInfo.isSigned()) {
253: if (cryptoInfo.hasCheckedSignature()) {
254: if (cryptoInfo.isSignatureValid()) {
255: sigStatus = SIGNATURE_VERIFIED;
256: } else {
257: sigStatus = SIGNATURE_BAD;
258: }
259: } else {
260: sigStatus = UNCHECKED_SIGNED;
261: }
262: }
263:
264: if (cryptoInfo.isEncrypted()) {
265: if (cryptoInfo.hasTriedDecryption()) {
266: if (cryptoInfo.isDecryptedSuccessfully()) {
267: cryptStatus = DECRYPTED_SUCCESSFULLY;
268: } else {
269: cryptStatus = DECRYPTED_UNSUCCESSFULLY;
270: }
271: } else {
272: cryptStatus = UNCHECKED_ENCRYPTED;
273: }
274: }
275:
276: cryptoUpdated(sigStatus, cryptStatus);
277:
278: } catch (javax.mail.MessagingException me) {
279: // ignore here.
280: }
281: }
282:
283: /**
284: * Updates the encryption information.
285: */
286: public void cryptoUpdated(int newSignatureStatus,
287: int newEncryptionStatus) {
288: currentCryptStatus = newEncryptionStatus;
289: currentSigStatus = newSignatureStatus;
290:
291: if (currentCryptStatus == NOT_ENCRYPTED
292: || currentCryptStatus == DECRYPTED_SUCCESSFULLY) {
293: if (currentSigStatus == NOT_SIGNED) {
294: if (currentCryptStatus == NOT_ENCRYPTED) {
295: setIcon(notEncryptedIcon);
296: } else {
297: setIcon(decryptedSuccessfullyIcon);
298: setToolBarColor(encryptedColor);
299: }
300: } else if (currentSigStatus == UNCHECKED_SIGNED) {
301: setIcon(uncheckedSignedIcon);
302: setToolBarColor(uncheckedColor);
303: } else if (currentSigStatus == SIGNATURE_VERIFIED) {
304: setIcon(signatureVerifiedIcon);
305: if (currentCryptStatus == NOT_ENCRYPTED)
306: setToolBarColor(signedColor);
307: else
308: setToolBarColor(signedEncryptedColor);
309: } else if (currentSigStatus == SIGNATURE_BAD) {
310: setIcon(signatureBadIcon);
311: setToolBarColor(failedColor);
312: } else if (currentSigStatus == SIGNATURE_FAILED_VERIFICATION) {
313: setIcon(signatureFailedVerificationIcon);
314: setToolBarColor(failedColor);
315: }
316: } else if (currentCryptStatus == UNCHECKED_ENCRYPTED) {
317: setIcon(uncheckedEncryptedIcon);
318: setToolBarColor(uncheckedColor);
319: } else if (currentCryptStatus == DECRYPTED_SUCCESSFULLY) {
320: setIcon(decryptedSuccessfullyIcon);
321: setToolBarColor(encryptedColor);
322: } else if (currentCryptStatus == DECRYPTED_UNSUCCESSFULLY) {
323: setIcon(decryptedUnsuccessfullyIcon);
324: setToolBarColor(failedColor);
325: } else {
326: setIcon(notEncryptedIcon);
327: }
328:
329: repaint();
330: }
331:
332: /**
333: * Sets the toolbar color.
334: */
335: public void setToolBarColor(Color newColor) {
336: /*
337: JToolBar tb = getToolBar();
338: if (tb != null) {
339: tb.setBackground(newColor);
340: } else {
341: System.err.println("toolbar = null.");
342: }
343: */
344: this .setBackground(newColor);
345: }
346:
347: /**
348: * Gets the toolbar this Button belongs to.
349: */
350: public JToolBar getToolBar() {
351: try {
352: return (JToolBar) getAncestorOfClass(Class
353: .forName("javax.swing.JToolBar"), this );
354: } catch (Exception e) {
355: e.printStackTrace();
356: return null;
357: }
358: }
359:
360: /**
361: * Workaround for jdk 1.5 weirdness.
362: */
363: private java.awt.Container getAncestorOfClass(Class c,
364: java.awt.Component comp) {
365: if (comp == null || c == null)
366: return null;
367: java.awt.Container parent = comp.getParent();
368: while (parent != null && !(c.isInstance(parent)))
369: parent = parent.getParent();
370: return parent;
371: }
372: }
|