Seedlet
is an easily-embedded, source-code-embeddable, simple AWT GUI for standalone Java applications. It can be used as a realtime test platform
for any class, as a GUI front-end for command-line APIs or as the basis for a complete desktop application. It provides a basic yet very flexible and
extensible GUI, more GUI-construction equipment for convenience and a lot of extra tools 'under the hood,' both for testing and for application use. The
Seedlet GUI itself is simple and straightforward but, since Seedlet
extends java.awt.Panel
, it can provide a GUI as complex as is
needed for any occasion.
Seedlets are designed to be source-code embedded. The first step is to include its code (cox/jmatt/java/seedlet/*
) in your project. It has no
external dependencies so there are no other libraries necessary. Just drop in the source code and it's ready to go. To create a Seedlet,
import cox.jmatt.java.seedlet.Seedlet; public class MySpecialSeedlet extends Seedlet { // Application code and overridden Seedlet methods. // All Seedlets Must Have A Name! public String getName() { return "My Special Seedlet"; } public static void main(String[] args) { new MySpecialSeedlet().runMyself(); } }and it is done. For testing a class, this is the only Seedlet reference needed. Create the class ('// Application code...') and define Seedlet methods to test it. GUI elements can be added or the six predefined Function Buttons can be used. Once the class being tested is ready, the Seedlet code can be deleted and the now-ready API deployed. Or, to allow further development, simply instruct the compiler to ignore it.
The protected final runMyslef()
method is where the magic happens. It creates the GUI, initializes the things that need it and begins the Seedlet
lifecycle. It handles the built-in GUI elements and provides other GUI services. The base Seedlet GUI consists of a BorderLayout Panel with a TextArea in the
center. This is 'The Console' and it receives text output. To the left are the six Function Buttons, F1 through F6, along with the Console Help button ('?').
Each of these buttons is connected to an empty method designed to be overridden. The 'F' buttons are totally empty and undedicated. The Help button connects
to the (empty) consoleHelp()
method intended to provide abbreviated help hints for using the program.
To the right of the console are the Clear button ('CC') along with seven Checkboxes. Five of these correspond to logging levels: Trace, Debug,
Info, Error and Fatal. The 'ST' checkbox enables/disables stack trace printing and the 'CB' checkbox controls clipboard access. There are
four more buttons at the very bottom: '[|<]', '[<<]', '[>>]', '[>|]'. These are used to flip between Panels (cards) when a CardLayout is
used. In order, the Button methods are firstCard(), previousCard(), nextCard() and lastCard()
. One of the things Seedlet does is to make using a
CardLayout completely hassle-free.
Since Seedlet
provides a console, it also provides a number of methods to use it. The most basic method is println()
This
method takes a String argument and prints it on the console along with a newline. The printClip()
method takes a String and places it into the
system clipboard subject to two things: the clipboard must be available and the 'CB' box must be checked. If the 'ST' box is checked, printStackTrace()
takes a Throwable
, extracts the stack trace (getStackTrace()
method) and prints it on the console.
Seedlet
defines a simple yet flexible logging mechanism. There are five levels: Trace for fine-grained use, Debug for development and trouble spots,
Info for useful information that isn't necessarily an error condition, Error for serious erros and potential crash-spots, and Fatal for conditions that will
terminate execution. Each of these levels has three methods defined for it: isLevelEnabled(), level(String) and level(String,
Throwable)
. If the corresponding Checkbox is checked, the message and stack trace ('ST checked) are printed to the console.
To avoid embedding Seedlet logging statememts, if that is desirable, the Seedlet package includes a helpler class: SeedJULHandler
. This extends
java.util.logging.Handler
and uses a Seedlet to receive log messages. Simply use Java's logging framework and configure the Seedlet to receive
messages. Then, when the other class is deployed, Java-based logging is already included.
Seedlet makes an excellent platform for working with XML. That's because of its auxillary classes SeedDefaultHandler, XMLSeedKit
and XMLTag.
SeedletDefaultHandler
extends the SAX Handler2 class and implements the XSLT and DOM Error-catching methods in order to direct them to the Seedlet logging
methods. None of the other methods are defined (Asterisk: startDocument()
clears out the SAX error counts) so all of the actual XML handling
methods are available. Extending this class allows the best of all worlds: total XML error handling plus whatever processing the application needs.
XMLSeedKit
provides an easy way to create and use SAX, DOM, XPATH and XSLT. It has a place for an alternate ClassLoader (and Seedlet provides one)
to locate and use any of the factory classes. Best of all, the XMLKit can handle parsing, XPath and transforms totally internally. Although it has the
ability to create the tools to manipulate XML, this is not necessary. Whenever it creates an XML tool, it retains an internal copy. It also defines the methods
to use these internal tools and present the results as simple Strings or whatever else is needed.
The XMLTag
class is a low-level String-crunching monster. Its primary purpose was creating large numbers of basically-similar XML tags but it can
be used for more than that. It doesn't worry about SAX, DOM or any high-level XML standards. All it does is crunch Strings to create well-formed XML tags. It
handles attributes, content and formatting and its toString()
method produces a well-formed XML tag. It's also designed for subclassing so it can
be used as a base class for creating other specific tag classes. As an added bonus, the class includes a macro language designed for quick tag creation and
configuration.
There are two templating engines (static methods) in the base Seedlet class. The basic one, fillTemplate()
accepts a String template and a String
array of replacement values. The process is position based; the template includes replacement tokens of the form '<N>' where N is the index
of the array element to replace. This method is designed for simple, position-based replacement.
fillMondoTemplate()
is a keyword-based process that uses a Map<String, String>
for replacement values. It includes a set of
built-in tokens, a String array for positional replacement, an index parameter and a timestamp-formatting String. This method is more versatile and more
flexible, at the cost of a slightly higher learning curve.
Seedlet.processMacro()
provides Seedlets and other arbitrary classes a way to embed a simple line-oriented macro interpreter. Although designed
with GUI configuration in mind, this is by far not the only use for this tool. In operation, each line is interpreted as a single command. The first non-whitespace
character is the command ('opcode') and the rest of the line, data. Including macro processing is as simple as implementing the MacroListener
interface. Seedlet implements it automatically but it is provided to allow macro capacity for other classes as well (e.g. XMLTag
).
One of the brightest crown jewels in the Seedlet package is its scripting capability. The static Seedlet.runSeedletScript()
method makes using
JSR 223 (javax.scripting.*
) both easy and fun. The ScriptListener
interface, again implemented by Seedlet, allows any class to include
and benefit from scripting. If that isn't enough, Seedlet also provides a GUI panel designed specifically to implement scripting.
The companion SeedConsole
class is designed to allow script access to Seedlet's handier methods. It also provides access to a Properties object
and a way to guarantee a return value from a script.
The Seedlet package provides a trifecta of JDBC/SQL tools: JDBCSeedKit, SQLListener
and the SQL (Loadable)Panel. JDBCSeedKit
contains
equipment to create and manipulate JDBC things in a completely 'hands-free' manner. Everything necessary to execute SQL statements is contained within
and error-wrapped for safety. On the other hand, it also allows full access and modification of each of these things. Using JDBCSeedKit, it's possible
to automatically create everything up to the java.sql.Statement
, pull it out of the box and handle things manually from that point on. Or, the
Statement can be adjusted and put back into the box for more automatic handling.
The SQLListener
interface provides execution- and result-processing tools. Executing SQL can produce a mixture of ResultSet
objects
and update counts. JDBCSeedKit's execution methods detect the what and the what order and dispatch to the SQLListener's methods accordingly. Add to the mix
the multi-talented static JDBCSeedKit.formatResultSet()
method, which actually uses Seedlet.fillTemplate()
under the hood, and the
result is a fast, simple way to create, query and format database operations. As an added bonus, formatting can be adjusted within the SQL by
a 'micro-macro' language embedded in SQL comments.
The SQL Panel provides a ready-made GUI element (LoadablePanel) capable of configuring and using JDBCSeedKit equipment from a GUI. Besides the Panel, there
is also an associated configuration Dialog
full of configuration options.
A LoadablePanel
is a BorderLayout Panel with four buttons standard and other components possible. The common buttons are 'Load', 'Run', 'Clip' and
'Clear'. 'Load' opens a FileDialog
and copies the contents of the selected file into the TextArea in the center. The 'Run' button makes something
happen, 'Clip' copies the TextArea into the clipboard and 'Clear' clears it.
The specific flavors of LoadablePanel
are Script Panel, Macro Panel, ClassLoader Panel, Mondo Template Panel and SQL Panel. The Script Panel loads and
runs a script. It has extra components for setting the language and script engine lookup method. The ClassLoader Panel provides a way to select files or other
URLs and build an URLClassLoader
from them. Classes that need it (such as XMLSeedKit) can access it through the protected '_altClassLoader' field
that Seedlet provides. The Mondo Template Panel holds a template (Mondo) and fills it from a Properties object.
The Macro Panel loads and executes a macro. It also provides a way to parse a Properties-formatted text file into a Properties
object and store
it in a protected field, '_scriptPizza'. Classes that need access have it and any Macro Panel can set it. Finally, Macro Panel can load an XMLTag
macro and create an instance from it. The SQL Panel puts a GUI on the JDBCSeedKit
class which provides an easy way to create and manipulate
databases via JDBC.
Besides the GUI, runMyself()
starts and manages the Seedlet lifecycle. There are five methods, four of which are patterend after Applet
and one that isn't. All of these methods are handled automatically and need only be overridden to take advantage of them.
init()
- Called one time only, after runMyself()
and before the GUI is created. This is the place to create any custom GUI
elements and to take care of resource creation and initialization.start()
- Called once (guaranteed) after init()
and any time the GUI is de-iconified. The GUI has been created and is available.
This method is best used to start tasks that require the user's undivided attention.stop()
- Called any time the GUI is iconified (minimized) and once, guaranteed, before destroy()
. The GUI is still active so
this is not the place to get rid of GUI elements.destroy()
- The last method called before the Seedlet dies. The GUI has already been taken down and disposed and won't be available. This
is the place to get rid of any external resources that need to be freed up or destroyed.reset()
method is not a formal part of the lifecycle but is considered as such. It was designed to give Seedlet subclasses 'reset' capability,
whatever that might entail.
Although not a part of the formal lifecycle, getMenus()
also deserves attention. Since the containing Frame is handled automatically, this method
provides a way to add Menus. The default implemention returns null but can return an array of Menus. If so, they will be added to the Frame's menu bar in array
order. A companion method, Seedlet.quickMenuItem()
, allows very fast creation and configuration of Menus, MenuItems and CheckboxMenuItems.
In addition to this, Seedlet
provides a lot more equipment and convenience methods, all designed to simplify application testing and development.
Most of these methods are designed around common tasks, to alleviate the need to re-do them in every single application. An example of this are the polymorphic
copyStream()
methods. These copy data from any combination of InputStream/Reader to OutputStream/Writer. Handy to have and easy to do,
through Seedlet
.
The Seedlet JAR is executable. Its Main-Class is TestSeedlet
and it is designed to showcase and demonstrate the machinery Seedlet provides. As
such, it also provides a basic scripting environment, complete with SeedConsole, XMLSeedKit
and others. The GUI demonstrates how easy it is to
use a CardLayout, each of the specific LoadablePanels, a generic one and two custom Panels. Although meant only to demonstrate, TestSeedlet
can
also be extended. Simply overriding configureScriptEngine()
allows extra scripting tools to be added, transforming the simple TestSeedlet into a
fully-customized and more powerful scripting environment.
The Seedlet package is released under the Apache Software License. Since it is designed for source-code embedding, this license applies only to the
Seedlet
source code. Anything outside the cox.jmatt.java.seedlet.*
namespace is excluded, and can be licensed any way, including
commercially. See the Seedlet package.html javadoc for details.
If desired, the Seedlet code can also be released under other licenses, provided they are open-source and encourage the use of Seedlet. The only proviso, and this includes the Apache license, is that the source code be included AS-IS, including the javadoc and 'package.html' file.
The Namespace. When using Seedlet, even for deployed applications, please do not use the cox.jmatt.java.*
namespace. The reason for this is
to avoid collision with other Java projects, which do or will use only this.
Seedlet had an interesting and humble beginning. The name is a rough contraction of 'CD Applet,' which was the original intent. The original, unpublished Seedlet was designed to provide a test platform for other classes or a GUI front-end for command-line packages. It was meant to be quickly written and burned to a CD as an executable JAR. This way no command line was required, only an operating system that understood executable JARs.
Seedlet
was initially written to provide a simple snap-on GUI for programs and packages that needed one. From those humble beginnings it grew.
Most of the functionality sprang from tasks that had to be done manually more than three times. After many iterations, the current Seedlet
was
born. This code is much lighter and more agile than its predecessors, hence the name SeedLite. Even though this is the name of the JAR file, the
class and philosophy are all Seedlet. It is designed to meet three goals.
A Test and Development Platform. Seedlet is an excellent way to develop classes designed for command-line use. It provides interactive testing and logging capability. Since it isn't meant to be deployed, the launch class can be included in the 'seedlet' directory alongside the other classes. This keeps all Seedlet code out of the files meant for deployment. When the class is ready to go, the Seedlet directory tree can be deleted or moved without a trace. Or, the compiler can be instructed to ignore it.
A GUI Front-End. The pre-Seedlet code came from a desire to experiment with the Apache Xerces, Xalan and FOP packages. The desire, if not the code, remained throughout Seedlet development. Seedlet can be compiled with or without the desired package code. For the latter option, simply include the required JAR files in the classpath and manifest file and deploy only the Seedlet. If the application only requires a single launch class, and no others, it can be included in the seedlet directory provided it is documented as an additional class and NOT part of the original code. All other conditions still apply.
Seedlet As An Application. This is the most versatile use for Seedlet. Seedlet-based applications allow the full range of equipment to be used throughout the entire application. The GUI becomes the easiest part to create with the lifecycle, scripting and other equipment as a bonus. To create a Seedlet application, include the Seedlet directory in the source code tree and create the launch class outside it. Done.
Licensed For Personal Use. And all other uses, of course, but especially for personal use. After the first few, writing Seedlets becomes automatic.
Give it a name, override init()
for custom GUI elements and start hacking out the code. This means it is basically a non-task to slap a GUI on
highly-specialized, personal-use programs. This makes GUI-based code almost as easy to write as command-line. Adding a manifest and JARring it yields a 'clickable'
application that can be burned to a CD, put on a pen drive etc. For extra versatility, write the main()
method to skip runMyself()
if the argument array is not empty. Presto! The result is an application usable from the GUI and command line both. Nothing in the Seedlet
precludes
a non-zero-argument constructor or requires that it have a GUI. In fact, a Seedlet doesn't become a Seedlet until runMyself()
is called.
The base Seedlet
code has no dependencies outside Java. No external packages are required unless a Seedlet-based application requires one.
This results in an incredibly easy application to deploy: simply copy the JAR anywhere, no batteries required. If the application doesn't require anything outside
Java, it can also be easily deployed anywhere.
For applications that do require external packages, including the source code still results in no external dependencies. This may not be the best option for
webapps or server-based technology but Seedlet
is designed for desktop applications where no dependencies is a good and desirable thing.
Since the GUI is simple, it's also ideal for large-scale deployment and support. Non-fluffy GUIs make for easier user support in a decentralized-deployment
environment. It also leads to fewer GUI-related problems.
(Copied from 'package.html'.)
If you use my code and you make lots of money, you owe me a pizza. Maybe two. If we ever meet in person, which isn't likely given how little I travel.
If you use my code and you really think I should get some money OR if you really like great science fiction, please consider buying my books. They're available at Amazon, Smashwords and DriveThruFiction. If you're into paper-and-dice fantasy RPGs, I've also published my own system: Dungeon Crawl Unlimited. Go from zero to game in 30 minutes or less and have a lot of fun doing it.
My contact information/pages are:
Whew! Having said all of this, I hope you enjoy using Seedlets
as much as I enjoyed writing them.
James Matthew Cox, Jr.
29 December, 2015