001: package org.dbbrowser.ui;
002:
003: import infrastructure.internationalization.InternationalizationManager;
004: import infrastructure.logging.Log;
005: import infrastructure.propertymanager.PropertyManager;
006: import java.awt.GridLayout;
007: import java.awt.event.ActionEvent;
008: import java.awt.event.ActionListener;
009: import java.awt.event.WindowListener;
010: import java.util.*;
011: import javax.swing.BorderFactory;
012: import javax.swing.BoxLayout;
013: import javax.swing.Icon;
014: import javax.swing.ImageIcon;
015: import javax.swing.JDialog;
016: import javax.swing.JLabel;
017: import javax.swing.JOptionPane;
018: import javax.swing.JPanel;
019: import javax.swing.JScrollPane;
020: import javax.swing.JTextField;
021: import javax.swing.SwingUtilities;
022: import javax.swing.event.DocumentEvent;
023: import javax.swing.event.DocumentListener;
024: import org.dbbrowser.db.engine.exception.DBEngineException;
025: import org.dbbrowser.db.engine.model.ColumnInfo;
026: import org.dbbrowser.db.engine.model.DBRow;
027: import org.dbbrowser.db.engine.model.DBTable;
028: import org.dbbrowser.db.engine.model.DBTableCell;
029: import org.dbbrowser.ui.panel.ButtonsPanel;
030: import org.dbbrowser.ui.widget.Button;
031: import org.dbbrowser.ui.helper.DBTableCellComparator;
032:
033: public class ViewRecordWindow implements ActionListener {
034: private static final long serialVersionUID = UIControllerForQueries.version;
035:
036: private static final String TITLE = InternationalizationManager
037: .getInstance().getMessage("dbbrowser-ui",
038: "dbbrowser-ui-dbbrowser-window-title-label", null);;
039:
040: private String firstRecordNavigationButtonLabel = InternationalizationManager
041: .getInstance()
042: .getMessage(
043: "dbbrowser-ui",
044: "dbbrowser-ui-dbbrowser-browser-view-record-window-navigate-first-button-label",
045: null);
046: private String previousRecordNavigationButtonLabel = InternationalizationManager
047: .getInstance()
048: .getMessage(
049: "dbbrowser-ui",
050: "dbbrowser-ui-dbbrowser-browser-view-record-window-navigate-previous-button-label",
051: null);
052: private String nextRecordNavigationButtonLabel = InternationalizationManager
053: .getInstance()
054: .getMessage(
055: "dbbrowser-ui",
056: "dbbrowser-ui-dbbrowser-browser-view-record-window-navigate-next-button-label",
057: null);
058: private String lastRecordNavigationButtonLabel = InternationalizationManager
059: .getInstance()
060: .getMessage(
061: "dbbrowser-ui",
062: "dbbrowser-ui-dbbrowser-browser-view-record-window-navigate-last-button-label",
063: null);
064: private String UPDATE_BUTTON_LABEL = InternationalizationManager
065: .getInstance()
066: .getMessage(
067: "dbbrowser-ui",
068: "dbbrowser-ui-dbbrowser-browser-view-record-window-update-button-label",
069: null);
070: private String COMMIT_BUTTON_LABEL = InternationalizationManager
071: .getInstance()
072: .getMessage(
073: "dbbrowser-ui",
074: "dbbrowser-ui-dbbrowser-browser-view-record-window-commit-button-label",
075: null);
076: private String ROLLBACK_BUTTON_LABEL = InternationalizationManager
077: .getInstance()
078: .getMessage(
079: "dbbrowser-ui",
080: "dbbrowser-ui-dbbrowser-browser-view-record-window-rollback-button-label",
081: null);
082:
083: private String firstRecordIconFileName = PropertyManager
084: .getInstance()
085: .getProperty(
086: "dbbrowser-ui-view-record-window-first-record-icon");
087: private String lastRecordIconFileName = PropertyManager
088: .getInstance().getProperty(
089: "dbbrowser-ui-view-record-window-last-record-icon");
090: private String previousRecordIconFileName = PropertyManager
091: .getInstance()
092: .getProperty(
093: "dbbrowser-ui-view-record-window-previous-record-icon");
094: private String nextRecordIconFileName = PropertyManager
095: .getInstance().getProperty(
096: "dbbrowser-ui-view-record-window-next-record-icon");
097:
098: private Icon iconForFirstRecordButton = new ImageIcon(
099: firstRecordIconFileName);
100: private Icon iconForLastRecordButton = new ImageIcon(
101: lastRecordIconFileName);
102: private Icon iconForPreviousRecordButton = new ImageIcon(
103: previousRecordIconFileName);
104: private Icon iconForNextRecordButton = new ImageIcon(
105: nextRecordIconFileName);
106:
107: private static final String UPDATE_RECORD_ICON_FILENAME = PropertyManager
108: .getInstance()
109: .getProperty(
110: "dbbrowser-ui-view-record-window-update-record-icon");
111: private static final String COMMIT_BUTTON_ICON_FILENAME = PropertyManager
112: .getInstance()
113: .getProperty(
114: "dbbrowser-ui-dbbrowser-window-sql-tab-commit-button-icon");
115: private static final String ROLLBACK_BUTTON_ICON_FILENAME = PropertyManager
116: .getInstance()
117: .getProperty(
118: "dbbrowser-ui-dbbrowser-window-sql-tab-rollback-button-icon");
119:
120: private JPanel mainPanel = new JPanel();
121: private JDialog dialog = null;
122: private UIControllerForUpdates uiControllerForUpdates = null;
123: private DBTable dbTable = null;
124: private int counterForRowNumber = 0;
125: private WindowListener listenerForWindowClosing = null;
126: private JPanel panelForData = new JPanel();
127: private JPanel panelForScrollPane = new JPanel();
128: private ButtonsPanel navigationButonsPanel = null;
129: private ButtonsPanel updateButtonPanel = null;
130: private Map mapOfTextFieldsToOriginalValue = null;
131: private List listOfTextFieldsWhichHaveChanged = null;
132:
133: public ViewRecordWindow(
134: UIControllerForUpdates uiControllerForUpdates,
135: DBTable dbTable, Integer rowNumber) {
136: this .uiControllerForUpdates = uiControllerForUpdates;
137: this .dbTable = dbTable;
138: this .counterForRowNumber = rowNumber.intValue();
139: initialize();
140: }
141:
142: private void initialize() {
143: //Setup the dialog
144: this .dialog = new JDialog();
145: this .dialog.setTitle(TITLE);
146: this .dialog.setModal(true);
147:
148: //Setup the main panel
149: panelForScrollPane.setLayout(new BoxLayout(
150: this .panelForScrollPane, BoxLayout.PAGE_AXIS));
151: this .mainPanel.setLayout(new BoxLayout(this .mainPanel,
152: BoxLayout.PAGE_AXIS));
153: JScrollPane pane = new JScrollPane(this .panelForData);
154: this .panelForScrollPane.add(pane);
155: this .mainPanel.add(this .panelForScrollPane);
156:
157: //Setup the frame
158: this .dialog.setSize(700, 500);
159: this .dialog.setLocationRelativeTo(null);
160: this .dialog.getContentPane().add(this .mainPanel);
161:
162: //Refresh the table
163: refresh();
164:
165: //Build the list of buttons for the navigation buttons panel
166: List listOfNavigationButtons = new ArrayList();
167: Button firstRecordButton = new Button(
168: firstRecordNavigationButtonLabel, this ,
169: firstRecordNavigationButtonLabel,
170: this .iconForFirstRecordButton, Boolean.FALSE);
171: listOfNavigationButtons.add(firstRecordButton);
172: Button previousRecordButton = new Button(
173: previousRecordNavigationButtonLabel, this ,
174: previousRecordNavigationButtonLabel,
175: this .iconForPreviousRecordButton, Boolean.FALSE);
176: listOfNavigationButtons.add(previousRecordButton);
177: Button nextRecordButton = new Button(
178: nextRecordNavigationButtonLabel, this ,
179: nextRecordNavigationButtonLabel,
180: this .iconForNextRecordButton, Boolean.TRUE);
181: listOfNavigationButtons.add(nextRecordButton);
182: Button lastRecordButton = new Button(
183: lastRecordNavigationButtonLabel, this ,
184: lastRecordNavigationButtonLabel,
185: this .iconForLastRecordButton, Boolean.FALSE);
186: listOfNavigationButtons.add(lastRecordButton);
187:
188: //Setup the navigation panel
189: navigationButonsPanel = new ButtonsPanel(
190: listOfNavigationButtons);
191: this .mainPanel.add(navigationButonsPanel);
192:
193: //Setup the panel for the update button if the uiControllerForUpdates is not null
194: if (this .uiControllerForUpdates != null) {
195: List listOfButtonsInUpdatePanel = new ArrayList();
196: Button updateButton = new Button(UPDATE_BUTTON_LABEL, this ,
197: UPDATE_BUTTON_LABEL, new ImageIcon(
198: UPDATE_RECORD_ICON_FILENAME), Boolean.FALSE);
199: listOfButtonsInUpdatePanel.add(updateButton);
200: Button commitButton = new Button(COMMIT_BUTTON_LABEL, this ,
201: COMMIT_BUTTON_LABEL, new ImageIcon(
202: COMMIT_BUTTON_ICON_FILENAME), Boolean.FALSE);
203: listOfButtonsInUpdatePanel.add(commitButton);
204: Button rollbackButton = new Button(ROLLBACK_BUTTON_LABEL,
205: this , ROLLBACK_BUTTON_LABEL, new ImageIcon(
206: ROLLBACK_BUTTON_ICON_FILENAME),
207: Boolean.FALSE);
208: listOfButtonsInUpdatePanel.add(rollbackButton);
209:
210: this .updateButtonPanel = new ButtonsPanel(
211: listOfButtonsInUpdatePanel);
212:
213: //If autocommit is on, disable all buttons
214: String autoCommitFlag = PropertyManager.getInstance()
215: .getProperty("dbbrowser-auto-commit");
216: if ("true".equals(autoCommitFlag)) {
217: //Disable the commit and rollback buttons
218: updateButtonPanel.enableButton(COMMIT_BUTTON_LABEL,
219: Boolean.FALSE);
220: updateButtonPanel.enableButton(ROLLBACK_BUTTON_LABEL,
221: Boolean.FALSE);
222: }
223:
224: //Add the buttons to the main panel
225: this .mainPanel.add(this .updateButtonPanel);
226: }
227: }
228:
229: private void refresh() {
230: //Get the selected row
231: DBRow dbRow = (DBRow) this .dbTable.getListOfRows().get(
232: this .counterForRowNumber);
233:
234: //Get the selected table cells
235: List listOfTableCells = dbRow.getListOFDBTableCells();
236:
237: //Get the internationalized string for displaying 'Record 1 of 20'
238: Integer[] values = new Integer[] {
239: new Integer(counterForRowNumber + 1),
240: new Integer(this .dbTable.getListOfRows().size()) };
241: String message = InternationalizationManager
242: .getInstance()
243: .getMessage(
244: "dbbrowser-ui",
245: "dbbrowser-ui-dbbrowser-browser-view-record-window-records-panel-title",
246: values);
247:
248: //if the table name is not null, show it in the title
249: if (this .dbTable.getTableName() != null) {
250: message = this .dbTable.getTableName() + " : " + message;
251: }
252:
253: this .panelForScrollPane.setBorder(BorderFactory
254: .createTitledBorder(message));
255:
256: //Remove all componenets from the panel
257: this .panelForData.removeAll();
258:
259: //Build a new map
260: this .mapOfTextFieldsToOriginalValue = new HashMap();
261: this .listOfTextFieldsWhichHaveChanged = new ArrayList();
262:
263: //if sorting enabled, sort the data in table and sort the columns
264: String sortColumnsFlag = PropertyManager.getInstance()
265: .getProperty("dbbrowser-ui-sort-columns-in-table");
266: if ("true".equals(sortColumnsFlag)) {
267: Collections.sort(listOfTableCells,
268: new DBTableCellComparator());
269: }
270:
271: //Iterate through the list of table cells
272: Iterator i = listOfTableCells.iterator();
273: while (i.hasNext()) {
274: DBTableCell dbTableCell = (DBTableCell) i.next();
275: ColumnInfo columnInfo = dbTableCell.getColumnInfo();
276: String formattedValue = dbTableCell.getFormattedValue();
277: String labelText = "";
278: JTextField textFieldForData = null;
279:
280: //if it is a primary key column or it is not editable, disable it
281: if (columnInfo.isPrimaryKeyColumn().booleanValue()
282: || (!columnInfo.isEditable().booleanValue())) {
283: //if it is a primary key column, append the (PK) label to the end
284: if (columnInfo.isPrimaryKeyColumn().booleanValue()) {
285: labelText = columnInfo.getColumnName() + "(PK)";
286: } else {
287: labelText = columnInfo.getColumnName();
288: }
289: textFieldForData = new JTextField(20);
290: textFieldForData.setText(formattedValue);
291: textFieldForData.setEnabled(false);
292: } else {
293: //If it is not a primary key column, show the name of column
294: labelText = columnInfo.getColumnName();
295: textFieldForData = new JTextField(20);
296: textFieldForData.setText(formattedValue);
297:
298: //Add the listener to detect changes
299: textFieldForData
300: .getDocument()
301: .addDocumentListener(
302: new DocumentListenerForDetectingChangeInTextField(
303: textFieldForData));
304:
305: //Add the textfield to the map
306: this .mapOfTextFieldsToOriginalValue.put(
307: textFieldForData, dbTableCell);
308: }
309: JLabel labelForData = new JLabel(labelText);
310:
311: JLabel labelForDataType = null;
312: if (ColumnInfo.COLUMN_TYPE_DATE.equals(columnInfo
313: .getColumnTypeName())
314: || ColumnInfo.COLUMN_TYPE_DATE_TIME
315: .equals(columnInfo.getColumnTypeName())) {
316: labelForDataType = new JLabel(columnInfo
317: .getColumnTypeName()
318: + "("
319: + columnInfo.getColumnDisplaySize().intValue()
320: + ")"
321: + " - "
322: + columnInfo.getNullableNature()
323: + " - " + DBTableCell.DATE_FORMAT_STRING);
324: } else {
325: labelForDataType = new JLabel(columnInfo
326: .getColumnTypeName()
327: + "("
328: + columnInfo.getColumnDisplaySize().intValue()
329: + ")" + " - " + columnInfo.getNullableNature());
330: }
331:
332: //Add the label to the panel for labels
333: this .panelForData.add(labelForData);
334: this .panelForData.add(labelForDataType);
335: this .panelForData.add(textFieldForData);
336: }
337:
338: //Set the layout on the panel
339: this .panelForData.setLayout(new GridLayout(listOfTableCells
340: .size(), 3));
341: }
342:
343: public void show() {
344: this .dialog.setVisible(true);
345: }
346:
347: public void actionPerformed(ActionEvent e) {
348: if (firstRecordNavigationButtonLabel.equals(e
349: .getActionCommand())) {
350: counterForRowNumber = 0;
351: this .refresh();
352: }
353:
354: if (previousRecordNavigationButtonLabel.equals(e
355: .getActionCommand())) {
356: if (counterForRowNumber != 0) {
357: counterForRowNumber = counterForRowNumber - 1;
358: this .refresh();
359: }
360: }
361:
362: if (nextRecordNavigationButtonLabel
363: .equals(e.getActionCommand())) {
364: if ((counterForRowNumber + 1) < this .dbTable
365: .getListOfRows().size()) {
366: counterForRowNumber = counterForRowNumber + 1;
367: this .refresh();
368: }
369: }
370:
371: if (lastRecordNavigationButtonLabel
372: .equals(e.getActionCommand())) {
373: if ((counterForRowNumber + 1) < this .dbTable
374: .getListOfRows().size()) {
375: counterForRowNumber = this .dbTable.getListOfRows()
376: .size() - 1;
377: this .refresh();
378: }
379: }
380:
381: if (UPDATE_BUTTON_LABEL.equals(e.getActionCommand())) {
382: //Get the list of values which have been changed by the user
383: Iterator i = this .listOfTextFieldsWhichHaveChanged
384: .iterator();
385: List listOfChangedCells = new ArrayList();
386:
387: while (i.hasNext()) {
388: JTextField textField = (JTextField) i.next();
389:
390: //Get the original value from the map
391: DBTableCell tableCell = (DBTableCell) this .mapOfTextFieldsToOriginalValue
392: .get(textField);
393:
394: //Get the new value typed by the user
395: String newValue = textField.getText();
396:
397: //Set the new value
398: DBTableCell newTableCell = new DBTableCell(tableCell
399: .getColumnInfo(), newValue, Boolean.TRUE);
400: listOfChangedCells.add(newTableCell);
401: }
402:
403: //Add the primary key columns
404: DBRow dbRow = (DBRow) this .dbTable.getListOfRows().get(
405: this .counterForRowNumber);
406: List listOfPrimaryKeyCells = dbRow
407: .getListOfPrimaryKeyDBTableCells();
408: listOfChangedCells.addAll(listOfPrimaryKeyCells);
409:
410: //Build the dbrow which needs to be updated
411: DBRow updatedDBRow = new DBRow(listOfChangedCells);
412:
413: //Update the DBRow
414: try {
415: //Set the auto commit flag
416: String autoCommitFlag = PropertyManager.getInstance()
417: .getProperty("dbbrowser-auto-commit");
418: if ("false".equals(autoCommitFlag)) {
419: this .uiControllerForUpdates.setAutoCommit(false);
420: }
421:
422: //Update
423: if (this .uiControllerForUpdates != null) {
424: this .uiControllerForUpdates.update(this .dbTable
425: .getSchemaName(), this .dbTable
426: .getTableName(), updatedDBRow);
427: }
428: } catch (DBEngineException exc) {
429: Log.getInstance().fatalMessage(exc.getMessage(),
430: ViewRecordWindow.class.getName());
431: String sqlFailedLabel = InternationalizationManager
432: .getInstance()
433: .getMessage(
434: "dbbrowser-ui",
435: "dbbrowser-ui-dbbrowser-window-sql-failed",
436: null);
437: JOptionPane.showMessageDialog(null, sqlFailedLabel
438: + " - " + exc.getMessage(), TITLE,
439: JOptionPane.ERROR_MESSAGE);
440: }
441: }
442:
443: if (COMMIT_BUTTON_LABEL.equals(e.getActionCommand())) {
444: try {
445: //Commit only if autocommit if off
446: String autoCommitFlag = PropertyManager.getInstance()
447: .getProperty("dbbrowser-auto-commit");
448: if ("false".equals(autoCommitFlag)) {
449: this .uiControllerForUpdates.commit();
450: }
451:
452: //Close the window
453: this .dialog.pack();
454: this .dialog.dispose();
455: this .dialog = null;
456: } catch (DBEngineException exc) {
457: String errorMessage = InternationalizationManager
458: .getInstance()
459: .getMessage(
460: "dbbrowser-ui",
461: "dbbrowser-ui-dbbrowser-window-sql-failed",
462: null);
463: JOptionPane.showMessageDialog(null, errorMessage
464: + " - " + exc.getMessage(), TITLE,
465: JOptionPane.ERROR_MESSAGE);
466: }
467: }
468:
469: if (ROLLBACK_BUTTON_LABEL.equals(e.getActionCommand())) {
470: try {
471: //Rollback only if autocommit if off
472: String autoCommitFlag = PropertyManager.getInstance()
473: .getProperty("dbbrowser-auto-commit");
474: if ("false".equals(autoCommitFlag)) {
475: this .uiControllerForUpdates.rollback();
476: }
477: } catch (DBEngineException exc) {
478: String errorMessage = InternationalizationManager
479: .getInstance()
480: .getMessage(
481: "dbbrowser-ui",
482: "dbbrowser-ui-dbbrowser-window-sql-failed",
483: null);
484: JOptionPane.showMessageDialog(null, errorMessage
485: + " - " + exc.getMessage(), TITLE,
486: JOptionPane.ERROR_MESSAGE);
487: }
488: }
489:
490: //Update the main panel
491: SwingUtilities.updateComponentTreeUI(this .mainPanel);
492: }
493:
494: private class DocumentListenerForDetectingChangeInTextField
495: implements DocumentListener {
496: private JTextField textFieldWhoseValueMayBeChangedByUser = null;
497:
498: public DocumentListenerForDetectingChangeInTextField(
499: JTextField textField) {
500: textFieldWhoseValueMayBeChangedByUser = textField;
501: }
502:
503: public void insertUpdate(DocumentEvent e) {
504: updateLog(e);
505: }
506:
507: public void removeUpdate(DocumentEvent e) {
508: updateLog(e);
509: }
510:
511: public void changedUpdate(DocumentEvent e) {
512: //Not used
513: }
514:
515: private void updateLog(DocumentEvent e) {
516: //if the list does not contain this field, add it
517: if (!listOfTextFieldsWhichHaveChanged
518: .contains(textFieldWhoseValueMayBeChangedByUser)) {
519: listOfTextFieldsWhichHaveChanged
520: .add(textFieldWhoseValueMayBeChangedByUser);
521: }
522: }
523: }
524: }
|