1 /******************************************************************************* 2 * Copyright (c) 2000, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jface.text.source; 15 16 import org.eclipse.swt.events.MouseEvent; 17 import org.eclipse.swt.graphics.Color; 18 import org.eclipse.swt.graphics.GC; 19 import org.eclipse.swt.widgets.Composite; 20 import org.eclipse.swt.widgets.Control; 21 22 import org.eclipse.core.runtime.Assert; 23 24 import org.eclipse.jface.internal.text.revisions.RevisionPainter; 25 import org.eclipse.jface.internal.text.source.DiffPainter; 26 import org.eclipse.jface.viewers.ISelectionProvider; 27 28 import org.eclipse.jface.text.revisions.IRevisionListener; 29 import org.eclipse.jface.text.revisions.IRevisionRulerColumn; 30 import org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension; 31 import org.eclipse.jface.text.revisions.RevisionInformation; 32 33 /** 34 * A vertical ruler column displaying line numbers and serving as a UI for quick diff. Clients 35 * usually instantiate and configure object of this class. 36 * 37 * @since 3.0 38 * @noextend This class is not intended to be subclassed by clients. 39 */ 40 public class LineNumberChangeRulerColumn extends LineNumberRulerColumn implements IChangeRulerColumn, IRevisionRulerColumn, IRevisionRulerColumnExtension { 41 /** The ruler's annotation model. */ 42 private IAnnotationModel fAnnotationModel; 43 /** <code>true</code> if changes should be displayed using character indications instead of background colors. */ 44 private boolean fCharacterDisplay; 45 /** 46 * The revision painter strategy. 47 * 48 * @since 3.2 49 */ 50 private final RevisionPainter fRevisionPainter; 51 /** 52 * The diff information painter strategy. 53 * 54 * @since 3.2 55 */ 56 private final DiffPainter fDiffPainter; 57 /** 58 * Whether to show number or to behave like a change ruler column. 59 * @since 3.3 60 */ 61 private boolean fShowNumbers= true; 62 63 /** 64 * Creates a new instance. 65 * 66 * @param sharedColors the shared colors provider to use 67 */ LineNumberChangeRulerColumn(ISharedTextColors sharedColors)68 public LineNumberChangeRulerColumn(ISharedTextColors sharedColors) { 69 Assert.isNotNull(sharedColors); 70 fRevisionPainter= new RevisionPainter(this, sharedColors); 71 fDiffPainter= new DiffPainter(this, sharedColors); 72 } 73 74 @Override createControl(CompositeRuler parentRuler, Composite parentControl)75 public Control createControl(CompositeRuler parentRuler, Composite parentControl) { 76 Control control= super.createControl(parentRuler, parentControl); 77 fRevisionPainter.setParentRuler(parentRuler); 78 fDiffPainter.setParentRuler(parentRuler); 79 return control; 80 } 81 82 @Override getLineOfLastMouseButtonActivity()83 public int getLineOfLastMouseButtonActivity() { 84 return getParentRuler().getLineOfLastMouseButtonActivity(); 85 } 86 87 @Override toDocumentLineNumber(int y_coordinate)88 public int toDocumentLineNumber(int y_coordinate) { 89 return getParentRuler().toDocumentLineNumber(y_coordinate); 90 } 91 92 @Override setModel(IAnnotationModel model)93 public void setModel(IAnnotationModel model) { 94 setAnnotationModel(model); 95 fRevisionPainter.setModel(model); 96 fDiffPainter.setModel(model); 97 updateNumberOfDigits(); 98 computeIndentations(); 99 layout(true); 100 postRedraw(); 101 } 102 setAnnotationModel(IAnnotationModel model)103 private void setAnnotationModel(IAnnotationModel model) { 104 if (fAnnotationModel != model) 105 fAnnotationModel= model; 106 } 107 108 109 /** 110 * Sets the display mode of the ruler. If character mode is set to <code>true</code>, diff 111 * information will be displayed textually on the line number ruler. 112 * 113 * @param characterMode <code>true</code> if diff information is to be displayed textually. 114 */ setDisplayMode(boolean characterMode)115 public void setDisplayMode(boolean characterMode) { 116 if (characterMode != fCharacterDisplay) { 117 fCharacterDisplay= characterMode; 118 updateNumberOfDigits(); 119 computeIndentations(); 120 layout(true); 121 } 122 } 123 124 @Override getModel()125 public IAnnotationModel getModel() { 126 return fAnnotationModel; 127 } 128 129 @Override createDisplayString(int line)130 protected String createDisplayString(int line) { 131 StringBuilder buffer= new StringBuilder(); 132 if (fShowNumbers) 133 buffer.append(super.createDisplayString(line)); 134 if (fCharacterDisplay && getModel() != null) 135 buffer.append(fDiffPainter.getDisplayCharacter(line)); 136 return buffer.toString(); 137 } 138 139 @Override computeNumberOfDigits()140 protected int computeNumberOfDigits() { 141 int digits; 142 if (fCharacterDisplay && getModel() != null) { 143 if (fShowNumbers) 144 digits= super.computeNumberOfDigits() + 1; 145 else 146 digits= 1; 147 } else { 148 if (fShowNumbers) 149 digits= super.computeNumberOfDigits(); 150 else 151 digits= 0; 152 } 153 if (fRevisionPainter.hasInformation()) 154 digits+= fRevisionPainter.getRequiredWidth(); 155 return digits; 156 } 157 158 @Override addVerticalRulerListener(IVerticalRulerListener listener)159 public void addVerticalRulerListener(IVerticalRulerListener listener) { 160 throw new UnsupportedOperationException(); 161 } 162 163 @Override removeVerticalRulerListener(IVerticalRulerListener listener)164 public void removeVerticalRulerListener(IVerticalRulerListener listener) { 165 throw new UnsupportedOperationException(); 166 } 167 168 @Override doPaint(GC gc, ILineRange visibleLines)169 void doPaint(GC gc, ILineRange visibleLines) { 170 Color foreground= gc.getForeground(); 171 if (visibleLines != null) { 172 if (fRevisionPainter.hasInformation()) { 173 fRevisionPainter.paint(gc, visibleLines); 174 } else if (fDiffPainter.hasInformation()) { // don't paint quick diff colors if revisions are painted 175 fDiffPainter.paint(gc, visibleLines); 176 } 177 } 178 gc.setForeground(foreground); 179 if (fShowNumbers || fCharacterDisplay) 180 super.doPaint(gc, visibleLines); 181 } 182 183 @Override getHover()184 public IAnnotationHover getHover() { 185 int activeLine= getParentRuler().getLineOfLastMouseButtonActivity(); 186 if (fRevisionPainter.hasHover(activeLine)) 187 return fRevisionPainter.getHover(); 188 if (fDiffPainter.hasHover(activeLine)) 189 return fDiffPainter.getHover(); 190 return null; 191 } 192 193 @Override setHover(IAnnotationHover hover)194 public void setHover(IAnnotationHover hover) { 195 fRevisionPainter.setHover(hover); 196 fDiffPainter.setHover(hover); 197 } 198 199 @Override setBackground(Color background)200 public void setBackground(Color background) { 201 super.setBackground(background); 202 fRevisionPainter.setBackground(background); 203 fDiffPainter.setBackground(background); 204 } 205 206 @Override setAddedColor(Color addedColor)207 public void setAddedColor(Color addedColor) { 208 fDiffPainter.setAddedColor(addedColor); 209 } 210 211 @Override setChangedColor(Color changedColor)212 public void setChangedColor(Color changedColor) { 213 fDiffPainter.setChangedColor(changedColor); 214 } 215 216 @Override setDeletedColor(Color deletedColor)217 public void setDeletedColor(Color deletedColor) { 218 fDiffPainter.setDeletedColor(deletedColor); 219 } 220 221 @Override setRevisionInformation(RevisionInformation info)222 public void setRevisionInformation(RevisionInformation info) { 223 fRevisionPainter.setRevisionInformation(info); 224 updateNumberOfDigits(); 225 computeIndentations(); 226 layout(true); 227 postRedraw(); 228 } 229 230 @Override getRevisionSelectionProvider()231 public ISelectionProvider getRevisionSelectionProvider() { 232 return fRevisionPainter.getRevisionSelectionProvider(); 233 } 234 235 /* 236 * @see org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension#setRenderingMode(org.eclipse.jface.text.revisions.IRevisionRulerColumnExtension.RenderingMode) 237 * @since 3.3 238 */ 239 @Override setRevisionRenderingMode(RenderingMode renderingMode)240 public void setRevisionRenderingMode(RenderingMode renderingMode) { 241 fRevisionPainter.setRenderingMode(renderingMode); 242 } 243 244 /** 245 * Sets the line number display mode. 246 * 247 * @param showNumbers <code>true</code> to show numbers, <code>false</code> to only show 248 * diff / revision info. 249 * @since 3.3 250 */ showLineNumbers(boolean showNumbers)251 public void showLineNumbers(boolean showNumbers) { 252 if (fShowNumbers != showNumbers) { 253 fShowNumbers= showNumbers; 254 updateNumberOfDigits(); 255 computeIndentations(); 256 layout(true); 257 } 258 } 259 260 @Override getWidth()261 public int getWidth() { 262 int width= super.getWidth(); 263 return width > 0 ? width : 8; // minimal width to display quick diff / revisions if no textual info is shown 264 } 265 266 /** 267 * Returns <code>true</code> if the ruler is showing line numbers, <code>false</code> 268 * otherwise 269 * 270 * @return <code>true</code> if line numbers are shown, <code>false</code> otherwise 271 * @since 3.3 272 */ isShowingLineNumbers()273 public boolean isShowingLineNumbers() { 274 return fShowNumbers; 275 } 276 277 /** 278 * Returns <code>true</code> if the ruler is showing revision information, <code>false</code> 279 * otherwise 280 * 281 * @return <code>true</code> if revision information is shown, <code>false</code> otherwise 282 * @since 3.3 283 */ isShowingRevisionInformation()284 public boolean isShowingRevisionInformation() { 285 return fRevisionPainter.hasInformation(); 286 } 287 288 /** 289 * Returns <code>true</code> if the ruler is showing change information, <code>false</code> 290 * otherwise 291 * 292 * @return <code>true</code> if change information is shown, <code>false</code> otherwise 293 * @since 3.3 294 */ isShowingChangeInformation()295 public boolean isShowingChangeInformation() { 296 return fDiffPainter.hasInformation(); 297 } 298 299 @Override showRevisionAuthor(boolean show)300 public void showRevisionAuthor(boolean show) { 301 fRevisionPainter.showRevisionAuthor(show); 302 updateNumberOfDigits(); 303 computeIndentations(); 304 layout(true); 305 postRedraw(); 306 } 307 308 @Override showRevisionId(boolean show)309 public void showRevisionId(boolean show) { 310 fRevisionPainter.showRevisionId(show); 311 updateNumberOfDigits(); 312 computeIndentations(); 313 layout(true); 314 postRedraw(); 315 } 316 317 @Override addRevisionListener(IRevisionListener listener)318 public void addRevisionListener(IRevisionListener listener) { 319 fRevisionPainter.addRevisionListener(listener); 320 } 321 322 @Override removeRevisionListener(IRevisionListener listener)323 public void removeRevisionListener(IRevisionListener listener) { 324 fRevisionPainter.removeRevisionListener(listener); 325 } 326 327 @Override handleDispose()328 protected void handleDispose() { 329 fRevisionPainter.setParentRuler(null); 330 fRevisionPainter.setModel(null); 331 fDiffPainter.setParentRuler(null); 332 fDiffPainter.setModel(null); 333 super.handleDispose(); 334 } 335 336 @Override handleMouseScrolled(MouseEvent e)337 void handleMouseScrolled(MouseEvent e) { 338 if (fRevisionPainter.isWheelHandlerInstalled()) { 339 return; // scroll event is already handled; don't interfere 340 } 341 super.handleMouseScrolled(e); 342 } 343 } 344