0001: package net.sourceforge.squirrel_sql.plugins.graph;
0002:
0003: import java.awt.FontMetrics;
0004: import java.awt.Point;
0005: import java.awt.Rectangle;
0006: import java.awt.event.ActionEvent;
0007: import java.awt.event.ActionListener;
0008: import java.awt.event.AdjustmentEvent;
0009: import java.awt.event.AdjustmentListener;
0010: import java.awt.event.ComponentAdapter;
0011: import java.awt.event.ComponentEvent;
0012: import java.awt.event.MouseAdapter;
0013: import java.awt.event.MouseEvent;
0014: import java.sql.DatabaseMetaData;
0015: import java.sql.ResultSet;
0016: import java.sql.SQLException;
0017: import java.util.ArrayList;
0018: import java.util.Arrays;
0019: import java.util.Comparator;
0020: import java.util.Enumeration;
0021: import java.util.Hashtable;
0022: import java.util.List;
0023: import java.util.Vector;
0024:
0025: import javax.swing.JCheckBoxMenuItem;
0026: import javax.swing.JComponent;
0027: import javax.swing.JMenuItem;
0028: import javax.swing.JPopupMenu;
0029: import javax.swing.JScrollPane;
0030: import javax.swing.JSeparator;
0031: import javax.swing.SwingUtilities;
0032: import javax.swing.event.InternalFrameAdapter;
0033: import javax.swing.event.InternalFrameEvent;
0034:
0035: import net.sourceforge.squirrel_sql.client.session.ISession;
0036: import net.sourceforge.squirrel_sql.client.session.ObjectTreeSearch;
0037: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
0038: import net.sourceforge.squirrel_sql.fw.sql.PrimaryKeyInfo;
0039: import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
0040: import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
0041: import net.sourceforge.squirrel_sql.fw.util.StringManager;
0042: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
0043: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
0044: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
0045: import net.sourceforge.squirrel_sql.plugins.graph.xmlbeans.ColumnInfoXmlBean;
0046: import net.sourceforge.squirrel_sql.plugins.graph.xmlbeans.ConstraintViewXmlBean;
0047: import net.sourceforge.squirrel_sql.plugins.graph.xmlbeans.TableFrameControllerXmlBean;
0048:
0049: public class TableFrameController {
0050: private static final StringManager s_stringMgr = StringManagerFactory
0051: .getStringManager(TableFrameController.class);
0052:
0053: /** Logger for this class. */
0054: private final static ILogger s_log = LoggerController
0055: .createLogger(TableFrameController.class);
0056:
0057: ////////////////////////////////////////
0058: // Serialized attributes
0059: private String _schema;
0060: private String _catalog;
0061: private String _tableName;
0062: private TableFrame _frame;
0063:
0064: private ColumnInfo[] _colInfos;
0065: private ConstraintView[] _constraintViews;
0066: private String[] _tablesExportedTo;
0067: //
0068: ///////////////////////////////////////////
0069:
0070: private ISession _session;
0071: private Rectangle _startSize;
0072: private GraphDesktopController _desktopController;
0073: private Vector<TableFrameControllerListener> _listeners = new Vector<TableFrameControllerListener>();
0074: private Vector<TableFrameController> _openFramesConnectedToMe = new Vector<TableFrameController>();
0075: private Hashtable<TableFrameController, ComponentAdapter> _compListenersToOtherFramesByFrameCtrlr = new Hashtable<TableFrameController, ComponentAdapter>();
0076: private Hashtable<TableFrameController, AdjustmentListener> _scrollListenersToOtherFramesByFrameCtrlr = new Hashtable<TableFrameController, AdjustmentListener>();
0077: private Hashtable<TableFrameController, ColumnSortListener> _columnSortListenersToOtherFramesByFrameCtrlr = new Hashtable<TableFrameController, ColumnSortListener>();
0078:
0079: private Vector<ColumnSortListener> _mySortListeners = new Vector<ColumnSortListener>();
0080:
0081: private JPopupMenu _popUp;
0082: private JMenuItem _mnuAddTableForForeignKey;
0083: private JMenuItem _mnuAddChildTables;
0084: private JMenuItem _mnuAddParentTables;
0085: private JMenuItem _mnuAddAllRelatedTables;
0086: private JMenuItem _mnuRefreshTable;
0087: private JMenuItem _mnuScriptTable;
0088: private JMenuItem _mnuViewTableInObjectTree;
0089: private JCheckBoxMenuItem _mnuOrderByName;
0090: private JCheckBoxMenuItem _mnuPksAndConstraintsOnTop;
0091: private JCheckBoxMenuItem _mnuDbOrder;
0092: private JMenuItem _mnuClose;
0093: private AddTableListener _addTablelListener;
0094: private ConstraintViewListener _constraintViewListener;
0095:
0096: private int _columnOrder = ORDER_DB;
0097: private static final int ORDER_DB = 0;
0098: private static final int ORDER_NAME = 1;
0099: private static final int ORDER_PK_CONSTRAINT = 2;
0100: private ColumnInfo[] _orderedColumnInfos;
0101: private static final String MNU_PROP_COLUMN_INFO = "MNU_PROP_COLUMN_INFO";
0102: private ZoomerListener _zoomerListener;
0103: private Rectangle _adjustBeginBounds;
0104: private double _adjustBeginZoom;
0105:
0106: public TableFrameController(ISession session,
0107: GraphDesktopController desktopController,
0108: AddTableListener listener, String tableName,
0109: String schemaName, String catalogName,
0110: TableFrameControllerXmlBean xmlBean) {
0111: try {
0112: _session = session;
0113: _desktopController = desktopController;
0114: _addTablelListener = listener;
0115:
0116: TableToolTipProvider toolTipProvider = new TableToolTipProvider() {
0117: public String getToolTipText(MouseEvent event) {
0118: return onGetToolTipText(event);
0119: }
0120: };
0121:
0122: if (null == xmlBean) {
0123: _tableName = tableName;
0124: _frame = new TableFrame(_tableName, null,
0125: toolTipProvider, _desktopController.getZoomer());
0126:
0127: _catalog = catalogName;
0128: _schema = schemaName;
0129:
0130: initFromDB();
0131:
0132: } else {
0133: _tableName = xmlBean.getTablename();
0134: _frame = new TableFrame(_tableName, xmlBean
0135: .getTableFrameXmlBean(), toolTipProvider,
0136: _desktopController.getZoomer());
0137: _catalog = xmlBean.getCatalog();
0138: _schema = xmlBean.getSchema();
0139: _columnOrder = xmlBean.getColumOrder();
0140: _colInfos = new ColumnInfo[xmlBean
0141: .getColumnIfoXmlBeans().length];
0142: for (int i = 0; i < _colInfos.length; i++) {
0143: _colInfos[i] = new ColumnInfo(xmlBean
0144: .getColumnIfoXmlBeans()[i]);
0145: }
0146:
0147: _constraintViews = new ConstraintView[xmlBean
0148: .getConstraintViewXmlBeans().length];
0149: for (int i = 0; i < _constraintViews.length; i++) {
0150: _constraintViews[i] = new ConstraintView(xmlBean
0151: .getConstraintViewXmlBeans()[i],
0152: _desktopController, _session);
0153: _constraintViews[i]
0154: .replaceCopiedColsByReferences(_colInfos);
0155: }
0156: }
0157:
0158: _constraintViewListener = new ConstraintViewListener() {
0159: public void foldingPointMoved(ConstraintView source) {
0160: onFoldingPointMoved(source);
0161: }
0162: };
0163:
0164: _frame.addInternalFrameListener(new InternalFrameAdapter() {
0165: public void internalFrameClosing(InternalFrameEvent e) {
0166: onClose();
0167: }
0168: });
0169:
0170: _frame.addComponentListener(new ComponentAdapter() {
0171: public void componentMoved(ComponentEvent e) {
0172: recalculateAllConnections();
0173: }
0174:
0175: public void componentResized(ComponentEvent e) {
0176: recalculateAllConnections();
0177: }
0178:
0179: public void componentShown(ComponentEvent e) {
0180: recalculateAllConnections();
0181: }
0182: });
0183:
0184: _frame.scrollPane.getVerticalScrollBar()
0185: .addAdjustmentListener(new AdjustmentListener() {
0186: public void adjustmentValueChanged(
0187: AdjustmentEvent e) {
0188: recalculateAllConnections();
0189: }
0190: });
0191:
0192: createPopUp();
0193:
0194: orderColumns();
0195:
0196: _zoomerListener = new ZoomerListener() {
0197: public void zoomChanged(double newZoom, double oldZoom,
0198: boolean adjusting) {
0199: onZoomChanged(newZoom, oldZoom, adjusting);
0200: }
0201:
0202: public void zoomEnabled(boolean b) {
0203: onZoomEnabled(b);
0204: }
0205:
0206: public void setHideScrollBars(boolean b) {
0207: onHideScrollBars(b);
0208: }
0209: };
0210:
0211: _desktopController.getZoomer().addZoomListener(
0212: _zoomerListener);
0213: onHideScrollBars(_desktopController.getZoomer()
0214: .isHideScrollbars());
0215:
0216: } catch (SQLException e) {
0217: throw new RuntimeException(e);
0218: }
0219: }
0220:
0221: /**
0222: * @return false if table doesnt exist anymore.
0223: */
0224: private boolean initFromDB() throws SQLException {
0225: DatabaseMetaData metaData = _session.getSQLConnection()
0226: .getConnection().getMetaData();
0227: SQLDatabaseMetaData md = _session.getSQLConnection()
0228: .getSQLMetaData();
0229: Hashtable<String, ConstraintData> constaintInfosByConstraintName = new Hashtable<String, ConstraintData>();
0230: Vector<ColumnInfo> colInfosBuf = new Vector<ColumnInfo>();
0231: if (s_log.isDebugEnabled()) {
0232: s_log.debug("initFromDB: _catalog=" + _catalog
0233: + " _schema=" + _schema + " _tableName="
0234: + _tableName);
0235: }
0236:
0237: TableColumnInfo[] infos = md.getColumnInfo(_catalog, _schema,
0238: _tableName);
0239: for (int i = 0; i < infos.length; i++) {
0240: TableColumnInfo info = infos[i];
0241: String columnName = info.getColumnName();
0242: String columnType = info.getTypeName();
0243: int columnSize = info.getColumnSize();
0244: int decimalDigits = info.getDecimalDigits();
0245: boolean nullable = "YES"
0246: .equalsIgnoreCase(info.isNullable());
0247:
0248: ColumnInfo colInfo = new ColumnInfo(columnName, columnType,
0249: columnSize, decimalDigits, nullable);
0250: colInfosBuf.add(colInfo);
0251:
0252: }
0253:
0254: _colInfos = colInfosBuf.toArray(new ColumnInfo[colInfosBuf
0255: .size()]);
0256:
0257: if (0 == _colInfos.length) {
0258: // Table was deleted from DB
0259: return false;
0260: }
0261:
0262: try {
0263: PrimaryKeyInfo[] pkinfos = md.getPrimaryKey(_catalog,
0264: _schema, _tableName);
0265: for (int i = 0; i < pkinfos.length; i++) {
0266: PrimaryKeyInfo info = pkinfos[i];
0267: for (int c = 0; c < _colInfos.length; c++) {
0268: if (_colInfos[c].getName().equals(
0269: info.getColumnName())) {
0270: _colInfos[c].markPrimaryKey();
0271: }
0272: }
0273: }
0274: } catch (SQLException e) {
0275: s_log.error("Unable to get Primary Key info", e);
0276: }
0277:
0278: ResultSet res = null;
0279: try {
0280: res = metaData.getImportedKeys(_catalog, _schema,
0281: _tableName);
0282: while (res.next()) {
0283: String pkTable = res.getString(3); // PKTABLE_NAME
0284: String pkColName = res.getString(4); // PKCOLUMN_NAME
0285: String fkColName = res.getString(8); // FKCOLUMN_NAME
0286: String fkName = res.getString(12); // FK_NAME
0287:
0288: ColumnInfo colInfo = findColumnInfo(fkColName);
0289: colInfo.setImportData(pkTable, pkColName, fkName);
0290:
0291: ConstraintData constraintData = constaintInfosByConstraintName
0292: .get(fkName);
0293:
0294: if (null == constraintData) {
0295: constraintData = new ConstraintData(pkTable,
0296: _tableName, fkName);
0297: constaintInfosByConstraintName.put(fkName,
0298: constraintData);
0299: }
0300: constraintData.addColumnInfo(colInfo);
0301: }
0302: } catch (SQLException e) {
0303: s_log.error("Unable to get Foriegn Key info", e);
0304: } finally {
0305: if (res != null) {
0306: try {
0307: res.close();
0308: } catch (SQLException e) {
0309: }
0310: }
0311: }
0312:
0313: ConstraintData[] constraintData = constaintInfosByConstraintName
0314: .values().toArray(new ConstraintData[0]);
0315:
0316: Hashtable<String, ConstraintView> oldConstraintViewsByConstraintName = new Hashtable<String, ConstraintView>();
0317:
0318: if (null != _constraintViews) {
0319: _desktopController.removeConstraintViews(_constraintViews,
0320: true);
0321: for (int i = 0; i < _constraintViews.length; i++) {
0322: String constraintName = _constraintViews[i].getData()
0323: .getConstraintName();
0324: oldConstraintViewsByConstraintName.put(constraintName,
0325: _constraintViews[i]);
0326: }
0327: }
0328:
0329: _constraintViews = new ConstraintView[constraintData.length];
0330: for (int i = 0; i < constraintData.length; i++) {
0331: ConstraintView oldCV = oldConstraintViewsByConstraintName
0332: .get(constraintData[i].getConstraintName());
0333:
0334: if (null != oldCV) {
0335: // The old view is preserved to eventually preserve folding points
0336: oldCV.setData(constraintData[i]);
0337: _constraintViews[i] = oldCV;
0338: } else {
0339: _constraintViews[i] = new ConstraintView(
0340: constraintData[i], _desktopController, _session);
0341: }
0342: }
0343:
0344: return true;
0345: }
0346:
0347: private void onZoomEnabled(boolean b) {
0348: if (false == b) {
0349: onHideScrollBars(false);
0350: } else {
0351: onHideScrollBars(_desktopController.getZoomer()
0352: .isHideScrollbars());
0353: }
0354: }
0355:
0356: private void onHideScrollBars(boolean b) {
0357: if (b) {
0358: _frame.scrollPane
0359: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0360: _frame.scrollPane
0361: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
0362: } else {
0363: _frame.scrollPane
0364: .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
0365: _frame.scrollPane
0366: .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
0367: }
0368: }
0369:
0370: private void onZoomChanged(double newZoom, double oldZoom,
0371: boolean adjusting) {
0372: if (null == _adjustBeginBounds) {
0373: _adjustBeginZoom = oldZoom;
0374: _adjustBeginBounds = new Rectangle(_frame.getBounds());
0375: }
0376:
0377: Rectangle bounds = new Rectangle();
0378: bounds.x = (int) (_adjustBeginBounds.x * newZoom
0379: / _adjustBeginZoom + 0.5);
0380: bounds.y = (int) (_adjustBeginBounds.y * newZoom
0381: / _adjustBeginZoom + 0.5);
0382: bounds.width = (int) (_adjustBeginBounds.width * newZoom
0383: / _adjustBeginZoom + 0.5);
0384: bounds.height = (int) (_adjustBeginBounds.height * newZoom
0385: / _adjustBeginZoom + 0.5);
0386: ;
0387: _frame.setBounds(bounds);
0388: recalculateAllConnections();
0389:
0390: if (false == adjusting) {
0391: _adjustBeginZoom = newZoom;
0392: _adjustBeginBounds = null;
0393: }
0394:
0395: }
0396:
0397: private String onGetToolTipText(MouseEvent event) {
0398: ColumnInfo ci = getColumnInfoForPoint(event.getPoint());
0399:
0400: if (null == ci) {
0401: return null;
0402: }
0403:
0404: return ci.getConstraintToolTipText();
0405:
0406: }
0407:
0408: private ColumnInfo getColumnInfoForPoint(Point point) {
0409: FontMetrics fm = _frame.txtColumsFactory.getGraphics()
0410: .getFontMetrics(_frame.txtColumsFactory.getFont());
0411:
0412: int zoomedFontHeight = (int) (fm.getHeight()
0413: * _desktopController.getZoomer().getZoom() + 0.5);
0414: for (int i = 0; i < _colInfos.length; i++) {
0415: int unscrolledHeight = _colInfos[i].getIndex()
0416: * zoomedFontHeight;
0417: if (unscrolledHeight <= point.y
0418: && point.y <= unscrolledHeight + zoomedFontHeight) {
0419: return _colInfos[i];
0420: }
0421: }
0422:
0423: return null;
0424: }
0425:
0426: public TableFrameControllerXmlBean getXmlBean() {
0427: TableFrameControllerXmlBean ret = new TableFrameControllerXmlBean();
0428: ret.setSchema(_schema);
0429: ret.setCatalog(_catalog);
0430: ret.setTablename(_tableName);
0431: ret.setTableFrameXmlBean(_frame.getXmlBean());
0432: ret.setColumOrder(_columnOrder);
0433:
0434: ColumnInfoXmlBean[] colXmlBeans = new ColumnInfoXmlBean[_colInfos.length];
0435: for (int i = 0; i < _colInfos.length; i++) {
0436: colXmlBeans[i] = _colInfos[i].getXmlBean();
0437: }
0438: ret.setColumnIfoXmlBeans(colXmlBeans);
0439:
0440: ConstraintViewXmlBean[] constViewXmlBeans = new ConstraintViewXmlBean[_constraintViews.length];
0441: for (int i = 0; i < _constraintViews.length; i++) {
0442: constViewXmlBeans[i] = _constraintViews[i].getXmlBean();
0443: }
0444: ret.setConstraintViewXmlBeans(constViewXmlBeans);
0445:
0446: ret.setTablesExportedTo(_tablesExportedTo);
0447:
0448: return ret;
0449: }
0450:
0451: private void createPopUp() {
0452: _popUp = new JPopupMenu();
0453:
0454: _mnuAddTableForForeignKey = new JMenuItem();
0455: _mnuAddTableForForeignKey
0456: .addActionListener(new ActionListener() {
0457: public void actionPerformed(ActionEvent e) {
0458: onAddTableForForeignKey((ColumnInfo) _mnuAddTableForForeignKey
0459: .getClientProperty(MNU_PROP_COLUMN_INFO));
0460: }
0461: });
0462:
0463: // i18n[graph.addChildTables=Add child tables]
0464: _mnuAddChildTables = new JMenuItem(s_stringMgr
0465: .getString("graph.addChildTables"));
0466: _mnuAddChildTables.addActionListener(new ActionListener() {
0467: public void actionPerformed(ActionEvent e) {
0468: onAddChildTables();
0469: }
0470: });
0471:
0472: // i18n[graph.addParentTables=Add parent tables]
0473: _mnuAddParentTables = new JMenuItem(s_stringMgr
0474: .getString("graph.addParentTables"));
0475: _mnuAddParentTables.addActionListener(new ActionListener() {
0476: public void actionPerformed(ActionEvent e) {
0477: onAddParentTables();
0478: }
0479: });
0480:
0481: // i18n[graph.addRelTables=Add all related tables]
0482: _mnuAddAllRelatedTables = new JMenuItem(s_stringMgr
0483: .getString("graph.addRelTables"));
0484: _mnuAddAllRelatedTables.addActionListener(new ActionListener() {
0485: public void actionPerformed(ActionEvent e) {
0486: onAddAllRelatedTables();
0487: }
0488: });
0489:
0490: // i18n[graph.refreshTable=Refresh table]
0491: _mnuRefreshTable = new JMenuItem(s_stringMgr
0492: .getString("graph.refreshTable"));
0493: _mnuRefreshTable.addActionListener(new ActionListener() {
0494: public void actionPerformed(ActionEvent e) {
0495: onRefresh();
0496: }
0497: });
0498:
0499: // i18n[graph.scriptTable=Script table]
0500: _mnuScriptTable = new JMenuItem(s_stringMgr
0501: .getString("graph.scriptTable"));
0502: _mnuScriptTable.addActionListener(new ActionListener() {
0503: public void actionPerformed(ActionEvent e) {
0504: onScriptTable();
0505: }
0506: });
0507:
0508: // i18n[graph.viewTableInObjectTree=View table in Object tree]
0509: _mnuViewTableInObjectTree = new JMenuItem(s_stringMgr
0510: .getString("graph.viewTableInObjectTree"));
0511: _mnuViewTableInObjectTree
0512: .addActionListener(new ActionListener() {
0513: public void actionPerformed(ActionEvent e) {
0514: onViewTableInObjectTree();
0515: }
0516: });
0517:
0518: // i18n[graph.dbOrder=db order]
0519: _mnuDbOrder = new JCheckBoxMenuItem(s_stringMgr
0520: .getString("graph.dbOrder"));
0521: _mnuDbOrder.addActionListener(new ActionListener() {
0522: public void actionPerformed(ActionEvent e) {
0523: onDBOrder();
0524: }
0525: });
0526:
0527: // i18n[graph.orderyName=order by name]
0528: _mnuOrderByName = new JCheckBoxMenuItem(s_stringMgr
0529: .getString("graph.orderyName"));
0530: _mnuOrderByName.addActionListener(new ActionListener() {
0531: public void actionPerformed(ActionEvent e) {
0532: onNameOrder();
0533: }
0534: });
0535:
0536: // i18n[graph.orderPksConstr=order PKs/constraints on top]
0537: _mnuPksAndConstraintsOnTop = new JCheckBoxMenuItem(s_stringMgr
0538: .getString("graph.orderPksConstr"));
0539: _mnuPksAndConstraintsOnTop
0540: .addActionListener(new ActionListener() {
0541: public void actionPerformed(ActionEvent e) {
0542: onPkConstraintOrder();
0543: }
0544: });
0545:
0546: // i18n[graph.close=close]
0547: _mnuClose = new JMenuItem(s_stringMgr.getString("graph.close"));
0548: _mnuClose.addActionListener(new ActionListener() {
0549: public void actionPerformed(ActionEvent e) {
0550: onClose();
0551: _frame.setVisible(false);
0552: _frame.dispose();
0553: }
0554: });
0555:
0556: _popUp.add(_mnuAddTableForForeignKey);
0557: _popUp.add(_mnuAddChildTables);
0558: _popUp.add(_mnuAddParentTables);
0559: _popUp.add(_mnuAddAllRelatedTables);
0560: _popUp.add(new JSeparator());
0561: _popUp.add(_mnuRefreshTable);
0562: _popUp.add(_mnuScriptTable);
0563: _popUp.add(_mnuViewTableInObjectTree);
0564: _popUp.add(new JSeparator());
0565: _popUp.add(_mnuDbOrder);
0566: _popUp.add(_mnuOrderByName);
0567: _popUp.add(_mnuPksAndConstraintsOnTop);
0568: _popUp.add(new JSeparator());
0569: _popUp.add(_mnuClose);
0570:
0571: _frame.txtColumsFactory.addMouseListener(new MouseAdapter() {
0572: public void mousePressed(MouseEvent e) {
0573: maybeShowPopup(e);
0574: }
0575:
0576: public void mouseReleased(MouseEvent e) {
0577: maybeShowPopup(e);
0578: }
0579: });
0580:
0581: }
0582:
0583: private void onViewTableInObjectTree() {
0584: new ObjectTreeSearch().viewObjectInObjectTree(getTableInfo()
0585: .getQualifiedName(), _session);
0586: }
0587:
0588: private void onScriptTable() {
0589: SqlScriptAcessor.scriptTablesToSQLEntryArea(_session,
0590: new ITableInfo[] { getTableInfo() });
0591: }
0592:
0593: ITableInfo getTableInfo() {
0594: return _session.getSchemaInfo().getITableInfos(_catalog,
0595: _schema, _tableName, new String[] { "TABLE" })[0];
0596: }
0597:
0598: private void onRefresh() {
0599: refresh();
0600: }
0601:
0602: void refresh() {
0603: try {
0604: if (initFromDB()) {
0605: orderColumns();
0606: recalculateAllConnections();
0607: _desktopController.repaint();
0608: } else {
0609: onClose();
0610: _frame.setVisible(false);
0611: _frame.dispose();
0612: }
0613: } catch (SQLException e) {
0614: throw new RuntimeException(e);
0615: }
0616: }
0617:
0618: private void onAddTableForForeignKey(ColumnInfo columnInfo) {
0619: _addTablelListener.addTablesRequest(new String[] { columnInfo
0620: .getImportedTableName() }, _schema, _catalog);
0621: }
0622:
0623: private void onPkConstraintOrder() {
0624: _columnOrder = ORDER_PK_CONSTRAINT;
0625: orderColumns();
0626: SwingUtilities.invokeLater(new Runnable() {
0627: public void run() {
0628: recalculateAllConnections();
0629: fireSortListeners();
0630: }
0631: });
0632: }
0633:
0634: private void onNameOrder() {
0635: _columnOrder = ORDER_NAME;
0636: orderColumns();
0637: SwingUtilities.invokeLater(new Runnable() {
0638: public void run() {
0639: recalculateAllConnections();
0640: fireSortListeners();
0641: }
0642: });
0643: }
0644:
0645: private void onDBOrder() {
0646: _columnOrder = ORDER_DB;
0647: orderColumns();
0648: SwingUtilities.invokeLater(new Runnable() {
0649: public void run() {
0650: recalculateAllConnections();
0651: fireSortListeners();
0652: }
0653: });
0654: }
0655:
0656: private void fireSortListeners() {
0657: ColumnSortListener[] listeners = _mySortListeners
0658: .toArray(new ColumnSortListener[_mySortListeners.size()]);
0659:
0660: for (int i = 0; i < listeners.length; i++) {
0661: listeners[i].columnOrderChanged();
0662: }
0663: }
0664:
0665: private void orderColumns() {
0666: Comparator<ColumnInfo> comp;
0667:
0668: switch (_columnOrder) {
0669: case ORDER_DB:
0670: _orderedColumnInfos = _colInfos;
0671: _mnuDbOrder.setSelected(true);
0672: _mnuOrderByName.setSelected(false);
0673: _mnuPksAndConstraintsOnTop.setSelected(false);
0674: break;
0675: case ORDER_NAME:
0676: _orderedColumnInfos = new ColumnInfo[_colInfos.length];
0677: System.arraycopy(_colInfos, 0, _orderedColumnInfos, 0,
0678: _colInfos.length);
0679:
0680: comp = new Comparator<ColumnInfo>() {
0681: public int compare(ColumnInfo c1, ColumnInfo c2) {
0682: return c1.getName().compareTo(c2.getName());
0683: }
0684: };
0685: Arrays.sort(_orderedColumnInfos, comp);
0686:
0687: _mnuDbOrder.setSelected(false);
0688: _mnuOrderByName.setSelected(true);
0689: _mnuPksAndConstraintsOnTop.setSelected(false);
0690: break;
0691: case ORDER_PK_CONSTRAINT:
0692: _orderedColumnInfos = new ColumnInfo[_colInfos.length];
0693: System.arraycopy(_colInfos, 0, _orderedColumnInfos, 0,
0694: _colInfos.length);
0695:
0696: comp = new Comparator<ColumnInfo>() {
0697: public int compare(ColumnInfo c1, ColumnInfo c2) {
0698: if (c1.isPrimaryKey() && false == c2.isPrimaryKey()) {
0699: return -1;
0700: } else if (false == c1.isPrimaryKey()
0701: && c2.isPrimaryKey()) {
0702: return 1;
0703: } else {
0704: if (null != c1.getConstraintName()
0705: && null == c2.getConstraintName()) {
0706: return -1;
0707: } else if (null == c1.getConstraintName()
0708: && null != c2.getConstraintName()) {
0709: return 1;
0710: } else {
0711: if (null != c1.getConstraintName()
0712: && null != c2.getConstraintName()) {
0713: String s1 = c1.getConstraintName()
0714: + "_" + c1.getName();
0715: String s2 = c2.getConstraintName()
0716: + "_" + c2.getName();
0717: return s1.compareTo(s2);
0718: } else {
0719: return c1.getName().compareTo(
0720: c2.getName());
0721: }
0722: }
0723: }
0724: }
0725: };
0726: Arrays.sort(_orderedColumnInfos, comp);
0727:
0728: _mnuDbOrder.setSelected(false);
0729: _mnuOrderByName.setSelected(false);
0730: _mnuPksAndConstraintsOnTop.setSelected(true);
0731: break;
0732: default:
0733: throw new IllegalStateException("Unknown order "
0734: + _columnOrder);
0735: }
0736:
0737: _frame.txtColumsFactory.setColumns(_orderedColumnInfos);
0738:
0739: SwingUtilities.invokeLater(new Runnable() {
0740: public void run() {
0741: JComponent bestReadyComponent = _frame.txtColumsFactory
0742: .getBestReadyComponent();
0743: if (null != bestReadyComponent) {
0744: _frame.txtColumsFactory.getBestReadyComponent()
0745: .scrollRectToVisible(
0746: new Rectangle(0, 0, 1, 1));
0747: }
0748: }
0749: });
0750: }
0751:
0752: private void onAddAllRelatedTables() {
0753: onAddChildTables();
0754: onAddParentTables();
0755: }
0756:
0757: private void onAddChildTables() {
0758: try {
0759: DatabaseMetaData metaData = _session.getSQLConnection()
0760: .getConnection().getMetaData();
0761:
0762: if (null == _tablesExportedTo) {
0763: Hashtable<String, String> exportBuf = new Hashtable<String, String>();
0764: ResultSet res = metaData.getExportedKeys(_catalog,
0765: _schema, _tableName);
0766: while (res.next()) {
0767: String tableName = res.getString("FKTABLE_NAME");
0768: exportBuf.put(tableName, tableName);
0769: }
0770: _tablesExportedTo = exportBuf.keySet().toArray(
0771: new String[0]);
0772: }
0773: _addTablelListener.addTablesRequest(_tablesExportedTo,
0774: _schema, _catalog);
0775:
0776: } catch (SQLException e) {
0777: throw new RuntimeException(e);
0778: }
0779: }
0780:
0781: private void onAddParentTables() {
0782: List<String> tablesToAdd = new ArrayList<String>();
0783:
0784: for (int i = 0; i < _constraintViews.length; i++) {
0785: tablesToAdd.add(_constraintViews[i].getData()
0786: .getPkTableName());
0787: }
0788:
0789: _addTablelListener.addTablesRequest(tablesToAdd
0790: .toArray(new String[tablesToAdd.size()]), _schema,
0791: _catalog);
0792: }
0793:
0794: private void maybeShowPopup(MouseEvent e) {
0795: if (e.isPopupTrigger()) {
0796:
0797: ColumnInfo ci = getColumnInfoForPoint(e.getPoint());
0798: if (null == ci || null == ci.getImportedTableName()) {
0799: _mnuAddTableForForeignKey.setEnabled(false);
0800: // i18n[graph.addTableRefByNoHit=add table referenced by (no hit on FK)]
0801: _mnuAddTableForForeignKey.setText(s_stringMgr
0802: .getString("graph.addTableRefByNoHit"));
0803: } else {
0804: _mnuAddTableForForeignKey.setEnabled(true);
0805: // i18n[graph.addTableRefBy=add table referenced by {0}]
0806: _mnuAddTableForForeignKey
0807: .setText(s_stringMgr.getString(
0808: "graph.addTableRefBy", ci.getName()));
0809: _mnuAddTableForForeignKey.putClientProperty(
0810: MNU_PROP_COLUMN_INFO, ci);
0811: }
0812:
0813: _popUp.show(e.getComponent(), e.getX(), e.getY());
0814: } else if (2 == e.getClickCount()
0815: && e.getID() == MouseEvent.MOUSE_PRESSED) {
0816: ColumnInfo ci = getColumnInfoForPoint(e.getPoint());
0817: if (null != ci && null != ci.getImportedTableName()) {
0818: _addTablelListener.addTablesRequest(new String[] { ci
0819: .getImportedTableName() }, _schema, _catalog);
0820: }
0821: }
0822:
0823: }
0824:
0825: void initAfterAddedToDesktop(TableFrameController[] openFrames,
0826: boolean resetBounds) {
0827: calculateStartSize();
0828: for (int i = 0; i < openFrames.length; i++) {
0829: tableFrameOpen(openFrames[i]);
0830: }
0831:
0832: if (resetBounds) {
0833: _frame.setBounds(_startSize);
0834: }
0835: _frame.setVisible(true);
0836:
0837: _frame.txtColumsFactory.getBestReadyComponent()
0838: .scrollRectToVisible(new Rectangle(0, 0, 1, 1));
0839: }
0840:
0841: private void onClose() {
0842: _desktopController.removeConstraintViews(_constraintViews,
0843: false);
0844: _desktopController.getZoomer().removeZoomListener(
0845: _zoomerListener);
0846:
0847: for (int i = 0; i < _listeners.size(); i++) {
0848: TableFrameControllerListener tableFrameControllerListener = _listeners
0849: .elementAt(i);
0850: tableFrameControllerListener.closed(this );
0851: }
0852:
0853: for (TableFrameController tfc : _compListenersToOtherFramesByFrameCtrlr
0854: .keySet()) {
0855: ComponentAdapter listenerToRemove = _compListenersToOtherFramesByFrameCtrlr
0856: .get(tfc);
0857: tfc._frame.removeComponentListener(listenerToRemove);
0858: }
0859:
0860: for (TableFrameController tfc : _scrollListenersToOtherFramesByFrameCtrlr
0861: .keySet()) {
0862: AdjustmentListener listenerToRemove = _scrollListenersToOtherFramesByFrameCtrlr
0863: .get(tfc);
0864: tfc._frame.scrollPane.getVerticalScrollBar()
0865: .removeAdjustmentListener(listenerToRemove);
0866: }
0867:
0868: }
0869:
0870: void tableFrameOpen(final TableFrameController tfc) {
0871: if (_openFramesConnectedToMe.contains(tfc)) {
0872: return;
0873: }
0874:
0875: if (false == recalculateConnectionsTo(tfc)) {
0876: return;
0877: }
0878:
0879: _openFramesConnectedToMe.add(tfc);
0880:
0881: ComponentAdapter compListener = new ComponentAdapter() {
0882: public void componentMoved(ComponentEvent e) {
0883: recalculateConnectionsTo(tfc);
0884: }
0885:
0886: public void componentResized(ComponentEvent e) {
0887: recalculateConnectionsTo(tfc);
0888: }
0889:
0890: public void componentShown(ComponentEvent e) {
0891: recalculateConnectionsTo(tfc);
0892: }
0893: };
0894:
0895: _compListenersToOtherFramesByFrameCtrlr.put(tfc, compListener);
0896: tfc._frame.addComponentListener(compListener);
0897:
0898: AdjustmentListener adjListener = new AdjustmentListener() {
0899: public void adjustmentValueChanged(AdjustmentEvent e) {
0900: recalculateConnectionsTo(tfc);
0901: }
0902: };
0903: tfc._frame.scrollPane.getVerticalScrollBar()
0904: .addAdjustmentListener(adjListener);
0905: _scrollListenersToOtherFramesByFrameCtrlr.put(tfc, adjListener);
0906:
0907: ColumnSortListener sortListener = new ColumnSortListener() {
0908: public void columnOrderChanged() {
0909: recalculateConnectionsTo(tfc);
0910: }
0911: };
0912:
0913: tfc.addSortListener(sortListener);
0914: _columnSortListenersToOtherFramesByFrameCtrlr.put(tfc,
0915: sortListener);
0916:
0917: }
0918:
0919: private void addSortListener(ColumnSortListener sortListener) {
0920: _mySortListeners.add(sortListener);
0921: }
0922:
0923: private void removeSortListener(ColumnSortListener sortListener) {
0924: _mySortListeners.remove(sortListener);
0925: }
0926:
0927: private void recalculateAllConnections() {
0928: for (int i = 0; i < _openFramesConnectedToMe.size(); i++) {
0929: TableFrameController tableFrameController = _openFramesConnectedToMe
0930: .elementAt(i);
0931: recalculateConnectionsTo(tableFrameController);
0932: }
0933: }
0934:
0935: public void tableFrameRemoved(TableFrameController tfc) {
0936: _openFramesConnectedToMe.remove(tfc);
0937:
0938: List<ConstraintView> constraintDataToRemove = new ArrayList<ConstraintView>();
0939: List<ConstraintView> newConstraintData = new ArrayList<ConstraintView>();
0940:
0941: for (int i = 0; i < _constraintViews.length; i++) {
0942: if (_constraintViews[i].getData().getPkTableName().equals(
0943: tfc._tableName)) {
0944: constraintDataToRemove.add(_constraintViews[i]);
0945: } else {
0946: newConstraintData.add(_constraintViews[i]);
0947: }
0948: }
0949:
0950: ComponentAdapter compListenerToRemove = _compListenersToOtherFramesByFrameCtrlr
0951: .remove(tfc);
0952: if (null != compListenerToRemove) {
0953: tfc._frame.removeComponentListener(compListenerToRemove);
0954: }
0955:
0956: AdjustmentListener adjListenerToRemove = _scrollListenersToOtherFramesByFrameCtrlr
0957: .remove(tfc);
0958: if (null != adjListenerToRemove) {
0959: tfc._frame.scrollPane.getVerticalScrollBar()
0960: .removeAdjustmentListener(adjListenerToRemove);
0961: }
0962:
0963: ColumnSortListener columnSortListener = _columnSortListenersToOtherFramesByFrameCtrlr
0964: .get(tfc);
0965: if (null != columnSortListener) {
0966: tfc.removeSortListener(columnSortListener);
0967: }
0968:
0969: ConstraintView[] buf = constraintDataToRemove
0970: .toArray(new ConstraintView[constraintDataToRemove
0971: .size()]);
0972: _desktopController.removeConstraintViews(buf, false);
0973: }
0974:
0975: private boolean recalculateConnectionsTo(TableFrameController other) {
0976: ConstraintView[] constraintView = findConstraintViews(other._tableName);
0977:
0978: if (0 == constraintView.length) {
0979: return false;
0980: }
0981:
0982: for (int i = 0; i < constraintView.length; i++) {
0983: ColumnInfo[] colInfos = constraintView[i].getData()
0984: .getColumnInfos();
0985:
0986: FoldingPoint firstFoldingPoint = constraintView[i]
0987: .getFirstFoldingPoint();
0988: FoldingPoint lastFoldingPoint = constraintView[i]
0989: .getLastFoldingPoint();
0990:
0991: ConnectionPoints fkPoints = getConnectionPoints(colInfos,
0992: this , other, firstFoldingPoint);
0993:
0994: ColumnInfo[] othersColInfos = new ColumnInfo[colInfos.length];
0995: for (int j = 0; j < othersColInfos.length; j++) {
0996: othersColInfos[j] = other.findColumnInfo(colInfos[j]
0997: .getImportedColumnName());
0998: }
0999:
1000: ConnectionPoints pkPoints = getConnectionPoints(
1001: othersColInfos, other, this , lastFoldingPoint);
1002:
1003: constraintView[i].setConnectionPoints(fkPoints, pkPoints,
1004: other, _constraintViewListener);
1005: }
1006:
1007: _desktopController.putConstraintViews(constraintView);
1008: _desktopController.repaint();
1009:
1010: return true;
1011:
1012: }
1013:
1014: private void onFoldingPointMoved(ConstraintView source) {
1015: recalculateConnectionsTo(source.getPkFramePointingTo());
1016: }
1017:
1018: private static ConnectionPoints getConnectionPoints(
1019: ColumnInfo[] colInfos, TableFrameController me,
1020: TableFrameController other, FoldingPoint myNextFoldingPoint) {
1021: int[] relPointHeights = me
1022: .calculateRelativeConnectionPointHeights(colInfos);
1023:
1024: Rectangle myBounds = me._frame.getBounds();
1025: Rectangle othersBounds = other._frame.getBounds();
1026:
1027: ConnectionPoints ret = new ConnectionPoints();
1028: ret.points = new Point[relPointHeights.length];
1029:
1030: for (int i = 0; i < ret.points.length; i++) {
1031:
1032: if (null == myNextFoldingPoint) {
1033: if (myBounds.x + myBounds.width * 3 / 4 < othersBounds.x) {
1034: ret.points[i] = new Point(myBounds.x
1035: + myBounds.width, myBounds.y
1036: + relPointHeights[i]);
1037: ret.pointsAreLeftOfWindow = false;
1038: } else {
1039: ret.points[i] = new Point(myBounds.x, myBounds.y
1040: + relPointHeights[i]);
1041: ret.pointsAreLeftOfWindow = true;
1042: }
1043: } else {
1044: if (myBounds.x + myBounds.width / 2 < myNextFoldingPoint
1045: .getZoomedPoint().x) {
1046: ret.points[i] = new Point(myBounds.x
1047: + myBounds.width, myBounds.y
1048: + relPointHeights[i]);
1049: ret.pointsAreLeftOfWindow = false;
1050: } else {
1051: ret.points[i] = new Point(myBounds.x, myBounds.y
1052: + relPointHeights[i]);
1053: ret.pointsAreLeftOfWindow = true;
1054: }
1055: }
1056: }
1057: return ret;
1058: }
1059:
1060: private ConstraintView[] findConstraintViews(String tableName) {
1061: List<ConstraintView> ret = new ArrayList<ConstraintView>();
1062: for (int i = 0; i < _constraintViews.length; i++) {
1063: if (_constraintViews[i].getData().getPkTableName().equals(
1064: tableName)) {
1065: ret.add(_constraintViews[i]);
1066: }
1067: }
1068: return ret.toArray(new ConstraintView[ret.size()]);
1069: }
1070:
1071: private int[] calculateRelativeConnectionPointHeights(
1072: ColumnInfo[] colInfos) {
1073: Hashtable<Integer, Integer> buf = new Hashtable<Integer, Integer>();
1074: FontMetrics fm = _frame.txtColumsFactory.getGraphics()
1075: .getFontMetrics(_frame.txtColumsFactory.getFont());
1076:
1077: for (int i = 0; i < colInfos.length; i++) {
1078: double zoom = _desktopController.getZoomer().getZoom();
1079:
1080: int unscrolledHeight = (int) ((colInfos[i].getIndex()
1081: * fm.getHeight() + fm.getHeight() / 2)
1082: * zoom + 0.5);
1083: int scrolledHeight;
1084: Rectangle viewRect = _frame.scrollPane.getViewport()
1085: .getViewRect();
1086:
1087: scrolledHeight = unscrolledHeight - viewRect.y;
1088: if (scrolledHeight < 0) {
1089: scrolledHeight = 0;
1090: }
1091: if (scrolledHeight > viewRect.height) {
1092: scrolledHeight = viewRect.height;
1093: }
1094:
1095: scrolledHeight += +_frame.getTitlePane().getSize().height + 2;// + 6;
1096:
1097: buf.put(Integer.valueOf(scrolledHeight), Integer
1098: .valueOf(scrolledHeight));
1099: }
1100:
1101: int[] ret = new int[buf.size()];
1102:
1103: int i = 0;
1104: for (Integer key : buf.keySet()) {
1105: ret[i++] = key.intValue();
1106: }
1107: return ret;
1108: }
1109:
1110: private ColumnInfo findColumnInfo(String colName) {
1111: for (int i = 0; i < _colInfos.length; i++) {
1112: if (_colInfos[i].getName().equals(colName)) {
1113: return _colInfos[i];
1114: }
1115: }
1116:
1117: throw new IllegalArgumentException("Column " + colName
1118: + " not found");
1119: }
1120:
1121: private void calculateStartSize() {
1122: int maxViewingCols = 15;
1123:
1124: FontMetrics fm = _frame.txtColumsFactory.getGraphics()
1125: .getFontMetrics(_frame.txtColumsFactory.getFont());
1126: int width = getMaxSize(_colInfos, fm) + 30;
1127: int height = Math.min(_colInfos.length, maxViewingCols)
1128: * (fm.getHeight()) + 47;
1129: _startSize = new Rectangle(width, height);
1130: }
1131:
1132: private int getMaxSize(ColumnInfo[] infos, FontMetrics fontMetrics) {
1133: int maxSize = 0;
1134: for (int i = 0; i < infos.length; i++) {
1135: int buf = fontMetrics.stringWidth(infos[i].toString());
1136: if (maxSize < buf) {
1137: maxSize = buf;
1138: }
1139: }
1140: return maxSize;
1141:
1142: }
1143:
1144: TableFrame getFrame() {
1145: return _frame;
1146: }
1147:
1148: public void addTableFrameControllerListener(
1149: TableFrameControllerListener l) {
1150: _listeners.add(l);
1151: }
1152:
1153: public boolean equals(Object obj) {
1154: if (obj instanceof TableFrameController) {
1155: TableFrameController other = (TableFrameController) obj;
1156:
1157: return other._tableName.equals(_tableName);
1158: } else {
1159: return false;
1160: }
1161:
1162: }
1163:
1164: public int hashCode() {
1165: return _tableName.hashCode();
1166: }
1167:
1168: }
|