TrekGui.groovy
package net.ebdon.trk21;
import groovy.swing.SwingBuilder;
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.*;
import java.awt.*;
import java.text.MessageFormat;
/**
* @file
* @author Terry Ebdon
* @date January 2019
* @copyright
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
@brief GUI for A Groovy version of the 1973 BASIC-PLUS program TREK.BAS
@author Terry Ebdon
@date JAN-2019
*/
@groovy.util.logging.Log4j2
final class TrekGui extends UiBase {
def swing = new SwingBuilder();
static main( args ) {
new TrekGui().run()
}
@Override void outln( final String str ) {
swing.output.text += "$str\n"
}
@Override void setConditionText( final String displayableCondition ) {
swing.condition.text = displayableCondition
}
def setDefaultFonts() {
// see: https://www.rgagnon.com/javadetails/java-0335.html
// Font f2 = new Font( 'monospaced', Font.BOLD, 20 ) // 28 )
Font f2 = new Font( *(config.gui.font.standard) )
java.util.Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get (key);
if (value instanceof javax.swing.plaf.FontUIResource) {
UIManager.put (key, f2);
}
}
}
@Override Float getFloatInput( final String prompt ) {
String rv = ''
while( !rv.isFloat() ) {
rv = JOptionPane.showInputDialog( swing.trekFrame, btnText( prompt ) )
if ( rv ) {
if ( !rv.isFloat() ) {
JOptionPane.showMessageDialog( swing.trekFrame, pleaseEnterNumber() )
}
} else {
rv = '0'
}
}
Float.parseFloat( rv )
}
/// @return A localised display string for the ship's condition
/// @todo Move displayableCondition() into FederationShip
/// @todo Localise via the #rb resource bundle.
/// @bug Code assumes that all condition values, other than "DOCKED",
/// are also valid HTML colours. This is currently true for ENGLISH
/// locales, but will fail for other languages. Colours and language
/// should be orthogonal.
/// @todo Consider splitting into two methods, to allow use where HTML is
/// not appropriate.
String displayableCondition() {
trek.ship.with {
/// @bug Can be condition GREEN without being docked.
/// e.g. if energy > 10% && no enemy in current
/// or surrounding sectors.
/// @todo Font size should be based on cong, not HTML.
def colour = condition != 'DOCKED' ? condition : 'GREEN'
"<html><font size=+2 color=$colour>${condition}</font></html>"
}
}
@Override void run() {
// assert damage
trek.setupGame()
log.info "Message font: ${config.gui.font.message}"
Font f2 = new Font( *(config.gui.font.message) )
setDefaultFonts()
javax.swing.UIManager.put("OptionPane.messageFont", f2 );
swing.edt {
frame(id: 'trekFrame', title: 'Trek GUI', defaultCloseOperation: JFrame.EXIT_ON_CLOSE, pack: true, show: true) {
vbox {
panel( id: 'btnPanel' ) {
gridLayout( cols: 2, rows: 0 )
button( text: btnText('Short Ranger Sensors'), actionPerformed: { trek.shortRangeScan() } )
button( text: btnText('Long Ranger Sensors'), actionPerformed: { trek.longRangeScan() } )
button( text: btnText('Set Course'), actionPerformed: { trek.setCourse() } )
button( text: btnText('Damage Control'), actionPerformed: { trek.reportDamage() } )
button( text: btnText('Fire torpedo'), actionPerformed: { trek.fireTorpedo() } )
button( text: btnText('Fire phasers'), actionPerformed: { trek.firePhasers() } )
button( id:'condition', text: displayableCondition() )
}
scrollPane( border:BorderFactory.createRaisedBevelBorder() ) {
textArea( id: 'output' ) //, text: '\n' * 20 )
}
}
}
}
trek.startGame()
// log.info "** Game Over **"
return
}
}