001: package net.sourceforge.squirrel_sql.plugins.graph;
002:
003: import net.sourceforge.squirrel_sql.client.session.ISession;
004: import net.sourceforge.squirrel_sql.plugins.graph.xmlbeans.ConstraintViewXmlBean;
005: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
006: import net.sourceforge.squirrel_sql.fw.util.StringManager;
007:
008: import javax.swing.*;
009: import javax.swing.plaf.basic.BasicInternalFrameUI;
010: import java.awt.*;
011: import java.awt.geom.AffineTransform;
012: import java.awt.geom.NoninvertibleTransformException;
013: import java.awt.event.ActionEvent;
014: import java.awt.event.ActionListener;
015: import java.awt.event.MouseEvent;
016: import java.util.Vector;
017:
018: public class ConstraintView implements GraphComponent {
019: private static final StringManager s_stringMgr = StringManagerFactory
020: .getStringManager(ConstraintView.class);
021:
022: private GraphDesktopController _desktopController;
023:
024: private boolean _isSelected;
025:
026: private JPopupMenu _connectLinePopup;
027: private JPopupMenu _foldingPointPopUp;
028:
029: private JMenuItem _mnuAddFoldingPoint;
030: private JMenuItem _mnuShowDDL;
031: private JMenuItem _mnuScriptDDL;
032: private JMenuItem _mnuRemoveFoldingPoint;
033:
034: private Point _lastPopupClickPoint;
035:
036: private ConstraintGraph _constraintGraph = new ConstraintGraph();
037:
038: private ConstraintData _constraintData;
039: public static final int STUB_LENGTH = 20;
040: private ISession _session;
041: private TableFrameController _pkFramePointingTo;
042: private Vector<ConstraintViewListener> _constraintViewListeners = new Vector<ConstraintViewListener>();
043:
044: public ConstraintView(ConstraintData constraintData,
045: GraphDesktopController desktopController, ISession session) {
046: _constraintData = constraintData;
047: _desktopController = desktopController;
048: _session = session;
049:
050: createPopup();
051: }
052:
053: public ConstraintView(ConstraintViewXmlBean constraintViewXmlBean,
054: GraphDesktopController desktopController, ISession session) {
055: _desktopController = desktopController;
056: _session = session;
057: _constraintData = new ConstraintData(constraintViewXmlBean
058: .getConstraintDataXmlBean());
059: _constraintGraph = new ConstraintGraph(constraintViewXmlBean
060: .getConstraintGraphXmlBean(), _desktopController
061: .getZoomer());
062:
063: createPopup();
064: }
065:
066: public ConstraintViewXmlBean getXmlBean() {
067: ConstraintViewXmlBean ret = new ConstraintViewXmlBean();
068:
069: ret.setConstraintDataXmlBean(_constraintData.getXmlBean());
070: ret.setConstraintGraphXmlBean(_constraintGraph.getXmlBean());
071:
072: return ret;
073: }
074:
075: private void createPopup() {
076: _connectLinePopup = new JPopupMenu();
077:
078: // i18n[graph.addFoldingPoint=add folding point]
079: _mnuAddFoldingPoint = new JMenuItem(s_stringMgr
080: .getString("graph.addFoldingPoint"));
081: _mnuAddFoldingPoint.addActionListener(new ActionListener() {
082: public void actionPerformed(ActionEvent e) {
083: onAddFoldingPoint();
084: }
085: });
086: _connectLinePopup.add(_mnuAddFoldingPoint);
087:
088: // i18n[graph.showddl=show DDL]
089: _mnuShowDDL = new JMenuItem(s_stringMgr
090: .getString("graph.showddl"));
091: _mnuShowDDL.addActionListener(new ActionListener() {
092: public void actionPerformed(ActionEvent e) {
093: onShowDDL();
094: }
095: });
096: _connectLinePopup.add(_mnuShowDDL);
097:
098: // i18n[graph.scriptdd=script DDL]
099: _mnuScriptDDL = new JMenuItem(s_stringMgr
100: .getString("graph.scriptdd"));
101: _mnuScriptDDL.addActionListener(new ActionListener() {
102: public void actionPerformed(ActionEvent e) {
103: onScriptDDL();
104: }
105: });
106: _connectLinePopup.add(_mnuScriptDDL);
107:
108: _foldingPointPopUp = new JPopupMenu();
109:
110: // i18n[graph.removeFoldingPoint=remove folding point]
111: _mnuRemoveFoldingPoint = new JMenuItem(s_stringMgr
112: .getString("graph.removeFoldingPoint"));
113: _mnuRemoveFoldingPoint.addActionListener(new ActionListener() {
114: public void actionPerformed(ActionEvent e) {
115: onRemoveFoldingPoint();
116: }
117: });
118: _foldingPointPopUp.add(_mnuRemoveFoldingPoint);
119: }
120:
121: private void onRemoveFoldingPoint() {
122: _constraintGraph.removeHitFoldingPoint();
123: _desktopController.repaint();
124: }
125:
126: private void onScriptDDL() {
127: String[] lines = _constraintData.getDDL();
128:
129: StringBuffer sb = new StringBuffer();
130: sb.append('\n');
131: for (int i = 0; i < lines.length; i++) {
132: sb.append(lines[i]).append('\n');
133: }
134: _session.getSessionSheet().getSQLEntryPanel().appendText(
135: sb.toString());
136: }
137:
138: private void onShowDDL() {
139: final String[] lines = _constraintData.getDDL();
140:
141: final JInternalFrame ddlFrame = new JInternalFrame(
142: _constraintData.getTitle(), true, true);
143:
144: StringBuffer sb = new StringBuffer();
145: sb.append(lines[0]);
146: for (int i = 1; i < lines.length; i++) {
147: sb.append('\n').append(lines[i]);
148: }
149:
150: final JTextPane txtDDL = new JTextPane();
151: txtDDL.setText(sb.toString());
152: txtDDL.setEditable(false);
153: ddlFrame.getContentPane().add(new JScrollPane(txtDDL));
154:
155: _desktopController.addFrame(ddlFrame);
156:
157: ddlFrame.setBounds(_lastPopupClickPoint.x,
158: _lastPopupClickPoint.y, 20, 20);
159: ddlFrame.setVisible(true);
160:
161: SwingUtilities.invokeLater(new Runnable() {
162: public void run() {
163: recalculateDDLFrameSize(ddlFrame, txtDDL, lines);
164: }
165: });
166: }
167:
168: private void recalculateDDLFrameSize(JInternalFrame ddlFrame,
169: JTextPane txtDDL, String[] lines) {
170:
171: FontMetrics fm = txtDDL.getFontMetrics(txtDDL.getFont());
172: int txtHeight = fm.getHeight() * lines.length;
173:
174: int txtWidht = 0;
175: for (int i = 0; i < lines.length; i++) {
176: txtWidht = Math.max(txtWidht, fm.stringWidth(lines[i]));
177: }
178:
179: BasicInternalFrameUI ui = (BasicInternalFrameUI) ddlFrame
180: .getUI();
181: int titleHeight = ui.getNorthPane().getHeight();
182:
183: ddlFrame.setSize(txtWidht + 20, txtHeight + titleHeight + 20);
184: }
185:
186: private void onAddFoldingPoint() {
187: double zoom = _desktopController.getZoomer().getZoom();
188: Point backTransformedPoint = new Point(
189: (int) (_lastPopupClickPoint.x / zoom + 0.5),
190: (int) (_lastPopupClickPoint.y / zoom + 0.5));
191:
192: _constraintGraph
193: .addFoldingPointToHitConnectLine(new FoldingPoint(
194: backTransformedPoint, _desktopController
195: .getZoomer()));
196: _desktopController.repaint();
197: }
198:
199: public void setConnectionPoints(ConnectionPoints fkPoints,
200: ConnectionPoints pkPoints,
201: TableFrameController pkFramePointingTo,
202: ConstraintViewListener constraintViewListener) {
203: double zoom = 1;
204:
205: if (null != _desktopController.getZoomer()) {
206: zoom = _desktopController.getZoomer().getZoom();
207: }
208:
209: _pkFramePointingTo = pkFramePointingTo;
210: addConstraintViewListener(constraintViewListener);
211:
212: int fkCenterY = getCenterY(fkPoints.points);
213: int pkCenterY = getCenterY(pkPoints.points);
214:
215: int signFkStub = fkPoints.pointsAreLeftOfWindow ? -1 : 1;
216: int signPkStub = pkPoints.pointsAreLeftOfWindow ? -1 : 1;
217:
218: Point fkGatherPoint = new Point((int) (fkPoints.points[0].x
219: + signFkStub * STUB_LENGTH * zoom + 0.5), fkCenterY);
220: Point pkGatherPoint = new Point((int) (pkPoints.points[0].x
221: + signPkStub * STUB_LENGTH * zoom + 0.5), pkCenterY);
222:
223: GraphLine[] fkStubLines = new GraphLine[fkPoints.points.length];
224: for (int i = 0; i < fkPoints.points.length; i++) {
225: fkStubLines[i] = new GraphLine(fkPoints.points[i],
226: fkGatherPoint);
227: }
228: _constraintGraph.setFkStubLines(fkStubLines);
229:
230: GraphLine[] pkStubLines = new GraphLine[pkPoints.points.length];
231: for (int i = 0; i < pkPoints.points.length; i++) {
232: pkStubLines[i] = new GraphLine(pkPoints.points[i],
233: pkGatherPoint);
234: }
235: _constraintGraph.setPkStubLines(pkStubLines);
236:
237: _constraintGraph.setFkGatherPoint(fkGatherPoint);
238: _constraintGraph.setPkGatherPoint(pkGatherPoint);
239: }
240:
241: public void paint(Graphics g, boolean isPrinting) {
242: Color colBuf = g.getColor();
243:
244: g.setColor(Color.black);
245:
246: GraphLine[] lines = _constraintGraph.getAllLines();
247: for (int i = 0; i < lines.length; i++) {
248: drawLine(g, lines[i]);
249: }
250:
251: GraphLine[] linesToArrow = _constraintGraph.getLinesToArrow();
252:
253: for (int i = 0; i < linesToArrow.length; i++) {
254: paintArrow(g, linesToArrow[i].getEnd().x, linesToArrow[i]
255: .getEnd().y, linesToArrow[i].getBegin().x,
256: linesToArrow[i].getBegin().y);
257: }
258:
259: if (_desktopController.isShowConstraintNames()) {
260: GraphLine mainLine = _constraintGraph.getMainLine();
261: drawConstraintNameOnLine(g, mainLine);
262: }
263:
264: Vector<FoldingPoint> foldingPoints = _constraintGraph
265: .getFoldingPoints();
266:
267: if (false == isPrinting) {
268: for (int i = 0; i < foldingPoints.size(); i++) {
269: drawFoldingPoint(g, foldingPoints.get(i));
270: }
271: }
272:
273: g.setColor(colBuf);
274: }
275:
276: private void drawConstraintNameOnLine(Graphics g, GraphLine line) {
277: Graphics2D g2d = (Graphics2D) g;
278: AffineTransform origTrans = g2d.getTransform();
279:
280: try {
281: double zoom = _desktopController.getZoomer().getZoom();
282: StringBuffer drawText = new StringBuffer(_constraintData
283: .getConstraintName());
284:
285: // if(line.begIsFoldingPoint || line.endIsFoldingPoint)
286: // {
287: // line = new GraphLine(line, zoom);
288: // }
289:
290: int lineLen = (int) Math.sqrt((line.getBegin().x - line
291: .getEnd().x)
292: * (line.getBegin().x - line.getEnd().x)
293: + (line.getBegin().y - line.getEnd().y)
294: * (line.getBegin().y - line.getEnd().y));
295:
296: FontMetrics fontMetrics = g2d.getFontMetrics(g2d.getFont());
297: while (lineLen < (fontMetrics.stringWidth(drawText
298: .toString())
299: * zoom + 0.5)) {
300: if (0 == drawText.length()) {
301: break;
302: }
303: drawText.setLength(drawText.length() - 1);
304: }
305:
306: Point right;
307: Point left;
308:
309: if (line.getBegin().x > line.getEnd().x) {
310: right = line.getBegin();
311: left = line.getEnd();
312: } else if (line.getBegin().x < line.getEnd().x) {
313: right = line.getEnd();
314: left = line.getBegin();
315: } else {
316: if (line.getBegin().y < line.getEnd().y) {
317: right = line.getEnd();
318: left = line.getBegin();
319: } else {
320: right = line.getBegin();
321: left = line.getEnd();
322: }
323: }
324:
325: double angle;
326:
327: if (0 != right.x - left.x) {
328: angle = Math.atan((double) (right.y - left.y)
329: / (double) (right.x - left.x));
330: } else {
331: angle = Math.PI / 2;
332: }
333:
334: AffineTransform at = new AffineTransform();
335: at.setToRotation(angle);
336: at.scale(zoom, zoom);
337: g2d.transform(at);
338:
339: Point invTransBeg = (Point) at.inverseTransform(left,
340: new Point());
341: g2d.drawString(drawText.toString(), invTransBeg.x,
342: invTransBeg.y);
343:
344: g2d.setTransform(origTrans);
345: } catch (NoninvertibleTransformException e) {
346: throw new RuntimeException(e);
347: } finally {
348: g2d.setTransform(origTrans);
349: }
350: }
351:
352: public Dimension getRequiredSize() {
353: Dimension ret = new Dimension();
354: for (int i = 0; i < _constraintGraph.getFoldingPoints().size(); i++) {
355: FoldingPoint fp = _constraintGraph.getFoldingPoints()
356: .get(i);
357:
358: if (fp.getZoomedPoint().x > ret.width) {
359: ret.width = fp.getZoomedPoint().x;
360: }
361:
362: if (fp.getZoomedPoint().y > ret.height) {
363: ret.height = fp.getZoomedPoint().y;
364: }
365: }
366:
367: ret.width += 5;
368: ret.height += 5;
369:
370: return ret;
371: }
372:
373: private void paintArrow(Graphics g, int x1, int y1, int x2, int y2) {
374: double zoom = _desktopController.getZoomer().getZoom();
375:
376: // defines the opening angle of the arrow (not rad or so but something fancy)
377: double sAng = 0.5;
378:
379: Point c = new Point(x2, y2);
380: Point a = new Point((int) (x1 + sAng * (y2 - y1)),
381: (int) (y1 - sAng * (x2 - x1)));
382: Point b = new Point((int) (x1 - sAng * (y2 - y1)),
383: (int) (y1 + sAng * (x2 - x1)));
384:
385: // defines the size of the arrow
386: double sLen = 10
387: / Math.sqrt((a.x - c.x) * (a.x - c.x) + (a.y - c.y)
388: * (a.y - c.y)) * zoom;
389:
390: Point arrPa = new Point((int) (c.x + sLen * (a.x - c.x)),
391: (int) (c.y + sLen * (a.y - c.y)));
392: Point arrPb = new Point((int) (c.x + sLen * (b.x - c.x)),
393: (int) (c.y + sLen * (b.y - c.y)));
394:
395: Polygon pg = new Polygon();
396: pg.addPoint(arrPa.x, arrPa.y);
397: pg.addPoint(arrPb.x, arrPb.y);
398: pg.addPoint(c.x, c.y);
399: g.fillPolygon(pg);
400: }
401:
402: private void drawFoldingPoint(Graphics g, FoldingPoint fp) {
403: int rad = 4;
404: if (_isSelected) {
405: rad = 5;
406: }
407:
408: //double zoom = _desktopController.getZoomer().getZoom();
409:
410: //g.fillOval((int)(zoom*fp.x + 0.5) - rad, (int)(zoom*fp.y+0.5) - rad, 2 * rad, 2 * rad);
411: g.fillOval((int) (fp.getZoomedPoint().x + 0.5) - rad, (int) (fp
412: .getZoomedPoint().y + 0.5)
413: - rad, 2 * rad, 2 * rad);
414:
415: }
416:
417: private void drawLine(Graphics g, GraphLine line) {
418: if (_isSelected) {
419: g
420: .fillPolygon(createPolygon(line.getBegin().x, line
421: .getBegin().y, line.getEnd().x, line
422: .getEnd().y, 1));
423: // if(line.begIsFoldingPoint && line.endIsFoldingPoint)
424: // {
425: // g.fillPolygon(createPolygon((int)(zoom*line.getBegin().x + 0.5), (int)(zoom*line.getBegin().y + 0.5), (int)(zoom*line.getEnd().x + 0.5), (int)(zoom*line.getEnd().y + 0.5), 1));
426: // }
427: // else if(line.begIsFoldingPoint && false ==line.endIsFoldingPoint)
428: // {
429: // g.fillPolygon(createPolygon((int)(zoom*line.getBegin().x + 0.5), (int)(zoom*line.getBegin().y + 0.5), line.getEnd().x, line.getEnd().y, 1));
430: // }
431: // else if(false == line.begIsFoldingPoint && line.endIsFoldingPoint)
432: // {
433: // g.fillPolygon(createPolygon(line.getBegin().x, line.getBegin().y, (int)(zoom*line.getEnd().x + 0.5), (int)(zoom*line.getEnd().y + 0.5), 1));
434: // }
435: // else
436: // {
437: // g.fillPolygon(createPolygon(line.getBegin().x, line.getBegin().y, line.getEnd().x, line.getEnd().y, 1));
438: // }
439: } else {
440: g.drawLine(line.getBegin().x, line.getBegin().y, line
441: .getEnd().x, line.getEnd().y);
442:
443: // if(line.begIsFoldingPoint && line.endIsFoldingPoint)
444: // {
445: // g.drawLine((int)(zoom*line.getBegin().x + 0.5), (int)(zoom*line.getBegin().y + 0.5), (int)(zoom*line.getEnd().x + 0.5), (int)(zoom*line.getEnd().y + 0.5));
446: // }
447: // else if(line.begIsFoldingPoint && false ==line.endIsFoldingPoint)
448: // {
449: // g.drawLine((int)(line.getBegin().x + 0.5), (int)(line.getBegin().y + 0.5), line.getEnd().x, line.getEnd().y);
450: // }
451: // else if(false == line.begIsFoldingPoint && line.endIsFoldingPoint)
452: // {
453: // g.drawLine(line.getBegin().x, line.getBegin().y, (int)(line.getEnd().x + 0.5), (int)(line.getEnd().y + 0.5));
454: // }
455: // else
456: // {
457: // g.drawLine(line.getBegin().x, line.getBegin().y, line.getEnd().x, line.getEnd().y);
458: // }
459: }
460:
461: }
462:
463: public Polygon createPolygon(int x1, int y1, int x2, int y2,
464: int halfThickness) {
465: Polygon ret = new Polygon();
466:
467: if (x1 < x2 && y1 < y2) {
468: ret.addPoint(x1 + halfThickness, y1 - halfThickness);
469: ret.addPoint(x1 - halfThickness, y1 + halfThickness);
470: ret.addPoint(x2 - halfThickness, y2 + halfThickness);
471: ret.addPoint(x2 + halfThickness, y2 - halfThickness);
472: } else if (x1 > x2 && y1 > y2) {
473: ret.addPoint(x1 - halfThickness, y1 + halfThickness);
474: ret.addPoint(x1 + halfThickness, y1 - halfThickness);
475: ret.addPoint(x2 + halfThickness, y2 - halfThickness);
476: ret.addPoint(x2 - halfThickness, y2 + halfThickness);
477: } else {
478: ret.addPoint(x1 + halfThickness, y1 + halfThickness);
479: ret.addPoint(x1 - halfThickness, y1 - halfThickness);
480: ret.addPoint(x2 - halfThickness, y2 - halfThickness);
481: ret.addPoint(x2 + halfThickness, y2 + halfThickness);
482: }
483:
484: //System.out.println("("+ x1 + ", " + y1 + ") - (" + x2 + ", " + y2 +")");
485:
486: return ret;
487: }
488:
489: private int getCenterY(Point[] points) {
490: int ret = 0;
491: for (int i = 0; i < points.length; i++) {
492: ret += points[i].y;
493: }
494:
495: return ret / points.length;
496:
497: }
498:
499: public boolean hitMe(MouseEvent e) {
500: Vector<FoldingPoint> foldingPoints = _constraintGraph
501: .getFoldingPoints();
502:
503: int hitDist = 8;
504: for (int i = 0; i < foldingPoints.size(); i++) {
505: FoldingPoint foldingPoint = foldingPoints.get(i);
506: if (Math.abs(e.getPoint().x
507: - foldingPoint.getZoomedPoint().x) < hitDist
508: && Math.abs(e.getPoint().y
509: - foldingPoint.getZoomedPoint().y) < hitDist) {
510: _constraintGraph.setHitFoldingPoint(foldingPoint);
511: return true;
512: }
513: }
514:
515: GraphLine[] lines = _constraintGraph.getConnectLines();
516: for (int i = 0; i < lines.length; i++) {
517: Polygon pg = createPolygon(lines[i].getBegin().x, lines[i]
518: .getBegin().y, lines[i].getEnd().x, lines[i]
519: .getEnd().y, 3);
520:
521: if (pg.contains(e.getPoint())) {
522: _constraintGraph.setHitConnectLine(lines[i]);
523: return true;
524: }
525: }
526:
527: return false;
528: }
529:
530: public void setSelected(boolean b) {
531: _isSelected = b;
532: _desktopController.repaint();
533: }
534:
535: public boolean isSelected() {
536: return _isSelected;
537:
538: }
539:
540: public void removeAllFoldingPoints() {
541: _constraintGraph.removeAllFoldingPoints();
542: }
543:
544: public boolean equals(Object obj) {
545: if (obj instanceof ConstraintView) {
546: return ((ConstraintView) obj)._constraintData
547: .equals(_constraintData);
548: } else {
549: return false;
550: }
551: }
552:
553: public int hashCode() {
554: return _constraintData.hashCode();
555: }
556:
557: public ConstraintData getData() {
558: return _constraintData;
559: }
560:
561: @SuppressWarnings("unused")
562: public void mouseClicked(MouseEvent e) {
563: }
564:
565: public void mouseReleased(MouseEvent e) {
566: maybeShowPopup(e);
567: }
568:
569: private void maybeShowPopup(MouseEvent e) {
570: if (e.isPopupTrigger()) {
571: _lastPopupClickPoint = new Point(e.getX(), e.getY());
572:
573: if (_constraintGraph.isHitOnConnectLine()) {
574: _connectLinePopup.show(e.getComponent(), e.getX(), e
575: .getY());
576: } else // hit is on folding point
577: {
578: _foldingPointPopUp.show(e.getComponent(), e.getX(), e
579: .getY());
580: }
581: }
582: }
583:
584: public void mousePressed(MouseEvent e) {
585: maybeShowPopup(e);
586: }
587:
588: public void mouseDragged(MouseEvent e) {
589: if (false == _constraintGraph.isHitOnConnectLine()) {
590: double zoom = _desktopController.getZoomer().getZoom();
591:
592: // hit is on folding point
593: Point backTransformedPoint = e.getPoint();
594: backTransformedPoint.x = (int) (backTransformedPoint.x
595: / zoom + 0.5);
596: backTransformedPoint.y = (int) (backTransformedPoint.y
597: / zoom + 0.5);
598: //_constraintGraph.moveLastHitFoldingPointTo(point);
599:
600: _constraintGraph
601: .moveLastHitFoldingPointTo(new FoldingPoint(
602: backTransformedPoint, _desktopController
603: .getZoomer()));
604:
605: ConstraintViewListener[] listeners = _constraintViewListeners
606: .toArray(new ConstraintViewListener[_constraintViewListeners
607: .size()]);
608: for (int i = 0; i < listeners.length; i++) {
609: listeners[i].foldingPointMoved(this );
610: }
611: }
612: }
613:
614: public FoldingPoint getFirstFoldingPoint() {
615: return _constraintGraph.getFirstFoldingPoint();
616: }
617:
618: public FoldingPoint getLastFoldingPoint() {
619: return _constraintGraph.getLastFoldingPoint();
620: }
621:
622: public TableFrameController getPkFramePointingTo() {
623: return _pkFramePointingTo;
624: }
625:
626: public void replaceCopiedColsByReferences(ColumnInfo[] colInfos) {
627: _constraintData.replaceCopiedColsByReferences(colInfos);
628: }
629:
630: public void addConstraintViewListener(
631: ConstraintViewListener constraintViewListener) {
632: _constraintViewListeners.remove(constraintViewListener);
633: _constraintViewListeners.add(constraintViewListener);
634: }
635:
636: public void setData(ConstraintData constraintData) {
637: _constraintData = constraintData;
638: }
639: }
|