KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > compare > internal > MergeSourceViewer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * Max Weninger (max.weninger@windriver.com) - Bug 131895 [Edit] Undo in compare
11  * Max Weninger (max.weninger@windriver.com) - Bug 72936 [Viewers] Show line numbers in comparision
12  *******************************************************************************/

13 package org.eclipse.compare.internal;
14
15 import java.util.*;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.compare.ICompareContainer;
19 import org.eclipse.core.commands.operations.*;
20 import org.eclipse.jface.action.*;
21 import org.eclipse.jface.preference.IPreferenceStore;
22 import org.eclipse.jface.preference.PreferenceConverter;
23 import org.eclipse.jface.text.*;
24 import org.eclipse.jface.text.source.*;
25 import org.eclipse.jface.util.IPropertyChangeListener;
26 import org.eclipse.jface.util.PropertyChangeEvent;
27 import org.eclipse.jface.viewers.ISelectionChangedListener;
28 import org.eclipse.jface.viewers.SelectionChangedEvent;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.custom.StyledText;
31 import org.eclipse.swt.graphics.*;
32 import org.eclipse.swt.widgets.*;
33 import org.eclipse.ui.IWorkbenchActionConstants;
34 import org.eclipse.ui.PlatformUI;
35 import org.eclipse.ui.editors.text.EditorsUI;
36 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
37 import org.eclipse.ui.texteditor.FindReplaceAction;
38 /**
39  * Extends the JFace SourceViewer with some convenience methods.
40  */

41 public class MergeSourceViewer extends SourceViewer
42                         implements ISelectionChangedListener, ITextListener, IMenuListener, IOperationHistoryListener {
43                                 
44     public static final String JavaDoc UNDO_ID= "undo"; //$NON-NLS-1$
45
public static final String JavaDoc REDO_ID= "redo"; //$NON-NLS-1$
46
public static final String JavaDoc CUT_ID= "cut"; //$NON-NLS-1$
47
public static final String JavaDoc COPY_ID= "copy"; //$NON-NLS-1$
48
public static final String JavaDoc PASTE_ID= "paste"; //$NON-NLS-1$
49
public static final String JavaDoc DELETE_ID= "delete"; //$NON-NLS-1$
50
public static final String JavaDoc SELECT_ALL_ID= "selectAll"; //$NON-NLS-1$
51
public static final String JavaDoc SAVE_ID= "save"; //$NON-NLS-1$
52
public static final String JavaDoc FIND_ID= "find"; //$NON-NLS-1$
53

54     class TextOperationAction extends MergeViewerAction {
55         
56         private int fOperationCode;
57         
58         TextOperationAction(int operationCode, boolean mutable, boolean selection, boolean content) {
59             this(operationCode, null, mutable, selection, content);
60
61         }
62         
63         public TextOperationAction(int operationCode, String JavaDoc actionDefinitionId, boolean mutable, boolean selection, boolean content) {
64             super(mutable, selection, content);
65             if (actionDefinitionId != null)
66                 setActionDefinitionId(actionDefinitionId);
67             fOperationCode= operationCode;
68             update();
69         }
70
71         public void run() {
72             if (isEnabled())
73                 doOperation(fOperationCode);
74         }
75
76         public boolean isEnabled() {
77             return fOperationCode != -1 && canDoOperation(fOperationCode);
78         }
79         
80         public void update() {
81             this.setEnabled(isEnabled());
82         }
83     }
84
85     private ResourceBundle fResourceBundle;
86     private Position fRegion;
87     private boolean fEnabled= true;
88     private HashMap fActions= new HashMap();
89     private IDocument fRememberedDocument;
90     
91     private boolean fAddSaveAction= true;
92     private boolean isConfigured = false;
93     
94     // line number ruler support
95
private IPropertyChangeListener fPreferenceChangeListener;
96     private boolean fShowLineNumber=false;
97     private LineNumberRulerColumn fLineNumberColumn;
98     private List JavaDoc textActions = new ArrayList();
99
100     public MergeSourceViewer(Composite parent, int style, ResourceBundle bundle, ICompareContainer container) {
101         super(parent, new CompositeRuler(), style | SWT.H_SCROLL | SWT.V_SCROLL);
102         
103         fResourceBundle= bundle;
104         
105         MenuManager menu= new MenuManager();
106         menu.setRemoveAllWhenShown(true);
107         menu.addMenuListener(this);
108         StyledText te= getTextWidget();
109         te.setMenu(menu.createContextMenu(te));
110         container.registerContextMenu(menu, this);
111         
112         // for listening to editor show/hide line number preference value
113
fPreferenceChangeListener= new IPropertyChangeListener() {
114             public void propertyChange(PropertyChangeEvent event) {
115                 MergeSourceViewer.this.handlePropertyChangeEvent(event);
116             }
117         };
118         EditorsUI.getPreferenceStore().addPropertyChangeListener(fPreferenceChangeListener);
119         fShowLineNumber= EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER);
120         if(fShowLineNumber){
121             updateLineNumberRuler();
122         }
123         
124         IOperationHistory history = getHistory();
125         if (history != null)
126             history.addOperationHistoryListener(this);
127     }
128     
129     public void rememberDocument(IDocument doc) {
130 // if (doc != null && fRememberedDocument != null) {
131
// System.err.println("MergeSourceViewer.rememberDocument: fRememberedDocument != null: shouldn't happen"); //$NON-NLS-1$
132
// }
133
fRememberedDocument= doc;
134     }
135     
136     public IDocument getRememberedDocument() {
137         return fRememberedDocument;
138     }
139     
140     public void hideSaveAction() {
141         fAddSaveAction= false;
142     }
143     
144     public void setFont(Font font) {
145         StyledText te= getTextWidget();
146         if (te != null)
147             te.setFont(font);
148         if (fLineNumberColumn != null) {
149             fLineNumberColumn.setFont(font);
150             layoutViewer();
151         }
152     }
153     
154     public void setBackgroundColor(Color color) {
155         StyledText te= getTextWidget();
156         if (te != null)
157             te.setBackground(color);
158         if (fLineNumberColumn != null)
159             fLineNumberColumn.setBackground(color);
160     }
161     
162     public void setEnabled(boolean enabled) {
163         if (enabled != fEnabled) {
164             fEnabled= enabled;
165             StyledText c= getTextWidget();
166             if (c != null) {
167                 c.setEnabled(enabled);
168                 Display d= c.getDisplay();
169                 c.setBackground(enabled ? d.getSystemColor(SWT.COLOR_LIST_BACKGROUND) : null);
170             }
171         }
172     }
173     
174     public boolean getEnabled() {
175         return fEnabled;
176     }
177
178     public void setRegion(Position region) {
179         fRegion= region;
180     }
181     
182     public Position getRegion() {
183         return fRegion;
184     }
185     
186     public boolean isControlOkToUse() {
187         StyledText t= getTextWidget();
188         return t != null && !t.isDisposed();
189     }
190                 
191     public void setSelection(Position position) {
192         if (position != null)
193             setSelectedRange(position.getOffset(), position.getLength());
194     }
195     
196     public void setLineBackground(Position position, Color c) {
197         StyledText t= getTextWidget();
198         if (t != null && !t.isDisposed()) {
199             Point region= new Point(0, 0);
200             getLineRange(position, region);
201         
202             region.x-= getDocumentRegionOffset();
203         
204             try {
205                 t.setLineBackground(region.x, region.y, c);
206             } catch (IllegalArgumentException JavaDoc ex) {
207                 // silently ignored
208
}
209         }
210     }
211     
212     public void resetLineBackground() {
213         StyledText t= getTextWidget();
214         if (t != null && !t.isDisposed()) {
215             int lines= getLineCount();
216             t.setLineBackground(0, lines, null);
217         }
218     }
219     
220     /*
221      * Returns number of lines in document region.
222      */

223     public int getLineCount() {
224         IRegion region= getVisibleRegion();
225
226         int length= region.getLength();
227         if (length == 0)
228             return 0;
229         
230         IDocument doc= getDocument();
231         int startLine= 0;
232         int endLine= 0;
233
234         int start= region.getOffset();
235         try {
236             startLine= doc.getLineOfOffset(start);
237         } catch(BadLocationException ex) {
238             // silently ignored
239
}
240         try {
241             endLine= doc.getLineOfOffset(start+length);
242         } catch(BadLocationException ex) {
243             // silently ignored
244
}
245         
246         return endLine-startLine+1;
247     }
248     
249     public int getViewportLines() {
250         StyledText te= getTextWidget();
251         Rectangle clArea= te.getClientArea();
252         if (!clArea.isEmpty())
253             return clArea.height / te.getLineHeight();
254         return 0;
255     }
256
257     public int getViewportHeight() {
258         StyledText te= getTextWidget();
259         Rectangle clArea= te.getClientArea();
260         if (!clArea.isEmpty())
261             return clArea.height;
262         return 0;
263     }
264     
265     /*
266      * Returns lines
267      */

268     public int getDocumentRegionOffset() {
269         int start= getVisibleRegion().getOffset();
270         IDocument doc= getDocument();
271         if (doc != null) {
272             try {
273                 return doc.getLineOfOffset(start);
274             } catch(BadLocationException ex) {
275                 // silently ignored
276
}
277         }
278         return 0;
279     }
280     
281     public int getVerticalScrollOffset() {
282         StyledText st= getTextWidget();
283         int lineHeight= st.getLineHeight();
284         return getTopInset() - ((getDocumentRegionOffset()*lineHeight) + st.getTopPixel());
285     }
286
287     /*
288      * Returns the start line and the number of lines which correspond to the given position.
289      * Starting line number is 0 based.
290      */

291     public Point getLineRange(Position p, Point region) {
292         
293         IDocument doc= getDocument();
294         
295         if (p == null || doc == null) {
296             region.x= 0;
297             region.y= 0;
298             return region;
299         }
300         
301         int start= p.getOffset();
302         int length= p.getLength();
303         
304         int startLine= 0;
305         try {
306             startLine= doc.getLineOfOffset(start);
307         } catch (BadLocationException e) {
308             // silently ignored
309
}
310         
311         int lineCount= 0;
312         
313         if (length == 0) {
314 // // if range length is 0 and if range starts a new line
315
// try {
316
// if (start == doc.getLineStartOffset(startLine)) {
317
// lines--;
318
// }
319
// } catch (BadLocationException e) {
320
// lines--;
321
// }
322

323         } else {
324             int endLine= 0;
325             try {
326                 endLine= doc.getLineOfOffset(start + length - 1); // why -1?
327
} catch (BadLocationException e) {
328                 // silently ignored
329
}
330             lineCount= endLine-startLine+1;
331         }
332                 
333         region.x= startLine;
334         region.y= lineCount;
335         return region;
336     }
337     
338     /*
339      * Scroll TextPart to the given line.
340      */

341     public void vscroll(int line) {
342
343         int srcViewSize= getLineCount();
344         int srcExtentSize= getViewportLines();
345
346         if (srcViewSize > srcExtentSize) {
347
348             if (line < 0)
349                 line= 0;
350
351             int cp= getTopIndex();
352             if (cp != line)
353                 setTopIndex(line + getDocumentRegionOffset());
354         }
355     }
356     
357     public void addAction(String JavaDoc actionId, MergeViewerAction action) {
358         fActions.put(actionId, action);
359     }
360     
361     public IAction getAction(String JavaDoc actionId) {
362         IAction action= (IAction) fActions.get(actionId);
363         if (action == null) {
364             action= createAction(actionId);
365             if (action == null)
366                 return null;
367             if (action instanceof MergeViewerAction) {
368                 MergeViewerAction mva = (MergeViewerAction) action;
369                 if (mva.isContentDependent())
370                     addTextListener(this);
371                 if (mva.isSelectionDependent())
372                     addSelectionChangedListener(this);
373                 
374                 Utilities.initAction(action, fResourceBundle, "action." + actionId + "."); //$NON-NLS-1$ //$NON-NLS-2$
375
}
376             addAction(actionId, action);
377                 
378         }
379         if (action instanceof MergeViewerAction) {
380             MergeViewerAction mva = (MergeViewerAction) action;
381             if (mva.isEditableDependent() && !isEditable())
382                 return null;
383         }
384         return action;
385     }
386     
387     protected IAction createAction(String JavaDoc actionId) {
388         if (UNDO_ID.equals(actionId))
389             return new TextOperationAction(UNDO, "org.eclipse.ui.edit.undo", true, false, true); //$NON-NLS-1$
390
if (REDO_ID.equals(actionId))
391             return new TextOperationAction(REDO, "org.eclipse.ui.edit.redo", true, false, true); //$NON-NLS-1$
392
if (CUT_ID.equals(actionId))
393             return new TextOperationAction(CUT, "org.eclipse.ui.edit.cut", true, true, false); //$NON-NLS-1$
394
if (COPY_ID.equals(actionId))
395             return new TextOperationAction(COPY, "org.eclipse.ui.edit.copy", false, true, false); //$NON-NLS-1$
396
if (PASTE_ID.equals(actionId))
397             return new TextOperationAction(PASTE, "org.eclipse.ui.edit.paste", true, false, false); //$NON-NLS-1$
398
if (DELETE_ID.equals(actionId))
399             return new TextOperationAction(DELETE, "org.eclipse.ui.edit.delete", true, false, false); //$NON-NLS-1$
400
if (SELECT_ALL_ID.equals(actionId))
401             return new TextOperationAction(SELECT_ALL, "org.eclipse.ui.edit.selectAll", false, false, false); //$NON-NLS-1$
402
return null;
403     }
404     
405     public void selectionChanged(SelectionChangedEvent event) {
406         Iterator e= fActions.values().iterator();
407         while (e.hasNext()) {
408             Object JavaDoc next = e.next();
409             if (next instanceof MergeViewerAction) {
410                 MergeViewerAction action = (MergeViewerAction) next;
411                 if (action.isSelectionDependent())
412                     action.update();
413             }
414         }
415     }
416                     
417     public void textChanged(TextEvent event) {
418         updateContentDependantActions();
419     }
420
421     void updateContentDependantActions() {
422         Iterator e= fActions.values().iterator();
423         while (e.hasNext()) {
424             Object JavaDoc next = e.next();
425             if (next instanceof MergeViewerAction) {
426                 MergeViewerAction action = (MergeViewerAction) next;
427                 if (action.isContentDependent())
428                     action.update();
429             }
430         }
431     }
432         
433     /*
434      * Allows the viewer to add menus and/or tools to the context menu.
435      */

436     public void menuAboutToShow(IMenuManager menu) {
437         
438         menu.add(new Separator("undo")); //$NON-NLS-1$
439
addMenu(menu, UNDO_ID);
440         addMenu(menu, REDO_ID);
441         menu.add(new GroupMarker("save")); //$NON-NLS-1$
442
if (fAddSaveAction)
443             addMenu(menu, SAVE_ID);
444         menu.add(new Separator("file")); //$NON-NLS-1$
445

446         menu.add(new Separator("ccp")); //$NON-NLS-1$
447
addMenu(menu, CUT_ID);
448         addMenu(menu, COPY_ID);
449         addMenu(menu, PASTE_ID);
450         addMenu(menu, DELETE_ID);
451         addMenu(menu, SELECT_ALL_ID);
452
453         menu.add(new Separator("edit")); //$NON-NLS-1$
454
menu.add(new Separator("find")); //$NON-NLS-1$
455
addMenu(menu, FIND_ID);
456         
457         menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
458         
459         menu.add(new Separator("text")); //$NON-NLS-1$
460
for (Iterator iterator = textActions.iterator(); iterator.hasNext();) {
461             IAction action = (IAction) iterator.next();
462             menu.add(action);
463         }
464         
465         menu.add(new Separator("rest")); //$NON-NLS-1$
466

467         // update all actions
468
// to get undo redo right
469
updateActions();
470     }
471     
472     private void addMenu(IMenuManager menu, String JavaDoc actionId) {
473         IAction action= getAction(actionId);
474         if (action != null)
475             menu.add(action);
476     }
477         
478     protected void handleDispose() {
479         
480         removeTextListener(this);
481         removeSelectionChangedListener(this);
482         EditorsUI.getPreferenceStore().removePropertyChangeListener(fPreferenceChangeListener);
483         
484         IOperationHistory history = getHistory();
485         if (history != null)
486             history.removeOperationHistoryListener(this);
487         
488         super.handleDispose();
489     }
490     
491     /**
492      * update all actions independent of their type
493      *
494      */

495     public void updateActions() {
496         Iterator e= fActions.values().iterator();
497         while (e.hasNext()) {
498             Object JavaDoc next = e.next();
499             if (next instanceof MergeViewerAction) {
500                 MergeViewerAction action = (MergeViewerAction) next;
501                 action.update();
502             } if (next instanceof FindReplaceAction) {
503                 FindReplaceAction action = (FindReplaceAction) next;
504                 action.update();
505             }
506         }
507     }
508     
509     public void configure(SourceViewerConfiguration configuration) {
510         if (isConfigured )
511             unconfigure();
512         isConfigured = true;
513         super.configure(configuration);
514     }
515     
516     /**
517      * specific implementation to support a vertical ruler
518      * @param x
519      * @param y
520      * @param width
521      * @param height
522      */

523     public void setBounds (int x, int y, int width, int height) {
524         if(getControl() instanceof Composite){
525             ((Composite)getControl()).setBounds(x, y, width, height);
526         } else {
527             getTextWidget().setBounds(x, y, width, height);
528         }
529     }
530     
531     /**
532      * handle show/hide line numbers from editor preferences
533      * @param event
534      */

535     protected void handlePropertyChangeEvent(PropertyChangeEvent event) {
536         
537         String JavaDoc key= event.getProperty();
538         
539         if(key.equals(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER)){
540             boolean b= EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER);
541             if (b != fShowLineNumber){
542                 toggleLineNumberRuler();
543             }
544         } else if (key.equals(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR)) {
545             updateLineNumberColumnPresentation(true);
546         }
547     }
548
549     /**
550      * Hides or shows line number ruler column based of preference setting
551      */

552     private void updateLineNumberRuler()
553     {
554         IVerticalRuler v= getVerticalRuler();
555         if (v!=null && v instanceof CompositeRuler) {
556             CompositeRuler c= (CompositeRuler) v;
557
558             if(!fShowLineNumber){
559                 if(fLineNumberColumn!=null){
560                     c.removeDecorator(fLineNumberColumn);
561                 }
562             } else {
563                 if(fLineNumberColumn==null){
564                     fLineNumberColumn = new LineNumberRulerColumn();
565                     updateLineNumberColumnPresentation(false);
566                 }
567                 c.addDecorator(0, fLineNumberColumn);
568             }
569         }
570     }
571
572     private void updateLineNumberColumnPresentation(boolean refresh) {
573         if (fLineNumberColumn == null)
574             return;
575         RGB rgb= getColorFromStore(EditorsUI.getPreferenceStore(), AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR);
576         if (rgb == null)
577             rgb= new RGB(0, 0, 0);
578         ISharedTextColors sharedColors= getSharedColors();
579         fLineNumberColumn.setForeground(sharedColors.getColor(rgb));
580         if (refresh) {
581             fLineNumberColumn.redraw();
582         }
583     }
584     
585     private void layoutViewer() {
586         Control parent= getControl();
587         if (parent instanceof Composite && !parent.isDisposed())
588             ((Composite) parent).layout(true);
589     }
590     
591     private ISharedTextColors getSharedColors() {
592         return EditorsUI.getSharedTextColors();
593     }
594     
595     private RGB getColorFromStore(IPreferenceStore store, String JavaDoc key) {
596         RGB rgb= null;
597         if (store.contains(key)) {
598             if (store.isDefault(key))
599                 rgb= PreferenceConverter.getDefaultColor(store, key);
600             else
601                 rgb= PreferenceConverter.getColor(store, key);
602         }
603         return rgb;
604     }
605
606     /**
607      * Toggles line number ruler column.
608      */

609     private void toggleLineNumberRuler()
610     {
611         fShowLineNumber=!fShowLineNumber;
612         
613         updateLineNumberRuler();
614     }
615
616     public void addTextAction(IAction textEditorPropertyAction) {
617         textActions.add(textEditorPropertyAction);
618     }
619
620     public void addAction(String JavaDoc id, IAction action) {
621         fActions.put(id, action);
622     }
623     
624     private IOperationHistory getHistory() {
625         if (PlatformUI.getWorkbench() == null) {
626             return null;
627         }
628         return PlatformUI.getWorkbench().getOperationSupport()
629                 .getOperationHistory();
630     }
631
632     public void historyNotification(OperationHistoryEvent event) {
633         // This method updates the enablement of all content operations
634
// when the undo history changes. It could be localized to UNDO and REDO.
635
IUndoContext context = getUndoContext();
636         if (context != null && event.getOperation().hasContext(context)) {
637             Display.getDefault().asyncExec(new Runnable JavaDoc() {
638                 public void run() {
639                     updateContentDependantActions();
640                 }
641             });
642         }
643     }
644
645     private IUndoContext getUndoContext() {
646         IUndoManager undoManager = getUndoManager();
647         if (undoManager instanceof IUndoManagerExtension)
648             return ((IUndoManagerExtension)undoManager).getUndoContext();
649         return null;
650     }
651 }
652
Popular Tags