?? console.groovy
字號:
package groovy.ui
import groovy.swing.SwingBuilder
import groovy.inspect.swingui.ObjectBrowser
import java.awt.BorderLayout
import java.awt.EventQueue
import java.awt.Color
import java.awt.Font
import java.awt.Insets
import java.awt.Toolkit
import java.awt.event.KeyEvent
import java.io.PrintWriter
import java.io.StringWriter
import java.util.EventObject
import javax.swing.*
import javax.swing.text.*
import javax.swing.event.*
import org.codehaus.groovy.runtime.InvokerHelper
/**
* Groovy Swing console.
*
* Allows user to interactively enter and execute Groovy.
*
* @author Danno Ferrin
* @author Dierk Koenig, changed Layout, included Selection sensitivity, included ObjectBrowser
* @author Alan Green more features: history, System.out capture, bind result to _
*/
class Console implements CaretListener {
// Whether or not std output should be captured to the console
def captureStdOut = true
// Maximum size of history
int maxHistory = 10
// Maximum number of characters to show on console at any time
int maxOutputChars = 10000
// UI
SwingBuilder swing
JFrame frame
JTextArea inputArea
JTextPane outputArea
JLabel statusLabel
JDialog runWaitDialog
// Styles for output area
Style promptStyle;
Style commandStyle;
Style outputStyle;
Style resultStyle;
// Internal history
List history = []
int historyIndex = 1 // valid values are 0..history.length()
// Current editor state
boolean dirty
int textSelectionStart // keep track of selections in inputArea
int textSelectionEnd
def scriptFile
// Running scripts
GroovyShell shell
int scriptNameCounter = 0
def systemOutInterceptor
def runThread = null
static void main(args) {
def console = new Console()
console.run()
}
Console() {
shell = new GroovyShell()
}
Console(Binding binding) {
shell = new GroovyShell(binding)
}
Console(ClassLoader parent, Binding binding) {
shell = new GroovyShell(parent,binding)
}
void run() {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
// if menu modifier is two keys we are out of luck as the javadocs
// indicates it returns "Control+Shift" instead of "Control Shift"
def menuModifier = KeyEvent.getKeyModifiersText(
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()).toLowerCase() + ' '
swing = new SwingBuilder()
frame = swing.frame(
title:'GroovyConsole',
location:[100,100],
size:[500,400],
defaultCloseOperation:javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE) {
def newFileAction = action(
name:'New File', closure: this.&fileNewFile, mnemonic: 'N',
accelerator: menuModifier + 'Q'
)
def newWindowAction = action(
name:'New Window', closure: this.&fileNewWindow, mnemonic: 'W'
)
def openAction = action(
name:'Open', closure: this.&fileOpen, mnemonic: 'O', accelerator: menuModifier + 'O'
)
def saveAction = action(
name:'Save', closure: this.&fileSave, mnemonic: 'S', accelerator: menuModifier + 'S'
)
def exitAction = action(
name:'Exit', closure: this.&exit, mnemonic: 'x', accelerator: 'alt F4'
)
def historyPrevAction = action(
name:'Previous', closure: this.&historyPrev, mnemonic: 'P', accelerator: 'ctrl P'
)
def historyNextAction = action(
name: 'Next', closure: this.&historyNext, mnemonic: 'N', accelerator: 'ctrl N'
)
def clearOutputAction = action(
name:'Clear Output', closure: this.&clearOutput, mnemonic: 'l', keyStroke: 'ctrl W',
accelerator: 'ctrl W'
)
def runAction = action(
name:'Run', closure: this.&runScript, mnemonic: 'R', keyStroke: 'ctrl ENTER',
accelerator: 'ctrl R'
)
def inspectLastAction = action(
name:'Inspect Last', closure: this.&inspectLast, mnemonic: 'I', keyStroke: 'ctrl I',
accelerator: 'ctrl I'
)
def inspectVariablesAction = action(
name:'Inspect Variables', closure: this.&inspectVariables, mnemonic: 'V', keyStroke: 'ctrl J',
accelerator: 'ctrl J'
)
def captureStdOutAction = action(
name:'Capture Standard Output', closure: this.&captureStdOut, mnemonic: 'C'
)
def largerFontAction = action(
name:'Larger Font', closure: this.&largerFont, mnemonic: 'L', keyStroke: 'alt shift L',
accelerator: 'alt shift L'
)
def smallerFontAction = action(
name:'Smaller Font', closure: this.&smallerFont, mnemonic: 'S', keyStroke: 'alt shift S',
accelerator: 'alt shift S'
)
def aboutAction = action(name:'About', closure: this.&showAbout, mnemonic: 'A')
menuBar {
menu(text:'File', mnemonic: 'F') {
menuItem() { action(newFileAction) }
menuItem() { action(newWindowAction) }
menuItem() { action(openAction) }
separator()
menuItem() { action(saveAction) }
separator()
menuItem() { action(exitAction) }
}
menu(text:'Edit', mnemonic: 'E') {
menuItem() { action(historyNextAction) }
menuItem() { action(historyPrevAction) }
separator()
menuItem() { action(clearOutputAction) }
}
menu(text:'Actions', mnemonic: 'A') {
menuItem() { action(runAction) }
menuItem() { action(inspectLastAction) }
menuItem() { action(inspectVariablesAction) }
separator()
checkBoxMenuItem(selected: captureStdOut) { action(captureStdOutAction) }
separator()
menuItem() { action(largerFontAction) }
menuItem() { action(smallerFontAction) }
}
menu(text:'Help', mnemonic: 'H') {
menuItem() { action(aboutAction) }
}
}
borderLayout()
splitPane(id:'splitPane', resizeWeight:0.50F,
orientation:JSplitPane.VERTICAL_SPLIT, constraints: BorderLayout.CENTER)
{
scrollPane {
inputArea = textArea(
margin: new Insets(3,3,3,3), font: new Font('Monospaced',Font.PLAIN,12)
) { action(runAction) }
}
scrollPane {
outputArea = textPane(editable:false, background: new Color(255,255,218))
addStylesToDocument(outputArea)
}
}
statusLabel = label(id:'status', text: 'Welcome to the Groovy.', constraints: BorderLayout.SOUTH,
border: BorderFactory.createLoweredBevelBorder())
} // end of frame
runWaitDialog = swing.dialog(title: 'Groovy executing', owner: frame, modal: true) {
//boxLayout(axis: BoxLayout.Y_AXIS) // todo mittie: dialog.setLayout -> dialog.contentPane.setLayout()
label(text: "Groovy is now executing. Please wait.",
border: BorderFactory.createEmptyBorder(10, 10, 10, 10), alignmentX: 0.5f)
button(action: action(name: 'Interrupt', closure: this.&confirmRunInterrupt),
border: BorderFactory.createEmptyBorder(10, 10, 10, 10), alignmentX: 0.5f)
} // end of runWaitDialog
// add listeners
frame.windowClosing = this.&exit
inputArea.addCaretListener(this)
inputArea.document.undoableEditHappened = { setDirty(true) }
systemOutInterceptor = new SystemOutputInterceptor(this.¬ifySystemOut)
systemOutInterceptor.start();
bindResults()
frame.show()
SwingUtilities.invokeLater({inputArea.requestFocus()});
}
void addStylesToDocument(JTextPane outputArea) {
StyledDocument doc = outputArea.getStyledDocument();
Style defStyle = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
Style regular = doc.addStyle("regular", defStyle);
StyleConstants.setFontFamily(regular, "Monospaced")
promptStyle = doc.addStyle("prompt", regular)
StyleConstants.setForeground(promptStyle, Color.BLUE)
commandStyle = doc.addStyle("command", regular);
StyleConstants.setForeground(commandStyle, Color.MAGENTA)
outputStyle = regular
resultStyle = doc.addStyle("result", regular)
StyleConstants.setBackground(resultStyle, Color.BLUE)
StyleConstants.setBackground(resultStyle, Color.YELLOW)
}
void addToHistory(record) {
history.add(record)
// history.size here just retrieves method closure
if (history.size() > maxHistory) {
history.remove(0)
}
// history.size doesn't work here either
historyIndex = history.size()
}
// Append a string to the output area
void appendOutput(text, style){
def doc = outputArea.styledDocument
doc.insertString(doc.length, text, style)
// Ensure we don't have too much in console (takes too much memory)
if (doc.length > maxOutputChars) {
doc.remove(0, doc.length - maxOutputChars)
}
}
// Append a string to the output area on a new line
void appendOutputNl(text, style){
def doc = outputArea.styledDocument
def len = doc.length
if (len > 0 && doc.getText(len - 1, 1) != "\n") {
appendOutput("\n", style);
}
appendOutput(text, style)
}
// Return false if use elected to cancel
boolean askToSaveFile() {
if (scriptFile == null || !dirty) {
return true
}
switch (JOptionPane.showConfirmDialog(frame,
"Save changes to " + scriptFile.name + "?",
"GroovyConsole", JOptionPane.YES_NO_CANCEL_OPTION))
{
case JOptionPane.YES_OPTION:
return fileSave()
case JOptionPane.NO_OPTION:
return true
default:
return false
}
}
private static void beep() {
Toolkit.defaultToolkit.beep()
}
// Binds the "_" and "__" variables in the shell
void bindResults() {
shell.setVariable("_", getLastResult()) // lastResult doesn't seem to work
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -