001: /*
002: Copyright 2003 J?rgen N?rgaard (jnp@anneli.dk)
003: This file is part of Gruntspud.
004: Gruntspud is free software; you can redistribute it and/or modify
005: it under the terms of the GNU General Public License as published by
006: the Free Software Foundation; either version 2 of the License, or
007: (at your option) any later version.
008: JavaCVS is distributed in the hope that it will be useful,
009: but WITHOUT ANY WARRANTY; without even the implied warranty of
010: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: GNU General Public License for more details.
012: You should have received a copy of the GNU General Public License
013: along with JavaCVS; if not, write to the Free Software
014: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
015: */
016: package allensoft.diff;
017:
018: import gruntspud.GruntspudContext;
019: import gruntspud.standalone.JDK13GruntspudHost;
020: import gruntspud.style.TextStyle;
021:
022: import java.awt.Color;
023: import java.awt.Dimension;
024: import java.awt.Graphics;
025: import java.awt.Image;
026: import java.awt.Insets;
027: import java.awt.Polygon;
028: import java.awt.event.MouseEvent;
029: import java.awt.event.MouseListener;
030: import java.util.List;
031: import java.util.Vector;
032:
033: import javax.swing.JPanel;
034:
035: /**
036: * DOCUMENT ME!
037: *
038: * @author $author$
039: */
040: public class DiffNavigator extends JPanel {
041: private List m_Left = null, m_Right = null;
042: private int prefWidth = 20;
043: private int prefHeigth = 20;
044: private TextStyle m_NonExistantStyle;
045: private TextStyle m_NoStyle, m_InsertStyle, m_DeleteStyle,
046: m_ChangeStyle;
047: private DiffViewer m_Parent = null;
048: private GruntspudContext context;
049:
050: public DiffNavigator(DiffViewer parent, List left, List right,
051: GruntspudContext context) {
052: this .context = context;
053: this .m_Parent = parent;
054: this .m_Left = left;
055: this .m_Right = right;
056:
057: // setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
058:
059: m_NonExistantStyle = context.getTextStyleModel().getStyle(
060: JDK13GruntspudHost.OPTIONS_STYLE_DIFF_NON_EXISTANT);
061: setStyle(DiffType.NONE, context.getTextStyleModel().getStyle(
062: JDK13GruntspudHost.OPTIONS_STYLE_DIFF_IDENTICAL));
063: setStyle(
064: DiffType.INSERTION,
065: context
066: .getTextStyleModel()
067: .getStyle(
068: JDK13GruntspudHost.OPTIONS_STYLE_DIFF_INSERTION));
069: setStyle(DiffType.DELETION, context.getTextStyleModel()
070: .getStyle(
071: JDK13GruntspudHost.OPTIONS_STYLE_DIFF_DELETION));
072: setStyle(DiffType.CHANGE, context.getTextStyleModel().getStyle(
073: JDK13GruntspudHost.OPTIONS_STYLE_DIFF_CHANGE));
074: addMouseListener(new ClickListener());
075:
076: }
077:
078: public synchronized void setStyle(DiffType type, TextStyle style) {
079: if (type == DiffType.NONE) {
080: m_NoStyle = style;
081: setBackground(style.getBackground());
082: } else if (type == DiffType.INSERTION)
083: m_InsertStyle = style;
084:
085: else if (type == DiffType.DELETION)
086: m_DeleteStyle = style;
087:
088: else
089: m_ChangeStyle = style;
090:
091: repaint();
092: }
093:
094: public TextStyle getStyle(DiffType type) {
095: TextStyle style = m_NoStyle;
096: if (type == DiffType.NONE)
097: ;
098: else if (type == DiffType.INSERTION)
099: style = m_InsertStyle;
100: else if (type == DiffType.DELETION)
101: style = m_DeleteStyle;
102: else
103: style = m_ChangeStyle;
104: return style;
105: }
106:
107: public Dimension getPreferredSize() {
108: return new Dimension(prefWidth, prefHeigth);
109: }
110:
111: public void paintComponent(Graphics g) {
112: Insets insets = getInsets();
113: int x = 0 + insets.left;
114: int y = 0 + insets.top;
115:
116: super .paintComponent(g);
117:
118: setUpNavigator();
119:
120: if (navigator != null) {
121: g.drawImage(navigator, x, y, m_NonExistantStyle
122: .getBackground(), null);
123: } else {
124: System.err.println("Uups");
125: }
126:
127: }
128:
129: private Image navigator = null;
130: private Vector regions = null;
131: private int effectiveHeight = -1;
132: private int maxLine = -1;
133:
134: private int currentDiff = -1;
135:
136: public void advanceDiff(boolean forward) {
137: // forward == true
138: // move forward/backward, circular if needed
139: if (regions.size() > 0) {
140: if (currentDiff == -1) {
141: currentDiff = 0;
142: } else {
143: currentDiff = (currentDiff + (forward ? 1 : -1))
144: % regions.size();
145: if (currentDiff < 0) {
146: currentDiff = regions.size() - 1;
147: }
148: }
149: RangePair rp = (RangePair) regions.elementAt(currentDiff);
150: m_Parent.setScrollPosition(rp.getFrom() - 2);
151: System.err.println("scoll: " + rp);
152: }
153: }
154:
155: private void setUpNavigator() {
156: Insets insets = getInsets();
157: int w = getWidth() - (insets.left + insets.right);
158: int h = getHeight() - (insets.top + insets.bottom);
159: int x = 0 + insets.left;
160: int y = 0 + insets.top;
161: maxLine = m_Left.size();
162: effectiveHeight = h;
163: // new Throwable().printStackTrace();
164: Vector leftRanges = new Vector();
165: Vector rightRanges = new Vector();
166:
167: navigator = createImage(w, h);
168:
169: Graphics g = navigator.getGraphics();
170:
171: g.setColor(m_NonExistantStyle.getBackground());
172: g.fillRect(x, y, w, h);
173:
174: if (m_Left.size() > 0) {
175: Line line = (Line) m_Left.get(0);
176: DiffType last = line.m_Type;
177: int lastIdx = 0;
178: for (int i = 1; i < m_Left.size(); i++) {
179: line = (Line) m_Left.get(i);
180: if (last != line.m_Type) {
181: if (last != DiffType.NONE) {
182: leftRanges.add(new RangePair(lastIdx, i - 1,
183: last, getStyle(last).getBackground()));
184: }
185: lastIdx = i;
186: last = line.m_Type;
187: }
188: }
189: if (lastIdx < m_Left.size() - 1 && last != DiffType.NONE) {
190: leftRanges.add(new RangePair(lastIdx,
191: m_Left.size() - 1, last, getStyle(last)
192: .getBackground()));
193: }
194: }
195: for (int i = 0; i < leftRanges.size(); i++) {
196: RangePair rp = (RangePair) leftRanges.elementAt(i);
197: int xs[] = new int[4];
198: int ys[] = new int[4];
199: xs[0] = x;
200: ys[0] = y
201: + (int) (((float) rp.getFrom() * (float) h) / ((float) maxLine));
202: xs[1] = w;
203: ys[1] = y
204: + (int) (((float) rp.getFrom() * (float) h) / ((float) maxLine));
205: xs[2] = w;
206: ys[2] = y
207: + (int) (((float) (rp.getTo() + 1) * (float) h) / ((float) maxLine));
208: xs[3] = x;
209: ys[3] = y
210: + (int) (((float) (rp.getTo() + 1) * (float) h) / ((float) maxLine));
211: Polygon pol = new Polygon(xs, ys, xs.length);
212: g.setColor(rp.getColor());
213: g.fillPolygon(pol);
214: }
215:
216: if (m_Right.size() > 0) {
217: Line line = (Line) m_Right.get(0);
218: DiffType last = line.m_Type;
219: int lastIdx = 0;
220: for (int i = 1; i < m_Right.size(); i++) {
221: line = (Line) m_Right.get(i);
222: if (last != line.m_Type) {
223: if (last != DiffType.NONE) {
224: rightRanges.add(new RangePair(lastIdx, i - 1,
225: last, getStyle(last).getBackground()));
226: }
227: lastIdx = i;
228: last = line.m_Type;
229: }
230: }
231: if (lastIdx < m_Right.size() - 1 && last != DiffType.NONE) {
232: rightRanges.add(new RangePair(lastIdx,
233: m_Right.size() - 1, last, getStyle(last)
234: .getBackground()));
235: }
236: }
237: for (int i = 0; i < rightRanges.size(); i++) {
238: RangePair rp = (RangePair) rightRanges.elementAt(i);
239: int xs[] = new int[4];
240: int ys[] = new int[4];
241: xs[0] = x;
242: ys[0] = y
243: + (int) (((float) rp.getFrom() * (float) h) / ((float) maxLine));
244: xs[1] = w;
245: ys[1] = y
246: + (int) (((float) rp.getFrom() * (float) h) / ((float) maxLine));
247: xs[2] = w;
248: ys[2] = y
249: + (int) (((float) (rp.getTo() + 1) * (float) h) / ((float) maxLine));
250: xs[3] = x;
251: ys[3] = y
252: + (int) (((float) (rp.getTo() + 1) * (float) h) / ((float) maxLine));
253: Polygon pol = new Polygon(xs, ys, xs.length);
254: g.setColor(rp.getColor());
255: g.fillPolygon(pol);
256: }
257:
258: // find regions
259: regions = new Vector();
260: for (int i = 0; i < leftRanges.size(); i++) {
261: RangePair rp = (RangePair) leftRanges.elementAt(i);
262: regions.add(rp);
263: }
264: for (int i = 0; i < rightRanges.size(); i++) {
265: RangePair rp = (RangePair) rightRanges.elementAt(i);
266: if (!regions.contains(rp)) {
267: regions.add(rp);
268: }
269: }
270: }
271:
272: private class RangePair {
273:
274: private int from, to;
275: private DiffType status;
276: private Color color;
277:
278: public RangePair(int from, int to, DiffType status, Color color) {
279: this .from = from;
280: this .to = to;
281: this .status = status;
282: this .color = color;
283: }
284:
285: public int getFrom() {
286: return from;
287: }
288:
289: public int getTo() {
290: return to;
291: }
292:
293: public DiffType getStatus() {
294: return status;
295: }
296:
297: public Color getColor() {
298: return color;
299: }
300:
301: public boolean equals(Object other) {
302: boolean res = false;
303: if (other instanceof RangePair) {
304: RangePair rp = (RangePair) other;
305: res = (this == rp)
306: || (rp == null ? (false) : (from == rp.from
307: && to == rp.to && true));
308: } else {
309: res = false;
310: }
311: return res;
312: }
313:
314: public String toString() {
315: return "(" + from + ", " + to + ") [" + status + ", "
316: + color + "]";
317: }
318: }
319:
320: private class ClickListener implements MouseListener {
321: public void mouseClicked(MouseEvent e) {
322: m_Parent
323: .setScrollPosition(((e.getY() * maxLine) / effectiveHeight) - 2);
324: }
325:
326: public void mouseEntered(MouseEvent e) {
327: }
328:
329: public void mouseExited(MouseEvent e) {
330: }
331:
332: public void mousePressed(MouseEvent e) {
333: }
334:
335: public void mouseReleased(MouseEvent e) {
336: }
337: }
338: }
|