KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > DeleteLineTarget


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

11
12 package org.eclipse.ui.texteditor;
13
14 import org.eclipse.core.runtime.Assert;
15 import org.eclipse.core.runtime.IStatus;
16 import org.eclipse.core.runtime.Status;
17
18 import org.eclipse.swt.SWTError;
19 import org.eclipse.swt.custom.StyledText;
20 import org.eclipse.swt.dnd.Clipboard;
21 import org.eclipse.swt.dnd.DND;
22 import org.eclipse.swt.dnd.TextTransfer;
23 import org.eclipse.swt.dnd.Transfer;
24 import org.eclipse.swt.events.FocusEvent;
25 import org.eclipse.swt.events.FocusListener;
26 import org.eclipse.swt.events.ModifyEvent;
27 import org.eclipse.swt.events.ModifyListener;
28 import org.eclipse.swt.events.MouseEvent;
29 import org.eclipse.swt.events.MouseListener;
30
31 import org.eclipse.jface.text.BadLocationException;
32 import org.eclipse.jface.text.IDocument;
33 import org.eclipse.jface.text.IRegion;
34 import org.eclipse.jface.text.ITextListener;
35 import org.eclipse.jface.text.ITextViewer;
36 import org.eclipse.jface.text.Region;
37 import org.eclipse.jface.text.TextEvent;
38
39 import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
40
41 import org.eclipse.jface.viewers.ISelectionChangedListener;
42 import org.eclipse.jface.viewers.SelectionChangedEvent;
43
44
45 /**
46  * A delete line target.
47  * @since 2.1
48  */

49 class DeleteLineTarget {
50
51     /**
52      * A clipboard which concatenates subsequent delete line actions.
53      */

54     private static class DeleteLineClipboard implements MouseListener, ModifyListener, ISelectionChangedListener, ITextListener, FocusListener {
55
56         /** The text viewer. */
57         private final ITextViewer fViewer;
58         /*
59          * This is a hack to stop a string of deletions when the user moves
60          * the caret. This kludge is necessary since:
61          * 1) Moving the caret does not fire a selection event
62          * 2) There is no support in StyledText for a CaretListener
63          * 3) The AcceleratorScope and KeybindingService classes are internal
64          *
65          * This kludge works by comparing the offset of the caret to the offset
66          * recorded the last time the action was run. If they differ, we do not
67          * continue the session.
68          *
69          * @see #saveState
70          * @see #checkState
71          */

72         /** The last known offset of the caret */
73         private int fIndex= -1;
74         /** The clip board. */
75         private Clipboard fClipboard;
76         /** A string buffer. */
77         private final StringBuffer JavaDoc fBuffer= new StringBuffer JavaDoc();
78         /** The delete flag indicates if a deletion is in progress. */
79         private boolean fDeleting;
80
81         /**
82          * Creates the clipboard.
83          *
84          * @param viewer the text viewer
85          */

86         public DeleteLineClipboard(ITextViewer viewer) {
87             Assert.isNotNull(viewer);
88             fViewer= viewer;
89         }
90
91         /**
92          * Returns the text viewer.
93          *
94          * @return the text viewer
95          */

96         public ITextViewer getViewer() {
97             return fViewer;
98         }
99
100         /**
101          * Saves the current state, to be compared later using
102          * <code>checkState</code>.
103          */

104         private void saveState() {
105             fIndex= fViewer.getTextWidget().getCaretOffset();
106         }
107
108         /**
109          * Checks that the state has not changed since it was saved.
110          *
111          * @return returns <code>true</code> if the current state is the same as
112          * when it was last saved.
113          */

114         private boolean hasSameState() {
115             return fIndex == fViewer.getTextWidget().getCaretOffset();
116         }
117
118         /**
119          * Checks the state of the clipboard.
120          */

121         public void checkState() {
122
123             if (fClipboard == null) {
124                 StyledText text= fViewer.getTextWidget();
125                 if (text == null)
126                     return;
127
128                 fViewer.getSelectionProvider().addSelectionChangedListener(this);
129                 text.addFocusListener(this);
130                 text.addMouseListener(this);
131                 text.addModifyListener(this);
132
133                 fClipboard= new Clipboard(text.getDisplay());
134                 fBuffer.setLength(0);
135
136             } else if (!hasSameState()) {
137                 fBuffer.setLength(0);
138             }
139         }
140
141         /**
142          * Appends the given string to this clipboard.
143          *
144          * @param deltaString the string to append
145          */

146         public void append(String JavaDoc deltaString) {
147             fBuffer.append(deltaString);
148             String JavaDoc string= fBuffer.toString();
149             Transfer[] dataTypes= new Transfer[] { TextTransfer.getInstance() };
150             Object JavaDoc[] data= new Object JavaDoc[] { string };
151             fClipboard.setContents(data, dataTypes);
152         }
153
154         /**
155          * Uninstalls this action.
156          */

157         private void uninstall() {
158
159             if (fClipboard == null)
160                 return;
161
162             StyledText text= fViewer.getTextWidget();
163             if (text == null)
164                 return;
165
166             fViewer.getSelectionProvider().removeSelectionChangedListener(this);
167             text.removeFocusListener(this);
168             text.removeMouseListener(this);
169             text.removeModifyListener(this);
170
171             fClipboard.dispose();
172             fClipboard= null;
173         }
174
175         /**
176          * Mark whether a deletion is in progress.
177          *
178          * @param deleting <code>true</code> if a deletion is in progress
179          */

180         public void setDeleting(boolean deleting) {
181             fDeleting= deleting;
182         }
183
184         /*
185          * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(MouseEvent)
186          */

187         public void mouseDoubleClick(MouseEvent e) {
188             uninstall();
189         }
190
191         /*
192          * @see org.eclipse.swt.events.MouseListener#mouseDown(MouseEvent)
193          */

194         public void mouseDown(MouseEvent e) {
195             uninstall();
196         }
197
198         /*
199          * @see org.eclipse.swt.events.MouseListener#mouseUp(MouseEvent)
200          */

201         public void mouseUp(MouseEvent e) {
202             uninstall();
203         }
204
205         /*
206          * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
207          */

208         public void selectionChanged(SelectionChangedEvent event) {
209             uninstall();
210         }
211
212         /*
213          * @see org.eclipse.swt.events.FocusListener#focusGained(FocusEvent)
214          */

215         public void focusGained(FocusEvent e) {
216             uninstall();
217         }
218
219         /*
220          * @see org.eclipse.swt.events.FocusListener#focusLost(FocusEvent)
221          */

222         public void focusLost(FocusEvent e) {
223             uninstall();
224         }
225
226         /*
227          * @see org.eclipse.jface.text.ITextListener#textChanged(TextEvent)
228          */

229         public void textChanged(TextEvent event) {
230             uninstall();
231         }
232
233         /*
234          * @see org.eclipse.swt.events.ModifyListener#modifyText(ModifyEvent)
235          */

236         public void modifyText(ModifyEvent e) {
237             if (!fDeleting)
238                 uninstall();
239         }
240     }
241
242     /**
243      * The clipboard manager.
244      */

245     private final DeleteLineClipboard fClipboard;
246
247     /**
248      * Creates a new target.
249      *
250      * @param viewer the viewer that the new target operates on
251      */

252     public DeleteLineTarget(ITextViewer viewer) {
253         fClipboard= new DeleteLineClipboard(viewer);
254     }
255
256     /**
257      * Returns the document's delete region specified by position and type.
258      *
259      * @param document the document
260      * @param offset the offset
261      * @param length the length
262      * @param type the line deletion type, must be one of
263      * <code>WHOLE_LINE</code>, <code>TO_BEGINNING</code> or <code>TO_END</code>
264      * @return the document's delete region
265      * @throws BadLocationException
266      */

267     private static IRegion getDeleteRegion(IDocument document, int offset, int length, int type) throws BadLocationException {
268
269         int line= document.getLineOfOffset(offset);
270         int resultOffset= 0;
271         int resultLength= 0;
272
273         switch (type) {
274         case DeleteLineAction.WHOLE:
275             resultOffset= document.getLineOffset(line);
276             int endOffset= offset + length;
277             IRegion endLineInfo= document.getLineInformationOfOffset(endOffset);
278             int endLine= document.getLineOfOffset(endLineInfo.getOffset());
279             if (endLineInfo.getOffset() == endOffset && endLine > 0 && length > 0)
280                 endLine= endLine - 1;
281             resultLength= document.getLineOffset(endLine) + document.getLineLength(endLine) - resultOffset;
282             break;
283
284         case DeleteLineAction.TO_BEGINNING:
285             resultOffset= document.getLineOffset(line);
286             resultLength= offset - resultOffset;
287             break;
288
289         case DeleteLineAction.TO_END:
290             resultOffset= offset;
291
292             IRegion lineRegion= document.getLineInformation(line);
293             int end= lineRegion.getOffset() + lineRegion.getLength();
294
295             if (offset == end) {
296                 String JavaDoc lineDelimiter= document.getLineDelimiter(line);
297                 resultLength= lineDelimiter == null ? 0 : lineDelimiter.length();
298
299             } else {
300                 resultLength= end - resultOffset;
301             }
302             break;
303
304         default:
305             throw new IllegalArgumentException JavaDoc();
306         }
307
308         return new Region(resultOffset, resultLength);
309     }
310
311     /**
312      * Deletes the specified fraction of the line of the given offset.
313      *
314      * @param document the document
315      * @param offset the offset
316      * @param length the length
317      * @param type the line deletion type, must be one of
318      * <code>WHOLE_LINE</code>, <code>TO_BEGINNING</code> or <code>TO_END</code>
319      * @param copyToClipboard <code>true</code> if the deleted line should be copied to the clipboard
320      * @throws BadLocationException if position is not valid in the given document
321      */

322     public void deleteLine(IDocument document, int offset, int length, int type, boolean copyToClipboard) throws BadLocationException {
323
324         IRegion deleteRegion= getDeleteRegion(document, offset, length, type);
325         int deleteOffset= deleteRegion.getOffset();
326         int deleteLength= deleteRegion.getLength();
327
328         if (deleteLength == 0)
329             return;
330
331         if (copyToClipboard) {
332
333             fClipboard.checkState();
334             try {
335                 fClipboard.append(document.get(deleteOffset, deleteLength));
336             } catch (SWTError e) {
337                 if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD)
338                     throw e;
339                 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59459
340
// don't delete if copy to clipboard fails, rather log & abort
341

342                 // log
343
Status status= new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, e.code, EditorMessages.Editor_error_clipboard_copy_failed_message, e);
344                 TextEditorPlugin.getDefault().getLog().log(status);
345
346                 fClipboard.uninstall();
347                 return; // don't delete
348
}
349
350             fClipboard.setDeleting(true);
351             document.replace(deleteOffset, deleteLength, null);
352             fClipboard.setDeleting(false);
353
354             fClipboard.saveState();
355
356         } else {
357             document.replace(deleteOffset, deleteLength, ""); //$NON-NLS-1$
358
}
359     }
360 }
361
Popular Tags