001: /*
002: * SQLeonardo :: java database frontend
003: * Copyright (C) 2004 nickyb@users.sourceforge.net
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: *
019: */
020:
021: package nickyb.sqleonardo.environment.ctrl;
022:
023: import java.awt.Cursor;
024: import java.awt.event.ActionEvent;
025:
026: import javax.swing.AbstractAction;
027: import javax.swing.JLabel;
028: import javax.swing.JScrollPane;
029: import javax.swing.JSlider;
030: import javax.swing.JTextArea;
031: import javax.swing.border.CompoundBorder;
032: import javax.swing.border.EmptyBorder;
033: import javax.swing.border.LineBorder;
034: import javax.swing.event.ChangeEvent;
035: import javax.swing.event.ChangeListener;
036:
037: import nickyb.sqleonardo.common.gui.BorderLayoutPanel;
038: import nickyb.sqleonardo.common.jdbc.ConnectionAssistant;
039: import nickyb.sqleonardo.environment.Application;
040: import nickyb.sqleonardo.environment.ctrl.content.ContentModel;
041: import nickyb.sqleonardo.environment.ctrl.content.ContentView;
042: import nickyb.sqleonardo.environment.ctrl.content.TaskRetrieve;
043: import nickyb.sqleonardo.environment.ctrl.content.TaskUpdate;
044: import nickyb.sqleonardo.environment.ctrl.content.UpdateModel;
045: import nickyb.sqleonardo.querybuilder.QueryBuilder;
046: import nickyb.sqleonardo.querybuilder.QueryModel;
047:
048: public class ContentPane extends BorderLayoutPanel implements
049: ChangeListener {
050: private JSlider sld;
051: private JLabel status;
052: private JTextArea syntax;
053: private ContentView view;
054:
055: private Thread task;
056: private String keycah;
057: private QueryModel qmodel;
058: private UpdateModel umodel;
059:
060: public ContentPane(String keycah, QueryModel qmodel,
061: UpdateModel umodel) {
062: super (2, 2);
063:
064: this .keycah = keycah;
065: this .qmodel = qmodel;
066: this .umodel = umodel;
067:
068: this .getActionMap()
069: .put("changes-save", new ActionSaveChanges());
070: this .getActionMap().put("record-insert",
071: new ActionInsertRecord());
072: this .getActionMap().put("record-delete",
073: new ActionDeleteRecord());
074: this .getActionMap().put("task-stop", new ActionStopTask());
075: this .getActionMap().put("task-go", new ActionRelaunch());
076:
077: sld = new JSlider(JSlider.VERTICAL);
078: sld.addChangeListener(this );
079: sld.setSnapToTicks(true);
080: sld.setInverted(true);
081: sld.setValue(0);
082: sld.setMinimum(0);
083: sld.setMaximum(0);
084:
085: status = new JLabel("...");
086: status.setBorder(new CompoundBorder(LineBorder
087: .createGrayLineBorder(), new EmptyBorder(2, 4, 2, 4)));
088:
089: JScrollPane scroll = new JScrollPane(syntax = new JTextArea());
090: syntax.setRows(3);
091:
092: syntax.setText(qmodel.toString(false));
093: syntax.setWrapStyleWord(true);
094: syntax.setLineWrap(true);
095: syntax.setEditable(false);
096: syntax.setOpaque(false);
097:
098: BorderLayoutPanel pnlSouth = new BorderLayoutPanel(2, 2);
099: pnlSouth.setComponentCenter(status);
100: pnlSouth.setComponentNorth(scroll);
101:
102: setComponentWest(sld);
103: setComponentSouth(pnlSouth);
104: setComponentCenter(view = new ContentView(this ));
105: }
106:
107: public boolean isReadOnly() {
108: return umodel == null;
109: }
110:
111: public String getHandlerKey() {
112: if (ConnectionAssistant.hasHandler(keycah)) {
113: QueryBuilder.identifierQuoteString = ConnectionAssistant
114: .getHandler(keycah).getObject(
115: "$identifierQuoteString").toString();
116: QueryBuilder.maxColumnNameLength = ((Integer) ConnectionAssistant
117: .getHandler(keycah).getObject(
118: "$maxColumnNameLength")).intValue();
119: }
120:
121: return keycah;
122: }
123:
124: public QueryModel getQueryModel() {
125: return qmodel;
126: }
127:
128: public UpdateModel getUpdateModel() {
129: return umodel;
130: }
131:
132: public void setUpdateModel(UpdateModel model) {
133: umodel = model;
134: }
135:
136: public JSlider getSlider() {
137: return sld;
138: }
139:
140: public ContentView getView() {
141: return view;
142: }
143:
144: public boolean isBusy() {
145: return task != null;
146: }
147:
148: public void doStop() {
149: // gestire cancel dello statement se attivo!!!
150: onEndTask();
151: }
152:
153: public void doRetrieve() {
154: onBeginTask(new TaskRetrieve(this ));
155: }
156:
157: public void doRetrieve(int limit) {
158: onBeginTask(new TaskRetrieve(this , limit));
159: }
160:
161: public void doUpdate() {
162: onBeginTask(new TaskUpdate(this ));
163: }
164:
165: private void onBeginTask(Runnable r) {
166: this .setCursor(new Cursor(Cursor.WAIT_CURSOR));
167:
168: this .getActionMap().get("task-go").setEnabled(false);
169: this .getActionMap().get("task-stop").setEnabled(true);
170: this .getActionMap().get("changes-save").setEnabled(false);
171: this .getActionMap().get("record-insert").setEnabled(false);
172: this .getActionMap().get("record-delete").setEnabled(false);
173:
174: task = new Thread(r);
175: task.start();
176: }
177:
178: private void onEndTask() {
179: task = null;
180:
181: this .getActionMap().get("task-go").setEnabled(true);
182: this .getActionMap().get("task-stop").setEnabled(false);
183: this .getActionMap().get("changes-save").setEnabled(true);
184: this .getActionMap().get("record-insert").setEnabled(true);
185: this .getActionMap().get("record-delete").setEnabled(true);
186:
187: this .setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
188: }
189:
190: public void doRefreshStatus() {
191: sld.setMaximum(view.getBlockCount() == 0 ? 0 : view
192: .getBlockCount() - 1);
193:
194: if (view.getRowCount() > 0)
195: status.setText("block " + view.getBlock() + " of "
196: + view.getBlockCount() + " | record "
197: + view.getLineAt(0) + " to "
198: + view.getLineAt(view.getRowCount() - 1) + " of "
199: + view.getFlatRowCount() + " | changes "
200: + view.getChanges().count());
201: else
202: status.setText("0 records");
203: }
204:
205: public void stateChanged(ChangeEvent e) {
206: JSlider source = (JSlider) e.getSource();
207: if (!source.getValueIsAdjusting()) {
208: int block = source.getValue() + 1;
209:
210: if (view != null && block != view.getBlock()) {
211: view.setBlock(block);
212: doRefreshStatus();
213: }
214: }
215: }
216:
217: private class ActionInsertRecord extends AbstractAction {
218: ActionInsertRecord() {
219: this .putValue(SMALL_ICON, Application.resources
220: .getIcon(Application.ICON_CONTENT_INSERT));
221: this .putValue(SHORT_DESCRIPTION, "insert record");
222: this .putValue(NAME, "insert record");
223: }
224:
225: public void actionPerformed(ActionEvent ae) {
226: int row = ContentPane.this .view.getRow();
227: int col = ContentPane.this .view.getColumn();
228:
229: ContentPane.this .view.insertRow(++row);
230: ContentPane.this .doRefreshStatus();
231:
232: if (row == ContentModel.MAX_BLOCK_RECORDS) {
233: row = 0;
234: ContentPane.this .sld.setValue(ContentPane.this .sld
235: .getValue() + 1);
236: }
237: ContentPane.this .view.setSelectedCell(row, (col == -1 ? 0
238: : col));
239: }
240: }
241:
242: private class ActionDeleteRecord extends AbstractAction {
243: ActionDeleteRecord() {
244: this .putValue(SMALL_ICON, Application.resources
245: .getIcon(Application.ICON_CONTENT_DELETE));
246: this .putValue(SHORT_DESCRIPTION, "delete record");
247: this .putValue(NAME, "delete record");
248: }
249:
250: public void actionPerformed(ActionEvent ae) {
251: int row = ContentPane.this .view.getRow();
252: int col = ContentPane.this .view.getColumn();
253:
254: if (row == -1)
255: return;
256:
257: ContentPane.this .view.deleteRow(row);
258: ContentPane.this .doRefreshStatus();
259:
260: if (ContentPane.this .view.getRowCount() == 0)
261: return;
262:
263: if (row >= ContentPane.this .view.getRowCount())
264: row = ContentPane.this .view.getRowCount() - 1;
265: ContentPane.this .view.setSelectedCell(row, (col == -1 ? 0
266: : col));
267: }
268: }
269:
270: private class ActionSaveChanges extends AbstractAction {
271: ActionSaveChanges() {
272: this .putValue(SMALL_ICON, Application.resources
273: .getIcon(Application.ICON_CONTENT_UPDATE));
274: this .putValue(SHORT_DESCRIPTION, "save changes");
275: }
276:
277: public void actionPerformed(ActionEvent ae) {
278: if (ContentPane.this .getUpdateModel() != null
279: && ContentPane.this .getUpdateModel()
280: .getRowIdentifierCount() > 0) {
281: doUpdate();
282: } else {
283: Application.alert(Application.PROGRAM,
284: "No update criteria defined!");
285: }
286: }
287: }
288:
289: private class ActionRelaunch extends AbstractAction {
290: ActionRelaunch() {
291: this .putValue(NAME, "relaunch query");
292: }
293:
294: public void actionPerformed(ActionEvent ae) {
295: if (!ContentPane.this .isBusy()) {
296: ContentPane.this .view.reset();
297: ContentPane.this .doRetrieve();
298: }
299: }
300: }
301:
302: private class ActionStopTask extends AbstractAction {
303: ActionStopTask() {
304: this .putValue(SMALL_ICON, Application.resources
305: .getIcon(Application.ICON_STOP));
306: }
307:
308: public void actionPerformed(ActionEvent ae) {
309: ContentPane.this.onEndTask();
310: }
311: }
312: }
|