package studio.ui;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.util.*;
import javax.swing.*;
import static javax.swing.JSplitPane.VERTICAL_SPLIT;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileView;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.table.TableModel;
import javax.swing.text.*;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import kx.c;
import org.netbeans.editor.*;
import org.netbeans.editor.Utilities;
import org.netbeans.editor.example.QKit;
import org.netbeans.editor.ext.ExtKit;
import org.netbeans.editor.ext.ExtSettingsInitializer;
import org.netbeans.editor.ext.q.QSettingsInitializer;
import studio.kdb.*;
import studio.utils.BrowserLaunch;
import studio.utils.OSXAdapter;
import studio.utils.SwingWorker;
public class Studio extends JPanel implements Observer,WindowListener {
static {
// Register us
LocaleSupport.addLocalizer(new Impl("org.netbeans.editor.Bundle"));
Settings.addInitializer(new BaseSettingsInitializer(),Settings.CORE_LEVEL);
Settings.addInitializer(new ExtSettingsInitializer(),Settings.CORE_LEVEL);
QKit editorKit = new QKit();
JEditorPane.registerEditorKitForContentType(editorKit.getContentType(),
editorKit.getClass().getName());
Settings.addInitializer(new QSettingsInitializer());
Settings.reset();
}
private JTable table;
private String exportFilename;
private String lastQuery = null;
private JMenuBar menubar;
private JToolBar toolbar;
private JEditorPane textArea;
private JSplitPane splitpane;
private JTabbedPane tabbedPane;
private Font font = null;
private UserAction arrangeAllAction;
private UserAction closeFileAction;
private UserAction newFileAction;
private UserAction openFileAction;
private UserAction openInExcel;
private UserAction codeKxComAction;
private UserAction openFileInNewWindowAction;
private UserAction saveFileAction;
private UserAction saveAsFileAction;
private UserAction exportAction;
private UserAction chartAction;
private ActionFactory.UndoAction undoAction;
private ActionFactory.RedoAction redoAction;
private BaseKit.CutAction cutAction;
private BaseKit.CopyAction copyAction;
private BaseKit.PasteAction pasteAction;
private BaseKit.SelectAllAction selectAllAction;
private Action findAction;
private Action replaceAction;
private UserAction stopAction;
private UserAction executeAction;
private UserAction executeCurrentLineAction;
private UserAction refreshAction;
private UserAction aboutAction;
private UserAction exitAction;
private UserAction toggleDividerOrientationAction;
private UserAction minMaxDividerAction;
private UserAction editServerAction;
private UserAction addServerAction;
private UserAction removeServerAction;
private static int scriptNumber = 0;
private static int myScriptNumber;
private JFrame frame;
public static java.util.List windowList = Collections.synchronizedList(new LinkedList());
private int menuShortcutKeyMask = java.awt.Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
public void refreshFrameTitle() {
String s = (String) textArea.getDocument().getProperty("filename");
if (s == null)
s = "Script" + myScriptNumber;
String title = s.replace('\\','/');
frame.setTitle(title + (getModified() ? " (not saved) " : "") + (server!=null?" @"+server.toString():"") +" Studio for kdb+ " + Lm.getVersionString());
}
public static class WindowListChangedEvent extends EventObject {
public WindowListChangedEvent(Object source) {
super(source);
}
}
public interface WindowListChangedEventListener extends EventListener {
public void WindowListChangedEventOccurred(WindowListChangedEvent evt);
}
public static class WindowListMonitor {
protected javax.swing.event.EventListenerList listenerList = new javax.swing.event.EventListenerList();
public synchronized void addEventListener(WindowListChangedEventListener listener) {
listenerList.add(WindowListChangedEventListener.class,listener);
}
public synchronized void removeEventListener(WindowListChangedEventListener listener) {
listenerList.remove(WindowListChangedEventListener.class,listener);
}
synchronized void fireMyEvent(WindowListChangedEvent evt) {
Object[] listeners = listenerList.getListenerList();
for (int i = 0;i < listeners.length;i += 2)
if (listeners[i] == WindowListChangedEventListener.class)
((WindowListChangedEventListener) listeners[i + 1]).WindowListChangedEventOccurred(evt);
}
}
public static WindowListMonitor windowListMonitor = new WindowListMonitor();
/*
private void updateKeyBindings(JEditorPane editorPane) {
InputMap inputMap = editorPane.getInputMap();
inputMap.put(KeyStroke.getKeyStroke("DELETE"),ExtKit.deleteNextCharAction);
inputMap.put(KeyStroke.getKeyStroke("BACK_SPACE"),ExtKit.deletePrevCharAction);
inputMap.put(KeyStroke.getKeyStroke("ENTER"),ExtKit.insertBreakAction);
inputMap.put(KeyStroke.getKeyStroke("UP"),ExtKit.upAction);
inputMap.put(KeyStroke.getKeyStroke("DOWN"),ExtKit.downAction);
inputMap.put(KeyStroke.getKeyStroke("LEFT"),ExtKit.backwardAction);
inputMap.put(KeyStroke.getKeyStroke("RIGHT"),ExtKit.forwardAction);
inputMap.put(KeyStroke.getKeyStroke("ctrl Z"),ExtKit.undoAction);
inputMap.put(KeyStroke.getKeyStroke("ctrl Y"),ExtKit.redoAction);
}
*/
private void updateUndoRedoState(UndoManager um) {
undoAction.setEnabled(um.canUndo());
redoAction.setEnabled(um.canRedo());
}
private void initDocument() {
initActions();
refreshActionState();
Document doc = null;
if (textArea == null) {
textArea = new JEditorPane("text/q","");
Action[] actions = textArea.getActions();
for (int i = 0;i < actions.length;i++)
if (actions[i] instanceof BaseKit.CopyAction) {
copyAction = (BaseKit.CopyAction) actions[i];
copyAction.putValue(Action.SHORT_DESCRIPTION,"Copy the selected text to the clipboard");
copyAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "copy.png"));
copyAction.putValue(Action.NAME,I18n.getString("Copy"));
copyAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_C));
copyAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_C,menuShortcutKeyMask));
}
else if (actions[i] instanceof BaseKit.CutAction) {
cutAction = (BaseKit.CutAction) actions[i];
cutAction.putValue(Action.SHORT_DESCRIPTION,"Cut the selected text");
cutAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "cut.png"));
cutAction.putValue(Action.NAME,I18n.getString("Cut"));
cutAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_T));
cutAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_X,menuShortcutKeyMask));
}
else if (actions[i] instanceof BaseKit.PasteAction) {
pasteAction = (BaseKit.PasteAction) actions[i];
pasteAction.putValue(Action.SHORT_DESCRIPTION,"Paste text from the clipboard");
pasteAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "paste.png"));
pasteAction.putValue(Action.NAME,I18n.getString("Paste"));
pasteAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_P));
pasteAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_V,menuShortcutKeyMask));
}
else if (actions[i] instanceof ExtKit.FindAction) {
findAction = actions[i];
findAction.putValue(Action.SHORT_DESCRIPTION,"Find text in the document");
findAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "find.png"));
findAction.putValue(Action.NAME,I18n.getString("Find"));
findAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_F));
findAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_F,menuShortcutKeyMask));
}
else if (actions[i] instanceof ExtKit.ReplaceAction) {
replaceAction = actions[i];
replaceAction.putValue(Action.SHORT_DESCRIPTION,"Replace text in the document");
replaceAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "replace.png"));
replaceAction.putValue(Action.NAME,I18n.getString("Replace"));
replaceAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_R));
replaceAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_R,menuShortcutKeyMask));
}
else if (actions[i] instanceof BaseKit.SelectAllAction) {
selectAllAction = (BaseKit.SelectAllAction) actions[i];
selectAllAction.putValue(Action.SHORT_DESCRIPTION,"Select all text in the document");
selectAllAction.putValue(Action.SMALL_ICON,null);
selectAllAction.putValue(Action.NAME,I18n.getString("SelectAll"));
selectAllAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_A));
selectAllAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_A,menuShortcutKeyMask));
}
else if (actions[i] instanceof ActionFactory.UndoAction) {
undoAction = (ActionFactory.UndoAction) actions[i];
undoAction.putValue(Action.SHORT_DESCRIPTION,"Undo the last change to the document");
undoAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "undo.png"));
undoAction.putValue(Action.NAME,I18n.getString("Undo"));
undoAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_U));
undoAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_Z,menuShortcutKeyMask));
}
else if (actions[i] instanceof ActionFactory.RedoAction) {
redoAction = (ActionFactory.RedoAction) actions[i];
redoAction.putValue(Action.SHORT_DESCRIPTION,"Redo the last change to the document");
redoAction.putValue(Action.SMALL_ICON,getImage(Config.imageBase2 + "redo.png"));
redoAction.putValue(Action.NAME,I18n.getString("Redo"));
redoAction.putValue(Action.MNEMONIC_KEY,new Integer(KeyEvent.VK_R));
redoAction.putValue(Action.ACCELERATOR_KEY,KeyStroke.getKeyStroke(KeyEvent.VK_Y,menuShortcutKeyMask));
}
doc = textArea.getDocument();
doc.putProperty("filename",null);
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
// doc.putProperty("created", Boolean.TRUE);
}
else
doc = textArea.getDocument();
JComponent c = (textArea.getUI() instanceof BaseTextUI) ? Utilities.getEditorUI(textArea).getExtComponent() : new JScrollPane(textArea);
doc.putProperty("server",server);
MarkingDocumentListener mdl = (MarkingDocumentListener) doc.getProperty("MarkingDocumentListener");
if (mdl == null) {
mdl = new MarkingDocumentListener(c);
doc.putProperty("MarkingDocumentListener",mdl);
doc.addDocumentListener(mdl);
}
mdl.setModified(false);
UndoManager um = (UndoManager) doc.getProperty(BaseDocument.UNDO_MANAGER_PROP);
if (um == null) {
um = new UndoManager() {
public void undoableEditHappened(UndoableEditEvent e) {
super.undoableEditHappened(e);
updateUndoRedoState(this);
}
public synchronized void redo() throws CannotRedoException {
super.redo();
updateUndoRedoState(this);
}
public synchronized void undo() throws CannotUndoException {
super.undo();
updateUndoRedoState(this);
}
};
doc.putProperty(BaseDocument.UNDO_MANAGER_PROP,um);
doc.addUndoableEditListener(um);
}
um.discardAllEdits();
updateUndoRedoState(um);
if (splitpane.getTopComponent() != c) {
splitpane.setTopComponent(c);
splitpane.setDividerLocation(0.5);
}
rebuildToolbar();
rebuildMenuBar();
textArea.requestFocus();
}
private void refreshActionState() {
newFileAction.setEnabled(true);
arrangeAllAction.setEnabled(true);
openFileAction.setEnabled(true);
openFileInNewWindowAction.setEnabled(true);
saveFileAction.setEnabled(true);
saveAsFileAction.setEnabled(true);
exportAction.setEnabled(false);
chartAction.setEnabled(false);
openInExcel.setEnabled(false);
stopAction.setEnabled(false);
executeAction.setEnabled(true);
executeCurrentLineAction.setEnabled(true);
refreshAction.setEnabled(false);
// helpAction.setEnabled(true);
aboutAction.setEnabled(true);
exitAction.setEnabled(true);
}
private String getFilename() {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter ff =
new FileFilter() {
public String getDescription() {
return "q script";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".q"))
return true;
else
return false;
}
};
chooser.addChoosableFileFilter(ff);
chooser.setFileFilter(ff);
String filename = (String) textArea.getDocument().getProperty("filename");
if (filename != null) {
File file = new File(filename);
File dir = new File(file.getPath());
chooser.setCurrentDirectory(dir);
}
int option = chooser.showOpenDialog(textArea);
if (option == JFileChooser.APPROVE_OPTION) {
File sf = chooser.getSelectedFile();
File f = chooser.getCurrentDirectory();
String dir = f.getAbsolutePath();
try {
filename = dir + "/" + sf.getName();
return filename;
}
catch (Exception e) {
}
}
return null;
}
private void exportAsExcel(final String filename) {
new ExcelExporter().exportTableX(frame,table,new File(filename),false);
}
private void exportAsDelimited(final TableModel model,final String filename,final char delimiter) {
final String message = "Exporting data to " + filename;
final String note = "0% complete";
String title = "Studio for kdb+";
UIManager.put("ProgressMonitor.progressText",title);
final int min = 0;
final int max = 100;
final ProgressMonitor pm = new ProgressMonitor(frame,message,note,min,max);
pm.setMillisToDecideToPopup(100);
pm.setMillisToPopup(100);
pm.setProgress(0);
Runnable runner = new Runnable() {
public void run() {
if (filename != null) {
String lineSeparator = (String) java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction("line.separator"));
BufferedWriter fw;
try {
fw = new BufferedWriter(new FileWriter(filename));
for (int col = 0;col < model.getColumnCount();col++) {
if (col > 0)
fw.write(delimiter);
fw.write(model.getColumnName(col));
}
fw.write(lineSeparator);
int maxRow = model.getRowCount();
int lastProgress = 0;
for (int r = 1;r <= maxRow;r++) {
for (int col = 0;col < model.getColumnCount();col++) {
if (col > 0)
fw.write(delimiter);
K.KBase o = (K.KBase) model.getValueAt(r - 1,col);
if (!o.isNull())
fw.write(o.toString(false));
}
fw.write(lineSeparator);
boolean cancelled = pm.isCanceled();
if (cancelled)
break;
else {
final int progress = (100 * r) / maxRow;
if (progress > lastProgress) {
final String note = "" + progress + "% complete";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pm.setProgress(progress);
pm.setNote(note);
}
});
Thread.yield();
}
}
}
fw.close();
}
catch (FileNotFoundException ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
catch (IOException ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
catch (Exception ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
finally {
pm.close();
}
}
}
};
Thread t = new Thread(runner);
t.setName("export");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
private void exportAsXml(final TableModel model,final String filename) {
final String message = "Exporting data to " + filename;
final String note = "0% complete";
String title = "Studio for kdb+";
UIManager.put("ProgressMonitor.progressText",title);
final int min = 0;
final int max = 100;
final ProgressMonitor pm = new ProgressMonitor(frame,message,note,min,max);
pm.setMillisToDecideToPopup(100);
pm.setMillisToPopup(100);
pm.setProgress(0);
Runnable runner = new Runnable() {
public void run() {
if (filename != null) {
String lineSeparator = (String) java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction("line.separator"));
BufferedWriter fw = null;
try {
fw = new BufferedWriter(new FileWriter(filename));
fw.write("<R>");
int maxRow = model.getRowCount();
int lastProgress = 0;
fw.write(lineSeparator);
String[] columns = new String[model.getColumnCount()];
for (int col = 0;col < model.getColumnCount();col++)
columns[col] = model.getColumnName(col);
for (int r = 1;r <= maxRow;r++) {
fw.write("<r>");
for (int col = 0;col < columns.length;col++) {
fw.write("<" + columns[col] + ">");
K.KBase o = (K.KBase) model.getValueAt(r - 1,col);
if (!o.isNull())
fw.write(o.toString(false));
fw.write("</" + columns[col] + ">");
}
fw.write("</r>");
fw.write(lineSeparator);
boolean cancelled = pm.isCanceled();
if (cancelled)
break;
else {
final int progress = (100 * r) / maxRow;
if (progress > lastProgress) {
final String note = "" + progress + "% complete";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pm.setProgress(progress);
pm.setNote(note);
}
});
Thread.yield();
}
}
}
fw.write("</R>");
fw.close();
}
catch (FileNotFoundException ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
catch (IOException ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
catch (Exception ex) {
ex.printStackTrace(); //To change body of catch statement use Options | File Templates.
}
finally {
pm.close();
}
}
}
};
Thread t = new Thread(runner);
t.setName("export");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
private void exportAsTxt(String filename) {
exportAsDelimited(table.getModel(),filename,'\t');
}
private void exportAsCSV(String filename) {
exportAsDelimited(table.getModel(),filename,',');
}
private void export() {
JFileChooser chooser = new JFileChooser();
chooser.setDialogType(JFileChooser.SAVE_DIALOG);
chooser.setDialogTitle("Export result set as");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter csvFilter = null;
FileFilter txtFilter = null;
FileFilter xmlFilter = null;
FileFilter xlsFilter = null;
if (table != null) {
csvFilter =
new FileFilter() {
public String getDescription() {
return "csv (Comma delimited)";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".csv"))
return true;
else
return false;
}
};
txtFilter =
new FileFilter() {
public String getDescription() {
return "txt (Tab delimited)";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".txt"))
return true;
else
return false;
}
};
xmlFilter =
new FileFilter() {
public String getDescription() {
return "xml";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".xml"))
return true;
else
return false;
}
};
xlsFilter =
new FileFilter() {
public String getDescription() {
return "xls (Microsoft Excel)";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".xls"))
return true;
else
return false;
}
};
chooser.addChoosableFileFilter(csvFilter);
chooser.addChoosableFileFilter(txtFilter);
chooser.addChoosableFileFilter(xmlFilter);
chooser.addChoosableFileFilter(xlsFilter);
}
if (exportFilename != null) {
File file = new File(exportFilename);
File dir = new File(file.getPath());
chooser.setCurrentDirectory(dir);
chooser.ensureFileIsVisible(file);
if (table != null)
if (exportFilename.endsWith(".xls"))
chooser.setFileFilter(xlsFilter);
else if (exportFilename.endsWith(".csv"))
chooser.setFileFilter(csvFilter);
else if (exportFilename.endsWith(".xml"))
chooser.setFileFilter(xmlFilter);
else if (exportFilename.endsWith(".txt"))
chooser.setFileFilter(txtFilter);
}
int option = chooser.showSaveDialog(textArea);
if (option == JFileChooser.APPROVE_OPTION) {
File sf = chooser.getSelectedFile();
File f = chooser.getCurrentDirectory();
String dir = f.getAbsolutePath();
// Cursor cursor= frame.getCursor();
try {
// frame.setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR));
FileFilter ff = chooser.getFileFilter();
exportFilename = dir + "/" + sf.getName();
if (table != null)
if (exportFilename.endsWith(".xls"))
exportAsExcel(exportFilename);
else if (exportFilename.endsWith(".csv"))
exportAsCSV(exportFilename);
else if (exportFilename.endsWith(".txt"))
exportAsTxt(exportFilename);
else if (exportFilename.endsWith(".xml"))
exportAsXml(table.getModel(),exportFilename);
/* else if (exportFilename.endsWith(".res")) {
exportAsBin(exportFilename);
}
*/
else
if (ff == csvFilter)
exportAsCSV(exportFilename);
else if (ff == xlsFilter)
exportAsExcel(exportFilename);
else if (ff == txtFilter)
exportAsTxt(exportFilename);
else if (ff == xmlFilter)
exportAsXml(table.getModel(),exportFilename);
/*else if( ff == binFilter){
exportAsBin(exportFilename);
}
*/
else
JOptionPane.showMessageDialog(frame,
"Warning",
"You did not specify what format to export the file as.\n Cancelling data export",
JOptionPane.WARNING_MESSAGE,
getImage(Config.imageBase + "32x32/warning.png"));
/* else {
exportAsBin(exportFilename);
}
*/
}
catch (Exception e) {
JOptionPane.showMessageDialog(frame,
"Error",
"An error occurred whilst writing the export file.\n Details are: " + e.getMessage(),
JOptionPane.ERROR_MESSAGE,
getImage(Config.imageBase + "32x32/error.png"));
}
finally {
// frame.setCursor(cursor);
}
}
}
public void newFile() {
try {
String filename = (String) textArea.getDocument().getProperty("filename");
if (!saveIfModified(filename))
return;
textArea.getDocument().remove(0,textArea.getDocument().getLength());
textArea.getDocument().putProperty("filename",null);
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
initDocument();
refreshFrameTitle();
}
catch (BadLocationException ex) {
ex.printStackTrace();
}
}
public void openFile() {
String filename = (String) textArea.getDocument().getProperty("filename");
if (!saveIfModified(filename))
return;
filename = getFilename();
if (filename != null) {
loadFile(filename);
addToMruFiles(filename);
}
}
// returns true to continue
public boolean saveIfModified(String filename) {
if (getModified()) {
int choice = JOptionPane.showOptionDialog(frame,
"Changes not saved.\nSave now?",
"Save changes?",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
getImage(Config.imageBase + "32x32/question.png"),
null, // use standard button titles
null); // no default selection
if (choice == JOptionPane.YES_OPTION) {
try {
if (saveFile(filename,false))
// was cancelled so return
return false;
}
catch (Exception e) {
return false;
}
return true;
}
else if ((choice == JOptionPane.CANCEL_OPTION) || (choice == JOptionPane.CLOSED_OPTION))
return false;
}
return true;
}
public void loadMRUFile(String filename,String oldFilename) {
if (!saveIfModified(oldFilename))
return;
loadFile(filename);
addToMruFiles(filename);
setServer(server);
}
private void addToMruFiles(String filename) {
if (filename == null)
return;
Vector v = new Vector();
v.add(filename);
String[] mru = Config.getInstance().getMRUFiles();
for (int i = 0;i < mru.length;i++)
if (!v.contains(mru[i]))
v.add(mru[i]);
Config.getInstance().saveMRUFiles((String[]) v.toArray(new String[0]));
rebuildMenuBar();
}
static public String getContents(File aFile) {
StringBuffer contents = new StringBuffer();
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(aFile),
"UTF-8");
BufferedReader input = new BufferedReader(isr);
try {
String line = null;
while ((line = input.readLine()) != null) {
contents.append(line);
contents.append(System.getProperty("line.separator"));
}
}
finally {
input.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
return contents.toString();
}
public void loadFile(String filename) {
try {
String s = getContents(new File(filename));
textArea.getDocument().remove(0,textArea.getDocument().getLength());
textArea.getDocument().insertString(0,s,null);
textArea.getDocument().putProperty("filename",filename);
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
initDocument();
textArea.setCaretPosition(0);
refreshFrameTitle();
}
catch (BadLocationException ex) {
ex.printStackTrace();
}
}
public boolean saveAsFile() {
JFileChooser chooser = new JFileChooser();
chooser.setDialogType(JFileChooser.SAVE_DIALOG);
chooser.setDialogTitle("Save script as");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter ff =
new FileFilter() {
public String getDescription() {
return "q script";
}
public boolean accept(File file) {
if (file.isDirectory() || file.getName().endsWith(".q"))
return true;
else
return false;
}
};
chooser.addChoosableFileFilter(ff);
chooser.setFileFilter(ff);
String filename = (String) textArea.getDocument().getProperty("filename");
if (filename != null) {
File file = new File(filename);
File dir = new File(file.getPath());
chooser.setCurrentDirectory(dir);
}
// chooser.setMultiSelectionEnabled(true);
int option = chooser.showSaveDialog(textArea);
if (option == JFileChooser.APPROVE_OPTION) {
File sf = chooser.getSelectedFile();
File f = chooser.getCurrentDirectory();
String dir = f.getAbsolutePath();
try {
filename = dir + "/" + sf.getName();
sf = new File(filename);
if (sf.exists()) {
int choice = JOptionPane.showOptionDialog(frame,
filename + " already exists.\nOverwrite?",
"Overwrite?",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
getImage(Config.imageBase + "32x32/question.png"),
null, // use standard button titles
null); // no default selection
if (choice != JOptionPane.YES_OPTION)
return false;
}
return saveFile(filename,true);
}
catch (Exception e) {
}
}
return false;
}
// private boolean wasLoaded=false;
// returns true if saved, false if error or cancelled
public boolean saveFile(String filename,boolean force) {
if (filename == null)
return saveAsFile();
try {
if (!force)
if (null == textArea.getDocument().getProperty("filename"))
return saveAsFile();
textArea.write(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), "UTF-8")));
textArea.getDocument().putProperty("filename",filename);
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
setModified(false);
addToMruFiles(filename);
refreshFrameTitle();
return true;
}
catch (Exception e) {
}
return false;
}
private void arrangeAll() {
int noWins = windowList.size();
Iterator i = windowList.iterator();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int noRows = noWins > 3 ? 3 : noWins;
int height = screenSize.height / noRows;
for (int row = 0;row < noRows;row++) {
int noCols = (noWins / 3);
if ((row == 0) && ((noWins % 3) > 0))
noCols++;
else if ((row == 1) && ((noWins % 3) > 1))
noCols++;
int width = screenSize.width / noCols;
for (int col = 0;col < noCols;col++) {
Object o = i.next();
JFrame f;
if (o instanceof Studio)
f = ((Studio) o).frame;
else
f = (JFrame) o;
f.setSize(width,height);
f.setLocation(col * width,((noRows - 1) - row) * height);
ensureDeiconified(f);
}
}
}
private void setModified(boolean value) {
if (textArea != null) {
Document doc = textArea.getDocument();
if (doc != null) {
MarkingDocumentListener mdl = (MarkingDocumentListener) doc.getProperty("MarkingDocumentListener");
if (mdl != null)
mdl.setModified(value);
}
}
}
private boolean getModified() {
if (textArea != null) {
Document doc = textArea.getDocument();
if (doc != null) {
MarkingDocumentListener mdl = (MarkingDocumentListener) doc.getProperty("MarkingDocumentListener");
if (mdl != null)
return mdl.getModified();
}
}
return true;
}
private void setServer(Server server) {
if (server == null)
return;
this.server = server;
if (textArea != null) {
Document doc = textArea.getDocument();
if (doc != null)
doc.putProperty("server",server);
Utilities.getEditorUI(textArea).getComponent().setBackground(server.getBackgroundColor());
}
if (server != null) {
new ReloadQKeywords(server);
Config.getInstance().setLRUServer(server);
}
refreshFrameTitle();
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
}
private void initActions() {
newFileAction = new UserAction(I18n.getString("New"),
getImage(Config.imageBase2 + "document_new.png"),
"Create a blank script",
new Integer(KeyEvent.VK_N),
null) {
public void actionPerformed(ActionEvent e) {
// PrintUtilities.printComponent(textArea);
newFile();
}
};
arrangeAllAction = new UserAction(I18n.getString("ArrangeAll"),
getImage(Config.imageBase2 + "blank.png"),
"Arrange all windows on screen",
new Integer(KeyEvent.VK_A),
null) {
public void actionPerformed(ActionEvent e) {
arrangeAll();
}
};
minMaxDividerAction = new UserAction(I18n.getString("MaximizeEditorPane"),
getImage(Config.imageBase2 + "blank.png"),
"Maximize editor pane",
new Integer(KeyEvent.VK_M),
KeyStroke.getKeyStroke(KeyEvent.VK_M,menuShortcutKeyMask)) {
public void actionPerformed(ActionEvent e) {
minMaxDivider();
}
};
toggleDividerOrientationAction = new UserAction(I18n.getString("ToggleDividerOrientation"),
getImage(Config.imageBase2 + "blank.png"),
"Toggle the window divider's orientation",
new Integer(KeyEvent.VK_C),
null) {
public void actionPerformed(ActionEvent e) {
toggleDividerOrientation();
}
};
closeFileAction = new UserAction(I18n.getString("Close"),
getImage(Config.imageBase2 + "blank.png"),
"Close current document",
new Integer(KeyEvent.VK_C),
null) {
public void actionPerformed(ActionEvent e) {
quitWindow();
if (windowList.size() == 0)
System.exit(0);
}
};
openFileAction = new UserAction(I18n.getString("Open"),
getImage(Config.imageBase2 + "folder.png"),
"Open a script",
new Integer(KeyEvent.VK_O),
KeyStroke.getKeyStroke(KeyEvent.VK_O,menuShortcutKeyMask)) {
public void actionPerformed(ActionEvent e) {
openFile();
}
};
openFileInNewWindowAction = new UserAction(I18n.getString("NewWindow"),
getImage(Config.imageBase2 + "blank.png"),
"Open a new window",
new Integer(KeyEvent.VK_N),
null) {
public void actionPerformed(ActionEvent e) {
new Studio(server,null);
}
};
editServerAction = new UserAction(I18n.getString("Edit"),
getImage(Config.imageBase2 + "server_information.png"),
"Edit the server details",
new Integer(KeyEvent.VK_E),
null) {
public void actionPerformed(ActionEvent e) {
Server s = new Server(server);
EditServerForm f = new EditServerForm(frame,s);
f.setModal(true);
f.pack();
Util.centerChildOnParent(f,frame);
f.show();
if (f.getResult() == DialogResult.ACCEPTED) {
if (stopAction.isEnabled())
stopAction.actionPerformed(e);
ConnectionPool.getInstance().purge(server);
Config.getInstance().removeServer(server);
s = f.getServer();
Config.getInstance().addServer(s);
setServer(s);
rebuildToolbar();
rebuildMenuBar();
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
}
}
};
addServerAction = new UserAction(I18n.getString("Add"),
getImage(Config.imageBase2 + "server_add.png"),
"Configure a new server",
new Integer(KeyEvent.VK_A),
null) {
public void actionPerformed(ActionEvent e) {
AddServerForm f = new AddServerForm(frame);
f.setModal(true);
f.pack();
Util.centerChildOnParent(f,frame);
f.show();
if (f.getResult() == DialogResult.ACCEPTED) {
Server s = f.getServer();
Config.getInstance().addServer(s);
ConnectionPool.getInstance().purge(s); //?
setServer(s);
rebuildToolbar();
rebuildMenuBar();
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
}
}
};
removeServerAction = new UserAction(I18n.getString("Remove"),
getImage(Config.imageBase2 + "server_delete.png"),
"Remove this server",
new Integer(KeyEvent.VK_R),
null) {
public void actionPerformed(ActionEvent e) {
int choice = JOptionPane.showOptionDialog(frame,
"Remove server " + server.getName() + " from list?",
"Remove server?",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
getImage(Config.imageBase + "32x32/question.png"),
null, // use standard button titles
null); // no default selection
if (choice == 0) {
Config.getInstance().removeServer(server);
Server[] servers = Config.getInstance().getServers();
if (servers.length > 0)
setServer(servers[0]);
rebuildToolbar();
rebuildMenuBar();
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
}
}
};
saveFileAction = new UserAction(I18n.getString("Save"),
getImage(Config.imageBase2 + "disks.png"),
"Save the script",
new Integer(KeyEvent.VK_S),
KeyStroke.getKeyStroke(KeyEvent.VK_S,menuShortcutKeyMask)) {
public void actionPerformed(ActionEvent e) {
String filename = (String) textArea.getDocument().getProperty("filename");
saveFile(filename,false);
}
};
saveAsFileAction = new UserAction(I18n.getString("SaveAs"),
getImage(Config.imageBase2 + "save_as.png"),
"Save script as",
new Integer(KeyEvent.VK_A),
null) {
public void actionPerformed(ActionEvent e) {
saveAsFile();
}
};
exportAction = new UserAction(I18n.getString("Export"),
getImage(Config.imageBase2 + "export2.png"),
"Export result set",
new Integer(KeyEvent.VK_E),
null) {
public void actionPerformed(ActionEvent e) {
export();
}
};
chartAction = new UserAction(I18n.getString("Chart"),
Util.getImage(Config.imageBase2 + "chart.png"),
"Chart current data set",
new Integer(KeyEvent.VK_E),
null) {
public void actionPerformed(ActionEvent e) {
new LineChart((KTableModel) table.getModel());
//new PriceVolumeChart(table);
}
};
stopAction = new UserAction(I18n.getString("Stop"),
getImage(Config.imageBase2 + "stop.png"),
"Stop the query",
new Integer(KeyEvent.VK_S),
null) {
public void actionPerformed(ActionEvent e) {
if (worker != null) {
worker.interrupt();
stopAction.setEnabled(false);
textArea.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
};
openInExcel = new UserAction(I18n.getString("OpenInExcel"),
getImage(Config.imageBase + "excel_icon.gif"),
"Open in Excel",
new Integer(KeyEvent.VK_O),
null) {
public void actionPerformed(ActionEvent e) {
try {
File file = File.createTempFile("studioExport",".xls");
new ExcelExporter().exportTableX(frame,table,file,true);
}
catch (IOException ex) {
ex.printStackTrace();
}
}
};
executeAction = new UserAction(I18n.getString("Execute"),
Util.getImage(Config.imageBase2 + "table_sql_run.png"),
"Execute the full or highlighted text as a query",
new Integer(KeyEvent.VK_E),
KeyStroke.getKeyStroke(KeyEvent.VK_E,menuShortcutKeyMask)) {
public void actionPerformed(ActionEvent e) {
executeQuery();
}
};
executeCurrentLineAction = new UserAction(I18n.getString("ExecuteCurrentLine"),
Util.getImage(Config.imageBase2 + "element_run.png"),
"Execute the current line as a query",
new Integer(KeyEvent.VK_ENTER),
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,menuShortcutKeyMask)) {
public void actionPerformed(ActionEvent e) {
executeQueryCurrentLine();
}
};
refreshAction = new UserAction(I18n.getString("Refresh"),
getImage(Config.imageBase2 + "refresh.png"),
"Refresh the result set",
new Integer(KeyEvent.VK_R),
KeyStroke.getKeyStroke(KeyEvent.VK_Y,menuShortcutKeyMask | Event.SHIFT_MASK)) {
public void actionPerformed(ActionEvent e) {
refreshQuery();
}
};
aboutAction = new UserAction(I18n.getString("About"),
Util.getImage(Config.imageBase2 + "about.png"),
"About Studio for kdb+",
new Integer(KeyEvent.VK_E),
null) {
public void actionPerformed(ActionEvent e) {
about();
}
};
exitAction = new UserAction(I18n.getString("Exit"),
getImage(Config.imageBase2 + "blank.png"),
"Close this window",
new Integer(KeyEvent.VK_X),
null) {
public void actionPerformed(ActionEvent e) {
if (quit())
System.exit(0);
}
};
codeKxComAction = new UserAction("code.kx.com",
Util.getImage(Config.imageBase2 + "text.png"),
"Open code.kx.com",
new Integer(KeyEvent.VK_C),
null) {
public void actionPerformed(ActionEvent e) {
try {
BrowserLaunch.openURL("http://code.kx.com/trac/wiki/Reference");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "Error attempting to launch web browser:\n" + ex.getLocalizedMessage());
}
}
};
}
public void about() {
HelpDialog help = new HelpDialog(frame);
Util.centerChildOnParent(help,frame);
// help.setTitle("About Studio for kdb+");
help.pack();
help.setVisible(true);
}
public boolean quit() {
boolean okToExit = true;
Object[] objs = windowList.toArray();
for (int i = 0;i < objs.length;i++) {
Object o = objs[i];
if (o instanceof Studio) {
if (!((Studio) o).quitWindow())
okToExit = false;
}
else
if (o instanceof JFrame) {
JFrame f = (JFrame) o;
f.setVisible(false);
f.dispose();
}
}
return okToExit;
}
public boolean quitWindow() {
if (getModified()) {
int choice = JOptionPane.showOptionDialog(frame,
"Changes not saved.\nSave now?",
"Save changes?",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
getImage(Config.imageBase + "32x32/question.png"),
null, // use standard button titles
null); // no default selection
if (choice == 0)
try {
String filename = (String) textArea.getDocument().getProperty("filename");
if (!saveFile(filename,false))
// was cancelled so return
return false;
}
catch (Exception e) {
return false;
}
else if ((choice == 2) || (choice == JOptionPane.CLOSED_OPTION))
return false;
}
windowList.remove(this);
windowListMonitor.removeEventListener(windowListChangedEventListener);
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
frame.dispose();
return true;
}
private void rebuildMenuBar() {
menubar = createMenuBar();
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
if (frame != null) {
frame.setJMenuBar(menubar);
menubar.validate();
menubar.repaint();
frame.validate();
frame.repaint();
}
}
});
}
private JMenuBar createMenuBar() {
JMenuBar menubar = new JMenuBar();
JMenu menu = new JMenu(I18n.getString("File"));
menu.setMnemonic(KeyEvent.VK_F);
menu.add(new JMenuItem(newFileAction));
menu.add(new JMenuItem(openFileAction));
menu.add(new JMenuItem(saveFileAction));
menu.add(new JMenuItem(saveAsFileAction));
menu.add(new JMenuItem(closeFileAction));
menu.addSeparator();
// menu.add(new JMenuItem(importAction));
menu.add(new JMenuItem(openInExcel));
menu.addSeparator();
menu.add(new JMenuItem(exportAction));
menu.addSeparator();
menu.add(new JMenuItem(chartAction));
String[] mru = Config.getInstance().getMRUFiles();
if (mru.length > 0) {
menu.addSeparator();
char[] mnems = "123456789".toCharArray();
for (int i = 0;i < (mru.length > mnems.length ? mnems.length : mru.length);i++) {
final String filename = mru[i];
JMenuItem item = new JMenuItem("" + (i + 1) + " " + filename);
item.setMnemonic(mnems[i]);
item.setIcon(getImage(Config.imageBase2 + "blank.png"));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
loadMRUFile(filename,(String) textArea.getDocument().getProperty("filename"));
}
});
menu.add(item);
}
}
if (!MAC_OS_X) {
menu.addSeparator();
menu.add(new JMenuItem(exitAction));
}
menubar.add(menu);
menu = new JMenu(I18n.getString("Edit"));
menu.setMnemonic(KeyEvent.VK_E);
menu.add(new JMenuItem(undoAction));
menu.add(new JMenuItem(redoAction));
menu.addSeparator();
menu.add(new JMenuItem(cutAction));
menu.add(new JMenuItem(copyAction));
menu.add(new JMenuItem(pasteAction));
menu.addSeparator();
menu.add(new JMenuItem(selectAllAction));
menu.addSeparator();
menu.add(new JMenuItem(findAction));
menu.add(new JMenuItem(replaceAction));
// menu.addSeparator();
// menu.add(new JMenuItem(editFontAction));
menubar.add(menu);
menu = new JMenu(I18n.getString("Server"));
menu.setMnemonic(KeyEvent.VK_S);
menu.add(new JMenuItem(addServerAction));
menu.add(new JMenuItem(editServerAction));
menu.add(new JMenuItem(removeServerAction));
Server[] servers = Config.getInstance().getServers();
if (servers.length > 0) {
JMenu subMenu = new JMenu(I18n.getString("Clone"));
subMenu.setIcon(Util.getImage(Config.imageBase2 + "data_copy.png"));
for (int i = 0;i < servers.length;i++) {
final Server s = servers[i];
JMenuItem item = new JMenuItem(s.getName());
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Server clone = new Server(s);
clone.setName("Clone of " + clone.getName());
EditServerForm f = new EditServerForm(frame,clone);
f.setModal(true);
f.pack();
Util.centerChildOnParent(f,frame);
// f.setStartLocation(frame);
f.setVisible(true);
if (f.getResult() == DialogResult.ACCEPTED) {
clone = f.getServer();
Config.getInstance().addServer(clone);
//ebuildToolbar();
setServer(clone);
ConnectionPool.getInstance().purge(clone); //?
windowListMonitor.fireMyEvent(new WindowListChangedEvent(this));
}
}
});
subMenu.add(item);
}
menu.add(subMenu);
}
menubar.add(menu);
menu = new JMenu(I18n.getString("Query"));
menu.setMnemonic(KeyEvent.VK_Q);
menu.add(new JMenuItem(executeCurrentLineAction));
menu.add(new JMenuItem(executeAction));
menu.add(new JMenuItem(stopAction));
menu.add(new JMenuItem(refreshAction));
menubar.add(menu);
menu = new JMenu(I18n.getString("Window"));
menu.setMnemonic(KeyEvent.VK_W);
menu.add(new JMenuItem(minMaxDividerAction));
menu.add(new JMenuItem(toggleDividerOrientationAction));
menu.add(new JMenuItem(openFileInNewWindowAction));
menu.add(new JMenuItem(arrangeAllAction));
if (windowList.size() > 0) {
menu.addSeparator();
int i = 0;
Iterator it = windowList.iterator();
while (it.hasNext()) {
String t = "unknown";
final Object o = it.next();
if (o instanceof Studio) {
Studio r = (Studio) o;
String filename = (String) r.textArea.getDocument().getProperty("filename");
if (filename != null)
t = filename.replace('\\','/');
if (r.server != null)
t = t + "[" + r.server.getName() + "]";
else
t = t + "[no server]";
}
else
if (o instanceof JFrame)
t = ((JFrame) o).getTitle();
JMenuItem item = new JMenuItem("" + (i + 1) + " " + t);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (o instanceof Studio) {
JFrame f = ((Studio) o).frame;
ensureDeiconified(f);
}
else
ensureDeiconified((JFrame) o);
}
});
if (o == this)
item.setIcon(getImage(Config.imageBase2 + "check2.png"));
else
item.setIcon(getImage(Config.imageBase2 + "blank.png"));
menu.add(item);
i++;
}
}
menubar.add(menu);
menu = new JMenu(I18n.getString("Help"));
menu.setMnemonic(KeyEvent.VK_H);
menu.add(new JMenuItem(codeKxComAction));
if (!MAC_OS_X)
menu.add(new JMenuItem(aboutAction));
menubar.add(menu);
return menubar;
}
private void ensureDeiconified(JFrame f) {
int state = f.getExtendedState();
state = state & ~Frame.ICONIFIED;
f.setExtendedState(state);
f.show();
}
private void rebuildToolbar() {
if (toolbar != null) {
toolbar.removeAll();
String[] names = Config.getInstance().getServerNames();
if ((names != null) && (names.length > 0)) {
toolbar.add(new JLabel(I18n.getString("Server")));
JComboBox combo = new JComboBox(names) {
public Dimension getMinimumSize() {
return getPreferredSize();
}
public Dimension getMaximumSize() {
return getPreferredSize();
}
};
int offset = Config.getInstance().getOffset(server);
if (offset == -1) {
Server[] servers = Config.getInstance().getServers();
if (servers.length > 0)
setServer(servers[0]);
offset = 0;
}
combo.setSelectedIndex(offset);
combo.setToolTipText("Select the server context");
final Observer o = this;
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
String selection = (String) ((JComboBox) e.getSource()).getSelectedItem();
setServer(Config.getInstance().getServer(selection));
// setLanguage(Language.Q);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
rebuildToolbar();
toolbar.validate();
toolbar.repaint();
}
});
}
};
combo.addActionListener(al);
combo.setRequestFocusEnabled(false);
toolbar.add(combo);
toolbar.addSeparator();
}
if (server == null) {
addServerAction.setEnabled(true);
editServerAction.setEnabled(false);
removeServerAction.setEnabled(false);
stopAction.setEnabled(false);
executeAction.setEnabled(false);
executeCurrentLineAction.setEnabled(false);
refreshAction.setEnabled(false);
}
else {
executeAction.setEnabled(true);
executeCurrentLineAction.setEnabled(true);
editServerAction.setEnabled(true);
removeServerAction.setEnabled(true);
}
toolbar.add(stopAction);
toolbar.add(executeAction);
toolbar.add(refreshAction);
toolbar.addSeparator();
toolbar.add(openFileAction);
toolbar.add(saveFileAction);
toolbar.add(saveAsFileAction);
toolbar.addSeparator();
// toolbar.add(importAction);
toolbar.add(openInExcel);
toolbar.addSeparator();
toolbar.add(exportAction);
toolbar.addSeparator();
toolbar.add(chartAction);
toolbar.addSeparator();
toolbar.add(undoAction);
toolbar.add(redoAction);
toolbar.addSeparator();
toolbar.add(cutAction);
toolbar.add(copyAction);
toolbar.add(pasteAction);
toolbar.addSeparator();
toolbar.add(findAction);
toolbar.add(replaceAction);
toolbar.addSeparator();
toolbar.add(codeKxComAction);
for (int j = 0;j < toolbar.getComponentCount();j++) {
Component c = toolbar.getComponentAtIndex(j);
if (c instanceof JButton)
((JButton) c).setRequestFocusEnabled(false);
}
}
}
private JToolBar createToolbar() {
toolbar = new JToolBar();
toolbar.setFloatable(false);
rebuildToolbar();
return toolbar;
}
private static class Impl extends FileView implements
LocaleSupport.Localizer {
// FileView implementation
public String getName(File f) {
return null;
}
public String getDescription(File f) {
return null;
}
public String getTypeDescription(File f) {
return null;
}
public Boolean isTraversable(File f) {
return null;
}
public Icon getIcon(File f) {
if (f.isDirectory())
return null;
// KitInfo ki = KitInfo.getKitInfoForFile(f);
// return ki == null ? null : ki.getIcon();
return null;
}
private ResourceBundle bundle;
public Impl(String bundleName) {
bundle = ResourceBundle.getBundle(bundleName);
}
// Localizer
public String getString(String key) {
return bundle.getString(key);
}
}
private WindowListChangedEventListener windowListChangedEventListener;
private int dividerLastPosition; // updated from property change listener
private void minMaxDivider(){
//BasicSplitPaneDivider divider = ((BasicSplitPaneUI)splitpane.getUI()).getDivider();
//((JButton)divider.getComponent(0)).doClick();
//((JButton)divider.getComponent(1)).doClick();
if(splitpane.getDividerLocation()>=splitpane.getMaximumDividerLocation()){
// Minimize editor pane
splitpane.getTopComponent().setMinimumSize(new Dimension());
splitpane.getBottomComponent().setMinimumSize(null);
splitpane.setDividerLocation(0.);
splitpane.setResizeWeight(0.);
}
else if(splitpane.getDividerLocation()<=splitpane.getMinimumDividerLocation()){
// Restore editor pane
splitpane.getTopComponent().setMinimumSize(null);
splitpane.getBottomComponent().setMinimumSize(null);
splitpane.setResizeWeight(0.);
// Could probably catch resize edge-cases etc in pce too
if(dividerLastPosition>=splitpane.getMaximumDividerLocation()||dividerLastPosition<=splitpane.getMinimumDividerLocation())
dividerLastPosition=splitpane.getMaximumDividerLocation()/2;
splitpane.setDividerLocation(dividerLastPosition);
}
else{
// Maximize editor pane
splitpane.getBottomComponent().setMinimumSize(new Dimension());
splitpane.getTopComponent().setMinimumSize(null);
splitpane.setDividerLocation(splitpane.getOrientation()==VERTICAL_SPLIT?splitpane.getHeight()-splitpane.getDividerSize():splitpane.getWidth()-splitpane.getDividerSize());
splitpane.setResizeWeight(1.);
}
}
private void toggleDividerOrientation() {
if (splitpane.getOrientation() == JSplitPane.VERTICAL_SPLIT)
splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
else
splitpane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitpane.setDividerLocation(0.5);
}
public Studio(Server server,String filename) {
super(true);
registerForMacOSXEvents();
windowListChangedEventListener = new WindowListChangedEventListener() {
public void WindowListChangedEventOccurred(WindowListChangedEvent evt) {
rebuildMenuBar();
rebuildToolbar();
}
};
windowListMonitor.addEventListener(windowListChangedEventListener);
splitpane = new JSplitPane();
frame = new JFrame();
windowList.add(this);
initDocument();
setServer(server);
menubar = createMenuBar();
toolbar = createToolbar();
tabbedPane = new JTabbedPane();
splitpane.setBottomComponent(tabbedPane);
splitpane.setOneTouchExpandable(true);
splitpane.setOrientation(JSplitPane.VERTICAL_SPLIT);
try {
Component divider = ((BasicSplitPaneUI) splitpane.getUI()).getDivider();
divider.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent event) {
if (event.getClickCount() == 2)
toggleDividerOrientation();
}
});
}
catch (ClassCastException e) {
}
splitpane.setContinuousLayout(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setJMenuBar(menubar);
if (filename != null)
loadFile(filename);
else
myScriptNumber = scriptNumber++;
refreshFrameTitle();
frame.getContentPane().add(toolbar,BorderLayout.NORTH);
frame.getContentPane().add(splitpane,BorderLayout.CENTER);
// frame.setSize(frame.getContentPane().getPreferredSize());
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(this);
frame.setSize((int) (0.8 * screenSize.width),
(int) (0.8 * screenSize.height));
frame.setLocation(((int) Math.max(0,(screenSize.width - frame.getWidth()) / 2.0)),
(int) (Math.max(0,(screenSize.height - frame.getHeight()) / 2.0)));
frame.setIconImage(getImage(Config.imageBase + "32x32/dot-chart.png").getImage());
// frame.pack();
frame.setVisible(true);
splitpane.setDividerLocation(0.5);
textArea.requestFocus();
splitpane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY,new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent pce){
String s=splitpane.getDividerLocation()>=splitpane.getMaximumDividerLocation()?I18n.getString("MinimizeEditorPane"):splitpane.getDividerLocation()<=splitpane.getMinimumDividerLocation()?I18n.getString("RestoreEditorPane"):I18n.getString("MaximizeEditorPane");
minMaxDividerAction.putValue(Action.SHORT_DESCRIPTION,s);
minMaxDividerAction.putValue(Action.NAME,s);
if(splitpane.getDividerLocation()<splitpane.getMaximumDividerLocation()&&splitpane.getDividerLocation()>splitpane.getMinimumDividerLocation())
dividerLastPosition=splitpane.getDividerLocation();
}
});
dividerLastPosition=splitpane.getDividerLocation();
}
public void update(Observable obs,Object obj) {
}
public static boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
private static boolean registeredForMaxOSXEvents = false;
public void registerForMacOSXEvents() {
if (registeredForMaxOSXEvents)
return;
if (MAC_OS_X)
try {
// Generate and register the OSXAdapter, passing it a hash of all the methods we wish to
// use as delegates for various com.apple.eawt.ApplicationListener methods
OSXAdapter.setQuitHandler(new QuitHandler(this),QuitHandler.class.getDeclaredMethod("quit",(Class[]) null));
OSXAdapter.setAboutHandler(new AboutHandler(this),AboutHandler.class.getDeclaredMethod("about",(Class[]) null));
registeredForMaxOSXEvents = true;
}
catch (Exception e) {
System.err.println("Error while loading the OSXAdapter:");
e.printStackTrace();
}
}
public static void init(String[] args) {
try {
String filename = null;
String[] mruFiles = Config.getInstance().getMRUFiles();
if(args.length>0){
File f=new File(args[0]);
if(f.exists())
filename=args[0];
} else if (mruFiles.length > 0) {
File f = new File(mruFiles[0]);
if (f.exists())
filename = mruFiles[0];
}
Locale.setDefault(Locale.US);
Server s = null;
String lruServer = Config.getInstance().getLRUServer();
if (lruServer != null)
s = Config.getInstance().getServer(lruServer);
new Studio(s,filename);
}
catch (Exception e) {
e.printStackTrace();
}
}
public void refreshQuery() {
table = null;
executeK4Query(lastQuery);
}
public void executeQueryCurrentLine() {
executeQuery(getCurrentLineEditorText(textArea));
}
public void executeQuery() {
executeQuery(getEditorText(textArea));
}
private void executeQuery(String text) {
table = null;
if (text == null) {
JOptionPane.showMessageDialog(frame,
"\nNo text available to submit to server.\n\n",
"Studio for kdb+",
JOptionPane.OK_OPTION,
getImage(Config.imageBase + "32x32/information.png"));
return;
}
refreshAction.setEnabled(false);
stopAction.setEnabled(true);
executeAction.setEnabled(false);
executeCurrentLineAction.setEnabled(false);
exportAction.setEnabled(false);
chartAction.setEnabled(false);
openInExcel.setEnabled(false);
executeK4Query(text);
lastQuery = text;
}
private String getEditorText(JEditorPane editor) {
String text = editor.getSelectedText();
if (text != null) {
if (text.length() > 0)
if (text.trim().length() == 0)
return null; // selected text is whitespace
}
else
text = editor.getText(); // get the full text then
if (text != null)
text = text.trim();
if (text.trim().length() == 0)
text = null;
return text;
}
private String getCurrentLineEditorText(JEditorPane editor) {
String newLine = "\n";
String text = null;
try {
int pos = editor.getCaretPosition();
int max = editor.getDocument().getLength();
if ((max > pos) && (!editor.getText(pos,1).equals("\n"))) {
String toeol = editor.getText(pos,max - pos);
int eol = toeol.indexOf('\n');
if (eol > 0)
pos = pos + eol;
else
pos = max;
}
text = editor.getText(0,pos);
int lrPos = text.lastIndexOf(newLine);
if (lrPos >= 0) {
lrPos += newLine.length(); // found it so skip it
text = text.substring(lrPos,pos).trim();
}
}
catch (BadLocationException e) {
}
if (text != null) {
text = text.trim();
if (text.length() == 0)
text = null;
}
return text;
}
private void processK4Results(K.KBase r) throws c.K4Exception {
if (r != null) {
exportAction.setEnabled(true);
if (FlipTableModel.isTable(r)) {
QGrid grid = new QGrid(r);
table = grid.getTable();
openInExcel.setEnabled(true);
//if(grid.getRowCount()<50000)
chartAction.setEnabled(true);
//else
// chartAction.setEnabled(false);
TabPanel frame = new TabPanel("Table [" + grid.getRowCount() + " rows] ",
getImage(Config.imageBase2 + "table.png"),
grid);
frame.setTitle(I18n.getString("Table")+" [" + grid.getRowCount() + " "+I18n.getString("rows")+"] ");
// frame.setBackground( Color.white);
tabbedPane.addTab(frame.getTitle(),frame.getIcon(),frame.getComponent());
}
else {
chartAction.setEnabled(false);
openInExcel.setEnabled(false);
LimitedWriter lm = new LimitedWriter(50000);
try {
if(!(r instanceof K.UnaryPrimitive&&0==((K.UnaryPrimitive)r).getPrimitiveAsInt()))
r.toString(lm,true);
}
catch (IOException ex) {
ex.printStackTrace();
}
catch (LimitedWriter.LimitException ex) {
}
JEditorPane pane = new JEditorPane("text/plain",lm.toString());
pane.setFont(font);
//pane.setLineWrap( false);
//pane.setWrapStyleWord( false);
JScrollPane scrollpane = new JScrollPane(pane,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
TabPanel frame = new TabPanel("Console View ",
getImage(Config.imageBase2 + "console.png"),
scrollpane);
frame.setTitle(I18n.getString("ConsoleView"));
tabbedPane.addTab(frame.getTitle(),frame.getIcon(),frame.getComponent());
}
}
else {
// Log that execute was successful
}
}
Server server = null;
public void executeK4Query(final String text) {
final Cursor cursor = textArea.getCursor();
textArea.setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR));
tabbedPane.removeAll();
worker = new SwingWorker() {
Server s = null;
c c = null;
K.KBase r = null;
Throwable exception;
boolean cancelled = false;
long execTime=0;
public void interrupt() {
super.interrupt();
cancelled = true;
if (c != null)
c.close();
cleanup();
}
public Object construct() {
try {
this.s = server;
c = ConnectionPool.getInstance().leaseConnection(s);
ConnectionPool.getInstance().checkConnected(c);
c.setFrame(frame);
long startTime=System.currentTimeMillis();
c.k(new K.KCharacterVector(text));
r = c.getResponse();
execTime=System.currentTimeMillis()-startTime;
}
catch (Throwable e) {
exception = e;
}
return null;
}
public void finished() {
if (!cancelled) {
if (exception != null)
try {
throw exception;
}
catch (IOException ex) {
JOptionPane.showMessageDialog(frame,
"\nA communications error occurred whilst sending the query.\n\nPlease check that the server is running on " + server.getHost() + ":" + server.getPort() + "\n\nError detail is\n\n" + ex.getMessage() + "\n\n",
"Studio for kdb+",
JOptionPane.ERROR_MESSAGE,
getImage(Config.imageBase + "32x32/error.png"));
}
catch (c.K4Exception ex) {
JTextPane pane = new JTextPane();
String hint = QErrors.lookup(ex.getMessage());
if (hint != null)
hint = "\nStudio Hint: Possibly this error refers to " + hint;
else
hint = "";
pane.setText("An error occurred during execution of the query.\nThe server sent the response:\n" + ex.getMessage() + hint);
pane.setForeground(Color.RED);
JScrollPane scrollpane = new JScrollPane(pane);
TabPanel frame = new TabPanel("Error Details ",
getImage(Config.imageBase2 + "error.png"),
scrollpane);
frame.setTitle("Error Details ");
tabbedPane.addTab(frame.getTitle(),frame.getIcon(),frame.getComponent());
// tabbedPane.setSelectedComponent(resultsTabbedPane);
}
catch (java.lang.OutOfMemoryError ex) {
JOptionPane.showMessageDialog(frame,
"\nOut of memory whilst communicating with " + server.getHost() + ":" + server.getPort() + "\n\nThe result set is probably too large.\n\nTry increasing the memory available to studio through the command line option -J -Xmx512m\n\n",
"Studio for kdb+",
JOptionPane.ERROR_MESSAGE,
getImage(Config.imageBase + "32x32/error.png"));
}
catch (Throwable ex) {
String message = ex.getMessage();
if ((message == null) || (message.length() == 0))
message = "No message with exception. Exception is " + ex.toString();
JOptionPane.showMessageDialog(frame,
"\nAn unexpected error occurred whilst communicating with " + server.getHost() + ":" + server.getPort() + "\n\nError detail is\n\n" + message + "\n\n",
"Studio for kdb+",
JOptionPane.ERROR_MESSAGE,
getImage(Config.imageBase + "32x32/error.png"));
}
else
try {
Utilities.setStatusText(textArea, "Last execution time:"+(execTime>0?""+execTime:"<1")+" mS");
processK4Results(r);
}
catch (Exception e) {
JOptionPane.showMessageDialog(frame,
"\nAn unexpected error occurred whilst communicating with " + server.getHost() + ":" + server.getPort() + "\n\nError detail is\n\n" + e.getMessage() + "\n\n",
"Studio for kdb+",
JOptionPane.ERROR_MESSAGE,
getImage(Config.imageBase + "32x32/error.png"));
}
cleanup();
}
}
private void cleanup() {
if (c != null)
ConnectionPool.getInstance().freeConnection(s,c);
//if( c != null)
// c.close();
c = null;
textArea.setCursor(cursor);
stopAction.setEnabled(false);
executeAction.setEnabled(true);
executeCurrentLineAction.setEnabled(true);
refreshAction.setEnabled(true);
System.gc();
worker = null;
}
};
worker.start();
}
private SwingWorker worker;
public void windowClosing(WindowEvent e) {
if (quitWindow())
if (windowList.size() == 0)
System.exit(0);
}
public void windowClosed(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
// ctrl-alt spacebar to minimize window
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
this.invalidate();
SwingUtilities.updateComponentTreeUI(this);
}
public void windowDeactivated(WindowEvent e) {
}
private class MarkingDocumentListener implements DocumentListener {
private boolean modified = false;
private void setModified(boolean b) {
modified = b;
}
private boolean getModified() {
return modified;
}
private Component comp;
public MarkingDocumentListener(Component comp) {
this.comp = comp;
}
private void markChanged(DocumentEvent evt) {
setModified(true);
refreshFrameTitle();
}
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent evt) {
markChanged(evt);
}
public void removeUpdate(DocumentEvent evt) {
markChanged(evt);
}
/** Document property holding String name of associated file */
private static final String FILE = "file";
/** Document property holding Boolean if document was created or opened */
private static final String CREATED = "created";
/** Document property holding Boolean modified information */
private static final String MODIFIED = "modified";
}
public static ImageIcon getImage(String strFilename) {
Class thisClass = Studio.class;
java.net.URL url = null;
if (strFilename.startsWith("/"))
url = thisClass.getResource(strFilename);
else
// Locate the desired image file and create a URL to it
url = thisClass.getResource("/toolbarButtonGraphics/" + strFilename);
// See if we successfully found the image
if (url == null)
//System.out.println("Unable to load the following image: " +
// strFilename);
return null;
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage(url);
return new ImageIcon(image);
}
}