diff options
| author | Robin Stocker | 2010-11-02 14:43:00 +0000 |
|---|---|---|
| committer | Matthias Sohn | 2010-11-09 23:33:21 +0000 |
| commit | 6bbea8ebb8dfff86cdf8f8f6c6aa4582719eec0b (patch) | |
| tree | 1b2fecbcedb9918b672cdb94301f7af3b6e394d7 | |
| parent | 3fe3bc1baa91c811c7269257dce7baa27ba2fc83 (diff) | |
| download | egit-6bbea8ebb8dfff86cdf8f8f6c6aa4582719eec0b.tar.gz egit-6bbea8ebb8dfff86cdf8f8f6c6aa4582719eec0b.tar.xz egit-6bbea8ebb8dfff86cdf8f8f6c6aa4582719eec0b.zip | |
Optionally hard-wrap commit message
When "hard-wrap" is enabled in the new Commit Dialog preference page,
the commit message editor automatically inserts newlines as the user is
typing the commit message.
The text width is 70. If a line the user is typing would be longer than
that, a newline is automatically inserted before the last word.
Existing newlines are not touched, to allow for manual formatting (e.g.
ASCII graphics).
The editor shows the commit message in a configurable font that defaults
to the text font. This font is usually fixed-width, so that the margin
line can be shown after exactly 70 characters.
CQ: 4628
Bug: 329489
Change-Id: Ic8ae2f99b595f5f994af3cdb08b9363d2d53e685
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
11 files changed, 440 insertions, 7 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/dialogs/commit/CommitMessageAreaTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/dialogs/commit/CommitMessageAreaTest.java new file mode 100644 index 0000000000..819b98ddf3 --- /dev/null +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/dialogs/commit/CommitMessageAreaTest.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (C) 2010, Robin Stocker + * + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.dialogs.commit; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.eclipse.egit.ui.internal.dialogs.CommitMessageArea; +import org.eclipse.egit.ui.internal.dialogs.CommitMessageArea.WrapEdit; +import org.junit.Test; + +public class CommitMessageAreaTest { + + @Test + public void dontWrapShortText() { + String input = "short message"; + assertWrappedEquals(input, input); + } + + @Test + public void dontWrapAlreadyWrappedText() { + String input = "This is a test of wrapping\n\nDid it work?\n\nHm?"; + assertWrappedEquals(input, input); + } + + @Test + public void dontWrapMaximumLengthText() { + String input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789."; + assertWrappedEquals(input, input); + } + + @Test + public void wrapOverlengthText() { + String input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789. 123"; + String expected = "123456789 123456789 123456789 123456789 123456789 123456789 123456789.\n123"; + assertWrappedEquals(expected, input); + } + + @Test + public void wrapOverlengthTextByOne() { + String input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789ab"; + String expected = "123456789 123456789 123456789 123456789 123456789 123456789\n123456789ab"; + assertWrappedEquals(expected, input); + } + + @Test + public void wrapOverlengthText2() { + String input = "123456789 123456789 123456789 123456789 123456789 123456789. 12345678901234"; + String expected = "123456789 123456789 123456789 123456789 123456789 123456789.\n12345678901234"; + assertWrappedEquals(expected, input); + } + + public void wrapOverlengthTextTwice() { + String input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789. " + + "123456789 123456789 123456789 123456789 123456789 123456789 123456789. " + + "123456789 123456789 123456789 123456789 123456789 123456789 123456789."; + String expected = "123456789 123456789 123456789 123456789 123456789 123456789 123456789.\n" + + "123456789 123456789 123456789 123456789 123456789 123456789 123456789.\n" + + "123456789 123456789 123456789 123456789 123456789 123456789 123456789."; + assertWrappedEquals(expected, input); + } + + @Test + public void dontWrapWordLongerThanOneLineAtStart() { + String input = "12345678901234567890123456789012345678901234567890123456789012345678901234567890 the previous was longer than a line"; + String expected = "12345678901234567890123456789012345678901234567890123456789012345678901234567890\nthe previous was longer than a line"; + assertWrappedEquals(expected, input); + } + + @Test + public void dontWrapWordLongerThanOneLine() { + String input = "This has to be on its own line: 12345678901234567890123456789012345678901234567890123456789012345678901234567890 this not"; + String expected = "This has to be on its own line:\n12345678901234567890123456789012345678901234567890123456789012345678901234567890\nthis not"; + assertWrappedEquals(expected, input); + } + + @Test + public void wrapSecondLongLine() { + String input = "First line\n123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789."; + String expected = "First line\n123456789 123456789 123456789 123456789 123456789 123456789 123456789\n123456789."; + assertWrappedEquals(expected, input); + } + + @Test + public void keepExistingNewlines() { + String input = "This\n\nis\nall\nok\n123456789 123456789 123456789 123456789 123456789 123456789 123456789."; + assertWrappedEquals(input, input); + } + + @Test + public void keepNewlineAtEnd() { + String input = "Newline\nat\nend\n"; + assertWrappedEquals(input, input); + } + + @Test + public void keepWhitespace() { + String input = " this is deliberate whitespace"; + assertWrappedEquals(input, input); + } + + @Test + public void keepTrailingSpace() { + String input = "space at end "; + assertWrappedEquals(input, input); + } + + private static void assertWrappedEquals(String expected, String input) { + assertWrappedEqualsOnUnix(expected, input); + assertWrappedEqualsOnWindows(expected, input); + } + + private static void assertWrappedEqualsOnUnix(String expected, String input) { + String wrapped = wrap(input, "\n"); + assertEquals(expected, wrapped); + } + + private static void assertWrappedEqualsOnWindows(String expected, + String input) { + String wrapped = wrap(input.replaceAll("\n", "\r\n"), "\r\n"); + assertEquals(expected.replaceAll("\n", "\r\n"), wrapped); + } + + private static String wrap(String text, String lineDelimiter) { + StringBuilder sb = new StringBuilder(text); + List<WrapEdit> wrapEdits = CommitMessageArea.calculateWrapEdits(text, 70, + lineDelimiter); + for (WrapEdit wrapEdit : wrapEdits) { + sb.replace(wrapEdit.getStart(), + wrapEdit.getStart() + wrapEdit.getLength(), lineDelimiter); + } + return sb.toString(); + } +} diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/AllLocalTests.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/AllLocalTests.java index ef5c6c53f1..65486e3320 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/AllLocalTests.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/AllLocalTests.java @@ -8,6 +8,7 @@ *******************************************************************************/ package org.eclipse.egit.ui.test; +import org.eclipse.egit.ui.dialogs.commit.CommitMessageAreaTest; import org.eclipse.egit.ui.prefpages.configuration.GlobalConfigurationPageTest; import org.eclipse.egit.ui.test.history.HistoryViewTest; import org.eclipse.egit.ui.test.team.actions.AllTeamActionTests; @@ -27,6 +28,7 @@ import org.junit.runners.Suite.SuiteClasses; SharingWizardTest.class, // AllTeamActionTests.class, // HistoryViewTest.class, // + CommitMessageAreaTest.class, TraceConfigurationDialogTest.class, SynchronizeViewTest.class}) public class AllLocalTests { diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties index 69b75b29ca..d6b3bfc1cb 100644 --- a/org.eclipse.egit.ui/plugin.properties +++ b/org.eclipse.egit.ui/plugin.properties @@ -55,6 +55,8 @@ Theme_CommitGraphHighlightFont_label=Commit graph highlight font Theme_CommitGraphHighlightFont_description=This font is used to highlight matching commits in the revision history. Theme_CommitMessageFont_label=Commit message font Theme_CommitMessageFont_description=This font is used to show a commit message. +Theme_CommitMessageEditorFont_label=Commit message editor font +Theme_CommitMessageEditorFont_description=This font is used when entering a commit message. Theme_UncommittedChangeForegroundColor_label=Uncommitted Change (Foreground) Theme_UncommittedChangeForegroundColor_description=This color is used for the foreground color for resources that have outgoing changes. Theme_UncommittedChangeBackgroundColor_label=Uncommitted Change (Background) @@ -65,6 +67,7 @@ Theme_UncommittedChangeFont_description=The font used to display outgoing change GitPreferences_name=Git GitPreferences_WindowCachePreferencePage_name=Window Cache GitPreferences_DecoratorPreferencePage_name=Label Decorations +GitPreferences_CommitDialogPreferencePage_name=Commit Dialog ShareProjectCommand_name=Share with Git ShareProjectCommand_desc=Share the project using Git diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml index ffc2c12f2e..ee2c43c900 100644 --- a/org.eclipse.egit.ui/plugin.xml +++ b/org.eclipse.egit.ui/plugin.xml @@ -328,7 +328,7 @@ id="org.eclipse.egit.ui.keyword.git"> </keywordReference> </page> - <page + <page category="org.eclipse.egit.ui.GitPreferences" class="org.eclipse.egit.ui.internal.preferences.GlobalConfigurationPreferencePage" id="org.eclipse.egit.ui.internal.preferences.GlobalConfigurationPreferencePage" @@ -336,7 +336,16 @@ <keywordReference id="org.eclipse.egit.ui.keyword.git"> </keywordReference> - </page> + </page> + <page + category="org.eclipse.egit.ui.GitPreferences" + class="org.eclipse.egit.ui.internal.preferences.CommitDialogPreferencePage" + id="org.eclipse.egit.ui.internal.preferences.CommitDialogPreferencePage" + name="%GitPreferences_CommitDialogPreferencePage_name"> + <keywordReference + id="org.eclipse.egit.ui.keyword.git"> + </keywordReference> + </page> </extension> <extension point="org.eclipse.ui.propertyPages"> @@ -441,6 +450,15 @@ %Theme_UncommittedChangeFont_description </description> </fontDefinition> + <fontDefinition + categoryId="org.eclipse.egit.ui.GitTheme" + defaultsTo="org.eclipse.jface.textfont" + id="org.eclipse.egit.ui.CommitMessageEditorFont" + label="%Theme_CommitMessageEditorFont_label"> + <description> + %Theme_CommitMessageEditorFont_description + </description> + </fontDefinition> </extension> <!-- ********** QuickDiff text editor support ************** --> diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java index 2908bfc6bb..4d0c355064 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java @@ -64,6 +64,7 @@ public class PluginPreferenceInitializer extends AbstractPreferenceInitializer { store.setDefault(UIPreferences.FINDTOOLBAR_IGNORE_CASE, true); store.setDefault(UIPreferences.FINDTOOLBAR_FIND_IN, 2); + store.setDefault(UIPreferences.COMMIT_DIALOG_HARD_WRAP_MESSAGE, true); store.setDefault(UIPreferences.REFESH_ON_INDEX_CHANGE, true); store.setDefault(UIPreferences.REFESH_ONLY_WHEN_ACTIVE, true); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java index 0d3c7f163f..57a20ea778 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java @@ -50,6 +50,8 @@ public class UIPreferences { public final static String FINDTOOLBAR_COMMITTER = "findtoolbar_committer"; //$NON-NLS-1$ /** */ public final static String FINDTOOLBAR_FIND_IN = "findtoolbar_find_in"; //$NON-NLS-1$ + /** */ + public final static String COMMIT_DIALOG_HARD_WRAP_MESSAGE = "commit_dialog_hard_wrap_message"; //$NON-NLS-1$ /** */ public final static String THEME_CommitGraphNormalFont = "org.eclipse.egit.ui.CommitGraphNormalFont"; //$NON-NLS-1$ @@ -58,6 +60,8 @@ public class UIPreferences { /** */ public final static String THEME_CommitMessageFont = "org.eclipse.egit.ui.CommitMessageFont"; //$NON-NLS-1$ /** */ + public final static String THEME_CommitMessageEditorFont = "org.eclipse.egit.ui.CommitMessageEditorFont"; //$NON-NLS-1$ + /** */ public final static String THEME_UncommittedChangeForegroundColor = "org.eclipse.egit.ui.UncommittedChangeForegroundColor"; //$NON-NLS-1$ /** */ public final static String THEME_UncommittedChangeBackgroundColor = "org.eclipse.egit.ui.UncommittedChangeBackgroundColor"; //$NON-NLS-1$ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index 118463be38..e3cf4cd7be 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -1303,6 +1303,9 @@ public class UIText extends NLS { public static String CommitDialog_AddChangeIdTooltip; /** */ + public static String CommitDialog_ConfigureLink; + + /** */ public static String ConfigurationEditorComponent_AddButton; /** */ @@ -1792,6 +1795,15 @@ public class UIText extends NLS { public static String BranchSelectionDialog_Rename; /** */ + public static String CommitDialogPreferencePage_title; + + /** */ + public static String CommitDialogPreferencePage_hardWrapMessage; + + /** */ + public static String CommitDialogPreferencePage_hardWrapMessageTooltip; + + /** */ public static String Decorator_exceptionMessage; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitDialog.java index 91352f3387..f14a4a2b0b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitDialog.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitDialog.java @@ -47,6 +47,7 @@ import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; @@ -72,12 +73,14 @@ import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; @@ -89,6 +92,7 @@ import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.history.IFileHistory; import org.eclipse.team.core.history.IFileHistoryProvider; import org.eclipse.team.core.history.IFileRevision; +import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.model.WorkbenchLabelProvider; /** @@ -194,8 +198,10 @@ public class CommitDialog extends Dialog { label.setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true, false).create()); commitText = new CommitMessageArea(container, commitMessage); + Point size = commitText.getTextWidget().getSize(); + int minHeight = commitText.getTextWidget().getLineHeight() * 3; commitText.setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true, true) - .hint(600, 200).create()); + .hint(size).minSize(size.x, minHeight).align(SWT.FILL, SWT.FILL).create()); commitText.setText(commitMessage); // allow to commit with ctrl-enter @@ -241,6 +247,20 @@ public class CommitDialog extends Dialog { committerHandler = UIUtils.addPreviousValuesContentProposalToText(committerText, COMMITTER_VALUES_PREF); + Link preferencesLink = new Link(container, SWT.NONE); + preferencesLink.setText(UIText.CommitDialog_ConfigureLink); + preferencesLink.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + String preferencePageId = "org.eclipse.egit.ui.internal.preferences.CommitDialogPreferencePage"; //$NON-NLS-1$ + PreferenceDialog dialog = PreferencesUtil + .createPreferenceDialogOn(null, preferencePageId, + new String[] { preferencePageId }, null); + dialog.open(); + commitText.reconfigure(); + } + }); + amendingButton = new Button(container, SWT.CHECK); if (amending) { amendingButton.setSelection(amending); @@ -599,7 +619,7 @@ public class CommitDialog extends Dialog { * @return The message the user entered */ public String getCommitMessage() { - return commitMessage.replaceAll(Text.DELIMITER, "\n"); //$NON-NLS-1$; + return commitMessage; } /** @@ -740,7 +760,7 @@ public class CommitDialog extends Dialog { @Override protected void okPressed() { - commitMessage = commitText.getText(); + commitMessage = commitText.getCommitMessage(); author = authorText.getText().trim(); committer = committerText.getText().trim(); signedOff = signedOffButton.getSelection(); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitMessageArea.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitMessageArea.java index aebcfcdd97..adb9594d34 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitMessageArea.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitMessageArea.java @@ -12,9 +12,13 @@ package org.eclipse.egit.ui.internal.dialogs; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.UIUtils; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; @@ -47,7 +51,11 @@ import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; 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.graphics.GC; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; @@ -118,6 +126,7 @@ public class CommitMessageArea extends Composite { } private final SourceViewer sourceViewer; + private ModifyListener hardWrapModifyListener; /** * @param parent @@ -130,10 +139,19 @@ public class CommitMessageArea extends Composite { AnnotationModel annotationModel = new AnnotationModel(); sourceViewer = new SourceViewer(this, null, null, true, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP); - getTextWidget().setIndent(2); + getTextWidget().setFont(UIUtils + .getFont(UIPreferences.THEME_CommitMessageEditorFont)); + + int endSpacing = 2; + int textWidth = getCharWidth() * 70 + endSpacing; + int textHeight = getLineHeight() * 7; + Point size = getTextWidget().computeSize(textWidth, textHeight); + getTextWidget().setSize(size); createMarginPainter(); + configureHardWrap(); + final SourceViewerDecorationSupport support = configureAnnotationPreferences(); final IHandlerActivation handlerActivation = installQuickFixActionHandler(); @@ -153,6 +171,39 @@ public class CommitMessageArea extends Composite { }); } + private void configureHardWrap() { + if (shouldHardWrap()) { + if (hardWrapModifyListener == null) { + final StyledText textWidget = getTextWidget(); + + hardWrapModifyListener = new ModifyListener() { + + private boolean active = true; + + public void modifyText(ModifyEvent e) { + if (!active) { + return; + } + String lineDelimiter = textWidget.getLineDelimiter(); + List<WrapEdit> wrapEdits = calculateWrapEdits(textWidget.getText(), 70, lineDelimiter); + // Prevent infinite loop because replaceTextRange causes a ModifyEvent + active = false; + for (WrapEdit wrapEdit : wrapEdits) { + textWidget.replaceTextRange(wrapEdit.getStart(), wrapEdit.getLength(), lineDelimiter); + } + active = true; + } + }; + textWidget.addModifyListener(hardWrapModifyListener); + } + } else { + if (hardWrapModifyListener != null) { + getTextWidget().removeModifyListener(hardWrapModifyListener); + hardWrapModifyListener = null; + } + } + } + private void configureContextMenu() { final TextViewerAction cutAction = new TextViewerAction(sourceViewer, ITextOperationTarget.CUT); cutAction.setText(UIText.CommitMessageArea_cut); @@ -311,12 +362,31 @@ public class CommitMessageArea extends Composite { private void createMarginPainter() { MarginPainter marginPainter = new MarginPainter(sourceViewer); - marginPainter.setMarginRulerColumn(65); + marginPainter.setMarginRulerColumn(70); marginPainter.setMarginRulerColor(Display.getDefault().getSystemColor( SWT.COLOR_GRAY)); sourceViewer.addPainter(marginPainter); } + private int getCharWidth() { + GC gc = new GC(getTextWidget()); + int charWidth = gc.getFontMetrics().getAverageCharWidth(); + gc.dispose(); + return charWidth; + } + + private int getLineHeight() { + return getTextWidget().getLineHeight(); + } + + /** + * @return if the commit message should be hard-wrapped (preference) + */ + private static boolean shouldHardWrap() { + return Activator.getDefault().getPreferenceStore() + .getBoolean(UIPreferences.COMMIT_DIALOG_HARD_WRAP_MESSAGE); + } + /** * @return widget */ @@ -352,6 +422,24 @@ public class CommitMessageArea extends Composite { } /** + * Return the commit message, converting platform-specific line endings. + * + * @return commit message + */ + public String getCommitMessage() { + String text = getText(); + text = text.replaceAll(getTextWidget().getLineDelimiter(), "\n"); //$NON-NLS-1$ + return text; + } + + /** + * Reconfigure this widget if a preference has changed. + */ + public void reconfigure() { + configureHardWrap(); + } + + /** * @return text */ public String getText() { @@ -372,4 +460,95 @@ public class CommitMessageArea extends Composite { return getTextWidget().setFocus(); } + /** + * Calculate a list of {@link WrapEdit} which can be applied to the text to + * get a new text that is wrapped at word boundaries. Existing line breaks + * are left alone (text is not reflowed). + * + * @param text + * the text to calculate the wrap edits for + * @param maxLineLength + * the maximum line length + * @param lineDelimiter + * line delimiter used in text and for wrapping + * @return a list of {@link WrapEdit} objects which specify how the text + * should be edited to obtain the wrapped text. Offsets of later + * edits are already adjusted for the fact that wrapping a line may + * shift the text backwards. So the list can just be iterated and + * each edit applied in order. + */ + public static List<WrapEdit> calculateWrapEdits(final String text, final int maxLineLength, final String lineDelimiter) { + List<WrapEdit> wrapEdits = new LinkedList<WrapEdit>(); + + int offset = 0; + int lineDelimiterLength = lineDelimiter.length(); + + String[] chunks = text.split(lineDelimiter, -1); + for (int chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) { + String chunk = chunks[chunkIndex]; + + String[] words = chunk.split(" ", -1); //$NON-NLS-1$ + int lineLength = 0; + + for (int wordIndex = 0; wordIndex < words.length; wordIndex++) { + String word = words[wordIndex]; + + int wordLength = word.length(); + int newLineLength = lineLength + wordLength + 1 /* the space */; + if (newLineLength > maxLineLength) { + /* don't break before a single long word */ + if (lineLength != 0) { + wrapEdits.add(new WrapEdit(offset, 1)); + /* adjust for the shifting of text after the edit is applied */ + offset += lineDelimiterLength; + } + lineLength = 0; + } else if (wordIndex != 0) { + lineLength += 1; + offset += 1; + } + offset += wordLength; + lineLength += wordLength; + } + + if (chunkIndex != chunks.length - 1) { + offset += lineDelimiterLength; + } + } + + return wrapEdits; + } + + /** + * Edit for replacing a space with a line delimiter to wrap a long line. + */ + public static class WrapEdit { + private int start; + private int length; + + /** + * @param start see {@link #getStart()} + * @param length see {@link #getLength()} + */ + public WrapEdit(int start, int length) { + this.start = start; + this.length = length; + } + + /** + * @return character offset of where the edit should be applied on the + * text + */ + public int getStart() { + return start; + } + + /** + * @return number of characters which should be replaced by the line + * delimiter + */ + public int getLength() { + return length; + } + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/CommitDialogPreferencePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/CommitDialogPreferencePage.java new file mode 100644 index 0000000000..8c85546575 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/CommitDialogPreferencePage.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (C) 2010, Robin Stocker <robin@nibor.org> + * + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.internal.preferences; + +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIPreferences; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +/** Preferences for commit dialog. */ +public class CommitDialogPreferencePage extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + /** */ + public CommitDialogPreferencePage() { + super(GRID); + setTitle(UIText.CommitDialogPreferencePage_title); + } + + public void init(IWorkbench workbench) { + // Nothing to do + } + + @Override + protected IPreferenceStore doGetPreferenceStore() { + return Activator.getDefault().getPreferenceStore(); + } + + @Override + protected void createFieldEditors() { + BooleanFieldEditor hardWrap = new BooleanFieldEditor( + UIPreferences.COMMIT_DIALOG_HARD_WRAP_MESSAGE, + UIText.CommitDialogPreferencePage_hardWrapMessage, + getFieldEditorParent()); + hardWrap.getDescriptionControl(getFieldEditorParent()).setToolTipText(UIText.CommitDialogPreferencePage_hardWrapMessageTooltip); + addField(hardWrap); + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 8cecdb5c4c..8ad3a635a6 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -455,6 +455,7 @@ CommitDialog_StatusUnknown=Unknown CommitDialog_StatusUntracked=Untracked CommitDialog_AddChangeIdLabel=Compute Change-Id for Gerrit Code Review CommitDialog_AddChangeIdTooltip=Inserts the final id when you press Commit +CommitDialog_ConfigureLink=<a>Configure Preferences...</a> ConfigureRemoteWizard_WizardTitle_Change=Change remote configuration {0} ConfigureRemoteWizard_WizardTitle_New=Create a new remote configuration @@ -598,6 +599,10 @@ RefreshPreferencePage_title=Git Detected Workspace Refresh RefreshPreferencesPage_RefreshOnlyWhenActive=Refresh only when workbench is &active RefreshPreferencesPage_RefreshWhenIndexChange=Refresh resources when &index changes +CommitDialogPreferencePage_title=Commit Dialog +CommitDialogPreferencePage_hardWrapMessage=Hard-wrap commit message +CommitDialogPreferencePage_hardWrapMessageTooltip=Wrap text in commit message editor while typing + BranchAction_branchFailed=Branch failed BranchAction_cannotCheckout=Cannot checkout now BranchAction_checkingOut=Checking out {0} |
