KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > themes > ColorsAndFontsPreferencePage


1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.themes;
12
13 import com.ibm.icu.text.MessageFormat;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.ResourceBundle JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.jface.preference.ColorSelector;
27 import org.eclipse.jface.preference.PreferenceConverter;
28 import org.eclipse.jface.preference.PreferencePage;
29 import org.eclipse.jface.resource.JFaceResources;
30 import org.eclipse.jface.resource.StringConverter;
31 import org.eclipse.jface.util.IPropertyChangeListener;
32 import org.eclipse.jface.util.PropertyChangeEvent;
33 import org.eclipse.jface.viewers.AbstractTreeViewer;
34 import org.eclipse.jface.viewers.DoubleClickEvent;
35 import org.eclipse.jface.viewers.IDoubleClickListener;
36 import org.eclipse.jface.viewers.IFontProvider;
37 import org.eclipse.jface.viewers.ISelectionChangedListener;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.ITreeContentProvider;
40 import org.eclipse.jface.viewers.LabelProvider;
41 import org.eclipse.jface.viewers.LabelProviderChangedEvent;
42 import org.eclipse.jface.viewers.SelectionChangedEvent;
43 import org.eclipse.jface.viewers.StructuredSelection;
44 import org.eclipse.jface.viewers.Viewer;
45 import org.eclipse.jface.viewers.ViewerComparator;
46 import org.eclipse.swt.SWT;
47 import org.eclipse.swt.custom.StackLayout;
48 import org.eclipse.swt.events.DisposeEvent;
49 import org.eclipse.swt.events.DisposeListener;
50 import org.eclipse.swt.events.SelectionAdapter;
51 import org.eclipse.swt.events.SelectionEvent;
52 import org.eclipse.swt.graphics.Color;
53 import org.eclipse.swt.graphics.Font;
54 import org.eclipse.swt.graphics.FontData;
55 import org.eclipse.swt.graphics.GC;
56 import org.eclipse.swt.graphics.Image;
57 import org.eclipse.swt.graphics.RGB;
58 import org.eclipse.swt.layout.FillLayout;
59 import org.eclipse.swt.layout.GridData;
60 import org.eclipse.swt.layout.GridLayout;
61 import org.eclipse.swt.widgets.Button;
62 import org.eclipse.swt.widgets.Composite;
63 import org.eclipse.swt.widgets.Control;
64 import org.eclipse.swt.widgets.Display;
65 import org.eclipse.swt.widgets.FontDialog;
66 import org.eclipse.swt.widgets.Label;
67 import org.eclipse.swt.widgets.Text;
68 import org.eclipse.ui.IWorkbench;
69 import org.eclipse.ui.IWorkbenchPreferencePage;
70 import org.eclipse.ui.PlatformUI;
71 import org.eclipse.ui.dialogs.FilteredTree;
72 import org.eclipse.ui.dialogs.PatternFilter;
73 import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
74 import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
75 import org.eclipse.ui.internal.Workbench;
76 import org.eclipse.ui.internal.WorkbenchMessages;
77 import org.eclipse.ui.internal.WorkbenchPlugin;
78 import org.eclipse.ui.internal.misc.StatusUtil;
79 import org.eclipse.ui.internal.util.PrefUtil;
80 import org.eclipse.ui.internal.util.Util;
81 import org.eclipse.ui.themes.ITheme;
82 import org.eclipse.ui.themes.IThemeManager;
83 import org.eclipse.ui.themes.IThemePreview;
84
85 /**
86  * Preference page for management of system colors, gradients and fonts.
87  *
88  * @since 3.0
89  */

90 public final class ColorsAndFontsPreferencePage extends PreferencePage
91         implements IWorkbenchPreferencePage {
92     
93     private static final String JavaDoc SELECTED_ELEMENT_PREF = "ColorsAndFontsPreferencePage.selectedElement"; //$NON-NLS-1$
94
/**
95      * The preference that stores the expanded state.
96      */

97     private static final String JavaDoc EXPANDED_ELEMENTS_PREF = "ColorsAndFontsPreferencePage.expandedCategories"; //$NON-NLS-1$
98
/**
99      * The token that seperates expanded elements in EXPANDED_ELEMENTS_PREF.
100      */

101     private static final String JavaDoc EXPANDED_ELEMENTS_TOKEN = "\t"; //$NON-NLS-1$
102

103     /**
104      * Marks category tokens in EXPANDED_ELEMENTS_PREF and SELECTED_ELEMENT_PREF.
105      */

106     private static final char MARKER_CATEGORY = 'T';
107     
108     /**
109      * Marks color tokens in EXPANDED_ELEMENTS_PREF and SELECTED_ELEMENT_PREF.
110      */

111     private static final char MARKER_COLOR = 'C';
112     
113     /**
114      * Marks font tokens in EXPANDED_ELEMENTS_PREF and SELECTED_ELEMENT_PREF.
115      */

116     private static final char MARKER_FONT = 'F';
117             
118     private class ThemeContentProvider implements ITreeContentProvider {
119
120         private IThemeRegistry registry;
121
122         /* (non-Javadoc)
123          * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
124          */

125         public Object JavaDoc[] getChildren(Object JavaDoc parentElement) {
126             if (parentElement instanceof ThemeElementCategory) {
127                 String JavaDoc categoryId = ((ThemeElementCategory) parentElement)
128                         .getId();
129                 Object JavaDoc[] defintions = (Object JavaDoc[]) categoryMap.get(categoryId);
130                 if (defintions == null) {
131                     defintions = getCategoryChildren(categoryId);
132                     categoryMap.put(categoryId, defintions);
133                 }
134                 return defintions;
135             }
136
137             ArrayList JavaDoc list = new ArrayList JavaDoc();
138             IHierarchalThemeElementDefinition def = (IHierarchalThemeElementDefinition) parentElement;
139             String JavaDoc id = def.getId();
140             IHierarchalThemeElementDefinition[] defs;
141             if (def instanceof ColorDefinition) {
142                 defs = registry.getColors();
143             } else {
144                 defs = registry.getFonts();
145             }
146
147             for (int i = 0; i < defs.length; i++) {
148                 if (id.equals(defs[i].getDefaultsTo())
149                         && ColorsAndFontsPreferencePage.equals(
150                                 ((ICategorizedThemeElementDefinition) def)
151                                         .getCategoryId(),
152                                 ((ICategorizedThemeElementDefinition) defs[i])
153                                         .getCategoryId())) {
154                     list.add(defs[i]);
155                 }
156             }
157             return list.toArray();
158         }
159
160         private Object JavaDoc[] getCategoryChildren(String JavaDoc categoryId) {
161             ArrayList JavaDoc list = new ArrayList JavaDoc();
162
163             if (categoryId != null) {
164                 ThemeElementCategory[] categories = registry.getCategories();
165                 for (int i = 0; i < categories.length; i++) {
166                     if (categoryId.equals(categories[i].getParentId())) {
167                         Set JavaDoc bindings = themeRegistry
168                                 .getPresentationsBindingsFor(categories[i]);
169                         if (bindings == null
170                                 || bindings.contains(workbench
171                                         .getPresentationId())) {
172                             list.add(categories[i]);
173                         }
174                     }
175                 }
176             }
177             {
178                 ColorDefinition[] colorDefinitions = themeRegistry
179                         .getColorsFor(currentTheme.getId());
180                 for (int i = 0; i < colorDefinitions.length; i++) {
181                     if (!colorDefinitions[i].isEditable()) {
182                         continue;
183                     }
184                     String JavaDoc catId = colorDefinitions[i].getCategoryId();
185                     if ((catId == null && categoryId == null)
186                             || (catId != null && categoryId != null && categoryId
187                                     .equals(catId))) {
188                         if (colorDefinitions[i].getDefaultsTo() != null
189                                 && parentIsInSameCategory(colorDefinitions[i])) {
190                             continue;
191                         }
192                         list.add(colorDefinitions[i]);
193                     }
194                 }
195             }
196             {
197                 FontDefinition[] fontDefinitions = themeRegistry
198                         .getFontsFor(currentTheme.getId());
199                 for (int i = 0; i < fontDefinitions.length; i++) {
200                     if (!fontDefinitions[i].isEditable()) {
201                         continue;
202                     }
203                     String JavaDoc catId = fontDefinitions[i].getCategoryId();
204                     if ((catId == null && categoryId == null)
205                             || (catId != null && categoryId != null && categoryId
206                                     .equals(catId))) {
207                         if (fontDefinitions[i].getDefaultsTo() != null
208                                 && parentIsInSameCategory(fontDefinitions[i])) {
209                             continue;
210                         }
211                         list.add(fontDefinitions[i]);
212                     }
213                 }
214             }
215             return list.toArray(new Object JavaDoc[list.size()]);
216         }
217
218         /**
219          * @param definition
220          * @return
221          */

222         private boolean parentIsInSameCategory(ColorDefinition definition) {
223             String JavaDoc defaultsTo = definition.getDefaultsTo();
224             ColorDefinition[] defs = registry.getColors();
225             for (int i = 0; i < defs.length; i++) {
226                 if (defs[i].getId().equals(defaultsTo)
227                         && ColorsAndFontsPreferencePage.equals(defs[i]
228                                 .getCategoryId(), definition.getCategoryId())) {
229                     return true;
230                 }
231             }
232             return false;
233         }
234
235         /**
236          * @param definition
237          * @return
238          */

239         private boolean parentIsInSameCategory(FontDefinition definition) {
240             String JavaDoc defaultsTo = definition.getDefaultsTo();
241             FontDefinition[] defs = registry.getFonts();
242             for (int i = 0; i < defs.length; i++) {
243                 if (defs[i].getId().equals(defaultsTo)
244                         && ColorsAndFontsPreferencePage.equals(defs[i]
245                                 .getCategoryId(), definition.getCategoryId())) {
246                     return true;
247                 }
248             }
249             return false;
250         }
251
252         /* (non-Javadoc)
253          * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
254          */

255         public Object JavaDoc getParent(Object JavaDoc element) {
256             return null;
257         }
258
259         /* (non-Javadoc)
260          * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
261          */

262         public boolean hasChildren(Object JavaDoc element) {
263             if (element instanceof ThemeElementCategory) {
264                 return true;
265             }
266
267             IHierarchalThemeElementDefinition def = (IHierarchalThemeElementDefinition) element;
268             String JavaDoc id = def.getId();
269             IHierarchalThemeElementDefinition[] defs;
270             if (def instanceof ColorDefinition) {
271                 defs = registry.getColors();
272             } else {
273                 defs = registry.getFonts();
274             }
275
276             for (int i = 0; i < defs.length; i++) {
277                 if (id.equals(defs[i].getDefaultsTo())
278                         && ColorsAndFontsPreferencePage.equals(
279                                 ((ICategorizedThemeElementDefinition) def)
280                                         .getCategoryId(),
281                                 ((ICategorizedThemeElementDefinition) defs[i])
282                                         .getCategoryId())) {
283                     return true;
284                 }
285             }
286
287             return false;
288         }
289
290         /*
291          * (non-Javadoc)
292          *
293          * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
294          */

295         public Object JavaDoc[] getElements(Object JavaDoc inputElement) {
296             ArrayList JavaDoc list = new ArrayList JavaDoc();
297             Object JavaDoc[] uncatChildren = getCategoryChildren(null);
298             list.addAll(Arrays.asList(uncatChildren));
299             ThemeElementCategory[] categories = ((IThemeRegistry) inputElement)
300                     .getCategories();
301             for (int i = 0; i < categories.length; i++) {
302                 if (categories[i].getParentId() == null) {
303                     Set JavaDoc bindings = themeRegistry
304                             .getPresentationsBindingsFor(categories[i]);
305                     if (bindings == null
306                             || bindings.contains(workbench.getPresentationId())) {
307                         list.add(categories[i]);
308                     }
309                 }
310             }
311             return list.toArray(new Object JavaDoc[list.size()]);
312         }
313
314         /* (non-Javadoc)
315          * @see org.eclipse.jface.viewers.IContentProvider#dispose()
316          */

317         public void dispose() {
318             categoryMap.clear();
319         }
320
321         /* (non-Javadoc)
322          * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
323          */

324         public void inputChanged(Viewer viewer, Object JavaDoc oldInput, Object JavaDoc newInput) {
325             categoryMap.clear();
326             registry = (IThemeRegistry) newInput;
327         }
328
329     }
330
331     private class PresentationLabelProvider extends LabelProvider implements
332             IFontProvider {
333
334         private HashMap JavaDoc fonts = new HashMap JavaDoc();
335
336         private HashMap JavaDoc images = new HashMap JavaDoc();
337
338         private int imageSize = -1;
339
340         private int usableImageSize = -1;
341
342         private IPropertyChangeListener listener = new IPropertyChangeListener() {
343             public void propertyChange(PropertyChangeEvent event) {
344                 fireLabelProviderChanged(new LabelProviderChangedEvent(
345                         PresentationLabelProvider.this));
346             }
347         };
348
349         private Image emptyImage;
350
351         /**
352          *
353          */

354         public PresentationLabelProvider() {
355             hookListeners();
356         }
357
358         /**
359          * Hook the listeners onto the various registries.
360          */

361         public void hookListeners() {
362             colorRegistry.addListener(listener);
363             fontRegistry.addListener(listener);
364         }
365
366         /* (non-Javadoc)
367          * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
368          */

369         public void dispose() {
370             super.dispose();
371             colorRegistry.removeListener(listener);
372             fontRegistry.removeListener(listener);
373             for (Iterator JavaDoc i = images.values().iterator(); i.hasNext();) {
374                 ((Image) i.next()).dispose();
375             }
376             images.clear();
377
378             if (emptyImage != null) {
379                 emptyImage.dispose();
380                 emptyImage = null;
381             }
382
383             //clear the fonts.
384
clearFontCache();
385         }
386
387         /**
388          * Clears and disposes all fonts.
389          */

390         public void clearFontCache() {
391             for (Iterator JavaDoc i = fonts.values().iterator(); i.hasNext();) {
392                 ((Font) i.next()).dispose();
393             }
394             fonts.clear();
395         }
396         
397         /**
398          * Clears and disposes all fonts and fires a label update.
399          */

400         public void clearFontCacheAndUpdate() {
401             clearFontCache();
402             fireLabelProviderChanged(new LabelProviderChangedEvent(
403                     PresentationLabelProvider.this));
404         }
405
406         /* (non-Javadoc)
407          * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object)
408          */

409         public Font getFont(Object JavaDoc element) {
410             Display display = tree.getDisplay();
411             if (element instanceof FontDefinition) {
412                 int parentHeight = tree.getViewer().getControl().getFont()
413                         .getFontData()[0].getHeight();
414                 Font baseFont = fontRegistry.get(((FontDefinition) element)
415                         .getId());
416                 Font font = (Font) fonts.get(baseFont);
417                 if (font == null) {
418                     FontData[] data = baseFont.getFontData();
419                     for (int i = 0; i < data.length; i++) {
420                         data[i].setHeight(parentHeight);
421                     }
422                     font = new Font(display, data);
423
424                     fonts.put(baseFont, font);
425                 }
426                 return font;
427             }
428
429             return JFaceResources.getDialogFont();
430         }
431
432         /* (non-Javadoc)
433          * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
434          */

435         public Image getImage(Object JavaDoc element) {
436             if (element instanceof ColorDefinition) {
437                 Color c = colorRegistry
438                         .get(((ColorDefinition) element).getId());
439                 Image image = (Image) images.get(c);
440                 if (image == null) {
441                     Display display = tree.getDisplay();
442                     ensureImageSize(display);
443                     //int size = presentationList.getControl().getFont().getFontData()[0].getHeight();
444
image = new Image(display, imageSize, imageSize);
445
446                     GC gc = new GC(image);
447                     gc.setBackground(tree.getViewer().getControl()
448                             .getBackground());
449                     gc.setForeground(tree.getViewer().getControl()
450                             .getBackground());
451                     gc.drawRectangle(0, 0, imageSize - 1, imageSize - 1);
452
453                     gc.setForeground(tree.getViewer().getControl()
454                             .getForeground());
455                     gc.setBackground(c);
456
457                     int offset = (imageSize - usableImageSize) / 2;
458                     gc.drawRectangle(offset, offset, usableImageSize - offset,
459                             usableImageSize - offset);
460                     gc.fillRectangle(offset + 1, offset + 1, usableImageSize
461                             - offset - 1, usableImageSize - offset - 1);
462                     gc.dispose();
463
464                     images.put(c, image);
465                 }
466                 return image;
467
468             } else if (element instanceof FontDefinition) {
469                 return workbench.getSharedImages().getImage(
470                         IWorkbenchGraphicConstants.IMG_OBJ_FONT);
471             } else {
472                 return workbench.getSharedImages().getImage(
473                         IWorkbenchGraphicConstants.IMG_OBJ_THEME_CATEGORY);
474             }
475         }
476
477         /**
478          * @param display
479          * @return
480          */

481         private void ensureImageSize(Display display) {
482             if (imageSize == -1) {
483                 imageSize = tree.getViewer().getTree().getItemHeight();
484                 usableImageSize = Math.max(1, imageSize - 4);
485             }
486         }
487
488         /* (non-Javadoc)
489          * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
490          */

491         public String JavaDoc getText(Object JavaDoc element) {
492             if (element instanceof IHierarchalThemeElementDefinition) {
493                 IHierarchalThemeElementDefinition themeElement = (IHierarchalThemeElementDefinition) element;
494                 if (themeElement
495                         .getDefaultsTo() != null) {
496                     String JavaDoc myCategory = ((ICategorizedThemeElementDefinition) themeElement)
497                             .getCategoryId();
498                     ICategorizedThemeElementDefinition def;
499                     if (element instanceof ColorDefinition) {
500                         def = themeRegistry
501                                 .findColor(themeElement
502                                         .getDefaultsTo());
503                     } else {
504                         def = themeRegistry
505                                 .findFont(themeElement
506                                         .getDefaultsTo());
507                     }
508
509                     if (!ColorsAndFontsPreferencePage.equals(def
510                             .getCategoryId(), myCategory)) {
511                             if (isDefault(themeElement)) {
512                             return MessageFormat
513                                     .format(
514                                             RESOURCE_BUNDLE
515                                                     .getString("defaultFormat_default"), new Object JavaDoc[] { themeElement.getName(), def.getName() }); //$NON-NLS-1$
516
}
517                         
518                             return MessageFormat
519                             .format(
520                                     RESOURCE_BUNDLE
521                                             .getString("defaultFormat_override"), new Object JavaDoc[] { themeElement.getName(), def.getName() }); //$NON-NLS-1$
522
}
523                 }
524             }
525             return ((IThemeElementDefinition) element).getName();
526         }
527
528         /**
529          * Return whether the element is set to default.
530          *
531          * @param def the definition
532          * @return whether the element is set to default
533          * @since 3.2
534          */

535         private boolean isDefault(IThemeElementDefinition def) {
536             if (def instanceof FontDefinition) {
537                 return ColorsAndFontsPreferencePage.this.isDefault((FontDefinition)def);
538             } else if (def instanceof ColorDefinition) {
539                 return ColorsAndFontsPreferencePage.this.isDefault((ColorDefinition)def);
540             }
541             return false;
542         }
543     }
544
545     /**
546      * The translation bundle in which to look up internationalized text.
547      */

548     private final static ResourceBundle JavaDoc RESOURCE_BUNDLE = ResourceBundle
549             .getBundle(ColorsAndFontsPreferencePage.class.getName());
550
551     /**
552      * Map to precalculate category color lists.
553      */

554     private Map JavaDoc categoryMap = new HashMap JavaDoc(7);
555
556     private Font appliedDialogFont;
557
558     /**
559      * The composite containing all color-specific controls.
560      */

561     private Composite colorControls;
562
563     /**
564      * Map of defintion id->RGB objects that map to changes expressed in this
565      * UI session. These changes should be made in preferences and the
566      * registry.
567      */

568     private Map JavaDoc colorPreferencesToSet = new HashMap JavaDoc(7);
569
570     private CascadingColorRegistry colorRegistry;
571
572     private Button colorResetButton;
573
574     private ColorSelector colorSelector;
575
576     /**
577      * Map of defintion id->RGB objects that map to changes expressed in this
578      * UI session. These changes should be made in the registry.
579      */

580     private Map JavaDoc colorValuesToSet = new HashMap JavaDoc(7);
581
582     /**
583      * The composite that contains the font or color controls (or none).
584      */

585     private Composite controlArea;
586
587     /**
588      * The layout for the controlArea.
589      */

590     private StackLayout controlAreaLayout;
591
592     /**
593      * The composite to use when no preview is available.
594      */

595     private Composite defaultPreviewControl;
596
597     private Text descriptionText;
598
599     private List JavaDoc dialogFontWidgets = new ArrayList JavaDoc();
600
601     private Button fontChangeButton;
602
603     /**
604      * The composite containing all font-specific controls.
605      */

606     private Composite fontControls;
607
608     private Map JavaDoc fontPreferencesToSet = new HashMap JavaDoc(7);
609
610     private CascadingFontRegistry fontRegistry;
611
612     private Button fontResetButton;
613
614     private Button fontSystemButton;
615
616     /**
617      * Map of defintion id->FontData[] objects that map to changes expressed in
618      * this UI session. These changes should be made in preferences and the
619      * registry.
620      */

621     private Map JavaDoc fontValuesToSet = new HashMap JavaDoc(7);
622
623     /**
624      * The list of fonts and colors.
625      */

626     //private TreeViewer presentationList;
627
/**
628      * The composite that is parent to all previews.
629      */

630     private Composite previewComposite;
631
632     /**
633      * A mapping from PresentationCategory->Composite for the created previews.
634      */

635     private Map JavaDoc previewMap = new HashMap JavaDoc(7);
636
637     /**
638      * Set containing all IPresentationPreviews created.
639      */

640     private Set JavaDoc previewSet = new HashSet JavaDoc(7);
641
642     /**
643      * The layout for the previewComposite.
644      */

645     private StackLayout stackLayout;
646
647     private final IThemeRegistry themeRegistry;
648
649     private ITheme currentTheme;
650
651     private PresentationLabelProvider labelProvider;
652
653     private CascadingTheme cascadingTheme;
654
655     private IPropertyChangeListener themeChangeListener;
656
657     private Workbench workbench;
658
659     private FilteredTree tree;
660
661     /**
662      * Create a new instance of the receiver.
663      */

664     public ColorsAndFontsPreferencePage() {
665         themeRegistry = WorkbenchPlugin.getDefault().getThemeRegistry();
666         //no-op
667
}
668
669     /**
670      * @param string
671      * @param string2
672      * @return
673      */

674     private static boolean equals(String JavaDoc string, String JavaDoc string2) {
675         if ((string == null && string2 == null)) {
676             return true;
677         }
678         if (string == null || string2 == null) {
679             return false;
680         }
681         if (string.equals(string2)) {
682             return true;
683         }
684
685         return false;
686     }
687
688     /**
689      * Create a button for the preference page.
690      * @param parent<