Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 4566a80b456127a1c21293c4f50f81864aa31ba9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.texteditor;


import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.ResourceBundle;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;

import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.TextUtilities;


/**
 * An action to convert line delimiters of a text editor document to a
 * particular line delimiter.
 * 
 * @since 2.0
 */
public class ConvertLineDelimitersAction extends TextEditorAction {

	/** The target line delimiter. */
	private final String fLineDelimiter;
	
	/**
	 * Creates a line delimiter conversion action.
	 * 
	 * @param editor the editor
	 * @param lineDelimiter the target line delimiter to convert the editor's document to
	 */
	public ConvertLineDelimitersAction(ITextEditor editor, String lineDelimiter) {
		this(EditorMessages.getResourceBundle(), "dummy", editor, lineDelimiter); //$NON-NLS-1$
	}

	/**
	 * Creates a line delimiter conversion action.
	 * 
	 * @param bundle the resource bundle
	 * @param prefix the prefix for the resource bundle lookup
	 * @param editor the editor
	 * @param lineDelimiter the target line delimiter to convert the editor's document to
	 */
	public ConvertLineDelimitersAction(ResourceBundle bundle, String prefix, ITextEditor editor, String lineDelimiter) {
		super(bundle, prefix, editor);
		fLineDelimiter= lineDelimiter;
		
		String platformLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
		setText(EditorMessages.getString(getLabelKey(fLineDelimiter, platformLineDelimiter)));

		update();
	}
		
	/*
	 * @see org.eclipse.jface.action.Action#run()
	 */
	public void run() {

		try {

			ITextEditor editor= getTextEditor();
			if (editor == null)
				return;

			if (!validateEditorInputState())
				return;
				
			Object adapter= editor.getAdapter(IRewriteTarget.class);
			if (adapter instanceof IRewriteTarget) {
				
				IRewriteTarget target= (IRewriteTarget) adapter;
				IDocument document= target.getDocument();
				if (document != null) {
					Shell shell= getTextEditor().getSite().getShell();
					ConvertRunnable runnable= new ConvertRunnable(target, fLineDelimiter);
	
					if (document.getNumberOfLines() < 40) {
						BusyIndicator.showWhile(shell.getDisplay(), runnable);
						
					} else {				
						ProgressMonitorDialog dialog= new ProgressMonitorDialog(shell);
						dialog.run(false, true, runnable);
					}
				}
			}

		} catch (InterruptedException e) {
			// action cancelled				

		} catch (InvocationTargetException e) {
			// should not happen
		}
	}

	/**
	 * A runnable that converts all line delimiters of a document to <code>lineDelimiter</code>.
	 */
	private static class ConvertRunnable implements IRunnableWithProgress, Runnable {

		/** The rewrite target */
		private final IRewriteTarget fRewriteTarget;
		/** The line delimiter to which to convert to */		
		private final String fLineDelimiter;
		
		/**
		 * Returns a new runnable for converting all line delimiters in
		 * the <code>rewriteTarget</code> to <code>lineDelimter</code>.
		 * @param rewriteTarget
		 * @param lineDelimiter
		 */
		public ConvertRunnable(IRewriteTarget rewriteTarget, String lineDelimiter) {
			fRewriteTarget= rewriteTarget;
			fLineDelimiter= lineDelimiter;	
		}
		
		/*
		 * @see IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
		 */
		public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

			IDocument document= fRewriteTarget.getDocument();
			final int lineCount= document.getNumberOfLines();
			monitor.beginTask(EditorMessages.getString("Editor.ConvertLineDelimiter.title"), lineCount); //$NON-NLS-1$
						
			fRewriteTarget.setRedraw(false);
			fRewriteTarget.beginCompoundChange();

			if (document instanceof IDocumentExtension)
				((IDocumentExtension) document).startSequentialRewrite(true);

			Map partitioners= TextUtilities.removeDocumentPartitioners(document);
			
			try {
				for (int i= 0; i < lineCount; i++) {
					if (monitor.isCanceled())
						throw new InterruptedException();
					
					final String delimiter= document.getLineDelimiter(i);
					if (delimiter != null && delimiter.length() > 0 && !delimiter.equals(fLineDelimiter)) {
						IRegion region= document.getLineInformation(i);
						document.replace(region.getOffset() + region.getLength(), delimiter.length(), fLineDelimiter);
					}

					monitor.worked(1);
				}

			} catch (BadLocationException e) {
				throw new InvocationTargetException(e);

			} finally {

				if (partitioners != null)
					TextUtilities.addDocumentPartitioners(document, partitioners);
									
				if (document instanceof IDocumentExtension)
					((IDocumentExtension) document).stopSequentialRewrite();

				fRewriteTarget.endCompoundChange();
				fRewriteTarget.setRedraw(true);
				
				monitor.done();
			}
		}
		
		/*
		 * @see Runnable#run()
		 */
		public void run() {
			try {
				run(new NullProgressMonitor());

			} catch (InterruptedException e) {
				// should not happen
				
			} catch (InvocationTargetException e) {
				// should not happen				
			}
		}
	}

//	/**
//	 * Returns whether the given document uses only the given line delimiter.
//	 * @param document the document to check
//	 * @param lineDelimiter the line delimiter to check for
//	 */
//	private static boolean usesLineDelimiterExclusively(IDocument document, String lineDelimiter) {
//
//		try {
//			final int lineCount= document.getNumberOfLines();
//			for (int i= 0; i < lineCount; i++) {
//				final String delimiter= document.getLineDelimiter(i);
//				if (delimiter != null && delimiter.length() > 0 && !delimiter.equals(lineDelimiter))
//					return false;
//			}
//
//		} catch (BadLocationException e) {
//			return false;
//		}
//		
//		return true;
//	}
	
	/**
	 * Computes and returns the key to be used to lookup the action's label in
	 * its resource bundle.
	 * 
	 * @param lineDelimiter the line delimiter
	 * @param platformLineDelimiter the platform line delimiter
	 * @return the key used to lookup the action's label
	 */
	private static String getLabelKey(String lineDelimiter, String platformLineDelimiter) {
		if (lineDelimiter.equals(platformLineDelimiter)) {

			if (lineDelimiter.equals("\r\n")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toWindows.default.label"; //$NON-NLS-1$
			
			if (lineDelimiter.equals("\n")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toUNIX.default.label"; //$NON-NLS-1$

			if (lineDelimiter.equals("\r")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toMac.default.label"; //$NON-NLS-1$
			
		} else {

			if (lineDelimiter.equals("\r\n")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toWindows.label"; //$NON-NLS-1$
			
			if (lineDelimiter.equals("\n")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toUNIX.label"; //$NON-NLS-1$

			if (lineDelimiter.equals("\r")) //$NON-NLS-1$
				return "Editor.ConvertLineDelimiter.toMac.label"; //$NON-NLS-1$
		}
		
		return null;
	}

	/**
	 * Internally sets the enable state of this action.
	 */
	private boolean doEnable() {
		return canModifyEditor();
	}
	
	/*
	 * @see IUpdate#update()
	 */
	public void update() {
		super.update();
		setEnabled(doEnable());	
	}

}

Back to the top