ClassSpecificationDialog.java revision b9cc48a43ed984587c939d02fba5316bf5c0df6e
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.gui;
22
23import proguard.*;
24import proguard.classfile.ClassConstants;
25import proguard.classfile.util.ClassUtil;
26
27import javax.swing.*;
28import javax.swing.border.*;
29import java.awt.*;
30import java.awt.event.*;
31import java.util.List;
32
33/**
34 * This <code>JDialog</code> allows the user to enter a String.
35 *
36 * @author Eric Lafortune
37 */
38final class ClassSpecificationDialog extends JDialog
39{
40    /**
41     * Return value if the dialog is canceled (with the Cancel button or by
42     * closing the dialog window).
43     */
44    public static final int CANCEL_OPTION = 1;
45
46    /**
47     * Return value if the dialog is approved (with the Ok button).
48     */
49    public static final int APPROVE_OPTION = 0;
50
51
52    private final JTextArea commentsTextArea = new JTextArea(4, 20);
53
54    private final JRadioButton keepClassesAndMembersRadioButton  = new JRadioButton(msg("keep"));
55    private final JRadioButton keepClassMembersRadioButton       = new JRadioButton(msg("keepClassMembers"));
56    private final JRadioButton keepClassesWithMembersRadioButton = new JRadioButton(msg("keepClassesWithMembers"));
57
58    private final JCheckBox allowShrinkingCheckBox    = new JCheckBox(msg("allowShrinking"));
59    private final JCheckBox allowOptimizationCheckBox = new JCheckBox(msg("allowOptimization"));
60    private final JCheckBox allowObfuscationCheckBox  = new JCheckBox(msg("allowObfuscation"));
61
62
63    private final JRadioButton[] publicRadioButtons;
64    private final JRadioButton[] finalRadioButtons;
65    private final JRadioButton[] abstractRadioButtons;
66    private final JRadioButton[] interfaceRadioButtons;
67    private final JRadioButton[] annotationRadioButtons;
68    private final JRadioButton[] enumRadioButtons;
69    private final JRadioButton[] syntheticRadioButtons;
70
71    private final JTextField annotationTypeTextField        = new JTextField(20);
72    private final JTextField classNameTextField             = new JTextField(20);
73    private final JTextField extendsAnnotationTypeTextField = new JTextField(20);
74    private final JTextField extendsClassNameTextField      = new JTextField(20);
75
76    private final MemberSpecificationsPanel memberSpecificationsPanel;
77
78    private int returnValue;
79
80
81    public ClassSpecificationDialog(JFrame owner, boolean fullKeepOptions)
82    {
83        super(owner, msg("specifyClasses"), true);
84        setResizable(true);
85
86        // Create some constraints that can be reused.
87        GridBagConstraints constraints = new GridBagConstraints();
88        constraints.anchor = GridBagConstraints.WEST;
89        constraints.insets = new Insets(1, 2, 1, 2);
90
91        GridBagConstraints constraintsStretch = new GridBagConstraints();
92        constraintsStretch.fill    = GridBagConstraints.HORIZONTAL;
93        constraintsStretch.weightx = 1.0;
94        constraintsStretch.anchor  = GridBagConstraints.WEST;
95        constraintsStretch.insets  = constraints.insets;
96
97        GridBagConstraints constraintsLast = new GridBagConstraints();
98        constraintsLast.gridwidth = GridBagConstraints.REMAINDER;
99        constraintsLast.anchor    = GridBagConstraints.WEST;
100        constraintsLast.insets    = constraints.insets;
101
102        GridBagConstraints constraintsLastStretch = new GridBagConstraints();
103        constraintsLastStretch.gridwidth = GridBagConstraints.REMAINDER;
104        constraintsLastStretch.fill      = GridBagConstraints.HORIZONTAL;
105        constraintsLastStretch.weightx   = 1.0;
106        constraintsLastStretch.anchor    = GridBagConstraints.WEST;
107        constraintsLastStretch.insets    = constraints.insets;
108
109        GridBagConstraints panelConstraints = new GridBagConstraints();
110        panelConstraints.gridwidth = GridBagConstraints.REMAINDER;
111        panelConstraints.fill      = GridBagConstraints.HORIZONTAL;
112        panelConstraints.weightx   = 1.0;
113        panelConstraints.weighty   = 0.0;
114        panelConstraints.anchor    = GridBagConstraints.NORTHWEST;
115        panelConstraints.insets    = constraints.insets;
116
117        GridBagConstraints stretchPanelConstraints = new GridBagConstraints();
118        stretchPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
119        stretchPanelConstraints.fill      = GridBagConstraints.BOTH;
120        stretchPanelConstraints.weightx   = 1.0;
121        stretchPanelConstraints.weighty   = 1.0;
122        stretchPanelConstraints.anchor    = GridBagConstraints.NORTHWEST;
123        stretchPanelConstraints.insets    = constraints.insets;
124
125        GridBagConstraints labelConstraints = new GridBagConstraints();
126        labelConstraints.anchor = GridBagConstraints.CENTER;
127        labelConstraints.insets = new Insets(2, 10, 2, 10);
128
129        GridBagConstraints lastLabelConstraints = new GridBagConstraints();
130        lastLabelConstraints.gridwidth = GridBagConstraints.REMAINDER;
131        lastLabelConstraints.anchor    = GridBagConstraints.CENTER;
132        lastLabelConstraints.insets    = labelConstraints.insets;
133
134        GridBagConstraints advancedButtonConstraints = new GridBagConstraints();
135        advancedButtonConstraints.weightx = 1.0;
136        advancedButtonConstraints.weighty = 1.0;
137        advancedButtonConstraints.anchor  = GridBagConstraints.SOUTHWEST;
138        advancedButtonConstraints.insets  = new Insets(4, 4, 8, 4);
139
140        GridBagConstraints okButtonConstraints = new GridBagConstraints();
141        okButtonConstraints.weightx = 1.0;
142        okButtonConstraints.weighty = 1.0;
143        okButtonConstraints.anchor  = GridBagConstraints.SOUTHEAST;
144        okButtonConstraints.insets  = advancedButtonConstraints.insets;
145
146        GridBagConstraints cancelButtonConstraints = new GridBagConstraints();
147        cancelButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
148        cancelButtonConstraints.weighty   = 1.0;
149        cancelButtonConstraints.anchor    = GridBagConstraints.SOUTHEAST;
150        cancelButtonConstraints.insets    = advancedButtonConstraints.insets;
151
152        GridBagLayout layout = new GridBagLayout();
153
154        Border etchedBorder = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
155
156        // Create the comments panel.
157        JPanel commentsPanel = new JPanel(layout);
158        commentsPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
159                                                                 msg("comments")));
160
161        JScrollPane commentsScrollPane = new JScrollPane(commentsTextArea);
162        commentsScrollPane.setBorder(classNameTextField.getBorder());
163
164        commentsPanel.add(tip(commentsScrollPane, "commentsTip"), constraintsLastStretch);
165
166        // Create the keep option panel.
167        ButtonGroup keepButtonGroup = new ButtonGroup();
168        keepButtonGroup.add(keepClassesAndMembersRadioButton);
169        keepButtonGroup.add(keepClassMembersRadioButton);
170        keepButtonGroup.add(keepClassesWithMembersRadioButton);
171
172        JPanel keepOptionPanel = new JPanel(layout);
173        keepOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
174                                                                   msg("keepTitle")));
175
176        keepOptionPanel.add(tip(keepClassesAndMembersRadioButton,  "keepTip"),                   constraintsLastStretch);
177        keepOptionPanel.add(tip(keepClassMembersRadioButton,       "keepClassMembersTip"),       constraintsLastStretch);
178        keepOptionPanel.add(tip(keepClassesWithMembersRadioButton, "keepClassesWithMembersTip"), constraintsLastStretch);
179
180        // Create the allow option panel.
181        final JPanel allowOptionPanel = new JPanel(layout);
182        allowOptionPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
183                                                                    msg("allowTitle")));
184
185        allowOptionPanel.add(tip(allowShrinkingCheckBox,    "allowShrinkingTip"),    constraintsLastStretch);
186        allowOptionPanel.add(tip(allowOptimizationCheckBox, "allowOptimizationTip"), constraintsLastStretch);
187        allowOptionPanel.add(tip(allowObfuscationCheckBox,  "allowObfuscationTip"),  constraintsLastStretch);
188
189        // Create the access panel.
190        JPanel accessPanel = new JPanel(layout);
191        accessPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
192                                                               msg("access")));
193
194        accessPanel.add(Box.createGlue(),                                labelConstraints);
195        accessPanel.add(tip(new JLabel(msg("required")), "requiredTip"), labelConstraints);
196        accessPanel.add(tip(new JLabel(msg("not")),      "notTip"),      labelConstraints);
197        accessPanel.add(tip(new JLabel(msg("dontCare")), "dontCareTip"), labelConstraints);
198        accessPanel.add(Box.createGlue(),                                constraintsLastStretch);
199
200        publicRadioButtons     = addRadioButtonTriplet("Public",     accessPanel);
201        finalRadioButtons      = addRadioButtonTriplet("Final",      accessPanel);
202        abstractRadioButtons   = addRadioButtonTriplet("Abstract",   accessPanel);
203        interfaceRadioButtons  = addRadioButtonTriplet("Interface",  accessPanel);
204        annotationRadioButtons = addRadioButtonTriplet("Annotation", accessPanel);
205        enumRadioButtons       = addRadioButtonTriplet("Enum",       accessPanel);
206        syntheticRadioButtons  = addRadioButtonTriplet("Synthetic",  accessPanel);
207
208        // Create the annotation type panel.
209        final JPanel annotationTypePanel = new JPanel(layout);
210        annotationTypePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
211                                                                       msg("annotation")));
212
213        annotationTypePanel.add(tip(annotationTypeTextField, "classNameTip"), constraintsLastStretch);
214
215        // Create the class name panel.
216        JPanel classNamePanel = new JPanel(layout);
217        classNamePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
218                                                                  msg("class")));
219
220        classNamePanel.add(tip(classNameTextField, "classNameTip"), constraintsLastStretch);
221
222        // Create the extends annotation type panel.
223        final JPanel extendsAnnotationTypePanel = new JPanel(layout);
224        extendsAnnotationTypePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
225                                                                              msg("extendsImplementsAnnotation")));
226
227        extendsAnnotationTypePanel.add(tip(extendsAnnotationTypeTextField, "classNameTip"), constraintsLastStretch);
228
229        // Create the extends class name panel.
230        JPanel extendsClassNamePanel = new JPanel(layout);
231        extendsClassNamePanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
232                                                                         msg("extendsImplementsClass")));
233
234        extendsClassNamePanel.add(tip(extendsClassNameTextField, "classNameTip"), constraintsLastStretch);
235
236
237        // Create the class member list panel.
238        memberSpecificationsPanel = new MemberSpecificationsPanel(this, fullKeepOptions);
239        memberSpecificationsPanel.setBorder(BorderFactory.createTitledBorder(etchedBorder,
240                                                                             msg("classMembers")));
241
242        // Create the Advanced button.
243        final JButton advancedButton = new JButton(msg("basic"));
244        advancedButton.addActionListener(new ActionListener()
245        {
246            public void actionPerformed(ActionEvent e)
247            {
248                boolean visible = !allowOptionPanel.isVisible();
249
250                allowOptionPanel          .setVisible(visible);
251                annotationTypePanel       .setVisible(visible);
252                extendsAnnotationTypePanel.setVisible(visible);
253
254                advancedButton.setText(msg(visible ? "basic" : "advanced"));
255
256                pack();
257            }
258        });
259        advancedButton.doClick();
260
261        // Create the Ok button.
262        JButton okButton = new JButton(msg("ok"));
263        okButton.addActionListener(new ActionListener()
264        {
265            public void actionPerformed(ActionEvent e)
266            {
267                returnValue = APPROVE_OPTION;
268                hide();
269            }
270        });
271
272        // Create the Cancel button.
273        JButton cancelButton = new JButton(msg("cancel"));
274        cancelButton.addActionListener(new ActionListener()
275        {
276            public void actionPerformed(ActionEvent e)
277            {
278                hide();
279            }
280        });
281
282        // Add all panels to the main panel.
283        JPanel mainPanel = new JPanel(layout);
284        mainPanel.add(tip(commentsPanel,              "commentsTip"),                    panelConstraints);
285        if (fullKeepOptions)
286        {
287            mainPanel.add(tip(keepOptionPanel,        "keepTitleTip"),                   panelConstraints);
288            mainPanel.add(tip(allowOptionPanel,       "allowTitleTip"),                  panelConstraints);
289        }
290        mainPanel.add(tip(accessPanel,                "accessTip"),                      panelConstraints);
291        mainPanel.add(tip(annotationTypePanel,        "annotationTip"),                  panelConstraints);
292        mainPanel.add(tip(classNamePanel,             "classTip"),                       panelConstraints);
293        mainPanel.add(tip(extendsAnnotationTypePanel, "extendsImplementsAnnotationTip"), panelConstraints);
294        mainPanel.add(tip(extendsClassNamePanel,      "extendsImplementsClassTip"),      panelConstraints);
295        mainPanel.add(tip(memberSpecificationsPanel,  "classMembersTip"),                stretchPanelConstraints);
296
297        mainPanel.add(tip(advancedButton, "advancedTip"), advancedButtonConstraints);
298        mainPanel.add(okButton,                           okButtonConstraints);
299        mainPanel.add(cancelButton,                       cancelButtonConstraints);
300
301        getContentPane().add(new JScrollPane(mainPanel));
302    }
303
304
305    /**
306     * Adds a JLabel and three JRadioButton instances in a ButtonGroup to the
307     * given panel with a GridBagLayout, and returns the buttons in an array.
308     */
309    private JRadioButton[] addRadioButtonTriplet(String labelText,
310                                                 JPanel panel)
311    {
312        GridBagConstraints labelConstraints = new GridBagConstraints();
313        labelConstraints.anchor = GridBagConstraints.WEST;
314        labelConstraints.insets = new Insets(2, 10, 2, 10);
315
316        GridBagConstraints buttonConstraints = new GridBagConstraints();
317        buttonConstraints.insets = labelConstraints.insets;
318
319        GridBagConstraints lastGlueConstraints = new GridBagConstraints();
320        lastGlueConstraints.gridwidth = GridBagConstraints.REMAINDER;
321        lastGlueConstraints.weightx   = 1.0;
322
323        // Create the radio buttons.
324        JRadioButton radioButton0 = new JRadioButton();
325        JRadioButton radioButton1 = new JRadioButton();
326        JRadioButton radioButton2 = new JRadioButton();
327
328        // Put them in a button group.
329        ButtonGroup buttonGroup = new ButtonGroup();
330        buttonGroup.add(radioButton0);
331        buttonGroup.add(radioButton1);
332        buttonGroup.add(radioButton2);
333
334        // Add the label and the buttons to the panel.
335        panel.add(new JLabel(labelText), labelConstraints);
336        panel.add(radioButton0,          buttonConstraints);
337        panel.add(radioButton1,          buttonConstraints);
338        panel.add(radioButton2,          buttonConstraints);
339        panel.add(Box.createGlue(),      lastGlueConstraints);
340
341        return new JRadioButton[]
342        {
343             radioButton0,
344             radioButton1,
345             radioButton2
346        };
347    }
348
349
350    /**
351     * Sets the KeepClassSpecification to be represented in this dialog.
352     */
353    public void setKeepSpecification(KeepClassSpecification keepClassSpecification)
354    {
355        boolean markClasses       = keepClassSpecification.markClasses;
356        boolean markConditionally = keepClassSpecification.markConditionally;
357        boolean allowShrinking    = keepClassSpecification.allowShrinking;
358        boolean allowOptimization = keepClassSpecification.allowOptimization;
359        boolean allowObfuscation  = keepClassSpecification.allowObfuscation;
360
361        // Figure out the proper keep radio button and set it.
362        JRadioButton keepOptionRadioButton =
363            markConditionally ? keepClassesWithMembersRadioButton :
364            markClasses       ? keepClassesAndMembersRadioButton  :
365                                keepClassMembersRadioButton;
366
367        keepOptionRadioButton.setSelected(true);
368
369        // Set the allow radio buttons.
370        allowShrinkingCheckBox   .setSelected(allowShrinking);
371        allowOptimizationCheckBox.setSelected(allowOptimization);
372        allowObfuscationCheckBox .setSelected(allowObfuscation);
373
374        setClassSpecification(keepClassSpecification);
375    }
376
377
378    /**
379     * Sets the ClassSpecification to be represented in this dialog.
380     */
381    public void setClassSpecification(ClassSpecification classSpecification)
382    {
383        String comments              = classSpecification.comments;
384        String annotationType        = classSpecification.annotationType;
385        String className             = classSpecification.className;
386        String extendsAnnotationType = classSpecification.extendsAnnotationType;
387        String extendsClassName      = classSpecification.extendsClassName;
388        List   keepFieldOptions      = classSpecification.fieldSpecifications;
389        List   keepMethodOptions     = classSpecification.methodSpecifications;
390
391        // Set the comments text area.
392        commentsTextArea.setText(comments == null ? "" : comments);
393
394        // Set the access radio buttons.
395        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,      publicRadioButtons);
396        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,       finalRadioButtons);
397        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,    abstractRadioButtons);
398        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE,   interfaceRadioButtons);
399        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
400        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM,        enumRadioButtons);
401        setClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC,   syntheticRadioButtons);
402
403        // Set the class and annotation text fields.
404        annotationTypeTextField       .setText(annotationType        == null ? ""  : ClassUtil.externalType(annotationType));
405        classNameTextField            .setText(className             == null ? "*" : ClassUtil.externalClassName(className));
406        extendsAnnotationTypeTextField.setText(extendsAnnotationType == null ? ""  : ClassUtil.externalType(extendsAnnotationType));
407        extendsClassNameTextField     .setText(extendsClassName      == null ? ""  : ClassUtil.externalClassName(extendsClassName));
408
409        // Set the keep class member option list.
410        memberSpecificationsPanel.setMemberSpecifications(keepFieldOptions, keepMethodOptions);
411    }
412
413
414    /**
415     * Returns the KeepClassSpecification currently represented in this dialog.
416     */
417    public KeepClassSpecification getKeepSpecification()
418    {
419        boolean markClasses       = !keepClassMembersRadioButton     .isSelected();
420        boolean markConditionally = keepClassesWithMembersRadioButton.isSelected();
421        boolean allowShrinking    = allowShrinkingCheckBox           .isSelected();
422        boolean allowOptimization = allowOptimizationCheckBox        .isSelected();
423        boolean allowObfuscation  = allowObfuscationCheckBox         .isSelected();
424
425        return new KeepClassSpecification(markClasses,
426                                     markConditionally,
427                                     allowShrinking,
428                                     allowOptimization,
429                                     allowObfuscation,
430                                     getClassSpecification());
431    }
432
433
434    /**
435     * Returns the ClassSpecification currently represented in this dialog.
436     */
437    public ClassSpecification getClassSpecification()
438    {
439        String comments              = commentsTextArea.getText();
440        String annotationType        = annotationTypeTextField.getText();
441        String className             = classNameTextField.getText();
442        String extendsAnnotationType = extendsAnnotationTypeTextField.getText();
443        String extendsClassName      = extendsClassNameTextField.getText();
444
445        ClassSpecification classSpecification =
446            new ClassSpecification(comments.equals("")              ? null : comments,
447                                   0,
448                                   0,
449                                   annotationType.equals("")        ? null : ClassUtil.internalType(annotationType),
450                                   className.equals("") ||
451                                   className.equals("*")            ? null : ClassUtil.internalClassName(className),
452                                   extendsAnnotationType.equals("") ? null : ClassUtil.internalType(extendsAnnotationType),
453                                   extendsClassName.equals("")      ? null : ClassUtil.internalClassName(extendsClassName));
454
455        // Also get the access radio button settings.
456        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_PUBLIC,      publicRadioButtons);
457        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_FINAL,       finalRadioButtons);
458        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ABSTRACT,    abstractRadioButtons);
459        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_INTERFACE,   interfaceRadioButtons);
460        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ANNOTATTION, annotationRadioButtons);
461        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_ENUM,        enumRadioButtons);
462        getClassSpecificationRadioButtons(classSpecification, ClassConstants.INTERNAL_ACC_SYNTHETIC,   syntheticRadioButtons);
463
464        // Get the keep class member option lists.
465        classSpecification.fieldSpecifications  = memberSpecificationsPanel.getMemberSpecifications(true);
466        classSpecification.methodSpecifications = memberSpecificationsPanel.getMemberSpecifications(false);
467
468        return classSpecification;
469    }
470
471
472    /**
473     * Shows this dialog. This method only returns when the dialog is closed.
474     *
475     * @return <code>CANCEL_OPTION</code> or <code>APPROVE_OPTION</code>,
476     *         depending on the choice of the user.
477     */
478    public int showDialog()
479    {
480        returnValue = CANCEL_OPTION;
481
482        // Open the dialog in the right place, then wait for it to be closed,
483        // one way or another.
484        pack();
485        setLocationRelativeTo(getOwner());
486        show();
487
488        return returnValue;
489    }
490
491
492    /**
493     * Sets the appropriate radio button of a given triplet, based on the access
494     * flags of the given keep option.
495     */
496    private void setClassSpecificationRadioButtons(ClassSpecification classSpecification,
497                                                   int                flag,
498                                                   JRadioButton[]     radioButtons)
499    {
500        int index = (classSpecification.requiredSetAccessFlags   & flag) != 0 ? 0 :
501                    (classSpecification.requiredUnsetAccessFlags & flag) != 0 ? 1 :
502                                                                                 2;
503        radioButtons[index].setSelected(true);
504    }
505
506
507    /**
508     * Updates the access flag of the given keep option, based on the given radio
509     * button triplet.
510     */
511    private void getClassSpecificationRadioButtons(ClassSpecification classSpecification,
512                                                   int                flag,
513                                                   JRadioButton[]     radioButtons)
514    {
515        if      (radioButtons[0].isSelected())
516        {
517            classSpecification.requiredSetAccessFlags   |= flag;
518        }
519        else if (radioButtons[1].isSelected())
520        {
521            classSpecification.requiredUnsetAccessFlags |= flag;
522        }
523    }
524
525
526    /**
527     * Attaches the tool tip from the GUI resources that corresponds to the
528     * given key, to the given component.
529     */
530    private static JComponent tip(JComponent component, String messageKey)
531    {
532        component.setToolTipText(msg(messageKey));
533
534        return component;
535    }
536
537
538    /**
539     * Returns the message from the GUI resources that corresponds to the given
540     * key.
541     */
542    private static String msg(String messageKey)
543    {
544         return GUIResources.getMessage(messageKey);
545    }
546}
547