1 19 package org.netbeans.modules.diff.builtin.visualizer.editable; 20 21 import org.netbeans.api.diff.Difference; 22 import org.netbeans.editor.*; 23 import org.openide.util.NbBundle; 24 25 import javax.swing.*; 26 import javax.swing.text.StyledDocument ; 27 import java.awt.*; 28 import java.awt.event.MouseMotionListener ; 29 import java.awt.event.MouseEvent ; 30 import java.awt.event.MouseListener ; 31 import java.awt.geom.Rectangle2D ; 32 import java.util.*; 33 import java.util.List ; 34 35 40 class LineNumbersActionsBar extends JComponent implements Scrollable, MouseMotionListener , MouseListener { 41 42 private static final int ACTIONS_BAR_WIDTH = 16; 43 private static final int LINES_BORDER_WIDTH = 4; 44 private static final Point POINT_ZERO = new Point(0, 0); 45 private static final int MAGIC_PADDING = 50; 47 private final Image insertImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/insert.png"); private final Image removeImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/remove.png"); 50 private final Image insertActiveImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/insert_active.png"); private final Image removeActiveImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/remove_active.png"); 53 private final DiffContentPanel master; 54 private final boolean actionsEnabled; 55 private final int actionIconsHeight; 56 private final int actionIconsWidth; 57 58 private final String lineNumberPadding = " "; 60 private int linesWidth; 61 private int actionsWidth; 62 63 private Color linesColor; 64 private int linesCount; 65 private int maxNumberCount; 66 67 private Point lastMousePosition = POINT_ZERO; 68 private HotSpot lastHotSpot = null; 69 70 private List <HotSpot> hotspots = new ArrayList<HotSpot>(0); 71 72 public LineNumbersActionsBar(DiffContentPanel master, boolean actionsEnabled) { 73 this.master = master; 74 this.actionsEnabled = actionsEnabled; 75 actionsWidth = actionsEnabled ? ACTIONS_BAR_WIDTH : 0; 76 actionIconsHeight = insertImage.getHeight(this); 77 actionIconsWidth = insertImage.getWidth(this); 78 setOpaque(true); 79 setToolTipText(""); addMouseMotionListener(this); 81 addMouseListener(this); 82 } 83 84 public void addNotify() { 85 super.addNotify(); 86 initUI(); 87 } 88 89 public void removeNotify() { 90 super.removeNotify(); 91 } 92 93 private Font getLinesFont() { 94 Map coloringMap = EditorUIHelper.getSharedColoringMapFor(master.getEditorPane().getEditorKit().getClass()); 95 96 Object colValue = coloringMap.get(SettingsNames.LINE_NUMBER_COLORING); 97 Coloring col = null; 98 if (colValue != null && colValue instanceof Coloring) { 99 col = (Coloring)colValue; 100 } else { 101 col = SettingsDefaults.defaultLineNumberColoring; 102 } 103 104 Font font = col.getFont(); 105 if (font == null) { 106 font = ((Coloring) coloringMap.get(SettingsNames.DEFAULT_COLORING)).getFont(); 107 } 108 return font; 109 } 110 111 private void initUI() { 112 Map coloringMap = EditorUIHelper.getSharedColoringMapFor(master.getEditorPane().getEditorKit().getClass()); 113 114 Object colValue = coloringMap.get(SettingsNames.LINE_NUMBER_COLORING); 115 Coloring col = null; 116 if (colValue != null && colValue instanceof Coloring) { 117 col = (Coloring)colValue; 118 } else { 119 col = SettingsDefaults.defaultLineNumberColoring; 120 } 121 122 linesColor = col.getForeColor(); 123 if (linesColor == null) { 124 linesColor = ((Coloring) coloringMap.get(SettingsNames.DEFAULT_COLORING)).getForeColor(); 125 } 126 Color bg = col.getBackColor(); 127 if (bg == null) { 128 bg = ((Coloring) coloringMap.get(SettingsNames.DEFAULT_COLORING)).getBackColor(); 129 } 130 setBackground(bg); 131 132 updateStateOnDocumentChange(); 133 } 134 135 private HotSpot getHotspotAt(Point p) { 136 for (HotSpot hotspot : hotspots) { 137 if (hotspot.getRect().contains(p)) { 138 return hotspot; 139 } 140 } 141 return null; 142 } 143 144 public String getToolTipText(MouseEvent event) { 145 Point p = event.getPoint(); 146 HotSpot spot = getHotspotAt(p); 147 if (spot == null) return null; 148 Difference diff = spot.getDiff(); 149 if (diff.getType() == Difference.ADD) { 150 return NbBundle.getMessage(LineNumbersActionsBar.class, "TT_DiffPanel_Remove"); } else if (diff.getType() == Difference.CHANGE) { 152 return NbBundle.getMessage(LineNumbersActionsBar.class, "TT_DiffPanel_Replace"); } else { 154 return NbBundle.getMessage(LineNumbersActionsBar.class, "TT_DiffPanel_Insert"); } 156 } 157 158 private void performAction(HotSpot spot) { 159 master.getMaster().rollback(spot.getDiff()); 160 } 161 162 public void mouseClicked(MouseEvent e) { 163 if (!e.isPopupTrigger()) { 164 HotSpot spot = getHotspotAt(e.getPoint()); 165 if (spot != null) { 166 performAction(spot); 167 } 168 } 169 } 170 171 public void mousePressed(MouseEvent e) { 172 } 174 175 public void mouseReleased(MouseEvent e) { 176 } 178 179 public void mouseEntered(MouseEvent e) { 180 } 182 183 public void mouseExited(MouseEvent e) { 184 lastMousePosition = POINT_ZERO; 185 if (lastHotSpot != null) { 186 repaint(lastHotSpot.getRect()); 187 } 188 lastHotSpot = null; 189 } 190 191 public void mouseMoved(MouseEvent e) { 192 Point p = e.getPoint(); 193 lastMousePosition = p; 194 HotSpot spot = getHotspotAt(p); 195 if (lastHotSpot != spot) { 196 repaint(lastHotSpot == null ? spot.getRect() : lastHotSpot.getRect()); 197 } 198 lastHotSpot = spot; 199 setCursor(spot != null ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor()); 200 } 201 202 public void mouseDragged(MouseEvent e) { 203 } 205 206 void onUISettingsChanged() { 207 initUI(); 208 updateStateOnDocumentChange(); 209 repaint(); 210 } 211 212 private void updateStateOnDocumentChange() { 213 assert SwingUtilities.isEventDispatchThread(); 214 StyledDocument doc = (StyledDocument ) master.getEditorPane().getDocument(); 215 int lastOffset = doc.getEndPosition().getOffset(); 216 linesCount = org.openide.text.NbDocument.findLineNumber(doc, lastOffset); 217 218 Graphics g = getGraphics(); 219 if (g != null) checkLinesWidth(g); 220 maxNumberCount = getNumberCount(linesCount); 221 revalidate(); 222 } 223 224 private int oldLinesWidth; 225 226 private boolean checkLinesWidth(Graphics g) { 227 FontMetrics fm = g.getFontMetrics(getLinesFont()); 228 Rectangle2D rect = fm.getStringBounds(Integer.toString(linesCount), g); 229 linesWidth = (int) rect.getWidth() + LINES_BORDER_WIDTH * 2; 230 if (linesWidth != oldLinesWidth) { 231 oldLinesWidth = linesWidth; 232 revalidate(); 233 repaint(); 234 return true; 235 } 236 return false; 237 } 238 239 private int getNumberCount(int n) { 240 int nc = 0; 241 for (; n > 0; n /= 10, nc++); 242 return nc; 243 } 244 245 public Dimension getPreferredScrollableViewportSize() { 246 Dimension dim = master.getEditorPane().getPreferredScrollableViewportSize(); 247 return new Dimension(getBarWidth(), dim.height); 248 } 249 250 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 251 return master.getEditorPane().getScrollableUnitIncrement(visibleRect, orientation, direction); } 253 254 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 255 return master.getEditorPane().getScrollableBlockIncrement(visibleRect, orientation, direction); 256 } 257 258 public boolean getScrollableTracksViewportWidth() { 259 return true; 260 } 261 262 public boolean getScrollableTracksViewportHeight() { 263 return false; 264 } 265 266 public Dimension getPreferredSize() { 267 return new Dimension(getBarWidth(), master.getEditorPane().getPreferredSize().height + MAGIC_PADDING); 268 } 269 270 private int getBarWidth() { 271 return actionsWidth + linesWidth; 272 } 273 274 public void onDiffSetChanged() { 275 updateStateOnDocumentChange(); 276 repaint(); 277 } 278 279 protected void paintComponent(Graphics gr) { 280 Graphics2D g = (Graphics2D) gr; 281 Rectangle clip = g.getClipBounds(); 282 283 if (checkLinesWidth(gr)) return; 284 285 EditorUI editorUI = org.netbeans.editor.Utilities.getEditorUI(master.getEditorPane()); 286 int lineHeight = editorUI.getLineHeight(); 287 288 g.setColor(getBackground()); 289 g.fillRect(clip.x, clip.y, clip.width, clip.height); 290 291 g.setColor(Color.LIGHT_GRAY); 292 int x = master.isFirst() ? 0 : getBarWidth() - 1; 293 g.drawLine(x, clip.y, x, clip.y + clip.height - 1); 294 295 DiffViewManager.DecoratedDifference [] diffs = master.getMaster().getManager().getDecorations(); 296 297 int actionsYOffset = (lineHeight - actionIconsHeight) / 2; 298 int offset = linesWidth; 299 300 List <HotSpot> newActionIcons = new ArrayList<HotSpot>(); 301 if (master.isFirst()) { 302 for (DiffViewManager.DecoratedDifference dd : diffs) { 303 g.setColor(master.getMaster().getColorLines()); 304 g.drawLine(0, dd.getTopLeft(), clip.width, dd.getTopLeft()); 305 if (dd.getBottomLeft() != -1) { 306 g.drawLine(0, dd.getBottomLeft(), clip.width, dd.getBottomLeft()); 307 } 308 if (actionsEnabled) { 309 if (dd.getDiff().getType() != Difference.ADD) { 310 Rectangle hotSpot = new Rectangle(1, dd.getTopLeft() + actionsYOffset, actionIconsWidth, actionIconsHeight); 311 if (hotSpot.contains(lastMousePosition)) { 312 g.drawImage(insertActiveImage, hotSpot.x, hotSpot.y, this); 313 } else { 314 g.drawImage(insertImage, hotSpot.x, hotSpot.y, this); 315 } 316 newActionIcons.add(new HotSpot(hotSpot, dd.getDiff())); 317 } 318 } 319 } 320 } else { 321 for (DiffViewManager.DecoratedDifference dd : diffs) { 322 g.setColor(master.getMaster().getColorLines()); 323 g.drawLine(clip.x, dd.getTopRight(), clip.x + clip.width, dd.getTopRight()); 324 if (dd.getBottomRight() != -1) { 325 g.drawLine(clip.x, dd.getBottomRight(), clip.x + clip.width, dd.getBottomRight()); 326 } 327 if (actionsEnabled) { 328 if (dd.getDiff().getType() == Difference.ADD) { 329 Rectangle hotSpot = new Rectangle(offset + 1, dd.getTopRight() + actionsYOffset, actionIconsWidth, actionIconsHeight); 330 if (hotSpot.contains(lastMousePosition)) { 331 g.drawImage(removeActiveImage, hotSpot.x, hotSpot.y, this); 332 } else { 333 g.drawImage(removeImage, hotSpot.x, hotSpot.y, this); 334 } 335 newActionIcons.add(new HotSpot(hotSpot, dd.getDiff())); 336 } 337 } 338 } 339 } 340 341 hotspots = newActionIcons; 342 343 int linesXOffset = master.isFirst() ? actionsWidth : 0; 344 linesXOffset += LINES_BORDER_WIDTH; 345 346 g.setFont(getLinesFont()); 347 g.setColor(linesColor); 348 int lineNumber = clip.y / lineHeight; 349 int yOffset = lineNumber * lineHeight; 350 yOffset -= lineHeight / 4; int linesDrawn = clip.height / lineHeight + 3; for (int i = 0; i < linesDrawn; i++) { 353 g.drawString(formatLineNumber(lineNumber), linesXOffset, yOffset); 354 lineNumber++; 355 yOffset += lineHeight; 356 } 357 } 358 359 private String formatLineNumber(int lineNumber) { 360 String strNumber = Integer.toString(lineNumber); 361 int nc = getNumberCount(lineNumber); 362 if (nc < maxNumberCount) { 363 StringBuilder sb = new StringBuilder (10); 364 sb.append(lineNumberPadding, 0, maxNumberCount - nc); 365 sb.append(strNumber); 366 return sb.toString(); 367 } else { 368 return strNumber; 369 } 370 } 371 372 private static class EditorUIHelper extends EditorUI { 373 377 public static Map getSharedColoringMapFor(Class kitClass) { 378 return EditorUIHelper.getSharedColoringMap(kitClass); 379 } 380 } 381 } 382 | Popular Tags |