org.tigris.subversion.subclipse.ui.comments.CommitCommentArea.java Source code

Java tutorial

Introduction

Here is the source code for org.tigris.subversion.subclipse.ui.comments.CommitCommentArea.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 2006 Subclipse project and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Subclipse project committers - initial API and implementation
 ******************************************************************************/
package org.tigris.subversion.subclipse.ui.comments;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.DeviceResourceException;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.text.DefaultTextHover;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.MarginPainter;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.MonoReconciler;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModel;
import org.eclipse.jface.text.source.AnnotationPainter;
import org.eclipse.jface.text.source.AnnotationRulerColumn;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.internal.ui.SWTUtils;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.tigris.subversion.subclipse.core.SVNException;
import org.tigris.subversion.subclipse.core.util.Util;
import org.tigris.subversion.subclipse.ui.ISVNUIConstants;
import org.tigris.subversion.subclipse.ui.Policy;
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
import org.tigris.subversion.subclipse.ui.dialogs.DialogArea;
import org.tigris.subversion.subclipse.ui.settings.CommentProperties;

/**
 * This area provides the widgets for providing the SVN commit comment
 */
public class CommitCommentArea extends DialogArea {
    private boolean showLabel = true;;

    public static final String SPELLING_ERROR = "spelling.error"; //$NON-NLS-1$

    private class TextBox implements ModifyListener, TraverseListener, FocusListener, Observer {

        private final StyledText fTextField; // updated only by modify events
        private final String fMessage;

        private String fText;
        private LocalResourceManager fResources;

        public TextBox(Composite composite, String message, String initialText) {

            fMessage = message;
            fText = initialText;
            // Create a resource manager for the composite so it gets automatically disposed
            fResources = new LocalResourceManager(JFaceResources.getResources(), composite);

            AnnotationModel annotationModel = new AnnotationModel();
            IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess();

            AnnotationRulerColumn annotationRuler = new AnnotationRulerColumn(annotationModel, 16,
                    annotationAccess);

            CompositeRuler compositeRuler = new CompositeRuler();
            compositeRuler.setModel(annotationModel);
            compositeRuler.addDecorator(0, annotationRuler);

            Composite cc = new Composite(composite, SWT.BORDER);
            cc.setLayout(new FillLayout());
            cc.setLayoutData(new GridData(GridData.FILL_BOTH));

            SourceViewer sourceViewer = new SourceViewer(cc, compositeRuler, null, true,
                    SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);

            if (modifyListener != null) {
                sourceViewer.getTextWidget().addModifyListener(modifyListener);
            }

            // TODO should be done in the source viewer configuration
            Font commentFont = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry()
                    .get(ISVNUIConstants.SVN_COMMENT_FONT);
            if (commentFont != null)
                sourceViewer.getTextWidget().setFont(commentFont);

            int widthMarker = 0;
            if (commentProperties != null)
                widthMarker = commentProperties.getLogWidthMarker();

            if (widthMarker > 0) {
                MarginPainter marginPainter = new MarginPainter(sourceViewer);
                marginPainter.setMarginRulerColumn(widthMarker);
                marginPainter.setMarginRulerColor(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
                sourceViewer.addPainter(marginPainter);
            }

            sourceViewer.showAnnotations(false);
            sourceViewer.showAnnotationsOverview(false);

            if (isSpellingAnnotationEnabled()) {
                // to paint the annotations
                AnnotationPainter ap = new AnnotationPainter(sourceViewer, annotationAccess);
                ap.addAnnotationType(SPELLING_ERROR);
                ap.setAnnotationTypeColor(SPELLING_ERROR, getSpellingErrorColor(composite));

                // this will draw the squiggles under the text
                sourceViewer.addPainter(ap);
            }

            Document document = new Document(initialText);

            // NOTE: Configuration must be applied before the document is set in order for
            // Hyperlink coloring to work. (Presenter needs document object up front)
            sourceViewer.configure(new SourceViewerConfig(annotationModel, document));

            sourceViewer.setDocument(document, annotationModel);

            fTextField = sourceViewer.getTextWidget();

            fTextField.addTraverseListener(this);
            fTextField.addModifyListener(this);
            fTextField.addFocusListener(this);
            fTextField.setWordWrap(mustWrapWord());

            MenuManager menuManager = new MenuManager();
            IMenuListener listener = new IMenuListener() {
                public void menuAboutToShow(IMenuManager manager) {
                    if (fTextField.getSelectionText() != null && fTextField.getSelectionText().length() > 0) {
                        Action cutAction = new Action("Cut") {
                            public void run() {
                                fTextField.cut();
                            }
                        };
                        manager.add(cutAction);
                        Action copyAction = new Action("Copy") {
                            public void run() {
                                fTextField.copy();
                            }
                        };
                        manager.add(copyAction);
                    }
                    Clipboard clipboard = new Clipboard(Display.getCurrent());
                    TextTransfer textTransfer = TextTransfer.getInstance();
                    final Object contents = clipboard.getContents(textTransfer);
                    if (contents instanceof String && ((String) contents).length() > 0) {
                        Action pasteAction = new Action("Paste") {
                            public void run() {
                                fTextField.insert((String) contents);
                            }
                        };
                        manager.add(pasteAction);
                    }
                    Action selectAllAction = new Action("Select All") {
                        public void run() {
                            fTextField.selectAll();
                        }
                    };
                    manager.add(selectAllAction);
                }
            };
            menuManager.addMenuListener(listener);
            menuManager.setRemoveAllWhenShown(true);
            Menu menu = menuManager.createContextMenu(fTextField);
            fTextField.setMenu(menu);
        }

        private boolean mustWrapWord() {
            if (commentProperties != null && commentProperties.getLogWidthMarker() > 0) {
                return false;
            }
            return true;
        }

        private boolean isSpellingAnnotationEnabled() {
            // Need to determine how to ask the proper question to the AnnotationPreferences
            return true;
        }

        private Color getSpellingErrorColor(Composite composite) {
            AnnotationPreference pref = EditorsUI.getAnnotationPreferenceLookup()
                    .getAnnotationPreference("org.eclipse.ui.workbench.texteditor.spelling"); // $NON-NLS-1$
            String preferenceKey = pref.getColorPreferenceKey();
            try {
                return fResources
                        .createColor(PreferenceConverter.getColor(EditorsUI.getPreferenceStore(), preferenceKey));
            } catch (DeviceResourceException e) {
                SVNUIPlugin.log(IStatus.ERROR, Policy.bind("internal"), e); //$NON-NLS-1$
                return JFaceColors.getErrorText(composite.getDisplay());
            }
        }

        public void modifyText(ModifyEvent e) {
            final String old = fText;
            fText = fTextField.getText();
            firePropertyChangeChange(COMMENT_MODIFIED, old, fText);
        }

        public void keyTraversed(TraverseEvent e) {
            if (e.detail == SWT.TRAVERSE_RETURN && (e.stateMask & SWT.SHIFT) != 0) {
                e.doit = false;
                return;
            }
            if (e.detail == SWT.TRAVERSE_RETURN && (e.stateMask & SWT.CTRL) != 0) {
                e.doit = false;
                firePropertyChangeChange(OK_REQUESTED, null, null);
            }
        }

        public void focusGained(FocusEvent e) {

            if (fText.length() > 0)
                return;

            fTextField.removeModifyListener(this);
            try {
                fTextField.setText(fText);
            } finally {
                fTextField.addModifyListener(this);
            }
        }

        public void focusLost(FocusEvent e) {

            if (fText.length() > 0)
                return;

            fTextField.removeModifyListener(this);
            try {
                fTextField.setText(fMessage);
                fTextField.selectAll();
            } finally {
                fTextField.addModifyListener(this);
            }
        }

        public void setEnabled(boolean enabled) {
            fTextField.setEnabled(enabled);
        }

        public void update(Observable o, Object arg) {
            if (arg instanceof String) {
                setText((String) arg); // triggers a modify event
                if (modifyListener != null)
                    modifyListener.modifyText(null);
            }
        }

        public String getText() {
            return fText;
        }

        public int getCommentLength() {
            if (fTextField == null)
                return 0;
            if (fTextField.getText().equals(Policy.bind("CommitCommentArea_0"))) //$NON-NLS-1$
                return 0;
            return fTextField.getText().trim().length();
        }

        private void setText(String text) {
            if (text.length() == 0) {
                fTextField.setText(fMessage);
                fTextField.selectAll();
            } else
                fTextField.setText(text);
        }

        public void setFocus() {
            fTextField.setFocus();
        }
    }

    public class SourceViewerConfig extends SourceViewerConfiguration {

        private CommentSpellingReconcileStrategy strategy;

        public SourceViewerConfig(AnnotationModel annotationModel, Document document) {
            strategy = new CommentSpellingReconcileStrategy(annotationModel);
            strategy.setDocument(document);
        }

        public IReconciler getReconciler(ISourceViewer sourceViewer) {
            MonoReconciler reconciler = new MonoReconciler(strategy, false);
            reconciler.setIsIncrementalReconciler(false);
            reconciler.setProgressMonitor(new NullProgressMonitor());
            reconciler.setDelay(200);
            return reconciler;
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getTextHover(org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
         */
        public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
            return new DefaultTextHover(sourceViewer);
        }

    }

    public class CommentSpellingReconcileStrategy implements IReconcilingStrategy {

        /** The document to operate on. */
        private IDocument fDocument;

        private SpellingContext fSpellingContext;

        private IAnnotationModel fAnnotationModel;

        public CommentSpellingReconcileStrategy(AnnotationModel annotationModel) {
            this.fAnnotationModel = annotationModel;
            fSpellingContext = new SpellingContext();
            fSpellingContext
                    .setContentType(Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT));
        }

        public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
            reconcile(subRegion);
        }

        public void reconcile(IRegion region) {
            SpellingProblemCollector collector = new SpellingProblemCollector(fAnnotationModel);
            EditorsUI.getSpellingService().check(fDocument, fSpellingContext, collector, null);
        }

        public void setDocument(IDocument document) {
            fDocument = document;
        }

        /**
         * Spelling problem collector that forwards {@link SpellingProblem}s as
         * {@link IProblem}s to the {@link org.eclipse.jdt.core.IProblemRequestor}.
         */
        private class SpellingProblemCollector implements ISpellingProblemCollector {

            /** Annotation model */
            private IAnnotationModel fAnnotationModel;

            /** Annotations to add <ErrorAnnotation, Position> */
            private Map fAddAnnotations;

            /**
             * Initializes this collector with the given annotation model.
             * 
             * @param annotationModel
             *          the annotation model
             */
            public SpellingProblemCollector(IAnnotationModel annotationModel) {
                fAnnotationModel = annotationModel;
            }

            /*
             * @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept(org.eclipse.ui.texteditor.spelling.SpellingProblem)
             */
            public void accept(SpellingProblem problem) {
                fAddAnnotations.put(new Annotation(SPELLING_ERROR, false, problem.getMessage()),
                        new Position(problem.getOffset(), problem.getLength()));
            }

            /*
             * @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#beginCollecting()
             */
            public void beginCollecting() {
                fAddAnnotations = new HashMap();
            }

            /*
             * @see org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#endCollecting()
             */
            public void endCollecting() {
                List removeAnnotations = new ArrayList();
                for (Iterator iter = fAnnotationModel.getAnnotationIterator(); iter.hasNext();) {
                    Annotation annotation = (Annotation) iter.next();
                    if (SPELLING_ERROR.equals(annotation.getType()))
                        removeAnnotations.add(annotation);
                }

                for (Iterator iter = removeAnnotations.iterator(); iter.hasNext();)
                    fAnnotationModel.removeAnnotation((Annotation) iter.next());
                for (Iterator iter = fAddAnnotations.keySet().iterator(); iter.hasNext();) {
                    Annotation annotation = (Annotation) iter.next();
                    fAnnotationModel.addAnnotation(annotation, (Position) fAddAnnotations.get(annotation));
                }

                fAddAnnotations = null;
            }
        }

    }

    private static class ComboBox extends Observable implements SelectionListener, FocusListener {

        private final String fMessage;
        private final String[] fComments;
        private String[] fCommentTemplates;
        private final Combo fCombo;

        public ComboBox(Composite composite, String message, String[] options, String[] commentTemplates) {

            fMessage = message;
            fComments = options;
            fCommentTemplates = commentTemplates;

            fCombo = new Combo(composite, SWT.READ_ONLY);
            fCombo.setLayoutData(SWTUtils.createHFillGridData());
            fCombo.setVisibleItemCount(20);

            // populate the previous comment list
            populateList();

            // We don't want to have an initial selection
            // (see bug 32078: http://bugs.eclipse.org/bugs/show_bug.cgi?id=32078)
            fCombo.addFocusListener(this);
            fCombo.addSelectionListener(this);
        }

        private void populateList() {
            fCombo.removeAll();

            fCombo.add(fMessage);
            for (int i = 0; i < fCommentTemplates.length; i++) {
                fCombo.add(Policy.bind("CommitCommentArea_6") + ": " + //$NON-NLS-1$
                        Util.flattenText(fCommentTemplates[i]));
            }
            for (int i = 0; i < fComments.length; i++) {
                fCombo.add(Util.flattenText(fComments[i]));
            }
            fCombo.setText(fMessage);
        }

        public void widgetSelected(SelectionEvent e) {
            int index = fCombo.getSelectionIndex();
            if (index > 0) {
                index--;
                setChanged();

                // map from combo box index to array index
                String message;
                if (index < fCommentTemplates.length) {
                    message = fCommentTemplates[index];
                } else {
                    message = fComments[index - fCommentTemplates.length];
                }
                notifyObservers(message);
            }
        }

        public void widgetDefaultSelected(SelectionEvent e) {
        }

        public void focusGained(FocusEvent e) {
        }

        /* (non-Javadoc)
         * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
         */
        public void focusLost(FocusEvent e) {
            fCombo.removeSelectionListener(this);
            try {
                fCombo.setText(fMessage);
            } finally {
                fCombo.addSelectionListener(this);
            }
        }

        public void setEnabled(boolean enabled) {
            fCombo.setEnabled(enabled);
        }

        void setCommentTemplates(String[] templates) {
            fCommentTemplates = templates;
            populateList();
        }
    }

    private static final String EMPTY_MESSAGE = Policy.bind("CommitCommentArea_0");
    private static final String COMBO_MESSAGE = Policy.bind("CommitCommentArea_1");

    public static final String OK_REQUESTED = "OkRequested";//$NON-NLS-1$
    public static final String COMMENT_MODIFIED = "CommentModified";//$NON-NLS-1$

    private TextBox fTextBox;
    private ComboBox fComboBox;

    private String fProposedComment;
    private Composite fComposite;
    private String enterCommentMessage;

    private CommentProperties commentProperties;
    private ModifyListener modifyListener;

    /**
    * Constructor for CommitCommentArea.
    * @param parentDialog
    * @param settings
    */
    public CommitCommentArea(Dialog parentDialog, IDialogSettings settings) {
        super(parentDialog, settings);
    }

    public CommitCommentArea(Dialog parentDialog, IDialogSettings settings, CommentProperties commentProperties) {
        this(parentDialog, settings);
        this.commentProperties = commentProperties;
    }

    /**
     * Constructor for CommitCommentArea.
     * @param parentDialog
     * @param settings
     * @param enterCommentMessage
     */
    public CommitCommentArea(Dialog parentDialog, IDialogSettings settings, String enterCommentMessage) {
        this(parentDialog, settings);
        this.enterCommentMessage = enterCommentMessage;
    }

    public CommitCommentArea(Dialog parentDialog, IDialogSettings settings, String enterCommentMessage,
            CommentProperties commentProperties) {
        this(parentDialog, settings, enterCommentMessage);
        this.commentProperties = commentProperties;
    }

    public Control createArea(Composite parent) {
        fComposite = createGrabbingComposite(parent, 1);
        initializeDialogUnits(fComposite);

        if (showLabel) {
            Label label = new Label(fComposite, SWT.NULL);
            label.setLayoutData(new GridData());
            if (enterCommentMessage == null)
                label.setText(Policy.bind("ReleaseCommentDialog.enterComment")); //$NON-NLS-1$
            else
                label.setText(enterCommentMessage);
        }

        fTextBox = new TextBox(fComposite, EMPTY_MESSAGE, getInitialComment());

        final String[] comments = SVNUIPlugin.getPlugin().getRepositoryManager().getCommentsManager()
                .getPreviousComments();
        final String[] commentTemplates = SVNUIPlugin.getPlugin().getRepositoryManager().getCommentsManager()
                .getCommentTemplates();
        fComboBox = new ComboBox(fComposite, COMBO_MESSAGE, comments, commentTemplates);

        Link templatesPrefsLink = new Link(fComposite, 0);
        templatesPrefsLink.setText("<a href=\"configureTemplates\">Configure Comment Templates...</a>"); //$NON-NLS-1$
        templatesPrefsLink.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {
                openCommentTemplatesPreferencePage();
            }

            public void widgetSelected(SelectionEvent e) {
                openCommentTemplatesPreferencePage();
            }
        });

        fComboBox.addObserver(fTextBox);
        return fComposite;
    }

    void openCommentTemplatesPreferencePage() {
        PreferencesUtil
                .createPreferenceDialogOn(null, "org.tigris.subversion.subclipse.ui.CommentTemplatesPreferences", //$NON-NLS-1$
                        new String[] { "org.tigris.subversion.subclipse.ui.CommentTemplatesPreferences" }, //$NON-NLS-1$
                        null)
                .open();
        fComboBox.setCommentTemplates(
                SVNUIPlugin.getPlugin().getRepositoryManager().getCommentsManager().getCommentTemplates());
    }

    public String getComment() {
        return getComment(false);
    }

    public String getComment(boolean save) {
        final String comment = fTextBox.getText();
        if (comment == null)
            return ""; //$NON-NLS-1$
        if (save)
            addComment(comment);
        return comment;
    }

    public void addComment(String comment) {
        if (comment != null && comment.trim().length() > 0)
            SVNUIPlugin.getPlugin().getRepositoryManager().getCommentsManager().addComment(comment);
    }

    public String getCommentWithPrompt(Shell shell) {
        final String comment = getComment(false);
        if (comment.length() == 0) {
            final IPreferenceStore store = SVNUIPlugin.getPlugin().getPreferenceStore();
            final String value = store.getString(ISVNUIConstants.PREF_ALLOW_EMPTY_COMMIT_COMMENTS);

            if (MessageDialogWithToggle.NEVER.equals(value))
                return null;

            if (MessageDialogWithToggle.PROMPT.equals(value)) {

                final String title = Policy.bind("CommitCommentArea_2");
                final String message = Policy.bind("CommitCommentArea_3");
                final String toggleMessage = Policy.bind("CommitCommentArea_4");

                final MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoQuestion(shell, title,
                        message, toggleMessage, false, store, ISVNUIConstants.PREF_ALLOW_EMPTY_COMMIT_COMMENTS);
                if (dialog.getReturnCode() != IDialogConstants.YES_ID) {
                    fTextBox.setFocus();
                    return null;
                }
            }
        }
        return getComment(true);
    }

    public void setFocus() {
        if (fTextBox != null) {
            fTextBox.setFocus();
        }
    }

    public void setProposedComment(String proposedComment) {
        if (proposedComment == null || proposedComment.length() == 0) {
            this.fProposedComment = null;
        } else {
            this.fProposedComment = proposedComment;
        }
    }

    public boolean hasCommitTemplate() {
        try {
            String commitTemplate = getCommitTemplate();
            return commitTemplate != null && commitTemplate.length() > 0;
        } catch (SVNException e) {
            SVNUIPlugin.log(e);
            return false;
        }
    }

    public void setEnabled(boolean enabled) {
        fTextBox.setEnabled(enabled);
        fComboBox.setEnabled(enabled);
    }

    public Composite getComposite() {
        return fComposite;
    }

    public int getCommentLength() {
        if (fTextBox == null)
            return 0;
        return fTextBox.getCommentLength();
    }

    protected void firePropertyChangeChange(String property, Object oldValue, Object newValue) {
        super.firePropertyChangeChange(property, oldValue, newValue);
    }

    private String getInitialComment() {
        if (fProposedComment != null)
            return fProposedComment;
        try {
            return getCommitTemplate();
        } catch (SVNException e) {
            SVNUIPlugin.log(e);
            return ""; //$NON-NLS-1$
        }
    }

    private String getCommitTemplate() throws SVNException {
        if ((commentProperties != null) && (commentProperties.getLogTemplate() != null)) {
            return commentProperties.getLogTemplate();
        }

        return ""; //$NON-NLS-1$
    }

    public void setModifyListener(ModifyListener modifyListener) {
        this.modifyListener = modifyListener;
    }

    public void setShowLabel(boolean showLabel) {
        this.showLabel = showLabel;
    }

}