5.8.1 A Fancy Example

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.MetadataincludeTargets << 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.GriffonNameUtilsclass @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.Consoleactions {
       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

- griffon-app

- controllers

- sample

- `SampleController`

- models

- sample

- `sampleModel`

- views

- sample

- `SampleActions`
- `SampleContent`
- `SampleMenuBar`
- `SampleStatusBar`
- `SampleView`

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.