This section demonstrates how an archetype can be created and put to good use for building applications.

#1 Create the archetype

The first step is to create the archetype project and its descriptor, which can be done by executing the following command

griffon create-archetype fancy
cd fancy

#2 Tweak the archetype descriptor

Locate the archetype descriptor (application.groovy) and open it in your favorite editor, paste the following snippet

import griffon.util.Metadata

includeTargets << griffonScript('CreateMvc')

target(name: 'createApplicationProject', description: 'Creates a new application project', prehook: null, posthook: null) { createProjectWithDefaults()

argsMap.model = 'MainModel' argsMap.view = 'MainView' argsMap.controller = 'MainController' createMVC()

createArtifact( name: mvcFullQualifiedClassName, suffix: 'Actions', type: 'MainActions', path: 'griffon-app/views')

createArtifact( name: mvcFullQualifiedClassName, suffix: 'MenuBar', type: 'MainMenuBar', path: 'griffon-app/views')

createArtifact( name: mvcFullQualifiedClassName, suffix: 'StatusBar', type: 'MainStatusBar', path: 'griffon-app/views')

createArtifact( name: mvcFullQualifiedClassName, suffix: 'Content', type: 'MainContent', path: 'griffon-app/views')

Metadata md = Metadata.getInstance(new File("${basedir}/application.properties")) installPluginExternal md, 'miglayout' }

setDefaultTarget(createApplicationProject)

This archetype overrides the default templates for Model, View and Controller that will be used for the initial MVC group. It also creates 4 additional files inside griffon-app/views. Finally it installs the latest version of the MigLayout plugin.

#3 Create the artifact templates

According to the conventions laid out in the archetype descriptor there must exist a file under templates/artifacts that matches each one of the specified artifact types, in other words we need the following files

MainModel.groovy

@artifact.package@import groovy.beans.Bindable
import griffon.util.GriffonNameUtils

class @artifact.name@ { @Bindable String status

void mvcGroupInit(Map args) { status = "Welcome to ${GriffonNameUtils.capitalize(app.config.application.title)}" } }

MainController.groovy

@artifact.package@class @artifact.name@ {
    def model
    def view

// void mvcGroupInit(Map args) { // // this method is called after model and view are injected // }

// void mvcGroupDestroy() { // // this method is called when the group is destroyed // }

def newAction = { evt = null -> model.status = 'New action' }

def openAction = { evt = null -> model.status = 'Open action' }

def saveAction = { evt = null -> model.status = 'Save action' }

def saveAsAction = { evt = null -> model.status = 'Save As action' }

def aboutAction = { evt = null -> model.status = 'About action' }

def quitAction = { evt = null -> model.status = 'Quit action' }

def cutAction = { evt = null -> model.status = 'Cut action' }

def copyAction = { evt = null -> model.status = 'Copy action' }

def pasteAction = { evt = null -> model.status = 'Paste action' } }

MainView.groovy

@artifact.package@build(@artifact.name.plain@Actions)
application(title: GriffonNameUtils.capitalize(app.config.application.title),
    pack: true,
    locationByPlatform:true,
    iconImage: imageIcon('/griffon-icon-48x48.png').image,
    iconImages: [imageIcon('/griffon-icon-48x48.png').image,
               imageIcon('/griffon-icon-32x32.png').image,
               imageIcon('/griffon-icon-16x16.png').image]) {
   menuBar(build(@artifact.name.plain@MenuBar))
   migLayout(layoutConstraints: 'fill')
   widget(build(@artifact.name.plain@Content), constraints: 'center, grow')
   widget(build(@artifact.name.plain@StatusBar), constraints: 'south, grow')
}

MainActions.groovy

@artifact.package@import groovy.ui.Console

actions { action( id: 'newAction', name: 'New', closure: controller.newAction, mnemonic: 'N', accelerator: shortcut('N'), smallIcon: imageIcon(resource:"icons/page.png", class: Console), shortDescription: 'New' ) action( id: 'openAction', name: 'Open...', closure: controller.openAction, mnemonic: 'O', accelerator: shortcut('O'), smallIcon: imageIcon(resource:"icons/folder_page.png", class: Console), shortDescription: 'Open' ) action( id: 'quitAction', name: 'Quit', closure: controller.quitAction, mnemonic: 'Q', accelerator: shortcut('Q'), ) action( id: 'aboutAction', name: 'About', closure: controller.aboutAction, mnemonic: 'B', accelerator: shortcut('B') )

action( id: 'saveAction', name: 'Save', closure: controller.saveAction, mnemonic: 'S', accelerator: shortcut('S'), smallIcon: imageIcon(resource:"icons/disk.png", class: Console), shortDescription: 'Save' ) action( id: 'saveAsAction', name: 'Save as...', closure: controller.saveAsAction, accelerator: shortcut('shift S') )

action(id: 'cutAction', name: 'Cut', closure: controller.cutAction, mnemonic: 'T', accelerator: shortcut('X'), smallIcon: imageIcon(resource:"icons/cut.png", class: Console), shortDescription: 'Cut' ) action(id: 'copyAction', name: 'Copy', closure: controller.copyAction, mnemonic: 'C', accelerator: shortcut('C'), smallIcon: imageIcon(resource:"icons/page_copy.png", class: Console), shortDescription: 'Copy' ) action(id: 'pasteAction', name: 'Paste', closure: controller.pasteAction, mnemonic: 'P', accelerator: shortcut('V'), smallIcon: imageIcon(resource:"icons/page_paste.png", class: Console), shortDescription: 'Paste' ) }

MainMenuBar.groovy

@artifact.package@import static griffon.util.GriffonApplicationUtils.*

menuBar = menuBar { menu(text: 'File', mnemonic: 'F') { menuItem(newAction) menuItem(openAction) separator() menuItem(saveAction) menuItem(saveAsAction) if( !isMacOSX ) { separator() menuItem(quitAction) } }

menu(text: 'Edit', mnemonic: 'E') { menuItem(cutAction) menuItem(copyAction) menuItem(pasteAction) }

if(!isMacOSX) { glue() menu(text: 'Help', mnemonic: 'H') { menuItem(aboutAction) } } }

MainContent.groovy

@artifact.package@label('Main content')

MainStatusBar.groovy

@artifact.package@label(id: 'status', text: bind { model.status })

#4 Package and install the archetype

This step is easily done with a pair of command invocations

griffon package-archetype
griffon install-archetype target/package/griffon-fancy-0.1.zip

#5 Use the archetype

Now that the archetype has been installed all that is left is put it to good use, like this

griffon create-app sample --archetype=fancy

This command should generate the following files in the application directory

If you inspect the application.properties file you'll notice that the miglayout plugin has been installed too.

Archetypes can be versioned, installed and released in the same way plugins are.