KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > diff > builtin > visualizer > editable > LineNumbersActionsBar


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

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 JavaDoc;
27 import java.awt.*;
28 import java.awt.event.MouseMotionListener JavaDoc;
29 import java.awt.event.MouseEvent JavaDoc;
30 import java.awt.event.MouseListener JavaDoc;
31 import java.awt.geom.Rectangle2D JavaDoc;
32 import java.util.*;
33 import java.util.List JavaDoc;
34
35 /**
36  * Draws both line numbers and diff actions for a decorated editor pane.
37  *
38  * @author Maros Sandor
39  */

40 class LineNumbersActionsBar extends JComponent implements Scrollable, MouseMotionListener JavaDoc, MouseListener JavaDoc {
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; // this should be at least height of a horizontal scrollbar
46

47     private final Image insertImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/insert.png"); // NOI18N
48
private final Image removeImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/remove.png"); // NOI18N
49

50     private final Image insertActiveImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/insert_active.png"); // NOI18N
51
private final Image removeActiveImage = org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/builtin/visualizer/editable/remove_active.png"); // NOI18N
52

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 JavaDoc lineNumberPadding = " "; // NOI18N
59

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 JavaDoc<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(""); // NOI18N
80
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 JavaDoc 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 JavaDoc 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 JavaDoc getToolTipText(MouseEvent JavaDoc 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"); // NOI18N
151
} else if (diff.getType() == Difference.CHANGE) {
152             return NbBundle.getMessage(LineNumbersActionsBar.class, "TT_DiffPanel_Replace"); // NOI18N
153
} else {
154             return NbBundle.getMessage(LineNumbersActionsBar.class, "TT_DiffPanel_Insert"); // NOI18N
155
}
156     }
157
158     private void performAction(HotSpot spot) {
159         master.getMaster().rollback(spot.getDiff());
160     }
161     
162     public void mouseClicked(MouseEvent JavaDoc 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 JavaDoc e) {
172         // not interested
173
}
174
175     public void mouseReleased(MouseEvent JavaDoc e) {
176         // not interested
177
}
178
179     public void mouseEntered(MouseEvent JavaDoc e) {
180         // not interested
181
}
182
183     public void mouseExited(MouseEvent JavaDoc e) {
184         lastMousePosition = POINT_ZERO;
185         if (lastHotSpot != null) {
186             repaint(lastHotSpot.getRect());
187         }
188         lastHotSpot = null;
189     }
190     
191     public void mouseMoved(MouseEvent JavaDoc 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 JavaDoc e) {
203         // not interested
204
}
205
206     void onUISettingsChanged() {
207         initUI();
208         updateStateOnDocumentChange();
209         repaint();
210     }
211     
212     private void updateStateOnDocumentChange() {
213         assert SwingUtilities.isEventDispatchThread();
214         StyledDocument JavaDoc doc = (StyledDocument JavaDoc) 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 JavaDoc 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);//123
252
}
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 JavaDoc<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; // baseline correction
351
int linesDrawn = clip.height / lineHeight + 3; // draw past clipping rectangle to avoid partially drawn numbers
352
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 JavaDoc formatLineNumber(int lineNumber) {
360         String JavaDoc strNumber = Integer.toString(lineNumber);
361         int nc = getNumberCount(lineNumber);
362         if (nc < maxNumberCount) {
363             StringBuilder JavaDoc sb = new StringBuilder JavaDoc(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         /**
374          * Gets the coloring map that can be shared by the components
375          * with the same kit. Only the component coloring map is provided.
376          */

377         public static Map getSharedColoringMapFor(Class JavaDoc kitClass) {
378             return EditorUIHelper.getSharedColoringMap(kitClass);
379         }
380     }
381 }
382
Popular Tags