Anda di halaman 1dari 91

Swing-XML Authoring Tool

v. 0.5.5

User Guide
byPaoloMarrone http://www.swixat.org Nov15,2006

TheSwingXMLAuthoringToolUserGuide

Table of Contents
Introduction.......................................................................................................................... .....................4 Chapter1:TheMVCParadigm........................................................................................................ ........5 HowtheMVCpatternisimplementedinSwiXAT................................................. ..........................6 TheView................................................................................................................ .............................8 TheController.............................................................................................................. ........................9 TheCommandBindingmechanism................................................................................. ..............9 Scripting............................................................................................................................... ..........11 ApplicationContextbasedmechanism........................................................ ...........................11 Directimportingbasedmechanism.......................................................................... ...............12 MeaningoftheReturnedValue................................................................................ ...............13 Automaticdeclarations............................................................................................................ ......14 ImportedPackages............................................................................................................. .......14 PredefinedObjects.................................................................................................................. ..14 EventsHandling.................................................................................................. ..........................15 Window'sEvents........................................................................................... ...........................15 Components'Events....................................................................................... ..........................17 IndirectCommandBinding:the<Action>tag..................................................... .......................19 SpecialActionCommands.................................................................................................... .........21 Reservedwords.............................................................................................................. ...........21 Staticmethodinvocation................................................................................................... .......22 Multiplecommandsupport............................................................................................. ........23 Invokingacommandfromwithinscriptcode............................................................. ................23 TheModel.............................................................................................................. ............................23 DataSources...................................................................................................................... .............24 The'origin'attribute.............................................................................................. ...................24 OriginattributeinJButtonandJMenuItem.......................................................... ..................24 Originattributeinbuttongroups................................................................................ .............25 The'render'attribute.............................................................................................................. ...25 TheDataSource'scommonattributes............................................................................ ..........26 The<ContextDataSource>................................................................................................... ...27 The<ScriptingDataSource>........................................................................... ........................27 The<XPathDataSource>.................................................................................. ......................27 The<ObjectDataSource>....................................................................................................... ..28 The<DOMDataSource>............................................................................................. .............29 HowtouseXPath................................................................................................................... .......29 TheContext............................................................................................................................... .....31 The'current'context.............................................................................................. ...................32 The'shared'context.............................................................................................. ....................34 Context'skeysaccessorsmethods............................................................................................ 34 Updatingthemodel:theUpdateOrigincommand................................................................... ....35 Usingthe'update(...)'command......................................................................... .....................36 Page2

TheSwingXMLAuthoringToolUserGuide

TheModel'seventshandling............................................................................. ...........................37 Chapter2:SpecialFeatures........................................................................................... .........................41 SupportforMDIapplications............................................................................................. ...............41 The<WindowMenu>tag........................................................................................... ...................41 The<MDIDesktopPane>tag.............................................................................................. ..........42 The<ModalInternalFrame>tag.......................................................................... .........................43 SupportforJComboBoxandJListcomponents.............................................................. ................43 The<ComboModel>and<ListModel>tags............................................................. ..................43 The<ComboBoxRenderer>tag................................................................................................... .44 TheComboBox'svaluesattribute................................................................................ .............45 SupportforJTreecomponents................................................................................................... ........45 The<TreeModel>and<TreeCellRenderer>tags.............................................................. ..........45 The<NestedTreeModel>and<TreeNode>tags......................................................................... .49 TheenhancedRenderermechanisms............................................................................ ....................50 The<XPanel>,<XMenuBar>and<XToolBar>tags................................................................... ....51 The<DatePanel>and<DateField>tags............................................................................ ...............52 The<TableChooser>tag................................................................................................................ ....53 SupportforJTablecomponent....................................................................................................... ....54 The<WizardPanel>tag............................................................................................ .........................57 The<CardPanel>tag................................................................................................. ........................60 SupportforDockingPanels....................................................................................................... .........62 SupportforPopPupMenus............................................................................................................. ...64 ThreadedActionCommands............................................................................................. ................65 SupportforTesting.................................................................................................................... .........67 Chapter3:TheApplicationContextXMLfile............................................................ .........................68 HowtolaunchaSwiXATbasedapplication.................................................................... ................69 HowtowritetheApplicationContext......................................................................... .....................69 TheApplicationspecificbeans.......................................................................................... ...............69 TheApplicationbean.................................................................................................... ...............70 TheCommandbeans............................................................................................................ .........73 TheApplicationindependentbeans..................................................................................... .............74 TheScriptManagerbean......................................................................................... ......................74 TheTagLibraryextensions........................................................................................................ ....75 TheSetterFactorybean.................................................................................... .............................76 Chapter4:GettingStarted..................................................................................................... .................78 HowtobuildSwiXATfromSource........................................................................................... ......78 HowtocreateaSwiXATbasedSampleApplication.................................................................... ..79 TheHelloWorldexample...................................................................................................... ............82 Example1:ThestaticHelloWorldexample........................................................ .......................82 Example2:InsertingaButton........................................................................................... ...........83 Example3:AddingaDataSource....................................................................... .........................85 Example4:Passingparametersbetweentwoframes.................................................. ................86 Example5:Validatingtheuser'sinput................................................................................. ........88 Chapter5:Extendingtheframework................................................................................. ....................90 Howtoaddnewcommands....................................................................................................... ........90 Page3

TheSwingXMLAuthoringToolUserGuide

Introduction

Introduction
This document aims to explain the functional details of the SwiXAT framework (SwingXML AuthoringToolhttp://www.swixat.org),inordertopermitanyoneinterestedtouseallthefeatures oftheframework. WhatisSwiXAT? SwiXATisthenameoftheframeworkbuiltwiththeaimofprovidingapowerfulUserInterface frameworkbasedonSwingandXML.ItallowsnewJavaapplicationstobebuildsimplybywriting XMLparametersandscriptedJavacode. WhyuseSwiXATifaGUIapplicationcanbesimplywrittenbyusingJavaSwing? IttakesalotofworktodevelopaSwingapplication,layingoutandconfiguringGUIcomponents, andthenintegratingthemwiththeapplicationfunctionality.SwiXATaddressesbothoftheseissues byprovidingaframeworkbasedonacompleteimplementationoftheMVCarchitecturalpattern. Thebenefitsobtainedbyasuchframeworkarethefollowings: 1. ArchitecturalCorrectness :ByadoptingatrueMVC(ModelViewController)basedframework, itisveryeasytocorrectlyimplementanyUIapplication.It'snotdifficulttowriteaJava/Swing application,butwhat'sverydifficultistobuildagood,welldesignedSwingapplication,where theadoptionoftheMVCparadigmpermitstoreducethemaintenancecosts,thankstotheclean separationbetweentheviewandtheapplicationlogic. 2. DevelopmentSpeed :Theadoptionofaframeworkreducesthedevelopmentcostbyproviding outofbox,wellintegratedandeasytousecommonfeatures,likewizards,plugins,supportfor MDI interfaces, etc. Moreover, theuseof XML todefine theuser interface, as well as the adoptionofaninterpretedscriptinglanguage,permitstoimplementthe'Code&Test'development style,wherethecompilationtimeisreducedtozero. 3. CodeReuse :Thenetseparationbetweentheviewandthecontrollogicpermitstowritereusable modules that can be combined in several manners. The developer is naturally induced to modularize the application and write reusable code, minimizing the effort of building new applicationsoraddingnewfunctionalitytoexistingones. Toaccomplishtheabovegoalswedon'tneedtoimplementamonolithicapplication,butrather thoughttodevelopapowerfulframeworkwheretheusercanassembleprebuiltbuildingblocksto implementtherequiredapplication. SwiXATisalltheabove,andwehopeyou'llappreciateoureffort.

Page4

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Chapter1:TheMVCParadigm
WhatweneedisthepossibilitytodefinetheUIpurelyintermsofwritingexternalparameters,for instancebymodifyingXMLfiles.ConsequentlyweneedaJavalibrarytodefineaswinguser interfacethroughXMLtags. Theideaisasfollows: WeneedtostartwiththedefinitionoftheMVCarchitecturalpattern,asdepictedinthefollowing figure:

Model

4 5
View

2 1 3
Controller

Method call Event notification


The View representstheuserinterface(frames,panels,etc)containingalltheavailablecontrols (buttons,labels,textboxes,etc). The Model represents the objects and the entities handled by the application (i.e. the internal representationofthebusinessmodel). TheControlleractslikeagatewaybetweentheViewandtheModel.Thisprovidesamechanismto notifytheModelaboutmodificationsmadebytheuser,andtodisplaychangestothemodelinthe correspondingView. Thecontinuousblackarrowsrepresentmethodcalls,whereasthedottedredarrowsrepresentevent notifications. Theinternalpatternmechanismworksasfollows: We'llstartfromasituationwhereaViewisalreadydisplayedtotheuser,ands/hestartstointeract withit.Followthenumberedarrowsintheabovefigure: Page5

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

1. TheViewnotifiestheControlleraboutauser'saction(likeabuttonclick). 2. TheControllercallsthecorrespondingmethodsontheModel'sobjectstoexecutethechanges theuserhasrequested(thestartofadownloadfromaremoteserver,forinstance). 3. TheControllershowsthecorrespondingViewinresponsetotheuser'saction(apanelcontaining theprogressbar,forinstance).Whendisplayed,theViewregistersitselfasaModel'sevents listener. 4. The Model notifies all the registered Views about any changes within it (for instance, the downloadofapercentageofbytes). 5. Inresponseoftheabovenotification,theViewgetsfromtheModelalltheinformationsitneeds toshowitself(forinstance,thecurrentdownloadedbytes). We will not discuss all the benefits of the MVC pattern at this time, because anyone who is interested can read a lot of documentation on Internet. We will instead concentrate on the implementationoftheMVCmoduleswithintheframework.

HowtheMVCpatternisimplementedinSwiXAT
BeforetostarttoexplainallthefeaturesofSwiXAT,webelieveit'sveryimportanttogiveyouan overviewabouthowthisframeworkisorganizedandwhatarethemainmodulesinterested. ThefollowingpictureillustratestheoverallarchitectureonwhichSwiXATisbased,intermsof usedlibrariesandneededexternalparameterfiles:

Model

Business Model

Data Model

DataSourceAdapters JXPath View SwiXML Controller BeanShell Spring XML Application Context

XML XML XML View View Views

XML XML View Scripts View

Page6

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Asclearlyshown,SwiXATrepresentsonlythegluebetweenthedifferenttechnologies/frameworks used.ThemaingoalistopermitthedeveloperstowriteanentireapplicationbywritingonlyXML andscriptingcode.Thenecessityforcompiledjavacodeisalmosttotallyeliminated,resultinginan improveddevelopingspeed,easeoftesting,codereusabilityandreadability. TheauthorsofSwiXAThavemadewhatanyconscientiousapplicationdesignershouldalwaysdo: todefineanoverallarchitecturebasedonwellknowndesignpatterns,andthenchoosethebestOS frameworksthatpermittoimplementeasilysuchdesignpatterns.Theparadigmis:donotstartfrom scratch,butclimbontheshouldersoftheGiants. Wehavesimplywrittenthecodeneededtoputitalltogether,hopingyou'llappreciateourchoices (beingitanOpenSourceproject,you'reinvitedtoparticipate,inordertochange/improvethethings youdon'tlike). ThemainelementsinvolvedinanyapplicationbuiltontopofSwiXATarethefollowing:

TheViewisbasedontheXULparadigm,wherethedesignoftheUIinterfaceismadebywriting XMLtagsinsteadofSwingJavacode.XMLpermitstowritelesscoderespecttotheequivalent javastatementsneededtobuildthesameuserinterface.SwiXMListheXULframeworkchosen for this purpose, mainly due to its fundamental characteristics like the robustness and extensibility. TheControllerhandlesrequestsandcreatesorpreparestheresponse.Typicallycontrollersneed accessbothtotheViewandtothebusinesslogic(theModel).Controllershandletherequestby instantiatingacommandobject,passingitrequestparameters.Controllershandletheresponseby delegatingtoaviewandoptionallypopulatingamodel.Controllersneedtobeconfiguredwith theSpringIoCframework.The Controller candelegatetheexecutionofthecontrollogicto scriptcodebasedontheBeanShellinterpreter(asofSwiXAT0.3.0wehaveaddedthesupport fortheGroovylanguage).Theuseofscriptingcodepermitsustowriteveryfastlyallthecontrol (NOTthebusiness)logicofourapplication.Forourchoice,allthescriptcodeisseparatedby theXMLusedtodescribetheviews;inthismannerweguaranteeacleanseparationbetweenthe viewandthecontroller,avoidingtobuildstrangemixturesofXML/JavaScriptthatmakethe applicationveryhardtoreadandmaintain.Thisdecouplingalsoguaranteesastrongreusability ofthedefinedviews(i.e.thesameviewusedindifferentcontextsmightneedadifferentlogic behindit).Ofcoursetheuseofscriptcodeisnotmandatory,becausethedeveloperisfreeto implementthecontrol'slogicwithinstandard(compiled)javaclasses. The Model,representedbyyourowndatamodeland/orobjectmodel,isaccessedbyspecific datasources,thatrepresentthebridgebetweentheModelandtheView/Controllerparts.Some prebuiltdatasourcesalreadyexist(andmanyotherswillbeimplementedinthenextreleases), butthey'reeasilyextensible,andanyonecanbuildanewonetoaccesstoanyspecificdata format.Inordertopermittonavigatethebusinessmodelobtainedbyadatasource,weuse XPath,averypowerfulquerylanguageusedtotraverseDOMtrees.Asanobjectmodelcanbe viewedasahierarchicaltree,weuseJXPathafreejavaimplementationoftheXPathlanguage tonavigateourownspecificobjectmodel Page7

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

AlltheabovecomponentsarekepttogetherbytheSpringFramework,acompleteandpowerful implementationoftheInversionofControlpattern.TheSpringIoCimplementationpermitsto definewithinanXMLfileallthecomponentsneededbytheapplication(alongwithalltheir dependencies).InthismannerSpringrepresentsapowerfulmechanismtodefineandaccessto alltheneededparameters(thesocalledApplicationContext),permittinginthismannerto write within external resources all the dependencies between the different pieces of our application (as an example, the binding between the UI components and the associated commandsisdefinedwithintheSpringXMLfile)

Inordertobuildanapplication,thedevelopersneedonlytowritetheexternalfilescontainingthe neededXML(todefineboththeapplicationcontextandtheviews)andJavaScriptcode(towrite thecontrollogic),depictedintheabovefigurewithwhiteboxes. Thefollowingchapterswillexplainallthedetailsoftheabovearchitecture.

TheView
InordertobeabletoeasilydefineaViewwithoutwritingJavacode,theuserinterfacewillbe definedbyXMLtagsasinthefollowingexample.Thefollowingcodemightbecontainedinafile namedControlPanel.xml. <Panel name=Control Panel> <button text=Start .../> <button text=Stop .../> ... </Panel> Inthismannerwecouldwriteseveralusefulreusablepanelsthattheusercouldconnecttogetherto buildthefinaluserinterface.Ofcoursetheusercanbuildnewpanelsifneeded. Severalpanelscouldbeassembledwithinaframe(oraanyotherContainerobject)justbyusingan appropriatetagbuiltto'include'onepanelwithinanother.Thistag hasbeennamed<XPanel> (standingforeXternalPanel)andusedinthismanner: <Frame ...> <SplitPane orientation=HORIZONTAL> <Xpanel xml=ControlPanel.xml/> <Xpanel xml=ProgressBar.xml/> <SplitPane/> </Frame> In this case we haveplaced two panels within aJSplitPane,but either of the panels could be includedinanotherframe,makingthemprebuilt,reusableUIobjects.Thisleavesthefreedomof choiceaboutthedesireduserinterfacetotheuser. TodefineaSwinginterfaceusingXMLcode,wehavechosenSwiXml,anOpenSourceframework downloadable from http://www.swixml.org/, hence you need to read the SwiXML available documentationinordertolearnmoreaboutit. Page8

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

TheController
Weneedamechanismtoexecuteacommandinresponsetoauser'saction.Todothis,weneedto write a Java class containing the code of the action and a mechanism to connect it to the correspondinguserinterfacecontrol. WecouldusethetagparameterActionCommandtodefinethecorrespondingaction: <button name=Start ActionCommand=StartDownload/> AtthispointweneedamechanismtolinktheActionCommandstringwiththecomponentthat implementstherequiredaction.

TheCommandBindingmechanism
InordertobindtheActionCommandwiththecodethatwillexecutethecorrespondingaction,we have defined an interface named org.swixat.commands.Binder. This interface exposes three properties(alongwiththecorrespondinggetter/settermethods):

Type:(optional)containsthenameofthecomponentthatexecutestheinvokedaction.Ifdefined, itcanpointeithertoacustomjavaclass,orafilecontainingJavainterpretedcode.Seethe paragraph'Scripting'below. Output: (optional) contains thename of theXML filedescribing the new View toshow in responsetoanuser'saction.Ifdeclared,theInternalFramedescribedintheXMLwillbeshown aftertheexecutionoftheaction. OnError:(optional)containsthenameoftheXMLfiledescribingtheviewtoshowincaseofthe executedactionsreturnsanerror.Ifdeclared,theInternalFramedescribedintheXMLwillbe shownaftertheexecutionoftheaction,incaseoferror.

TheBinderinterfaceisactuallyimplementedbythe org.swixat.commands.CommandBinder class.Howeveryoudon'tneedtocalldirectlytheCommandBinder'smethods,becausewehave implementedaneasymechanismtodeclaretheneededcommandbindings,simplybyusingXML tagswrittenwithinaconfigurationfile(namedalso'ApplicationContext'.Seethe 'Inversionof Control(IoC)'sectiontolearnmoreabouttheXMLApplicationContextsyntaxandcontent). Inordertodeclareacommandusedtorespondtotheuser'sactions,weneedtowritewithinthe XMLapplicationContext: <beanid="commandName"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>some/path/command.bsh</value> </property> <propertyname="output"> <value>somepath/outputFrame.xml</value> </property> <propertyname="onError"> Page9

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

<value>somepath/errorFrame.xml</value> </property> </bean> Thebasicrulefortheinterpretationofthevalueofthetag'type'isthefollowing: Ifthetypepropertycontainsastringterminatingwith.bsh,thenthatstringis interpretedasthenameofthefilecontainingthescriptingcode(withthefilepath relativetotheclasspathoftheapplication),otherwisethestringisinterpretedasthe classnameoftheobjectimplementingtheGuiCommandinterface(thatmustalso bepresentintheclasspath).

Inthismannerweletthedeveloperfreetochoosehowtoimplementthecontroller'slogicofthe application.Infactitisn'tmandatorytowriteonlyscriptcode,because,forsomespecifictasks,the developercanchoosetoimplementthelogicwithinclassicjavaclasses. Boththe'type'andthe'output'propertiesareoptional(althoughatleastoneoftheabovetagsmust bepresent)becausewecouldhavethefollowingthreesituations: <beanid="open"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>bsh/checkSelection.bsh</value> </property> <propertyname="output"> <value>xml/custDetailsFrame.xml</value> </property> <propertyname="onError"> <value>xml/errorNoSelectionFrame.xml</value> </property> </bean> <beanid="exit"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>org.swixat.commands.ExitCommand</value> </property> </bean> <beanid="about"class="org.swixat.commands.CommandBinder"> <propertyname="output"> <value>xml/AboutFrame.xml</value> </property> </bean> Thefirstcommandnamed'open'isusedtoopenanewframe(custDetailsFrame.xml)after havingverified(byinvokingthescriptcontainedinthecheckSelection.bshfile)thattheuser hasmadesomeselectiononthecurrentframe.Incaseoferror(noselection),anerrorpanelis displayed(errorNoSelectionFrame.xml). Page10

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Thecommand'exit'isusedtoclosetheapplication,henceonlythe'type'tagisdeclared,within which the class org.swixat.commands.ExitCommand is invoked (as the corresponding valuedoesn'tterminateswith'.bsh',the ExitCommand referencesajavaobjectdeclaredinthe framework'sclasspath). Thelastexampleshowsthe'about'commandusedtoopentheaboutboxoftheapplication.Ituses thetag'output'toopentheframedescribedbyAboutFrame.xml. NowitshouldbeclearhowtolinktheActionCommandofaUIcomponenttothecorresponding commandassociatedtoit.

Scripting
Oneofthemaingoalsofthisframeworkistoprovideeasycustomizationoftheapplicationthrough thewritingofexternalscripts/parameters.Therefore,apowerfulmechanismtoobtainthisgoalis representedbyscriptingcodeusedinresponseofanyuseraction. WehavechosentheBeanShell(http://www.beanshell.org/)interpreterwhichallowsJavacode(not onlyJavaScript)tobeexecutedfromafile. As of SwiXAT 0.3.0 we have refactored the scripting mechanism in order to make it easily extensible.Thankstothatrefactoring,theGroovy(http://groovy.codehaus.org/)languagesupport has been added (see the ScriptManager declaration in the 'Applicationindependent properties' sectionofthisdocumenttoknowhowtoactivatethedesiredinterpreter). Wehaveimplementedtwodistinctmechanismsthatcanbeusedinordertoinvokeascriptcodein responseofauser'saction. ApplicationContextbasedmechanism Wheneverweneedtoexecutesomecode,inresponseofwhichwewanttoshoweitheranoutput vieworanerrorview,andwhentheaboveassociationcontroller/outputviewisknownapriori,we candeclarethatassociationwithintheApplicationContextXMLfile,asalreadydescribedinthe abovesection. Todothis,wehavetospecializethecontentofthetypepropertyoftheBinderinterface.Where wewantto executeJavacodeinresponseofanaction,thevalueof thattagmustbeastring representingthenameofafilecontainingthecodetoexecute. Ifweneedtoexecutethecodecontainedintothefilepath/start.bshinresponseoftheaction Start,andthenshowthe'path/startView.xml'view,wewouldwriteintheApplicationContext XML: <beanid="Start"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>path/start.bsh</value> </property> <propertyname=output> <value>path/startView.xml</value> </property> Page11

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

</bean> andthenwecouldreferencetheabovecommandinanyUIactionCommand: <Buttontext=StartactionCommand=Start/> Note:thescriptfiledeclaredwithinthe<type>propertymustcontainNOTonlyfunctions(i.e.not only script code contained within a function's body 'funcName() {...}'). In fact, the frameworkwillexecuteonlythecodewrittenoutsideanyfunction'sbody.Thatcode,however,can invokewhateverfunctiondeclaredwithinthesamescriptfile,ifneeded. Directimportingbasedmechanism AsofSwiXAT0.3.5wehaveaddedthepossibilitytodirectlyimportascriptfilewithinanyXML viewinthismanner: <Frame...> <Scriptid=scriptsrc=/some/path/script.bsh/> ... <buttonid=b1text=StartactionCommand=start()/> ... </Frame> notethatthebutton'sActionCommandparametercontainsthestringstart(),thatmustbethename ofafunctiondeclaredinthescriptpreviouslyimported(theActionCommandparameter,inthis case,mustcontainafunctioncallterminatingeitherwith)or);inordertopermitthe frameworktodiscriminatebetweenthetwoscriptinvocationmethods). Thescript.bshfilewillcontainsomethinglikethis(writteninBeanShellsyntax): start(){ //Yourowncodehere ... } Of course a single script file can contain any number of functions. In this manner we have eliminatedtheexistingconstraintrepresentedbythenecessitytowriteasinglefunctionwithineach scriptfile. In this case, if the script needs to open, as response, a new view, it must return a org.swixat.framework.OutputView object,byinstantiatingitwiththenameofthefile containingtheview'sXML,asinthisexample: importorg.swixat.framework.OutputView; funcName(){ Page12

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

... returnnewOutputView(/some/path/to/nextView.xml); } Note: thescriptfileimportedwiththe<script>tagmustcontain only functions(i.e.onlyscript code contained within a function's body 'funcName() {...}'). This is because we cannot controlthemomentatwhichthecodeoutsideanyfunctionwillbeexecuted,obtaininguncertain andundesiredbehavior. Youcanalsopasswhateverparametertotheinvokedfunction,likeinthefollowingexample: <Frame...> <Scriptid=scriptsrc=/some/path/buttons.bsh/> ... <buttonid=b1text=1actionCommand=buttonHandler(1)/> <buttonid=b2text=2actionCommand=buttonHandler(2)/> <buttonid=b3text=3actionCommand=buttonHandler(3)/> ... </Frame> ifthebuttons.bshfilecontainsthefollowingcode: buttonHandler(intx){ System.out.println(Youhavepressedthekey'+x+'); } then,wheneverabuttonwillbepressed,theprogramwillprintthecorrespondingnumberonthe standardoutputconsole. MeaningoftheReturnedValue Regardlessoftheusedinvocationmethod,ascriptcodecanreturnavaluetothecallerapplication. Thevaluereturnedisajava.lang.Object,soyoucanputintoitwhatevervalue/object.Thereturned valueisusedinadifferentmanner,dependingonthecontextwithinwhichthescriptisexcuted: WithinascriptinvokedbytheController,thereturnedobjectcanbeusedtoindicatetheresultof theelaboration:itcontainsaninstanceoftheIntegerclasscontainingeitherthevalue0incaseof success,or1incaseoferror.Inthislastcase,ifthescriptwasinvokedbyacommanddeclared withinaCommandBinder,theassociated'onError'viewisshown. As for SwiXAT 0.3.5 we have extended this behavior by permitting to return, optionally, a org.swixat.framework.OutputViewclass.Ifreturned,thisclassmustcontainthenameoftheXML filedescribingtheviewtoshowinresponseoftheinvokedscriptcode. Example: ... returnnewOutputView(/some/path/nextView.xml); Page13

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Inthismannerthedevelopercandynamicallychoosewhichviewmustbeshowninresponseofan ActionCommand. IndeedtheOutputViewclassexposesothertwodifferentconstructors: 1. OutputView(Stringview,Stringkey,Objectvalue) the'key'and'value' parameters,ifnotsettonull,representavaluethatweneedtopasstothenewviewbyinserting itwithinthecurrentcontext,indexedbythe'key'string. 2. OutputView(String view, Map context) In this case the 'context' parameter containsnotonlyasinglekeyvaluepair,butanentirecontext,representedbyaninstanceofthe java.util.Mapclass.AllthekeysdefinedwithintheMapwillbeinsertedinthecurrentcontextof thecalledview. Byusingoneoftheabovecontructors,thedevelopercanpasswhateverparametertothenewview thatwillbeshowninresponseofthecommand.Thenewviewwillbeabletoaccesstothose parameters simply by reading the corresponding keys of thecurrent context, eitherby using a <ContextDataSourcecontext=current...> tagfromwithintheXMLview,orby usingthe'currentContext'variablefromwithinscriptcode(seethe'Automaticdeclarations' section below). For commands declared in the XML Application Context, the above two constructorscanbecalledalsobysettingtheview'snametonull;inthiscasewewantsimplyto invokethenewview(thenameofwhichisdeclaredintheXMLapplicationcontext)bysettingits initialcontextwithsomekeyvaluepairs. Within a script invokedbyaScriptingDataSource(seethe'Model' sectionbelow),instead, the returnedvalueisusedasrootobjectreturnedbythedatasource.Inthismannerwecanaccessto whateverpropertyofthatobjectbyusinganXPathexpressioninordertobindwhateverreturned valuetoanyUIcontrol.

Automaticdeclarations
Theframeworkprovidestheuserwithsomepredeclaredobjects/packagesusefultoaccesstosome internalfeaturefromwithinascriptcode: ImportedPackages In order to declare that some packages have to be imported by default, you can add the corresponding 'import' statement within the ScriptManager declaration, as described in the 'Applicationindependentproperties'sectionofthisdocument. In this manner you don't need to declare every time the complete package name, in order to instantiatethemostfrequentlyusedclasses. PredefinedObjects Theframeworkdeclaresalsothefollowingobjects: currentContext points to an org.swixat.model.Context object containing all the internal : variablesdeclaredintheapplicationintheformkeyvaluepairs.Youcanaccesstoanydeclared valuebycallingcurrentContext.getData(key)(tolearnmoreaboutthisobject,read Page14

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

the'CurrentContext'paragraph).Itcontainsthefollowingpredefinedmethods: 1. getWidget:permitstoaccesstothemapcontainingalltheUIcomponentsdeclaredin the current frame, indexed by their ID. Example.:


currentContext.getWidget(someID)

2. getFrame:returnsaninstanceoftheorg.swixat.framework.AbstractFrameclass,thatis theframethatcontainsthecurrentview.Thispropertyisusefulinordertobeabletocall someusefulmethodoftheAbstractFrameclass,asforinstancetheexecuteCommand method. Example: if we need to close the current view from within the script code invoked in response to a command, we can use the following syntax: currentContext.getFrame().executeCommand(cancel) 3. getShared:whenanewframeisopened,ifintheparentframe'scontextthekey'shared' ispresent(i.e.ithasbeensetwiththesetShared(someValue)method),thenitsvalueis copied within the newly created frame's context with the same key. Useful to share contextsbetweenchildsofthesameparentframe. 4. getParent:withinaframeinvokedbyanotherframe,thismethodreturnsthecaller's idMap.Example:currentContext.getParent().get(someParentID) application :pointstotheApplicationobject,asdeclaredinthe'application'beanintheXML IoCpropertiesfile,sothatyoucaneasilyaccesstotheapplicationspecificproperties.(Seethe 'Applicationspecificproperties'sectionofthisdocument). context points to the instance of ContextBinder, which is the container of all the existing : contextsdeclaredwithinourownapplication.(Seetheparagraph'Context'below).

EventsHandling
Otherthantheuser'sactions,aGUInormallyneedstohandlespecificeventsraisedbytheUI componentsthemselves.Inordertoaccomplishthisgoal,wehaveimplementedamechanismvery similartothatoneusedtohandletheuseractions.

Window'sEvents Inordertohandleallthewindow'sevents,wehaveextendedtheSwiXMLtaglibrarywiththe followingnewtags: Tagname <WindowEvents> Attributes onOpened onClosing onClosed(*) onActivated onDeactivated onIconified onDeiconified onGainedFocus onLostFocus Page15 Notes (*)TheonClosedeventcanbe annulledbytheuser(see descriptionbelow)

<WindowFocusEvents>

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Tagname <WindowStateEvents>

Attributes onStateChanged

Notes

Theyareinserted,normally,withinaFrame(orInternalFrame),inthefollowingmanner: <Frametitle=Sometitle...> <WindowEventsid=windowEvents onOpened=actionOnOpened onClosing=actionOnClose .../> <WindowFocusEventsid=focusEvents onGainedFocus=actionGainedFocus .../> ... </Frame> The value of the above properties contains the name of the action to execute when the correspondingeventisraised,exactlyasalreadyexplainedfortheActionCommandpropertyofany UIcomponent. Themeaningandpurposeoftheaboveeventsisclear,Ithink,butaconsiderationmustbedonefor theWindowEvents'onClosingattribute. Whilealltheaboveeventsmustbeconsideredjustassimple'notifications'ofthecorresponding event(i.e.theycannotbeannulled),theonClosingeventistheonlyonethatcanbeannulled,giving theuserthepossibilitytoavoidthewindowclosing,whenrequested.Theruleisthatifthevalue returnedbytheinvokedactionisequaltozero,thentheactionisconfirmed,andtheframeisclosed (and then the onClosed event is raised and the corresponding action executed, if declared), otherwisethecloseactionisannulled. Lookatthefollowingexample,wherewehavethefollowingframe: <Frame...> <WindowEventsid=eventsonClosing=askForClose> ... </Frame> and the askForClose action points, within the XML application context, to the askForClose.bshscriptfile,withinwhichthefollowingcodeiswritten: returnjavax.swing.JOptionPane.showConfirmDialog(null, "ClosetheWindow?",//Message "CloseConfirmation",//Title JOptionPane.YES_NO_OPTION, JoptionPane.QUESTION_MESSAGE); then,whentheuserclosestheabovewindow,apanelaskingfortheclosingconfirmationwill appear: Page16

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

asthevalue returnedbythescriptwillcontain0onlyiftheuserpressesthe'Yes'button,the applicationframewillbeclosedonlyiftheuserconfirmstheaction. Components'Events Also for each UI component we can intercept and handle some events, otherthan thealready declaredActionCommand,asillustratedinthefollowingtable:

Tagname <MouseEvents>

Attributes onClicked onDblClicked onEntered onExited onPressed onReleased onDragged onMoved onWheelMoved onPressed onReleased onTyped onStateChanged

Notes

<MouseMotionEvents> <MouseWheelEvents> <KeyEvents>

<ItemEvents>

AppliesonlytoSwing componentsthatinheritthe AbstractButtonclass.

<FocusEvents> <InputMethodEvents> <ComponentEvents>

onFocusGained onFocusLost onCaretPositionChanged onInputMethodTextChanged onHidden onMoved onResized onShown Page17

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Tagname <ChangeEvents> onChange

Attributes

Notes AppliestoAbstractButton, JTabbedPane,Jspinner,Jslider, Viewport,JProgressBar,...and whateverelseSwingcomponent thatexposes 'addChangeListener' AppliestoJTablecomponents AppliestoJTreecomponents

<TableEvents> <TreeSelectionEvents> <ContainerEvents> <PropertyChangeEvents>

onTableChanged onValueChanged onAdded onRemoved onChange propertyName(*)

(*)ThepropertyNameattribute mustbesetwiththenameof thecomponent'spropertyto monitor (ex:propertyName=text) AppliesonlytoSwing componentsthatinheritthe JTextComponentclass. (*)Ifdeclaredalongwithother specificeventattributes,it's calledafterallothers.Example: ifonChangeUpdateand onModifiedareusedtogether, theonModifiedactionis invokedafteronChangeUpdate.

<VetoableChangeEvents> <DocumentEvents>

onChange onChangeUpdate onChangeInsertUpdate onRemoveUpdate onModified(*)

<CaretEvents>

onCaretUpdate

AppliesonlytoSwing componentsthatinheritthe JTextComponentclass. AppliesonlytoSwing componentsthatinheritthe JTextComponentclass. AppliesonlytoJList components

<HyperlinkEvents>

onHyperlinkUpdate

<ListSelectionEvents>

onValueChanged

AlltheabovetagsmustbeinsertedaschildoftheUIcomponentforwhichthecorrespondingevent mustbehandled,asinthefollowingexample:

Page18

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

<TextFieldid=name...> <MouseEventsid=mouseonDblClicked=dblClickAction/> <FocusEventsid=focusonFocusGained=focusGainedAction/> </TextField> The script invoked by the corresponding event will be able to access to the instance of the associated event (java.awt.event.FocusEvent or java.awt.event.MouseEvent in theaboveexample)byinvokingthemethodgetArgument()ofthecurrentcontext,asinthis example: event=currentContext.getArgument(); ... Asthedescriptionofthemeaningofalltheaboveeventsisoutofthescopeofthisdocument,we recommendyoutoreadthecorrespondingdocumentationavailablebothonInternetandonseveral technicalbooks.

IndirectCommandBinding:the<Action>tag
Sometimesit'susefultoassociateboththesameattributesandthesamebehaviortodifferentUI components.Think,forexample,tothe'Save'commandaccessiblebothfromamenuiteminthe Filemenuandfromabuttoninthetoolbar.Ofcoursetheymustsharethesametext(eventually translatedaccordingtothelocalesetting),aswellasthesamestate(the'Save'commandmustbe disabledifthereisn'tanydocumentopened). Butifwedeclarethe'Save'commandinthefollowingmanner: <MenuItemid="saveItm"text="txtSave"icon="imgSave" mnemonic=mnSaveaccelerator=accSaveActionCommand="save"/> ... <Buttonid="saveBtn"text=txtSave mnemonic=mnSaveaccelerator=accSaveActionCommand="save"/> wehaveduplicatedalotofcode,becauseasyoucansay,the'text',the'mnemonic'andthe 'accelerator'attributesaredeclaredinboththeplaceswiththesamevalues. Moreover,wehavesomeproblemwhenwetrytoenable/disablethecommand,becauseweshould callthesetEnabledmethodoneachButton/MenuItemconnectedtothatActionCommand. The<Action>tagcomeinouraidbyprovidingasimplemechanismtosharethesamecommand betweendifferentUIcontrols.Wecanrewritethepreviouscodeinthefollowingmanner: <Actionid=saveActtext="txtSave"mnemonic=mnSave accelerator=accSavecommand=save/> ... <MenuItemid="saveItm"icon="imgSave"ActionCommand="saveAct"/> ... <Buttonid="saveBtn"ActionCommand="saveAct"/> Page19

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

As you can see, all the shared attributes now are declared only in the Action tag. The ActionCommandattributeofeachUIcomponentpointstotheIDoftheActionelement,andits 'command'attributeindicateswhichcommandmustbeinvokedforthisAction. Notonlywehavewrittenthesharedattributesonlyonce,butnowwecandisabletheSavecommand (andconsequentlyalltheassociatedUIcontrols)simplybywritingasinglerowofscriptcode: currentContext.getData(idMap).get(saveAct).setEnabled(false); TheadvantagesofusingtheActiontagaren'tfinishedhere,becausethismechanismpermitsalsoto easilyreusethesamepanelwithindifferentcontexts. Imaginewehavethenecessitytosaveafileindifferentformats(saybinaryorXML)dependingon theframe(i.e.thecontext)fromwithinthe'Save'commandisinvoked;moreover,imaginethatwe havebuiltareusablepanelthatcontainstheSavebutton,thatwillbedisplayedwithinthetwo differentframes(imagineaframewherethepanelisdisplayedalone,whileinanotheronethesame panelisdisplayedtogetherwithotherpanels,forinstancewithinasideofaSplitPane). You knowwecanusetheXPaneltagtoimportthesamepanelwithindifferentframes,but a problemariseswhenwetrytodeterminethecontentoftheSavebutton'sActionCommandattribute declaredwithintheimportedpanel. Imaginewehavedeclaredthefollowingcommandsintheapplicationcontext: <beanid="saveAsXML"class="org.swixat.commands.CommandBinder"> <propertyname="type"><value>saveAsXML.bsh</value></property> </bean> <beanid="saveAsBinary"class="org.swixat.commands.CommandBinder"> <propertyname="type"><value>saveAsBinary.bsh</value></property> </bean> we cannotlinktheSavebutton'sActionCommandtoanyoftheabovecommands,becausethe buttonwillbeusedindifferentcontexts. You'llhaveguessedthatbyusingtheActiontagwecanresolveeasilythedilemma,simplyby writing,intheFrame_A.xml: <Actionid=saveActtext=txtSaveAsXMLmnemonic=mnSave accelerator=accSavecommand=saveAsXML/> ... <XPanelxml=xml/myPanel.xml/> andintheFrame_B.xml: <Actionid=saveActtext=txtSaveAsBinarymnemonic=mnSave accelerator=accSavecommand=saveAsBinary/> ... <XPanelxml=xml/myPanel.xml/> whereas,inthemyPanel.xml,wecansimplywrite: Page20

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

... <Buttonid=saveBtnactionCommand=saveAct/> Notethat,thankstothismechanism,we'vebeenablealsotodifferentiatethetextdisplayedinthe Savebutton('txtSaveAsXML'intheFrame_Aand'txtSaveAsBinary'intheFrame_B,both declaredinthelocalepropertyfile).

SpecialActionCommands
Reservedwords InordertospecifysomespecificbehaviorinresponseofanActionCommand,wehavedeclaredthe followingreservedwords: Cancel: when a component's ActionCommand contains the string 'Cancel', the corresponding command will close the current frame. The onClosing and onClosed events will be raised, if declared. Thefollowingbutton: <Buttontext=Cancel/> whenpressed,willclosetheframewhereitappears,withoutthenecessitytowriteanyexternal scriptcode.Inthiscasewedon'tneedtodeclaretheActionCommandattributebecausebydefault thebutton'stextrepresentsalsothenameoftheassociatedActionCommand. RefreshView:thisActionCommandwillrefreshthecontentofthecurrentframe'sUIcomponents, byrereadingallthedeclaredDataSources. Wecanusethiscommandindifferentmanners: refreshViewrefreshesallcomponents refreshView()refreshesallcomponents refreshView($id)refreshesthecomponenthavingthegivenid refreshView("id")refreshesthecomponenthavingthegivenid refreshView($id1,$id2,$id3,...)refreshesallthecomponentsinargument refreshView($id1,"id2","id3",...)refreshesallthecomponentsinargument RefreshViewPattern:similartorefreshView,refreshesthecomponentshavingtheidthatmatches oneormorepatterns:

refreshViewPattern("pattern"); refreshViewPattern("pattern1","pattern2","pattern3",...);

Thepatternstringsmustcontainavalidregexpexpression. example:refreshViewPattern("^.*?ButtonPanel$"); refreshesallthecomponentswithidlike'PersonButtonPanel',or'CompanyButtonPanel' RefreshData:thiscommandclearsthecontentofallthecacheableDataSourceswithinthecurrent frame.Seethechapter'DataSources'inordertolearnmoreaboutcacheabledatasources. Page21

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Staticmethodinvocation Asfortheversion0.4.5,wehaveintroducedthepossibilitytoinvokewhateverstaticpublicmethod ofanyclassdeclaredintheclasspathoftheapplication. Thesyntaxisthefollowing:


ActionCommand=SomeClass.someMethod($someSource)

SomeClass istheusedclass,andtheframeworksearchesforthisclassbyusingthe'basedir' propertydeclaredincontext.xmlasthepackagename,afterhavingsubstitutedeach'/'with'.' Ifbasedir=my/package/name/,theclassfullyqualifiednameisconstructedlikethis: my.package.name.ClassName Iftheclassisnotfoundwithinthepackagepointedby'basedir',theclassissearchedwithoutany package. The'someMethod'issearchedandinvokedforthatclass.Ofcoursetheinvokedmethodmustbe declaredasstatic. IntheJavaclassyoucanhavedeclaredmoreargumentsthanintheXMLcode,asinthisexample: publicclassMyClass{ publicstaticvoidmyMethod( Applicationapp, AbstractFrameparentFrame, StringdataFromMyDataSource){ ... } } whiletheXMLviewcontains: <Buttonid=btnactionCommand=MyClass.myMethod($myDataSource)/> asyoucansee,thefirsttwoargumentsaredeclaredonlyinthejavaclass,whiletheXMLcode containsonlyoneargument.Thefirstparameterscanbelongonlytosomespecifictypes,sothat theycanbesubstitutedbythecorrespondingobjects'instancesintheframework: org.swixat.framework.Application org.swixat.framework.Frame org.swixat.model.Context whentheactionisinvoked,respectivelythecurrentApplication,FrameorContextispassedtothe method,accordingtothematchingdatatype.Wealsosearchthemissingargumentsin_share, idmapand_parentcontext,inordertocallcorrectlytheJavamethod. All the remaining parameters declared in the XML view are considered as the name of some Page22

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

DataSourcedeclaredinthecurrentFrame,sothatthecorrespondingvaluewillbepassedtothe invokedmethod(tolearnmoreaboutDataSources,readthefollowingchapter'TheModel'). Asfortheversion0.5.0,wecanuse $e asoneoftheparametersintheXMLcall,where $e representsapointertotheraisedeventinterceptedbytheActionCommand.Ofcoursethemethod musthavedeclaredacorrespondingparameterbelongingtoacompatibletype. Ifthemethodreturnsvoid,thennewInteger(0)isreturned,otherwiseisthesamethingthatwith any other invoked script function (i.e. the method can return, for example, an instance of OutputView,ifneeded). Multiplecommandsupport Youcanhavemorethanoneactioninactioncommand,eachactionmustbeseparateby';'. example: <Button...actionCommand="update($textfield/text,$MyObject/name); refreshView"/>

Invokingacommandfromwithinscriptcode
Sometimesitcouldbeusefultoinvokeacommanddirectlyfromwithinscriptcode,forexample whenwewanttoexecutesomeactionbeforetoinvokethecommand. Todothat,wecansimplywrite: ... currentContext.getData(_frame).executeCommand(command); Ofcoursethecommandstringcanrepresentacommanddeclaredintheapplicationcontextfile,a scriptfunctionimportedinthecurrentframe,oroneofthereservedcommands(either'cancel'or 'refreshView'). Thereservedkey'_frame'inthecurrentcontextreturnsapointertothecurrentAbstractFrame class,henceyoucancallwhateverelsepublicmethodonit.

TheModel
Thisisrepresentedbytheobjectmodelofthecallingapplication,hencewedonotneedtobuildany newclasstoimplementit.WedohoweverneedamechanismtopermitaViewtogetallthedatait needstofillitsinternalUIcontrols(seethearrow#5intheMVCschema). Todothis,wehavedefinedamechanismbasedonDataSources.

Page23

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

DataSources
BylookingattheSwiXAT'sMVCimplementationpresentedatthebeginningofthisdocument, you'll have noticed that the object model of our application is accessed by a layer named 'DataSource'. ItrepresentsthebridgebetweentheModelandtheView/Controllermodules.Alltheproblems inherent the access to specific sources of data are delegated to some specific DataSource implementation. SwiXATprovidestheuserwithsomeprebuiltDataSource,butnewonescanbeaddedsimplyby implementingtheorg.swixat.databinding.DataSourceinterface. Theuseoftheaboveinterfacepermitstheapplicationtoaccessinthesamemannertowhatever sourceofdata,regardlessitsnatureand/orlocation.Thisfeaturefreesusfrombeingworriedabout thekindofdataweneedtoaccessto. The'origin'attribute AnyDataSourceimplementationmusthaveapropertynamed'id',thatindicatestheDataSource's nameusedbytheSwingUIcomponentsinordertobelinkedtothecorrespondingdatasource,as explainedinthefollowingexample: <ContextDataSource id=DSName .../> TheSwingcomponentthatneedstobefilledbytheabovedatasourcemustdeclaretheproperty 'origin',settingitsvaluetotheidofthecorrespondingdatasource: <label id=name origin=$DSName default=some/XPath .../> InthiswayaViewisabletogettherequiredModel'sdatabysimplyconnectingtheUIcontrolto thecorrespondingDataSourceusingtheparametertag'origin'. When a Viewis displayed,theframeworkwill invokeall thegetDatamethods onthedefined DataSourceobjects. The'origin'attributecancontainalsoaXPathexpression,inordertonavigateandaccesstoa particularpropertyoftheobjecttreereturnedbytheDataSource,likeinthefollowingexample: <Labelorigin=$Customer/address/city/> ReadtheHowtouseXpathparagraphinordertolearnmoreaboutXpathexpressions. Ifthe'default'attributeisfound,thevaluereturnedbythecorresponding XPath isusedasthe component'soriginincasetheactualorigin'svaluereturnsnull.Ignorediftheorigin'svalueisnot null. OriginattributeinJButtonandJMenuItem As for the version 0.5.0, the 'origin' attribute can be applied also to JButton and JMenuItem Page24

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

components,butinthiscasethebehaviorisslightlydifferent.Forthesetwocomponents,infact,the value returned by the DataSource pointed by the origin attribute is used to enable/disable the correspondingbuttonormenuitem:ifthevaluereturnediseitheranonnullvalueoranonempty resultset,thecomponentisenabled.Otherwiseitisdisabled.Thecomponentisalsodisabledifthe valuereturnedbytheorigindatasourceisBoolean.FALSE. Originattributeinbuttongroups IfthebuttonhasthebuttonGroupattribute,thenthebuttonisaddedtothespecifiedbuttonGroup (creationofthebuttonGroupisautomaticifneeded). Thevaluereturnedbytheoriginattributechangesthebutton'sstate: Boolean.FALSEornull=unchecked Boolean.TRUEornotnull=checked

The'render'attribute Asfortheversion0.5.0wehaveaddedalsothe'render'attribute,thatpermitstosetthecontentofa UIcomponentbyapplyingwhatevervalidXPathfunction. Let'sexplainwithanexample:supposeanorigin'sXPathexpressionusedforaJLISTorsomesuch readsasfollows: <Listorigin="$company/department[@name=$dept]/employee"> where $company and $dept are variables that reference previously established xpath data sources. Imaginewewouldlikethewidgettodisplay,oneachlineofthelist,thefullnameofeachemployee e.g.JohnDoe,obtainedfromthe@firstnameand@lastnameattributesofemployee. OursolutionhasbeentoaddanewrenderattributetotheGUIcomponentthatcontainsanoptional XPathexpressionthatrendersthedesiredresult.So,inthisinstance: <Listorigin=... render=concat(./@first,'',./@last)> Asyoucansee,the'.'(dot)isusedtoreferencetheobjectpointedbythe'origin'attribute. Forthosethatmaynotknow,XPath1.0containsanumberofhandystringmanipulationroutines, andmanyotherbesidesthatcanservetoformatcontent. concat()canbethoughtofasasprintforprintlnequivalent,withmuchgreaterexpressivepower relativetodataretrieval,asnestedxpathexpressionscanbeemployedasdoneintheexample. The scheme is very general, and applies to widgets that either handle lists (set attribute iterate="true",asexplainedbelow)orsinglestrings. Moreover, whenever a render attribute is encountered, the node set (a List when iterate=true) obtainedbyevaluatingtheoriginxpathexpressionissavedinthecomponent's"originNodes"client Page25

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

property,soyoucanaccesstothe'origin'datafromwithinscriptcodebywritingthefollowing code: originData=Component.getClientProperty(originNodes); whereComponentisapointertotheGUIcomponentobtainedbyitsID(seethe'currentcontext' paragraph). TheDataSource'scommonattributes AlltheDataSourcescomponentshavethefollowingcommonattributes: The'path'attribute ThisattributecontainstheXPathusedtogettheneededvalue.Itusesasroottheobjectpointedby thedatasource.Inordertolearnmoreabouthowtousethisattribute,readthesection'Howtouse XPath'below. The 'iterate' attribute Thisbooleanattributespecifiesiftheobjectreturnedbytheapplicationofthexpathexpression containsa'scalar'value(falsethedefault),ora'vectorial'value(true).Thisattributemakessenseif wethinkthatanXPathoperatesonaDOMtree.Insomecircumstancesthexpathexpressioncould returnmultiplenodes,sointhesecasesitcouldbeusefultosettotruethe'iterate'attribute,inorder togetalltheinstancesfoundinthedocument. Forexample,forthefollowingXMLdatasource(butthesameconceptappliesalsoforothertypes ofdatasources): <developpers> <person><name>paolo</name></person> <person><name>benjamin</name></person> </developpers> theXPath/developpers/person/namereturns: theList[paolo,benjamin]ifiterateistrue theStringpaolootherwise The 'cacheable' attribute EachDataSourcecanbedeclaredcacheable,bysettingtotruethepropertycacheable(falseby default).Afterthefirstinvocation,acacheabledatasourcestoresitsdatawithinaninternalbuffer, avoidingsotoextractthedataateachcalloftheDataSource.getDatamethod.Thisisaveryuseful featurewhenthedataaccess/extractionisveryexpensiveintermsofelaborationtimeorresources occupied,andthesourceofdatadoesn'tchangeveryoften. Ofcoursethispropertydoesn'tmakesenseforeveryexistingDataSources,soinsomecasesits valuedoesn'taffectthebehaviorofthecorrespondingDataSource. A cacheable DataSource can be cleared by calling the 'refreshData' command (either within a component'sactionCommandattribute,orwithinscriptcode).AfterarefreshDatacommand,the Page26

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

nextcalltotheDataSource'sgetDatawillrereadfromtheoriginalsource. The<ContextDataSource> <ContextDataSourceid="DSname"cacheable=true|false context="contextName" source="sourceObjName" path="some/XPath/selectedProperty" iterate="true|false" /> TheContextDataSourceisusedtogetthedatafromanapplication'scontext,andownsthefollowing properties:

context :astringcontainingthenameofthecontextfromwhichthedataistaken.Thereisone contextalreadydeclaredcurrentthatcontainsalltheUISwingcomponentsdeclaredinthe XMLfileofthecurrentframe(seethe'currentcontext'sectionbelow). source :astringcontainingthekeyoftheobjectstoredwithinthedeclaredcontext. :astringcontainingtheXPathusedtogettheneededvalue.Itusesasroottheobject path pointedbythedeclared'source'withinthe'context'.

The<ScriptingDataSource> <ScriptingDataSourceid="DSname"cacheable=true|false script="somePath/scriptFile.bsh" path="some/XPath/selectedProperty" iterate="true|false" /> TheScriptingDataSourceisusedtogetthedatabyusinginterpretedBeanShelljavacode,andowns thefollowingproperties:


script :astringcontainingthenameandpathofthefilecontainingthescriptingcode.Withinthe scriptcode,thereturnedobjectmustbeputinthepredefined'retValue'variable. :astringcontainingtheXPathusedtogettheneededvalue.Itusesasroottheobject path returnedbytheinvokedscriptcode. iterate :abooleanvalueindicatingifthevaluereturnedbythedatasourceisascalarvalue(false) orcontainsanarrayofvalues(true).

The<XPathDataSource> <XPathDataSourceid="DSname" path="$DataSourceID/some/XPath" Page27

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

/> TheXPathDataSourceisusedtogetthedatafromanotherDataSource,andownsthefollowing property:

: a stringcontainingtheXPathusedtogettheneededvalue.It MUSTbeginwith the path referencetotheDataSourceIDthatwillreturntherootobjectonwhichtheremainingXPath expressionwillbeapplied.

ThisDataSourceisusefulinsituationswhereweneedtotraversemanytimesthesameobjecttree, inordertoextractdifferentobjects/properties,startingfromthesamerootobjectpointedbyanother DataSource.Thispermitsustoreusethesamesourceofdataavoidingtorepeatmanytimesthe samexpathexpression,likeillustratedinthefollowingexample: <!TherootCUSTOMERobject> <ScriptingDataSourceid="EMPLOYEE"script="queryData.bsh" path=department[@name=$dept]/employee/> <!ReferencestotheCUSTOMERobject'sproperties> <XPathDataSourceid=FIRSTNAMEpath=$EMPLOYEE/firstName/> <XPathDataSourceid=LASTNAMEpath=$EMPLOYEE/lastName/> <XPathDataSourceid=ADDRESSpath=$EMPLOYEE/address/> ... <Labelorigin=$FIRSTNAME/> <Labelorigin=$LASTNAME/> <Labelorigin=$ADDRESS/> InthismannerwedecoupletheGUIcomponentfromthecorrespondingdatasource,sowe'reable toreusethesameGUI(forexamplebyusingtheXPaneltag)withdifferentdatasources. The<ObjectDataSource> <ObjectDataSourceid="DSname"cacheable=true|false source="spring_Bean_ID" path="some/XPath/selectedProperty" /> ThisDataSourceusesassourceofdataaninstanceoftheobjectdeclaredintheSpringXML applicationcontext,pointedbyIDcontainedinthe'source'attribute. Itsattributesare: source :astringcontainingtheIDoftheobjectdeclaredwithintheSpringapplicationcontext. path :astringcontainingtheXPathusedtogettheneededvalue.Itusesasrootthebeanpointed bythedeclared'source'object.

Page28

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

The<DOMDataSource> <DOMDataSourceid="DSname"cacheable=true|false source="spring_DOM_ID" path="some/XPath/selectedProperty" iterate="true|false" /> ThisDataSourceaccessestotheDOMobtainedbytheparsingofaresourcecontainingawell formedXMLfile.TheXMLresourcenamemustbedeclaredintheSpringapplicationcontextand ispointedbythe'source'parameter.

source :astringcontainingtheIDoftheDOMobject,declaredwithintheSpringapplication context.Itmustpointtoabeanbelongingtooneofthefollowingclasses: String(containingavalidURI) java.net.URL java.io.InputStream :astringcontainingtheXPathusedtogettheneededvalue.ItusesasroottheDOM path instancepointedbythedeclared'source'object. iterate :abooleanvalueindicatingifalltheinstancesfoundmustbereturned(falsebydefault)

ThisDataSourceisveryusefultoget,forexample,XMLdatafromanHTTPserver,onwhichthe XMLcouldbeformatteddynamicallyby,forinstance,JSP,PHP,...anyotherservertechnologyor language.

HowtouseXPath
WithineachDataSourcecomponent,the'path'tagcontainsastringthatpointstothepropertyofthe objectextractedbythecorrespondingdatasource. It must contain a path according to the W3C standard XPath syntax1 (see http://www.w3.org/TR/xpath). XPathisaverypowerfulmechanismthatpermitstotraversehierarchicalstructures.Itwasthought tonavigateXMLfiles(i.e.DOMstructures),butanobjecttreeiscomparabletoaDOMstructure andcanbetraversedveryeasilyusingJXPath(http://jakarta.apache.org/commons/jxpath/),alibrary builttopermittoapplyXPathtowhateverJavaobjecttree. Letwehavethefollowingtwojavaobjectsinourownobjectmodel: publicclassEmployee{ publicStringgetName(){ ... } publicAddressgetHomeAddress(){ ... }
1 AgoodstartingpointtolearnmoreaboutXPathistheW3Schoolstutorialathttp://www.w3schools.com/xpath

Page29

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

} publicclassAddress{ publicStringgetStreetNumber(){ ... } } WecanaccesstotheStreetNumberofthecurrentEmployeesimplybyusingthefollowingXPath: homeAddress/streetNumber OfcourseintheaboveexampletherootobjectisaninstanceoftheclassEmployee. Havingasrootobject,instead,acontainerclasscontainingalistofemployees: publicclassEmployees{ publicArrayListgetEmployees(){ ... } } Wecouldselectaparticularemployeehavingthename'Fred'withthefollowingXPath: employees[name=Fred]/streetNumber AsthecompletesyntaxoftheXPathexpressionsisoutofthescopeofthispaper,werecommend youtoreadtheavailableJXPathdocumentationonthecorrespondingwebsite. WhatwewanttoillustratehereishowtouseXPathwithintheSwiXATframework. Continuingwiththeaboveexample,ifwehaveinthecurrentcontextalistofemployees,wecould extractthestreetnumberoftheemployeenamed'Fred'byusingthefollowingdatasource: <ContextDataSourceid="DSStreetNumber" context="current" source="employees" path="employees[name='Fred']/StreetNumber"/> Todisplaytheextractedstreetnumberwithinalabel,wecanwrite,inthesameXMLfile: <Labelid=streetNumorigin=$DSStreetNumber/> It'simportantthatthedatasourcereferencedbythe'origin'propertyisdeclaredwithinthesame frame/panelcontainingtheswingcomponentthatusesit. The'origin'parametercancontainalsoanXPath,sowecaneasilyreusethesamedatasourceby pointingtodifferentobjectsbelongingtothesameobjecttree,asinthefollowingexample: <ContextDataSourceid="DS1" context="current" source="employees" path="employees[name='Fred']/> Page30

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

... <Labelid=nameorigin=$DS1/name/> <Labelid=streetNumorigin=$DS1/homeAddress/streetNumber/> InthiscasewehaveusedaDataSourceinordertoextracttheentireinstanceoftheEmpoyeenamed 'Fred';afterthat,thetwolabelsaccesstotwodifferentpropertiesoftheextractedobject,byusing twodifferentXPaths(intheform'$DataSourceName/some/XPath'). Remember:WhereverintheXMLviewavalueofanattributestartswith$,thenthestringis interpretedandevaluatedasanXPathexpression. Note:Theoriginstringmustalwaysbeginwiththe'$'character,regardlessofthepresenceofapath aftertheDataSource'sID. WecanalsoreuseapreviouslydeclareddatasourceaskeywithinwhateverelseXPath: <ContextDataSourceid="NAME" context="current" source="parent" path="name"/> <ContextDataSourceid="EMPLOYEES" context="myContext" source="employees"/> ... <Labelid=streetNum origin="$EMPLOYEES/employees[name=$NAME]/StreetNumber"/> IntheaboveexamplewehavedeclaredthedatasourceNAME,thatextractsthewantednamefrom aTextFieldcontainedinthepreviousframe(theparent),andthenwehaveusedthatdatasource byreferencingitwithintheLabel's'origin'property,inordertoextractthecorrespondingstreet numberoftheEmployeehavingtheselectedname. Therealvalueandusefulnessoftheabovemechanismwillbeclearestafterhavingreadthenext paragraphaboutwhatareandhowtousetheContexts.

TheContext
TopermitthepassingofparametersbetweentheModelandtheView(andbetweentwoormore Views),acontextcanbecreatedandhandled. Eachcontextisrepresentedbyadatastructurethatstoresalltheparametersintheformkeyvalue pairs,permittingget/setoperationsbasedonthatname. Inordertobeabletodifferentiateparameterswiththesamename,butdeclaredindifferentViews, wehaveimplementedamechanismtostoredifferentcontexts,eachoneidentifiedbyacontext name.Consequentlywehaveimplementeda'contextbyname'accessingmechanism,basedonthe ContextBindercomponent. Page31

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Thewriting/readingofwhatevercontext's valuecanbedonefromwithinscriptingcodein the followingmanner: myObject=context.getContext("contextName").getData("objID"); where:

Theimplicitvariable'context'pointstothecontainerofallthedeclaredcontexts(representedin theframeworkbytheorg.swixat.model.ContextBinderclass) ThestringcontextNameisthenameofthecontexttowhichwewanttoaccess.Usethestring 'current'toaccesstothecontextcontainingalltheUIcomponentsofthecallingframe.This parameterisomittedifwewanttoaccesstothe'default'context(whichonecreatedbythe frameworkitself). ThestringobjID'isthekeyidentifyingtheobjectwithinthecontext.Forthe'current'context, usethe'id'oftheneededSwingcomponent(asdeclaredintheframe'sXMLfile)

Ifthecontextnameisnull,thenthe'default'contextisreturned.The'default'contextiscreatedby theframeworkwhentheapplicationisstarted,soyoucanuseittotemporarystore/retrieveyour owndata. Inordertocreateanewcontext,youcanwritewithinscriptcode:


newContext=context.setContext(contextName,newGenericContext());

andthen,toputakeyvaluepairwithinit:
newContext.setData(newKey,value);

or:
context.getContext(contextName).setData(newKey,value);

NOTE: becausetheglobalcontexts,ifnotaccuratelycleanedfromtheoldunused values,cancreatememoryleaks,you'reinvitedtoavoidtousethisglobalmechanism ofmemorystorage.Inanycase,remembertodeallocatetheresourceswhennotmore used,bysettingto'null'thecorrespondingkey:


toremoveacontext'skey,use:
context.removeData(key)

toremoveanentirecontext,instead,use:
context.setContext(contextName,null)

Useinsteadthecurrentcontext,asdescribedinthenextsection.

The'current'context Assaid,the'current'contextcontainsallthedeclaredvariablesofourapplication(intheformkey Page32

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

valuepairs).ItcanbeaccessedeitherbytheContextDataSourcetagwithintheXMLview(using current as context name), or from within any script code by using the predefined variable currentContext. Thereisadifferentcurrentcontextforeachframeopenedwithinourapplication.Thismeansthat, whenaframeisclosed,thecorrespondingcontextisdestroyed,anditscontentispassedtothe invokedframewithinthekeyparent.Henceinanygivenmoment,eachframecanaccessbothto itsowncontextandthecallerframe'scontext. Infactthecurrentcontextcontainsthefollowingpredefinedkeys: idMap: a java.util.Map containing all the UI components declared in the current frame, indexedbytheirID.Example.:currentContext.getData(idMap).get(someID) parent: within a frame invoked by another frame, this key points to the caller's idMap. Example:currentContext.getData(parent).get(someParentID) Thefollowingschemeillustrateshowthecontextismanagedbytheframeworkwhentwoframes needtosharesomeUIcontrol'scontent: Thenumbersindicatethestepsinvolved:
CurrentContextA idMap
Key name Value XYZ

CurrentContextB 3 parent
Key name Value XYZ

FrameA
Name: XYZ

4 FrameB
Name: XYZ

OK

1. TheuserfillsthetextfieldintheFrameAandthenpushesthebutton'OK'(intheconfiguration file,theActionCommandlinkedtothatbuttonopensanewwindownamed'FrameB'). 2. Inresponseofthebutton'sActionCommand,beforetoopentheFrameB,theframeworkstores alltheUIcomponentsintheidMapofthecurrentcontext,intheformofkeyvaluepairs(this isadefaultactionalwaysexecutedbytheframework).Note:evenifinthecontexttablewehave indicatedthecontentofthetextfield(thestring'XYZ'),indeedintheidMaptheframework storesareferencetotheTextFieldcomponentitself. 3. The framework,beforetoopenthenewframe,createsanewcontext (thatwill become the currentcontextofthenewopenedframe),andinsertsintoitareferencetotheFrameA'sidMap, withthekeyparent(note:it'sareference,NOTacopy). Page33

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

4. Theframework,intheinitializationcodeoftheFrameB,fillstheUIcomponentswiththevalues gotfromthedeclareddatasources,accordingthetagswrittenintheframe'sXMLdescription file. Thecodeusedinthepreviousexampleshouldbe: IntheFrameA.xml:


<TextFieldid=name/> ... <Buttonid=oktext=OKActionCommand=openFrameB/>

IntheFrameB.xml:
<ContextDataSourceid=DSNamecontext=currentsource=parent path=name/text/> ... <Labelid=custNameorigin=$DSName/>

So,whenthissecondpanelwillbedisplayed,thegetTextmethodwillbeinvokedontheTextField componentoftheFrameA(thatonehaving'name'asid),andthelabel'custName'willbefilled withthereturnedtext. The'shared'context In some cases, it could be useful to share some values between more frames, all of them descendantsofauniqueparentframe.Wehaveresolvedthisrequirementbyaddingareserved context'skeynamed'_shared'. Whenanewframeisopened,ifintheparentframe'scontextthekey'_shared'ispresent,thenits valueiscopiedwithinthenewlycreatedframe'scontextwiththesamekey.

Context'skeysaccessorsmethods AsofSwiXAT0.5.5,inordertosimplifytheaccesstointerestingcontextvalues,wehavedefined thefollowingmethods: ctx.getParent():Context returnsthecontextoftheparentframe ctx.getShared():Context returnsthesharedcontext ctx.containsData("key"):boolean checksifthekeyhasbeendefinedinthecontext ctx.getFrame():AbstractFrame returnstheframeassociatedwiththiscontext ctx.getWidget(id):Object methodtoaccessdirectlytotheWidgetregisteredwith'id'inXMLcontextfile ThefollowingJavaScriptcode:
if(currentContext.getData("idMap").get("id").getSelectedIndex()==1)

Page34

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

{...

canbewrittenas:
if(currentContext.getWidget("id").getSelectedIndex()==1) {...

ChangesintroducedinSwiXAT0.5.5 Note:currentContext.getData(someKey)returnsnowContext.UNINITIALIZEDifsomeKey doesn'texistinthecontext.Thispermitstodifferentiatebetweenanullvalueputbytheuser,andno existingkey. Consequently,thefollowingJavaScriptcode:


if(currentContext.getData(key)!=null){...

doesn'tworkanymore,soitmustberewrittenas:
if(currentContext.containsData(key)){...

Updatingthemodel:theUpdateOrigincommand
Thisnew commandisusedtoupdatetheorigin,orwhateverotherthingpointedbyanXPath expression,whenthecorrespondingeventisthrown. ItmustbeinsertedwithinanxxxEventstagintheXMLView.Wehavepreparedsomeexamplesin ordertoexplainhowdoesthismechanismwork. Example1:theTextField'soriginisusedastarget. <TextField id="TF" origin="$DataSource/someProperty"> <DocumentEvents onChangedUpdate="UpdateOrigin" onInsertUpdate="UpdateOrigin" onRemoveUpdate="UpdateOrigin"> <UpdateOrigin source="$TF/text"/> </DocumentEvents> </TextField> Asyoucansee,theUpdateOrigincommandisexecutedinresponsetosomedocument'sevents. Whenthecommandisexecuted,the<UpdateOrigin>tagissearched,andits'source'attributeis parsed in order to extract the data used to update the property pointed by the origin's XPath expression.IntheaboveexampletheDataSource.somePropertywillbeupdatedwiththevaluefrom thetextpropertyoftheTextFieldcomponentnamed'TF'). Example2:weuseaspecifiquetargetbecausetheList'soriginisusedaslistmodel. <List id="list" origin="$xpath/to/listModel"> <MouseEvents onClicked="UpdateOrigin"> <UpdateOrigin source="$list/selectedItem" Page35

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

target="$AppObject/some/attribute"/> </MouseEvents> </List> Sameasthepreviousexample,butinthiscasethe<UpdateOrigin>tagcontainsalsoa'target' attribute.ThisisbecausetheList'soriginattributecannotbeused,asitpointstoaListModel,notto anObject'sproperty. Example3:herecheckForAttributeValidityistheactionCommandexecutedinorderto verifysomecondition:if0isreturned,thentheUpdateOriginisperformed,elsenothingis done. <TextField id="TF" origin="$AppObject/xpath/to/attribute"> <DocumentEvents onChangedUpdate="UpdateOrigin" onInsertUpdate="UpdateOrigin" onRemoveUpdate="UpdateOrigin"> <UpdateOrigin condition="checkForAttributeValidity" source="$TF/text"/> </DocumentEvents> </TextField> Ifatypeconversionisneededbetweensourceandtargetvalues,youcanwriteandputaspecific converterbycalling: org.apache.commons.beanutils.ConvertUtils.register(Converterconverter,Classclazz); TheUpdateOrigintagacceptsalsoanactionCommandattribute.Ifpresent,thenthedeclared actionCommandisexecutedaftertheupdateactionisperformed. Usingthe'update(...)'command UpdateOrigincanbereplacedsimplybytheupdate(...)command:

updatesearchesUpdateOrigincomponentincallerifcalleristheContainerthatmust performtheupdate update(xpathSource)thedestinationistheoriginattributeontheparentcomponent update(xpathSource,xpathTarget)bothsourceandtargetareindicated update(xpathSource,xpathTarget,postActionCommand)sameasabove,alongwiththe commandtoexecuteaftertheupdatingisdone update(preConditionCommand,xpathSource,xpathTarget,postActionCommand)the preConditionCommandisexecutedbeforetheupdatingisdone.Mustreturn0iftheupdate mustbeperformed,1otherwise.

Example:aselectionintheComboBoxchangesthevalueintheTextField,andviceversa. <ComboBox id="combo" origin="$articles" Page36

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

/> <TextField id="field"> <DocumentEvents onModified="update($field/text,$combo/selectedValue/price)" /> </TextField> IntheaboveexamplewecanseetheimportancetokeeptherealobjectinSwingcomponents,and nottheStringrepresentation. Intheaboveexamplewedidn'tcheckthepricebeforeupdatingtheobject,ifwewanttocheckthe price,wecanuseaspecificUpdateOriginXMLelement,asillustratedinthefollowingexample: <ComboBox id="combo" origin="$articles" actionCommand="update($combo/selectedValue/price, $field/text)"/> <TextField id="field"> <DocumentEvents onModified="update(Util.checkStringIsNumber($field/text), $field/text, $combo/selectedValue/price, '')"/> </TextField> Iftheconditionintheupdatereturns0,thentheupdateisdone.

actionCommand="update($combo/selectedValue/price, $field/text)"

TheModel'seventshandling
Someonewillhavenoticedthatwestilldidn'tspeakaboutthehandlingofthemodel'sevents,as contemplatedbytheMVCpattern,andasdescribedbythearrow#4intheMVCschemashownat thebeginningofthisdocument. AsofSwiXAT0.3.0wehaveaddedamechanismtohandleanyeventraisedbyanybusinessobject ofourmodel. Themodel'seventhandlingisbasedonacustomclassthatmustbewrittenbythedeveloper.This classrepresentsa'bridge'betweenthebusinessobjectthatraisestheeventandthecorresponding framework'sclassthathandlesthatevent. Thankstothismechanism,thebusinessobjectsusedbyourapplicationarenotawareofSwiXAT, astheydon'tneedtobecoupledwiththeframeworkinanyway. The'bridge'classmustimplementtheinterfaceofthebusinessobject'seventslistener.Moreover,it mustextendtheorg.swixat.events.AbstractModelEventsclass. The mechanism is adherent to the Observer design pattern, and is described in the following schema:

Page37

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

TheclassesintheaboveschemabelongtotheStockPickerexamplethatyoucanfindwithinthe samplesdirectoryoftheSwiXATdistributionpackage. StockListenerisanexistinginterfaceintheapplication'sobjectmodel,anddescribestheinterfaceto implementtowriteamodel'seventlistener. TheAbstractModelEventsclassisdeclaredintheframework,andmustbeextendedbythecustom eventhandlerclass,thatinthisexampleisrepresentedbytheStockListenerImpl. Thefollowinglistingshowsitssourcecode:


publicclassStockListenerImplextendsAbstractModelEventsimplements StockListener{ privatestaticStringPRICE_CHANGED="onPriceChanged"; /**SpecificStockListener'sevent. *InheritedfromtheStockListenerinterface */ publicvoidonChange(PriceChangedEventpce){ ModelEventevent=newModelEvent(PRICE_CHANGED,pce.getSource(),pce); fireOnEvent(event); } /**Methodsinvokedbytheframeworkinordertoregisterthiswrapperas *model'seventlistener. */ publicvoidregisterAsListener(){ ((StockPicker)getSource()).addStockListener(this); } /**Methodsinvokedbytheframeworkinordertounregisterthiswrapperas *model'seventlistener. */ publicvoidunregisterAsListener(){ ((StockPicker)getSource()).removeStockListener(this); } }

Page38

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

Asyoucansee,wehaveimplementedonlythreemethods:

The'registerAsListener'and'unregisterAsListener'methods,thatareinvokedbytheframeworkin ordertopermitthewrappertoberegistered/unregisteredasthemodel'seventlistener.Asthe mechanismusedtoregisteramodel'slistenerisdependentonthemodel'simplementation,we needtowriteherecustomcode,accordingtotheobjectmodelwe'reusing.Intheexamplewe call the business object's addStockListener method, passing as parameter a reference to the wrapperitself(thisispossiblebecausethewrapperimplementstheStockListenerinterface,as expected bythatmethod).Themodelobjecttowhichthewrapperneedstoberegistered is containedwithinthe'source'propertyofthisclass,andpointstotheobjectreferencedbythe XPathwritteninthe'origin'parameterofthecorrespondingtagwherethislistenerhasbeen declared(seeview'sXMLcodebelow). The'onChange'methodisthespecificeventhandlerinvokedbythebusinessobjectwhenthe requestedeventisraised.ItisdeclaredwithintheStockListenerinterfaceanditssignaturecan changedependingonyourownbusinessmodel.Withinthiseventhandlerweneedtoinstantiate aModelEventobject(theeventobjectexpectedbythewrapper'slistener)passingasconstructor's parametersthenameofthecapturedevent,alongwithareferencetotheobjectthathasgenerated theevent(inourexamplewegetitbycallingtheevent.getSource()method,butalsothiscan change, anddepends on the specific behavior of your business model). After that,we must invokethefireOnEventmethod,thatisinheritedbytheAbstractModelEventsclass.Thismethod willpermittheSwiXATframeworktonotifythelistenerofthiswrapper(i.e.thecurrentView), inordertopermittheexecutionofthecorrespondingaction.

That'sall.Asyoucansee,thecodeyouneedtowriteisreallysimpleandiscomposedonlybyfew rowsofjavacode.Ofcoursethisclassmustbecompiledandinsertedwithintheclasspathofyour application. Inordertobeinstantiated,thisclassmustbeassociatedtoanewtag,andtodoit,weneedtoextend thetaglibrarybywritingintheXMLapplicationcontext,withinthenewTagsbean(readthe Chapter3TheApplicationContextXMLfiletolearnmoreaboutit),thefollowingcode:


<!TagLibraryextensions> <beanid="newTags"class="org.swixat.framework.TagLibraryExt"> <propertyname="newTags"> <map> <entrykey="StockPickerEventHandler"> <value>org.swixat.samples.stockPicker.model.StockListenerImpl</value> </entry> </map> </property> </bean>

Sowecaninstantiateandusethelistenerwithinaview'sframe(orinternalframe)inthismanner:
<Frame...> <!Thesourcebusinessobject> <ContextDataSourceid="getStock"context="current"source="stockPicker"/>

Page39

TheSwingXMLAuthoringToolUserGuide

Chapter1:TheMVCParadigm

<!Model'sEventHandler> <StockPickerEventHandlerorigin="$getStock"onPriceChanged="refreshView"/> ...

Nowwehaveallthepiecesofthepuzzleintherightplace,solet'sshowhowtheentiremechanism doeswork: 1. Thetag<StockPickerEventHandler>isparsedbytheframeworkwhenthecorresponding viewisinvoked 2. Thecorrespondingclass(StockListenerImpl)isregisteredasalistenerofthebusinessobject declaredbythe'origin'attribute(aninstanceoftheStockPickerclass,intheaboveexample returnedbytheContextDataSourcenamed'getStock').Weknowthattheregistrationismade byinvokingthe method registerAsListener,wheretheprogrammerwillhavewrittenthe correspondingcode 3. Whenthebusinessobjectwillraisethe'priceChanged'event,the'onChange'eventhandler will be invoked, within which the 'fireOnEvent' method will be invoked, causing the execution of the command declared in the 'onPriceChanged' attribute of the <StockPickerEventHandler>tag('refreshView'intheaboveexample). Within the commandinvokedbythecorrespondingeventhandler,it'spossibletoreference the originalmodel'seventobjectsimplybyaccessingtothe'_arg'keyofthecurrentcontext(like alreadyseenintheUIcomponent'seventhandling).Thisisveryusefulinallthesituationswhere theraisedmodel'seventcontainssomecustompropertytowhichweneedtoaccess. Asyoucansee,it'sverysimpletousethispowerfulmechanism.Allyouneedtodoistowritethe simpleclassthatimplementsyourownbusinessobject'slistener,alongwithfewrowsofXMLcode. Asalreadysaid,thebusinessmodeldoesn'tneedtoknowanythingabouttheSwiXATframework, becausethewrappercreatestheneededuncouplingbetweenthemodelandtheframework. Thisisusefulinordertopermittoreusewhateverexistingbusinessobjectwithoutmodifications. Thatwrapperistheonlyclassthedeveloperneedstowrite,becausealltheremainingparameters havetobewrittensimplywithinthecorrespondingXMLparameterfiles.

Page40

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Chapter2:SpecialFeatures
BeingSwiXATbasedonSwiXml,allthetagsdefinedinthatframeworkcanbeusedwithinthe XMLthatdescribesaview.Toseealistofalltheacceptedtagsalongwiththeirattributes,goto http://www.swixml.org/tagdocs/index.html. SwiXAT,however,canbeextendedwithnewtags,inordertoaddwhatevernewfeaturetoaview. Otherthansomespecifictags,likethosethatpermittodeclareadatasource,thatwillbeexplained indetailinthenextchapters,let'sexplainherewhatarethetagswehavedeclaredtoaddsome specificUIcontroltoaview.

SupportforMDIapplications
SwiXATprovidesastrongsupportforMDIMultiDocumentInterfaceapplications,particularly withtheavailabilityofthe<InternalFrame>tag,usedtoinstantiateaJinternalFrame. InordertodeclareaMDIapplication,youneedtoinserta<DesktopPane>tagwithintheFrame XML view, and declare the ID of that pane within the XML application context (see the 'Applicationbean'paragraphintheChapter3). Afterthat,youcanuseallthetagsillustratedinthisparagraph,inordertouseallthefeatures SwiXATprovidesyou.

The<WindowMenu>tag
Ausefulfeature,forMDIapplications,istohaveamenucontainingthelistoftheopeninternal frames,alongwithsometooltoadjustautomaticallythesizeandpositionofthoseframes. The tag <WindowMenu> permits to add such a menu within whatever menu bar, like in the followingexample: <menubar> ... <WindowMenuid="menuWindow"text="Window"/> ... </menubar> Theaboveview,whendisplayed,willgeneratea'Window'menulikethis:

Page41

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Asyoucansee,itcontainsthelistoftheopenedinternalframes,wheretheusercaneitherchoose theframetobringtofront,oraligntheinternalframesintwopredefinedmanners(cascadeortile). Wheneveraninternalframeisopenedorclosed,theabovelistisupdatedtoreflecttheframes existinginthemainwindow. Alltheabovefeaturesareavailableoutofbox,withoutwritinganylineofcode! Astheclassinstantiatedbythe'WindowMenu'tagextendstheSwing'sMenuclass,itacceptsallthe attributespermittedforthe<Menu>tag,like'mnemonic','accelerator',etc.

The<MDIDesktopPane>tag
AnotherusefulfeatureforMDIapplicationsisthepossibilitytohaveascrollabledesktoppane,so that,whenaninternalframeismovedoutsidethevisiblewindow'sarea,ascrollbarisdisplayed. Thatdesktoppaneisobtainedbyusingthetag<MDIDesktopPane>insteadof<DesktopPane>,like inthefollowingexample: <Frame...> ... <ScrollPaneconstraints="BorderLayout.CENTER"> <MDIDesktopPaneid="desktop"opaque="false"/> </ScrollPane> </Frame> NotethattheMDIDesktopPane,inordertoworkproperly,mustbeinsertedwithinaScrollPane component. ThisisthevisualbehaviorofaMDIDesktopPanewhenaninternalframeismovedbeyondthe externalborderofthemainwindow...

Page42

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

...asyoucansee,ahorizontalscrollbarappeared. Ofcourseaverticalscrollbarwouldbeappearedifwehadmovedtheinternalframebeyondthe loweredgeofthewindow.

The<ModalInternalFrame>tag
Bydefault,alltheinternalframesdeclaredwiththetag<InternalFrame>areinstantiatedasno modalframes.Nomodalframespermittheusertoclickanywhereintheapplication'swindow, outsidethenomodalframe,inordertochoose/activatewhateverelseavailablefeature. Although the above behavior is the preferred in many situations within a MDI application, sometimesit'susefultodisplayaninternalframewithoutgivingtheuserthepossibilitytoactivate otherframes/functionalitiesoftheapplicationuntilthatframeisnotclosed. This kind of frame is called 'modal', and can be instantiated in SwiXAT by using the tag <ModelInternalFrame>,likeinthefollowingexample: <ModalInternalFrameid="aboutFrame"size="350,180"title="AboutBox" layout="BorderLayout"Maximizable="false"Closable="true"> ... </ModalInternalFrame> The'AboutBox'isaclassicalexampleofamodalframe,andasshownbytheaboveexample,the tagModelInternalFramecanbeusedexactlyasyou'duseanyInternalFrametag. Theuniquedifferenceisthatinthismanneryoucreatea'modal'internalframe.

SupportforJComboBoxandJListcomponents
The<ComboModel>and<ListModel>tags
Wehavealreadyseen,invariousexamples,thatthe'origin'attributeofaGUIcomponentpointsto Page43

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

theDataSourcethatextractsandreturnsthedatausedtofillthecontentoftheGUIcomponent. This is true also for JList and JComboBox components, because we can fill them by using a DataSourcethatreturnsanarrayofvalues. Sometimes,instead,weneedtointerpretthe'origin'attributeas'thevaluetouseascurrentvaluefor thecomponent'. In order to accomplish this requirement, as for the version 0.5.0, the support for the JComboBoxModelandJListModelhasbeenadded. Let'sshowhowtousethemwithanexample(we'lluseaJComboBox,butthesamesyntaxcanbe usedforaJList): <ComboBoxorigin=$DS1/some/path/selectedValue> <ComboBoxModelorigin=$DS2/some/path/listOfValues/> </ComboBox> Asyoucansee,wehavetwo'origin'attributes: ThatoneattheleveloftheComboBoxModeltagpointstothelistofvaluesusedtofillthecontent oftheComboBox,whiletheComboBox'soriginattributepointstothecurrentselectedvalueinthe list.Thisisveryusefulwhen,forexample,weextractthelistofpossiblechoicesfromacolumnofa tableinadatabase,andthecurrentvalueisread,instead,fromthequerymadeonadifferenttable. Of course the two 'origin' attributes can point indifferently either to the same or to different DataSources.

The<ComboBoxRenderer>tag
TheComboBoxRenderertagpermitstoencapsulaterealRenderers. Tolearnmoreaboutrenderers,seethejavadocumentationaboutjavax.swing.ListCellRenderer interface. TherealrenderermustbeachildofthistagintheXMLdescription. Thispermitstousewhateverrendererimplementedforanormalswingapplicationinaverysimple manner,likeinthisexample: <ComboBoxorigin=$Data> <ComboBoxRenderer> <MyDefaultRenderer/> <MyPersonRenderertype="Person" childsPropertyName="address/city"/> <MyAddressRenderertype="Address"childsPropertyName="city"/> <MyStringRenderertype="String"/> </ComboBoxRenderer> </ComboBox> Asyoucansee,youcanusedifferentrenderersforthesameGUIcomponent. Intheaboveexample: 1. MyDefaultRendererisusedwhennootherrendererisfound. 2. MyPersonRendererisusedfordatabelongingtotheclassPerson,andthevaluedisplayed willbethevaluereturnedbyPerson.getAddress().getCity() 3. MyAddressRendereristhesamething,onlyforinstancesoftheAddressclass. Page44

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

4. MyStringRendereristhesamethingforStringobjects. Therealrendererusedwillbethatonehavingthe'type'attributecorrespondingtotheclassofthe datapointedbythe'origin'attribute.Ifthereisn'tanymatchingrenderer,thatonewithoutthe'type' attributewillbeused.Ifnoemptyrendererisfound,the javax.swing.BasicComboBoxRenderer classwillbeused. EachxxxRenderertaglistedintheXMLviewmustbedeclaredintheXMLapplicationcontext, withinthe'newTags'section(see'TheTagLibraryextensions'paragraph),andmustpointtoaclass implementingthejavax.swing.ListCellRenderer interface.

TheComboBox'svaluesattribute
Ifvalues="..."isfoundonComboBoxtag,it'susedasthemodel.Thevaluesarecommaseparated. YoucanuseanXPathexpressionforeachvalue. Example: <ComboBox values='"String","Int","Float",$DS/type'/> Wehavealsoaddedthesupportforemptyfirstelement:wehaveaddedthebooleanfirstNull attributetopermittohaveanemptyrowatthefirstposition: <ComboBox firstNull="true" ...>

SupportforJTreecomponents
ForJTreecomponents,wehaveimplementedseveralmechanismsusefultofilltheinternaltree, startingfromthecustomobjectmodeloftheapplication. Normally,ifthe'origin'attributedeclaredwithinthe<Tree>tagpointstoaDataSourcethat returnsaTreeModelinstance,thatmodelwillbesimplyusedasthetree'smodel. Beside this simple basic mechanism, we have implemented two different techniques to set the contentofaJTree,asillustratedinthefollowingparagraphs.

The<TreeModel>and<TreeCellRenderer>tags
InordertopermittouseaJTree,andfillitsinternalmodelwithatreethatisloadedstartingfrom somehierarchicalstructuremirroringourownbusinessmodel,wehaveinsertedthe<TreeModel> tag. Itssyntaxisthefollowing: <Treeid="names"origin="$xpath/to/tree/root"> <TreeModelchildsPropertyName="rootPropName"> <TreeModelMappingtype="some.path.to.subTreeClass" childsPropertyName="subTreePropName"/> </TreeModel> <TreeCellRenderertextPropertyName="textPropName" Page45

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

toolTipTextPropertyName="toolTipPropName"> <TreeCellRendererMappingtype="some.path.to.subTreeClass" textPropertyName="subTreeTextPropName" toolTipTextPropertyName="subTreeToolTipPropName"/> </TreeCellRenderer> </Tree> Asyoucansee,theTreeModelandTreeCellRenderertagsmustbeinsertedwithinthe<Tree>tagof whichtheydescribeboththemodelandtheappearance.The'childsPropertyName'attributesmust containthenameofthegetterpropertiesthatpermitto'traverse'theobjecttreefordatabelongingto the class described in the 'type' atribute, whereas the textPropertyName and toolTipTextPropertyNamecontainthemethodsthatreturnrespectivelythedescriptionandthetool tiptextofeachkindof'type'node. Asexample,let'shavethefollowingjavaclasses: publicclassAnimals{ privatestaticfinalAnimalrootAnimal=createAnimals(); privatestaticfinalAnimalcreateAnimals(){ Animalroot=newAnimal("Animals"); root.setChilds(newArrayList()); //Elementslinkedbythe'childs'property Animalmammals=newAnimal("mammals"); root.getChilds().add(mammals); mammals.setChilds(newArrayList()); mammals.getChilds().add(newAnimal("rabbit")); mammals.getChilds().add(newAnimal("dog")); ... //Elementslinkedbythe'subCategories'property NoneAnimalmystic=newNoneAnimal("mystic"); root.getChilds().add(mystic); mystic.setSubCategories(newArrayList()); mystic.getSubCategories().add(newNoneAnimal("hydra")); mystic.getSubCategories().add(newNoneAnimal("pegasus")); returnroot; } publicAnimalgetRootAnimal(){ returnrootAnimal; } } publicclassAnimal{ privateCollectionchilds; ... publicCollectiongetChilds(){ returnthis.childs; } Page46

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

publicStringgetName(){ returnthis.name; } } publicclassNoneAnimal{ privateCollectionsubCategories; ... publicCollectiongetSubCategories(){ returnthis.subCategories; } publicStringgetDescription(){ returnthis.description; } } Theabovethreeclassesrepresentourownobjecttree: 1. TheAnimalsclassbuildstheentireAnimals'tree,andits getRootAnimalmethodreturns theAnimal'sinstancerepresentingtherootofthetree. 2. TheAnimalclassrepresentsakindofnodesofthetree,andthegetChildsmethodpointsto itschildsnodes,constitutedthemselvesbyinstancesoftheAnimalclass. 3. Finally,theNoneAnimalclassrepresentsanotherkindofnodesbelongingtothesametree,and the getSubCategories method returns its childs, constituted by instances of the NoneAnimalclass. InordertofillaJTreewiththeaboveobjecttree,weneedfirstofalltowriteascriptthatcreates andreturnstheinstanceoftheAnimalsclass(bsh/getAnimals.bsh): returnnewAnimals(); NowweneedtoinstantiateaJTreehavingasmodeltheabovecreatedobjecttree: <ScriptingDataSourceid="ANIMALS"script="bsh/getAnimals.bsh"/> <ScrollPaneconstraints="BorderLayout.CENTER"> <Treeid="names"origin="$ANIMALS/rootAnimal"> <TreeModelchildsPropertyName="childs"> <TreeModelMapping type="org.swixat.samples.baseApp.model.tree.NoneAnimal" childsPropertyName="subCategories"/> </TreeModel> <TreeCellRenderertextPropertyName="name" toolTipTextPropertyName="name"> <TreeCellRendererMapping type="org.swixat.samples.baseApp.model.tree.NoneAnimal" textPropertyName="description" Page47

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

toolTipTextPropertyName="description"/> </TreeCellRenderer> </Tree> </ScrollPane> InthisexampletheXPathexpressionwrittenintheJTree'soriginattributepointstotherootAnimal propertyoftheAnimalsclassreturnedbytheScriptingDataSource. The TreeModel, in order to fill the entire tree, will traverse the object model by calling the 'getChilds'propertyforeachnodeofkindAnimal,andthe'getSubCategories'propertyforeach nodeofkindNoneAmimal,asdeclaredbythechildsPropertyNameattributes. The'getName'and'getDescription'methods,instead,areusedtogetthetextandtooltiptextforthe twokindsofnodeobjects. Theresultingtreeisthefollowing:

Wecanalsofillamultiroottreebyusingthesame<TreeModel>tag. Theuniquedifferenceisrepresentedbytherootofthetree,thatinthiscasemustbeaCollection containingalltherootsofourtree. Todoit,we'llchangetheXMLviewinthismanner: <ScriptingDataSourceid="ANIMALS"script="bsh/getAnimals.bsh"/> <ScrollPaneconstraints="BorderLayout.CENTER"> <Treeid="names"origin="$ANIMALS/rootAnimal" rootVisible="false"> <TreeModelchildsPropertyName="childs"/> ... </Tree> ... </ScrollPane> Notethattheuniquedifferenceisrepresentedbythe'rootVisible'JTree'sproperty,settofalse Page48

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

inordertomaketheJTreeamultiroottree. Theresultoftheabovechangesaredisplayedinthefollowingfigure:

Withthissimplemechanismwe'reabletofillaJTreewithanykindofhierarchicalobjecttree, regardlessoftheinternalstructureofourobjectmodel. TheTreeCellRenderertagacceptsalsotheclosedIcon,leafIconandopenIconattributes,thatmust containtheicons'pathsusedforthedifferentkind/stateofeachtree'snode.Noresourcekeyis supportedatthemoment.

The<NestedTreeModel>and<TreeNode>tags
WehaveimplementedanewTreeModel,namedNestedTreeModel,topermittodisplaymoreeasily abusinessmodel'streeofobjectsinsituationswheresomenodesrepresentsimplythecategory's name(notderivedbyrealobject'sinstances)withinwhichsomechildnodesmustbegrouped. Ifwehaveanobject'Person'likethis:

IfwewanttodisplayonepersonasRootTreeNode,andsomethinklikethisfortree: GeorgeBrown+ +Parents+ |+Mother Page49

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

|+Father +Children +Friends+ +SamBlack +RalphWhite wherethe'Parents','Children'and'Friends'nodesdon'tderivedirectlyfromsomeobject'scallable method. WecanwritewithintheXMLview:


<Treeid="tree"name="tree"> <NestedTreeModelid="treeModel"> <TreeNodeid="rootTreeNode"origin="$Person"> <TreeNodename="Parents"> <TreeNodetreeOrigin="../.."childsPropertyName="parents"/> </TreeNode> <TreeNodename="Children"> <TreeNodetreeOrigin="../.."childsPropertyName="childs"/> </TreeNode> <TreeNodename="Friends"> <TreeNodetreeOrigin="../.."childsPropertyName="friends"/> </TreeNode> </TreeNode> </NestedTreeModel> </Tree>

Wegetthefollowinginterestingfeatures: WecanputanynumberofTreeNodesinaTreeNode. treeOrigintakeorginefromanotherTreeNode,only..ispermittedor../../..,etc childsPropertyNamecontainsanXPathpointingtoapropertybelongingtothenode'sorigin pointedbytreeOrigin WecanputtheoriginattributeinanyTreeNode,ifneeded It'sveryeasytofindtheTreeNodeassociatedwithanyuserobject.OnNestedTreeModel, youhavegetNode(userObject):TreeNodemethod(ifthesameuserObjectisusedmorethan once,thelastisreturned).Thispermits,withinscriptcode,toselecteasilyNodesinaTree whenwehaveapointertooneoftheuseduserobjects Aslabelofeachnode,thevaluereturnedbytheDataSourcepointedbythe'origin'attributeisused, if declared. Otherwise treeOrigin.childsPropertyName is used; finally, the 'name' attribute in treeNodeisused,ifnoneoftheaboveapplies.

TheenhancedRenderermechanisms
AsofSwiXAT0.5.5(thankstothegreatworkmadebyBenjaminPoussin),anewenhanceditems renderingmechanismhasbeenimplemented.Byusingit,nowit'spossibletochooseadifferent rendererbasedontheclasseachsingleitembelongsto. ThismechanismworksforJList,JComboBox,JTreeandJTablecomponents. Page50

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Thecorrespondingtagsare: <ListRenderer>and<DefaultListCellRenderer> <ComboBoxRenderer>and<DefaultComboBoxRenderer> <TreeRenderer>and<DefaultTreeRenderer> <TableRenderer>and<DefaultTableCellRenderer> Forexample,wecanhave,foraJTreeobject: <Tree id="tree" name="tree"> <NestedTreeModel id="treeModel"> <TreeNode ..../> </NestedTreeModel> <TreeRenderer> <DefaultTreeRenderer type="some.package.Person" childsPropertyName="firstname" toolTipPropertyName="firstname"/> <DefaultTreeRenderer type="some.package.Company" childsPropertyName="name"/> ... </TreeRenderer> </Tree> inthiscasewehavedifferentrenderersfordifferentClasses(PersonandCompanyintheexample). Wecanalsowritesomethinglikethisifalltheobjectsinthetreeexposethesameproperty('name' intheexample) <Tree id="tree" name="tree" renderer="name"> <NestedTreeModel id="treeModel"> <TreeNode ..../> </NestedTreeModel> </Tree>

The<XPanel>,<XMenuBar>and<XToolBar>tags
Wheneverweneedtoreusesomepanel,menubarortoolbar,wecanusethesethreetags,that permittoimportthecorrespondingGUIdefinitionfragmentfromanexternalfile. Theirsyntaxisthefollowing:
<XToolBarxml=path/to/aToolBar.xml/> <XMenuBarxml=path/to/aMenuBar.xml/> <XPanelxml=path/to/aPanel.xml/>

Page51

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

As you can see, all the above tags accept an attribute named 'xml', that must point to the name of the XML file containing the corresponding GUI definition fragment. Of course the root element within each external file must be of a type compatible with the type expected by the corresponding import statement, as in the following examples: aToolBar.xml: <toolbarorientation="HORIZONTAL"...> ... </toolbar> aMenuBar.xml: <menubar> <menu...> ... </menubar> aPanel.xml: <panellayout=GridBagLayout...> ... </panel>

The<DatePanel>and<DateField>tags
Thepossibilitytochooseadatefromauserfriendlycalendarlikepanel,insteadofinsertingdirectly thedatebyhand,isveryusefulformanyapplicationsthatneedtoasktheuserforadate. SwiXATpermitstodoitthankstotwotags,namedrespectivelyDatePanelandDateField. Theyareusedinthefollowingmanner: <DatePanelid=someIDorigin=$xpath/to/aDatedate=mm/dd/yyyy /> the'origin'andthe'date'attributesarebothoptionalandmutuallyexclusive,becauseboththeycan beusedtosettheinitialdisplayeddate(settotodaybydefault),respectivelyinadynamicorstatic manner. Theresultingcomponentshownintheviewisthefollowing:

TheDateFieldtagissimilar,becauseitacceptsthesameattributesoftheabovecomponent.The uniquedifferenceisthatitdisplaysasingledatefield,similartoacombobox,andthecalendar Page52

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

panelisdisplayedonlywhenthearrownearthefieldispressed. The above two components are derived by the Nachocalendar project (http://sf.net/projects/nachocalendar), hence you can read the project documentation in order to learnmoreaboutthesecomponents.

The<TableChooser>tag
ThiscomponentextendsaJTable,whereoneofthecolumnsisreservedtoshowacheckbox. TheTableChooserisusefulwheneverwewanttoshowalistofitemscomposedbydifferentfields (displayedwithindifferentcolumnsofthetable),andwanttopermittheusertochoosesomerows ofthetablebyclickingonthecorrespondingcheckbox. TheTableChoosercomponentcanbeinstantiatedinthefollowingmanner: <TableChooserid="TChooser" columnsName="ColName1|ColName2|..." checkBoxCol="n" origin="$DataSourceID /> Itexposesthefollowingproperties:

columnsName :Thelistofcolumns'namesseparatedbythecharacter'|'.Ifomitted,thecolumns willbenamedColumn1,Column2,etc. checkBoxCol :Anintegerindicatingwhichcolumnwillbereservedtocontainthecheckboxes origin :PointstotheIDofthedatasourcethatwillreturnthedatacontainedinthetable.The returnedvaluemustbea2DarrayofObjects.Thenumberofthetable'scolumnswillbeequalto thenumberofcolumnsofthearray+1(thatonecontainingthecheckboxes)

Forexample,ifwehaveaDataSourcenamedCUSTOMERSthatreturnsthefollowing2Darray ofStrings: RalphWhite SamBlack TomYellow PaulGreen WhiteStreet,44London BlackStreet,55NewYork YellowStreet,66Paris GreenStreet,77Rome

andourXMLviewcontainsthefollowingcode: <ScrollPane> <TableChooserid="TChooser" columnsName="Name|Call|Address" checkBoxCol="2"origin="$CUSTOMERS"/> </ScrollPane> Page53

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

thefollowingTableChooserwillbeshown:

Asyoucansee,thesecondcolumn,thatcontainsthecheckboxes,hasbeenaddedbythe TableChooseritself,asouroriginaltablewascomposedbya2columnsarray. Inordertogetthelistofselectedrows,wecanwritethefollowingscriptcode: chooser=currentContext.getData(idMap).get(TChooser); Boolean[]selections=chooser.getCheckData(); ... obtainingsoanarrayofBooleanswhereeachelementistrueonlyifthecorrespondingtable's checkboxischecked.

SupportforJTablecomponent
AsforSwiXAT0.5.5wehaveaddedthepossibilitytoeasilyfillaTablebydeclaringthesourceof datawiththe'origin'attributeandaTableModeltag. Example1: <table origin="$DS/datas" renderer="name"/>

originisusedasdataforDefaultTableModel,mustbea2Darray,ora Collection<Collection> rendererisusedtorenderdata.Thevalueisusedaspropertynametoaccesstothemodel

Example2: <table origin="$DS/selected"> <tableModel origin="$DS/list" columns="name, firstname, address/city" columnNames="Name, Firstname, City" columnEditables="false, false, true"/> </table>

originintablepermitstoselectrowsintable originintableModelisaListofObjects columnisanXPathlist,oneXPathforeachcolumn columnNamesisusedasthetableheader,ifmissedthecolumnxpathsareused Page54

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

columnEditablepermitstoindicatewhichcolumnsareeditable

Example3: <table> <tableModel origin="$DS/number" column="$DS/person$[row]/name, $DS/person$[row]/firstname,$DS/person$[row]/address/city" columnName="Name, Firstname, City"/> </table>

inthiscaseoriginisjustusedtoknowhowmanyrowsthetablemusthave eachcolumngetsallitsowndatafromtheindicatedXPath.Whenthetableasksfordata, eachXPathisevaluatedbysettingthe$rowvariabletothecurrentrow,and$otothecurrent originobject

Example4: <table> <tableModel> <MyTableModel> </tableModel> </table>

inthiscaseMyTableModelisanexistingtablemodel(thedataaccessiscabledincode)

Example5: <table> <tableModel origin="$Persons"> <column title="Name" property="name" editable="false" type="String" actionEdit="update($e/value, $e/object/name)"/> <column title="Firstname" property="firstname"/> <column title="City" property="address/City" editable="true" type="String"/> <column title="Developer" property="jobs/developer" editable="true" type="boolean"/> <column title="Project" property="project" renderer="concat(name, ' ', startDate)"/> </tableModel> </table>

titleisusedascolumnname propertyisusedtotakethevalueforacell,propertyisanXPaththatstartsfromcurrent origin'srow editableisusedtomakethecelleditable typepermitstouseeasilythedefaulteditorregisteredonthetable rendererpermitstodefinethestringrepresentationforthecell;rendererisanXPaththat Page55

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

startsfromthecurrentcellvalue.WecanhaverendererdefineddirectlyontableModel,in thiscaseitisusedifthereisnospecificrendereroncolumn. whenachangeismadeonthecolumnName,thecorrespondingvalueinobjectpersonis directlymodified(actionEdit=...) ForactionEditin$evariableinthecommandwehave: $e/object:objectforthecurrentrow $e/value:newvalueenteredbytheuser $e/row:therowthatchanged. $e/column:thecolumnthatchanged

AnotherexampleofactionEdit: <scrollPane constraints="tableConfig"> <table id="tableConfig"> <tableModel origin="entrySet(my.package.SomeObject.getProperties())"> <column title="Property" property="key"/> <column title="Value" property="value" editable="true" actionEdit="my.package.SomeObject.setProperty( $e/object/key, $e/value)"/> </tableModel> </table> </scrollPane> Example6: YoucanusetheattributelayDown="true"intheTabletagtoreversecolumnsandrows: <table layDown="true"> <tableModel origin="..."> <column title="first" ...> <column title="second" ...> <column title="third" ...> ... Theresultis:

first second third

... ... ...

... ... ...

... ... ...

Page56

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

The<WizardPanel>tag
SwiXATprovidesapowerfulandeasytousemechanismtodefinewizards,i.e.sequentialpanels thatdrivetheusertocompletesomekindoffunctionalitiesbyaskinghimtheneededinformations inauserfriendlymanner.Anautoinstallersetupprogramisaclassicalexampleofawizard. Normallyawizardmustrespectsomesimplerules:

Thepathtoreachthefinalgoal(as,forinstance,thecorrectinstallationofanapplication)must followapredefinedsequenceofpanels Theusercannot'jump'forwardtoanypanelbeyondthenextinthesequence Theusercangobacktothepreviouspanelsinordertoreviewhisownchoices Theusercanaborttheoperationinanymoment,regardlessofthenumberofcoveredpanels Apanelcancontaininformationsthatdependonthepreviouschoicesmadeinanyprevious panel

Wehaveimplementedthe'wizard'mechanisminSwiXATbyrespectingalltheaboverules,butas we'llshowyou,someofthemcanbeeasilychanged. Let'sshowhowawizardcanbebuilt. Asthetitleofthissectionindicates,wemustusethe<WizardPanel>tag,putwithinwhateverframe (eitherIndependentFrameorInternalFrame),asinthefollowingexample: <internalFrameid="wizardFrame"title="SimpleWizard" size="450,350"layout="BorderLayout"Maximizable="false" Closable="true"> ... <panelconstraints="BorderLayout.NORTH"layout="BorderLayout"> <panelconstraints="BorderLayout.NORTH"/> <WizardPanelid="wizpnl"xml="xml/wizPanel.xml" onChange="newTab()"/> </panel> <panelconstraints="BorderLayout.CENTER"> <buttonid="prev"text="Prev" actionCommand="prev"enabled="false"/> <buttonid="next"text="Next" actionCommand="next"/> <buttonid="finish"text="Finish" actionCommand="finished()"enabled="false"/> <buttontext="Cancel" actionCommand="cancel"/> </panel> </panel> ... </internalFrame> TheaboveframecontainstheWizardPanelalongwiththebuttonsnormallyusedinanywizard: 'prev','next','finish'and'cancel'.Theirmeaningisclear,Ithink. Page57

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Notethatboththe'prev'and'finish'buttonsareinitiallydisabled,asitdoesn'tmakesensetogotoa panelbeforethefirstone,andalsotheusercannotfinishthewizard(atleastinthisexample) withouthavingtraversedallthewizard'spanels. Asyoucansee,thereisn'tanypredefinedlayout,becauseyou'refreetodefinewhateverlook&feel foryourwizardsimplybyusingtheusualSwiXMLsyntax. TheWizardPaneltagcontainstwoattributes: xmlindicatesthenameoftheresourcecontainingtheXMLdescribingthelayoutofthewizard (i.e.allthepanelsthatcomposeit) onChangepointstothecommandtoexecutewhenevertheuserchangesthepanel(inboththe twodirections).Asalways,itcanbeeitheracommanddefinedintheapplicationcontextfile,or thenameofafunctiondefinedwithinsomescriptfileimportedintheviewwiththe<Script>tag Let'sshowwhatthefilepointedbythe'xml'attributecontains: <panelname="wizpnl"> <tabbedpaneid="tabPane"> <panelname="Panel1"> ...putherethecontentofthefirstpanel... </panel> <panelname="Panel2"> ...putherethecontentofthesecondpanel... </panel> </tabbedPane> </panel> It'scomposedbyapanelcontainingaJtabbedPanecomponent.EachpanelwithintheTabbedPane representsapanelofourwizard,andwemustsimplyputwithinthemalltheUIcomponentswe need to compose our wizard. The 'name' attribute of each panel will be the label of the correspondingtabwithintheTabbedPane. HereisasimplewizardthatyoucanseebylaunchingthebaseAppsampleapplicationdistributed withSwiXAT:

Page58

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Onceagain,you'refreetodefineyourownlayoutforeachpanelinyourwizard.Simplyputthe neededXMLtagswithinthepanelscontainedintheTabbedPane. Whathappenswhentheuserclickeitheronthe'next'buttonoronthetabofthenextpanel? Assaid,thecommanddefinedinthe'onChange'attributeisexecuted. Hereisasimpleskeletonthatyoucanuseasstartingpointtodefinethecontrollogicofyour wizard: intnewTab(){ //Getsthepointerstothewizard'sbuttons prev=currentContext.getData("idMap").get("prev"); next=currentContext.getData("idMap").get("next"); finish=currentContext.getData("idMap").get("finish"); tabPane=currentContext.getData("idMap").get("tabPane"); //Getsthedirectionofthetabchange(+1,1) step=currentContext.getData("_step").intValue(); //Getsthetabselectedbytheuser tab=tabPane.getSelectedIndex(); if(tab>0){ /*Checksiftheusercangototheselectedpanel*/ if(..somecondition..){ return1;//Error.Theselectedtabisnotactivated } prev.setEnabled(true); }else{ prev.setEnabled(false); } //Enables/disablesthenextandfinishbuttons Page59

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

if(tab==tabPane.getTabCount()1){ next.setEnabled(false); finish.setEnabled(true); }else{ next.setEnabled(true); finish.setEnabled(false); } returntab;//AllOK,returnsthetab#toactivate } Asyoucansee,wehavethecompletecontroloveranyaspectofthewizard'sbehavior:

Wecanreadwhichtabhasbeenselectedbytheuser,alongwiththedirectionofthetabchange (seethevariable'step'intheabovelisting,thatgetsitsvaluefromthekey'_step'inthecurrent context:itwillcontain+1iftheuserisgoingforwardinthewizard,otherwise1). Thescriptmustreturnanintegercontainingtheindexofthetabtoactivate.Itnormallyissetto thevaluereturnedbyTabbedPane.getSelectedIndex(),butbyreturningadifferentvaluewecan selectwhateverelsetab,forcinginthismannersomeparticularpathinthewizardwhensome specificconditionisverified. Wecanalsocheckiftheusercanactivatethechosenpanel,havingthepossibilitytoblockthe action, in case of error, by returning the value 1 (in this case the selected tab remains unchanged). Wecanalsoaccesstowhatevercomponentofourpanels,havingthepossibilitytoenable/disable whateverUIcontroldependingonanycondition.

LookatthesourcecodeofthewizardimplementedinthebaseAppexampleinorderetolearnall thepossibilitiesofthisusefulbuilinfeature.

The<CardPanel>tag
ThispanelisjustaJPanelwithaCardLayoutmanager.Thiswidgetisusefulifusedalongwiththe CardPanelModel.Tochangethedisplayedpanel,justchangestateinCardPanelModel. Bydefault,whenthecurrentpanelchanges,refreshViewiscalled.Butyoucanchangethisbeaviour bydeclaringtherefreshCommandattributewiththefollowingcontents: refreshView(id) refreshViewPattern(pattern) anyothercommand(script,staticjava,xpath:,...) youcanalsodeactivatetheviewrefreshingbyusingrefreshCommand=""(emptystring).. Youcaninvokeanyactionwhenthecurrentpanelchangeswith <CardPanelonChange="...code..."> Page60

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Thiscomponent,ifusedalongwithCardPanelModel,canbeusefultoeasilyimplementwizard panels. example: <frame id="myWizard" visible="true" Size="400,100" title="myWizard"> <ContextDataSource id="wizardModel" context="current" source="wizardModel"/> <cardPanel origin="$wizardModel" refreshCommand="refreshViewPattern('navBut.*')"> <panel constraints="begin">...</panel> <panel constraints="step1">...</panel> <panel constraints="step2">...</panel> <panel constraints="end">...</panel> <panel constraints="AnotherPossibleTerminalState">...</panel> </cardPanel> <button id="navButPrec" text="Prec" origin="not($wizardModel/begin)" actionCommand="prev"/> <button id="navButNext" text="Next" origin="not($wizardModel/end)" actionCommand="next"/> <button id="navButFinish" text="Finish" origin="$wizardModel/end" actionCommand="... my command ..."/> <button text="Cancel" actionCommand="cancel"/> </frame> YoucanuseyourownactionCommandifyoudon'thaveoverloadedprec,next,andfinishmethods inyourownmodel. InthiscaseyouractionCommandmustchangethepropertystateofthemodelinordertochange thevisiblepage. Ifyoudon'tneedtoskipstepsanddon'thavedifferentchoices(morethanonefinalstep),youdon't needtouseanyspecificCardPanelModel. example: <frame id="myWizard" visible="true" Size="400,100" title="MyWiard"> <cardPanel id="wizardPanel"> <panel constraints="begin">...</panel> <panel constraints="step1">...</panel> <panel constraints="step2">...</panel> Page61

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

<panel constraints="end">...</panel> </cardPanel> <button text="Prec" origin="not($wizardPanel/begin)" actionCommand="prev"/> <button text="Next" origin="not($wizardPanell/end)" actionCommand="next"/> <button text="Finish" origin="$wizardPanel/end" actionCommand="...your method..."/> <button text="Cancel" actionCommand="cancel"/> </frame> IfyouuseCardPanelModel,youcancreateyourownchildimplementationtouseasmodel,andadd somespecificmethodtosetthepropertiesinthismodelinordertocollectinformationsduringthe wizardusageinconjunctionwithUpdateOrigin(orupdate).

SupportforDockingPanels
We have added the support for docking panels by integrating the FlexDock (https://flexdock.dev.java.net/)framework. Thedockingpanels(knownalsoasfloatingwindows)permittomovetheframeswithinamulti panelGUIsimplybydraggingthetitlebarofeachframe. Theycanbemovedaroundandmanipulatedbytheuser(intermsofsize,position,andstacking). ThistypeofconfigurableUIwhereviewscanbesnappedintoplaceistypicallyreferredtoasa dockingUI. ComplexUIssuchasEclipseandNetbeanshaveadockingUI. YoucandefineadockingUIwiththefollowingsyntax: <DockingPort? shadowBorder="true" floatingEnabled="true"> <GradientDockablePane id="ID1" title="Root docking panel" dock="root" layout="BorderLayout"> <!-- First panel's UI components here --> </GradientDockablePane> <GradientDockablePane id="ID2" title="Second docking panel" dock="ID1" region="SOUTH" ratio="20"> <!-- Second panel's UI components here --> </GradientDockablePane> <GradientDockablePane id="explorer" title="Explorer" dock="ID1" region="WEST" ratio="30" layout="BorderLayout"> <!-- Third panel's UI components here --> </GradientDockablePane> </DockingPort> Thecontainerofallthedockingpanelsisrepresentedbya<DockingPort>tag. Page62

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Eachdockablepanelmustbedeclaredwitha<GradientDockablePane>tag. Eachdockablepanelmustbeidentifiedbyanid,becausewecanrefertoitwheninsertingother panels,bymeansoftheattributesdock="parentID"andregion="NORTH|SOUTH|WEST|EAST". Theratioattribute,ifpresent,containsthepanel'ssizeinpercentage. Ifregionisomitted,thenewpanelisstackedwithintheparentpanel. Adockablepanelwithdock="root"mustbeALWAYSinserted,andcorrespondstotherootpanel, i.e.thepanelthatis'child'oftheDockingPort?,andistheparentofalltheotherdockingpanels. InsteadofGradientDockablePane(thatdisplayspanelswithagradienttitlebarandapintohidethe panel),wecanusealsoDockableView,havingthesameattributes,butdisplayedwithoutthepin, withaflatcolortitlebar. Seetheexamplein/samples/dockingdirectoryoftheSwiXATpackage. Example: ThefollowingXMLcode: ... <DockingPort shadowBorder="true" floatingEnabled="true"> <GradientDockablePane id="editor" title="Document1.txt" dock="root" layout="BorderLayout"> <ScrollPane constraints="BorderLayout.CENTER"> <TextArea text="This is the text of the Document 1..." /> </ScrollPane> </GradientDockablePane> <GradientDockablePane id="output" title="Output" dock="editor" region="SOUTH" ratio="20"/> <GradientDockablePane id="explorer" title="Explorer" dock="editor" region="WEST" ratio="30" layout="BorderLayout"> <ScrollPane constraints="BorderLayout.CENTER"> <Tree/> </ScrollPane> </GradientDockablePane> <GradientDockablePane id="editor2" title="Document2.txt" dock="editor" layout="BorderLayout"> <ScrollPane constraints="BorderLayout.CENTER"> <TextArea text="This is the text of the Document 2..." /> </ScrollPane> </GradientDockablePane> <GradientDockablePane id="properties" title="Properties" dock="explorer" region="SOUTH" ratio="30"/> </DockingPort> ...

Page63

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Generatesthefollowingframe:

Intheaboveframeyoucan: Changethepositionofanypanelbyclickingonthecorrespondingtitlebaranddraggingit tothenewposition. Changethesizeofanypanelbymovingthecorrespondingseparator(likeinanySplitPanel). Hideapanelbyclickingonthe'pin'situatedontherightofanytitlebar.

SupportforPopPupMenus
ApopupmenucanbedisplayedwithinawhateverUIcomponent,byusingthefollowingsyntax: <TextArea id="text"> <popupmenu> <menuitem text="copy" ActionCommand="copyCmd"/> <menuitem text="cut" ActionCommand="cutCmd"/> <menuitem text="paste" ActionCommand="pasteCmd"/> <menuitem text="Select All" ActionCommand="selectAll"/> </popupmenu> </TextArea>

Page64

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

Thepopupmenuisautomaticallydisplayedwhenthemouserightbuttonispressedwithinthe displayedareaoftheparentUIcomponent(aTextAreaintheaboveexample). Youcanusemnemonicsandaccelerators,asinanyothermenu.

ThreadedActionCommands
WeaddedanewActiontodosometaskinanewthread,andalsoamechanismtopermittohavethe UIshowingtheprogressoftheaction. Let'sshowthismechanismwithanexample: Imaginewehavedeclaredtheactioncodewithinastaticjavamethod,sowecaninvokeitwiththe followingXMLcode: <button constraints="buttonSave" text="Save" origin="$EntityModified" actionCommand='thread:InputRegion.save("FisheryRegion", $FisheryRegion)'/> Thestaticmethodisthefollowing: public class InputRegion { static public Object save(AbstractFrame frame, String type, FisheryRegion fisheryRegion) { log.debug("save called"); try{ ... frame.setInfoText("Checking cell"); ... frame.setProgressMin(0); frame.setProgressMax(latNumber * lonNumber); int progresscpt = 0; ... for(...){ for(...){ ... frame.setProgressValue(++progresscpt); } } frame.setInfoText("Removing unnecessary cells"); frame.setProgressMin(0); frame.setProgressMax(cells.size()); progresscpt = 0; for(Cell cell:cells){ Page65

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

... frame.setProgressValue(++progresscpt);

frame.setInfoText("Commiting the changes"); ... frame.refreshView("inputFisheryRegion"); frame.setInfoText("Finished"); } catch(Exception eee){ log.error("Can't load save region", eee); return new OutputView("Error.xml", "error", eee.getMessage()); } return null; } Asyoucansee,somenewpropertyhavehadaddedtotheAbstractFrameclassinordertosetthe valuesrelatedtothetask'sprogress. ThisisthePanelwhereweputthestatusbarusedintheframewherewehavesomeactiondoneina separatedthread: <panel border="LoweredBevelBorder" layout="XMLGridLayout(fr/ifremer/isisfish/ui/StatusBar.xgl)"> <ActionMonitor preThreadCommand="xpath:setVisible($stopCommand, 'true')" postThreadCommand="xpath:setVisible($stopCommand, 'false')" progressStartTime="5" messageTime="7" messageDisplayer="$labelStatus" progressDisplayer="$progressStatus"/> <progressbar id="progressStatus" constraints="progressStatus"/> <label id="labelStatus" constraints="labelStatus"/> <button id="stopCommand" actionCommand="stopCommand" visible="false" text="Stop" ToolTipText="Stop the process" Margin="0,0,0,0" border="EmptyBorder" constraints="stopCommand"/> <MemoryStatus constraints="memoryStatus"/> </panel> ActionMonitoristheessentialcomponentthatpermitstodescribehowtoshowthetask'sprogress totheuser. Page66

TheSwingXMLAuthoringToolUserGuide

Chapter2:SpecialFeatures

ThiscomponentlinkstheFrame'sparametersseenabove(setInfoText,setProgressValue,...)tothe correspondingUIcomponent.Itacceptsthefollowingparameters:

progressStartTimeisthetimeinsecondstostartaprogressundefinedtasklengthiftheuser doesn'tuseitinhisownaction(value1=neverstartautomaticaly) messageTimeisthetimeinsecondsthetextisdisplayed(1=neverremoved) messageDisplayerandprogressDisplayeraretheXPathexpressionsthatpointstothe JComponentusedtodisplaytheprogress(oftenJLabelandJProgressBar)

youcanhavemorethanoneActionMonitorforthesameframe;inthiscase,allthelabelswill displaythesametextandwillshowthesameprogressvalue. Note: if you want to use a graphical element in your action, you must use SwingUtilities.invokeLater()orSwingUtilities.invokeAndWait(),likeinanywelldesignedswing application. All the frame.refreshView* commands already use SwingUtilities.invokeLater() if necessary.Soyoucaninvokethemsimplyinyourcodewithoutproblems.

SupportforTesting
Inordertosimplifythetestingoftheapplication,intermsofcorrectnessoftheXMLfiles,wehave addedtheorg.swixat.tools.CheckToolutilityclass. ThistoolcanbeusedinJUnittesttoseeifallthedefinedactionCommandsexist,toverifiyifthe XMLsyntaxisright,etc. Hereisanexampleabouthowtousethisfeature: public class myAppTest extends TestCase { ... public void testXML() { SwiXAT.initFactory("some/path/to/context.xml"); CheckTool.checkView("View1.xml"); CheckTool.checkView("View2.xml"); } } WhereView1.xmlandView2.xmlrepresentthenameoftheXMLfilescontainingtheview definitionsthatwewanttocheck(theymustcontaina<Frame>asrootcomponent). Incaseoferror,anexceptionisthrown.

Page67

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

Chapter3:TheApplicationContextXML file
OneofthemostimportantrequirementsoftheSwiXATframeworkisthepossibilitytoimplement whateverSwingbasedUIwithout(almost)changinganyrowsofjavacode(ofcourseweassume thattheneededclassesexistandhavebeendeclaredintheapplication'sclasspath). Agreatandnewparadigmthatwehavefoundveryusefulforourpurposeisatechniquecalled 'InversionofControl'.Itissocalledbecauseitcreatestheentireobjectmodelbyinstantiatingand connectingalltherequestedclassessimplybystartingfromanexternaldefinition,sothemain applicationcanaccessitwithoutbeworriedabouttheinstantiationoftheneededclasses. Inotherwords,withinthemainprocedureofourapplicationitdoesn'texistanySwiXATclasses' initializationcode,butsimplywecallsomecomponentsofanexternalframeworkthatdoesthisfor us,simplybyreadingtheinitialconfigurationfromaXMLfile. A very great implementation of a IoC framework is represented by the Spring Framework (http://www.springframework.org),thatwehavechosenduetoitsrobustnessanditsverysmall footprint. ASpringXMLpropertyfilelookslikethefollowing:
... <beanid="myClass"class="my.package.myClass"> <!AsimpleStringproperty> <propertyname="prop_name"> <value>propertyvalue</value> </property> ... <!Abeanusedasvalueofaproperty> <propertyname="pointer_name"> <beanclass="my.package.myPointedClass"> <propertyname="some_name">... </bean> </property> </bean>

Thetag<bean...>containsthedeclarationofajavaclasstoinstantiate,whereasthe<property...> tagpermitstodeclareavalueofwhateverparameteroftheinstantiatedclass.Asyoucansee,the representationisrecursive,becausewecandeclareanew<bean>asvalueofa<property...>. WhentheSpringframeworkisaskedforabeandeclaredintheXMLfile(byusingasidentifierthe stringcontainedinthe'id'attributeofthe<bean...>tag),itinstantiatestherequestedclassandsets allthedeclaredpropertiesbyinvokingthecorrespondingsetters. BychangingtheaboveSpringXMLpropertyfile,theusercaninstantiatedifferentapplications withoutchanginganylineofjavacode,because,oncethedesiredclasseshavebeendeclaredinthe Page68

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

XMLparameterfile,theywillbeinstantiatedbytheIoCframework.
AsthecompletedescriptionofthefeaturesoftheSpringframeworkisoutofthescopeofthispaper,werecommendyou todownloadandreadtheSpring'sdocumentationathttp://www.springframework.org/documentation.html. Inthefollowingchapterswe'llassumethatthereaderhasabasic(evenifnotcomplete)knowledgeaboutthesyntaxofthe Spring'sXMLparameterfile.

HowtolaunchaSwiXATbasedapplication
EachapplicationbasedontheSwiXATframeworkislaunchedbythefollowingcommand: javaorg.swixat.SwiXAT<configuration_file.xml> The configuration file is written by using the SpringFramework syntax, and contains all the parametersusefultodescribehowtoinstantiateourownapplication. As of SwiXAT 0.4.0, we have added the possibility to invoke the framework by passing the configurationfileasa'resource'insteadofasafilename.Thismeansthatthefilenameissearched withintheapplication'sclasspath,permittingsotoinsertanddistributetheapplicationcontextfile withinthesamejarcontainingallthefilesneededbytheapplication.Thisfeatureisveryusefulto distributeanapplicationbyusingtheWebStarttechnology. Inordertousethisfeature,youneedtowritethefollowingcodewithinyourownapplication: SwiXAT.launch(some/path/context.xml); It'salsopossibletopassaninitialcontexttotheapplication: SwiXAT.launch(some/path/context.xml,initialContext); whereinitialContextisaMapcontainingthekeyvaluepairsthatcomposetheinitialcontext. Youcanalsousetheorg.swixat.SwiXATLauncherclasstoinvokeyourSwiXATapplication, simplybypassingtheresource'snameasthecommandlineargument. Let'sshownowhowanXMLApplicationContextmustbewritten:

HowtowritetheApplicationContext
Anyapplicationcontextxmlfileiscomposedbytwomainlogicsections: 1. the'Applicationspecific'context,containingallthebeansthatmustbeconfiguredwithspecific valuesforeachapplication 2. the'Applicationindependent'context,wherewe'llfindallthebeansusefultoSwiXATthat normallydon'tneedtobechanged

TheApplicationspecificbeans
WithinthissectionweneedtodeclaretheApplicationobject,thatwillcontainalltheproperties usefultoinstantiateourapplication. Page69

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

TheApplicationbean
Thisbeancontainssomeparametersusedbyourapplication: <beanid="application"class="org.swixat.framework.Application"> <propertyname="title"><value>Appl.Title</value></property> <propertyname="baseDir"> <value>some/base/path/</value></property> <propertyname="initialFrame"> <value>path/to/initialFrame.xml</value></property> <propertyname="onStart"><value>someAction</value></property> <propertyname="scriptManager"> <refbean="scriptManager"/></property> <propertyname="desktopPane"><value>desktop</value></property> <propertyname="fileExtensions"> <map> <entrykey="filterName"> <list> <refbean="filterID1"/> <refbean="filterID2"/> </list> </entry> <entrykey="anotherFilterName"> ... </entry> </map> </property> </bean> Theidoftheabovebeanmustbealwaysequaltothestring'application',becauseSwiXAT searches for that name within the configuration file in order to know how to instantiate the application. Thisbeanownsthefollowingproperties:

:(optional)containsthetitleoftheapplication.Itcanbeusedwhereverweneedtodisplay title theapplication'stitle(forinstancewithinthemainframe'stitlebar) baseDir (optional) this property contains the common directory prefix of all the resources : declaredwithinourapplication.Ifthispropertycontains,forinstance,thevalue'org/myPath/', then a resource pointed by 'xml/myView.xml' will be searched into the absolute path 'org/myPath/xml/myView.xml'.Inpresenceofthisproperty,it'spossiblehowevertodeclarean absolutepathsimplybyinsertinga'/'asfirstcharacter:'/my/absolute/path/resource.xml'.Evenif notmandatory,it'simportanttodeclarethispropertyinordertomaketheapplicationeasily relocatable. initialFrame :thisisthenameoftheXMLfilethatdescribestheinitialframeofourapplication. onStart :(optional)thispropertyindicateswhatistheactiontoinvokewhentheapplicationstarts (i.e.beforetheinitialframeisdisplayed).Usefultoexecutewhateverinitializationcode. scriptManager :theScriptManagerobject'sidthatpointstothechosenscriptinglanguage.Seethe 'Applicationindependentproperties'sectionbelow. Page70

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

desktopPane :(optional)IncaseofanMDIapplication,thisistheidofthedesktopPaneobject,as declaredwithintheinitialframeoftheapplication.Ifnotdeclared,theapplicationisconsidered anSDIapplication. fileExtensions :(optional)HereyoucandefineallthefilefiltersusedwhenaJfileChooseris instantiated,inordertoshowonlythefileshavingaspecificextension.Thispropertymustpoint toaMapcontainingkeyvaluepairs,wherethekeycontainsthefilefilter'sname,whereasthe value is a List of classes implementing the javax.swing.filechooser.FileFilter class. We have implementedagenericextensionofthatclasswithintheorg.swixat.util.GenericFileFilterclass.

Inordertoexplainwellhowtousethisfeature,weneedtomakealittleexample. Ifwe'rewritinganapplicationthatcanopenhtmlfiles,weneedtomakethefollowingdeclarations withintheapplicationcontextfile: <beanid="application"class="org.swixat.framework.Application"> ... <propertyname="fileExtensions"> <map> <entrykey="htmlFiles"> <list> <refbean="htmlFilter"/> <list> </entry> </map> </property> </bean> ... <!Fileextensions> <beanid="htmlFilter"class="org.swixat.util.GenericFileFilter"> <propertyname="description"> <value>HTMLfiles(*.htm|*.html)</value> </property> <propertyname="extensions"> <list> <value>htm</value> <value>html</value> </list> </property> </bean> Intheaboveexample,wehavedeclaredanentrynamed'htmlFiles'.Thatentrypointstoaunique FileFilterinstancehavingthename'htmlFilter'asbeanid. The'htmlFilter'beandeclaresaninstanceoftheGenericFileFilterclass,thatexposestwoproperties: description :containsastringthatindicatesthekindoffilesthatwillbefilteredbythisclass extensions :isaListofstringscontainingallthefileextensionsfilteredbythisclass Page71

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

Intheaboveexamplewe'llshowonlythefileshaving'.htm'or'.html'asextension.Ok,buthowcan weusetheabovefilter? Fromwithinscriptcode,byusingthefollowingsyntax: ... chooser=application.getFileChooser(htmlFiles); ... we'llgetaninstanceoftheJFileChooserclassthat,whenused,willshowonlythefileshavingthe specifiedextensions,asillustratedinthefollowingfigure:

Of course we can add whatever filter to each single map's entry, hence if we need to open, alternatively,alsothefileswiththe.jspextension,wecanwrite,withintheapplicationbean: <propertyname="fileExtensions"> <map> <entrykey="webFiles"> <list> <refbean="htmlFilter"/> <refbean="jspFilter"/> <list> </entry> </map> </property>

addingalsothefollowingnewfilter: <beanid="jspFilter"class="org.swixat.util.GenericFileFilter"> Page72

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

<propertyname="description"> <value>JSPfiles(*.jsp)</value> </property> <propertyname="extensions"> <list> <value>jsp</value> </list> </property> </bean>

We'llobtainthefollowingresult:

TheCommandbeans
Inthissectionoftheapplicationcontextweneedalsotodeclareallthecommandsusedbyour application: <!Commands> <beanid="commandName"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>some/path/command.bsh</value> </property> <propertyname="output"> <value>some/path/outputFrame.xml</value> </property> <propertyname="onError"> <value>some/path/errorFrame.xml</value> </property> </bean> Page73

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

... ItinstantiatesaCommandBinderobject,soyoucanrecognizeallthetagscorrespondingtoallthe propertiesofthatclass(seethechapter'TheCommandBindingmechanism'):


:(optional)containsthenameofthecomponentthatexecutestheinvokedaction.Ifdefined, type itcanpointeithertoacustomjavaclass,orafilecontainingJavainterpretedcode. output (optional) contains thename of the XML filedescribingthe new View toshow in : responsetoanuser'saction.Ifdeclared,theInternalFramedescribedintheXMLwillbeshown aftertheexecutionoftheaction. onError :(optional)containsthenameoftheXMLfiledescribingtheviewtoshowincasethe executedactionreturnsanerror. Ifdeclared,theInternalFramedescribedintheXMLwillbe shownaftertheexecutionoftheaction,incaseoferror.

Asallthecommandsaredeclaredoutsidetheframes'XMLfiles,theycanbeusedanywhereinto anyframeoftheapplication. In fact the commands declared in this section can be used by any UI component, as well as referencedbyany<WindowEvent>and<EventHandler>tag. Inthismannerthecodereuseisfacilitated,makingtheapplicationmaintenancesimpler. Last,butnotleast,ifyouhavedeclaredsome<EventHandler>withinsomeXMLviewdefinition file,youneedtodeclarethecorrespondingwrapperyouhavebuilt,asinthefollowingexample: <!Eventwrapper> <beanid="wrapperID"class="some.package.YourOwnWrapper" singleton="false"/> Theidofthisbeanmustbeequaltothecontentofthe'wrapper'propertyofthecorresponding <EventHandler>tag.ThereferencedclassmustinherittheAbstractModelEventWrapperclass,as descibedinthe'Howtowriteaneventwrapper'section. Remembertoset always theparameter'singleton'tofalse,inordertocreateadifferentwrapper instanceforeachdeclared<EventHandler>tag.

TheApplicationindependentbeans
Inthissectionwe'llputallthedeclarationsthatareindependentfromanyspecificapplication,so thepropertiesdeclaredherecanbecopied(almost)withoutmodificationstotheconfigurationfile ofanySwiXATbasedapplication.

TheScriptManagerbean
Firstofall,inthissectionwefindtheScriptManagerdeclaration,usefultochoosethescripting language: <beanid="scriptManager"class="org.swixat.script.ScriptManager"> Page74

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

<propertyname="scriptEngine"> <!value>org.swixat.script.GroovyScripting</value> <value>org.swixat.script.BeanShellScripting</value> </property> <propertyname="evals"> <!Initialscriptcodetoevaluate> <list> <value>//AddhereyourownJSstatements</value> <value>importorg.swixat.*;</value> </list> </property> </bean> Theidofthisbeanmustbethesameindicatedwithinthe'application.ScriptManager'property(see theprevioussection). Itexposestwoproperties: ScriptEngine :itindicatestheclassnameofthe'wrapper'forthechosenscriptinglanguage.All the invoked script code will be interpreted by using that wrapper. The indicated class must implementtheorg.swixat.script.Scriptinginterface.Atthismomentthereexisttwowrappers: org.swixat.script.BeanShellScripting: the BeanShell (http://www.beanshell.org) wrapper 2 org.swixat.script.GroovyScripting:theGroovylanguage (http://groovy.codehaus.org/) wrapper Evals :Containsthecodetobeexecutedautomaticallyatthebeginningofanyscriptinvocation, and it's normally used to define all the needed import statements. (Note: as the code is interpreted atruntime,statements like'importsome.package.*;'will slowdown the execution,becauseforanyreferencedclass,theinterpretermustscanalltheimportstatementsin ordertosearchforthepackagecontainingthatclass.Useinsteadfullyqualifiedclassnames,like 'importsome.package.myClass;').

TheTagLibraryextensions
Amongtheapplicationindependentpropertieswefindalsothetaglibraryextensions,usedtoadd newtagstotheframe'sXMLfiles. HereisthedeclarationoftheactualTaglibextensions:
<beanid="newTags"class="org.swixat.framework.TagLibraryExt"> <propertyname="newTags"> <map> <!AnewTag> <entrykey="newTagName"> <value>some.package.TagLibImplementation</value> </entry> <!AnotherTag...> <entrykey="anotherTag"> <value>...</value>
2 TheGroovylanguagesupportcannotbeconsideredfullytestedandworking,henceyoucouldexperiencesomestrange andunexpectedbehavior.UseinsteadtheBeanShellinterpreter.

Page75

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

</entry> </map> </property> </bean>

As you can see, we instantiate the class org.swixat.framework.TagLibraryExt that representsthecontainerofalltheTaglibextensions. Itexposesapropertynamed'newTags',thatisaMapwithinwhichallthenewtagswillbeaddedas a keyvalue pair: the key is the name of the new tag (newTagName in the above example), whereasthevalueisrepresentedbythenameoftheclassthatimplementsthebehaviorofthattag (some.package.TagLibImplementationclassintheexample). Now,inyourapplicationyoucaninstantiatethenewtagbywriting,inanyXMLview:
<newTagNameattribName=value.../>

The attributesacceptedbythetagmust bedeclaredintheimplementationclass asparameters accessed by the corresponding getter and setter methods, in the form getAttribName() and setAttribName()respectively. Important:duetosomeconstraintsimposedbySwiXML,theimplementationclassMUSTinherit (eitherdirectlyorindirectly)thejavax.swing.JComponentclass.

TheSetterFactorybean
ThibeancontainsalltheclassesusedtoimplementthebindingbetweentheSwingcomponentsand thecorrespondingwrapperclassesusedtoinitializethem:
<!SwingcomponentsSetterFactories> <beanid="SetterFactory"class="org.swixat.databinding.SetterFactory"> <propertyname="propertySetters"> <map> <entrykey="your.own.SwingComponent"> <value>some.package.YourOwnPropertySetter</value> </entry> ... </map> </property> </bean>

Thecontainerclassinthiscaseisrepresentedbyorg.swixat.databinding.SetterFactory thatexposesaMapnamed'propertySetters'.Intothatmapwewillinsert,askey,theclassnameof theSwingcomponent,andasvaluethecorrespondingpropertysetter'sclassname. Thepropertysetterclassmustimplementtheorg.swixat.databinding.PropertySetterinterface. Youneedtoimplementthefollowingtwomethods: boolean isCompatible(JComponent component): method called by the framework in order to verifythecompatibilityofthecomponentwiththispropertysetter.Itmustreturntrueonlyifthe Page76

TheSwingXMLAuthoringToolUserGuide

Chapter3:TheApplicationContextXMLfile

componentpassedasparametercanbehandledbytheimplementedpropertysetter. voidsetProperty(JComponentcomponent,Objectdata):methodcalledbytheframeworktoset thecontentofthecomponentpassedasparameter.Thecontentispointedbythe'data'parameter, and contains the value returned by the xpath written in the 'origin' attribute within the correspondingtagoftheXMLview. Aspreviouslysaid,thissectiondoesn'tneedtobechangedbythenormalframework'suser,soonly whowantstoextendtheframeworkneedstochangetheaboveproperties.

Page77

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

Chapter4:GettingStarted
HowtobuildSwiXATfromSource
SwiXATusesMavenforbuild. DownloadMaven(ifMavenisalreadyinstalledonyourmachineskipthisstep): DownloadMavenfromhttp://maven.apache.org/start/download.html. TrytheLatestStableRelease.

TellMavenhowtogettheSwiXATDependencies: SwiXAThasit'sownMavenRepository.Youhavetoaddthisrepositorytomaven'sremote repositorypropertiy.

Createafilecalledbuild.propertiesinyouruserhomedirectoryandinsertthisline:
maven.repo.remote=http://www.ibiblio.org/maven/,http://swixat.sourceforge.net/maven/

ThistellsmaventousetheofficialMavenRepositoryandtheSwiXATRepository. Youwillfindmoreinformationsaboutrepositoriesat http://maven.apache.org/using/repositories.html. CheckouttheSwiXATsources:

FollowtheinstructionsonthesourceforgeCVSpageathttp://sourceforge.net/cvs/?group_id=99002. Youwillneedthe'swixat'module. BuildSwiXAT:

Changetothe'swixat'directoryandtypemavenjar:install Youshouldgetthefollowingoutput:
$mavenjar:install |\/|_Apache___ ||\/|/_`\V/_)'\~intelligentprojects~ |_||_\,_|\_/\_|_||_|v.1.0.2 build:start: java:preparefilesystem: mkdirCreateddir:/home/jbader/projects/swixat/swixat/target/classes java:compile: echoCompilingto/home/jbader/projects/swixat/swixat/target/classes javacCompiling75sourcefilesto/home/jbader/projects/swixat/swixat/target/classes java:jarresources:

Page78

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

test:preparefilesystem: mkdirCreateddir:/home/jbader/projects/swixat/swixat/target/testclasses mkdirCreateddir:/home/jbader/projects/swixat/swixat/target/testreports test:testresources: test:compile: echoNotestsourcefilestocompile. test:test: echoNoteststorun. jar:jar: jarBuildingjar:/home/jbader/projects/swixat/swixat/target/swixat0.4.1.jar copyCopying11filesto/home/jbader/projects/swixat/swixat/target Copying:from'/home/jbader/projects/swixat/swixat/target/swixat0.4.1.jar'to: '/home/jbader/.maven/repository/swixat/jars/swixat0.4.1.jar' Copying:from'/home/jbader/projects/swixat/swixat/project.xml'to: '/home/jbader/.maven/repository/swixat/poms/swixat0.4.1.pom' BUILDSUCCESSFUL Totaltime:7seconds Finishedat:ThuAug1109:10:41CEST2005

Ifyou'rerunningmavenforthefirsttimeonyoursystem,itwilldownloadalltheexternallibraries neededtocorrectlybuildSwiXAT,henceyouneedanactiveconnectiontoInternet. YouwillfindMavenPluginsforseveralIDEsathttp://mevenide.codehaus.org/ Runtheexamples: Changetothe'target'directoryandtype./BaseApp.sh(BaseApp.batforWindowssystems)or whateverelsesampleshellscript.

HowtocreateaSwiXATbasedSampleApplication
SwiXATcomeswithanusefulmavenpluginthatpermitstocreatetheinitialdirectorystructure alongwiththeinitialpropertiesfilesneededtowriteanewapplicationbasedonSwiXAT. Ofcourseyou'refreetocreatebyhandthedirectorystructureyoulike,butbyusingthisplugin you'll save many timeandwill obtainacompleteenvironment withinwhichyou canstart the developmentofyourownapplicationbasedonSwiXAT. DownloadMaven(ifMavenisalreadyinstalledonyourmachineskipthisstep): DownloadMavenfromhttp://maven.apache.org/start/download.html. TrytheLatestStableRelease.

TellMavenhowtogettheSwiXATDependencies: SwiXAThasit'sownMavenRepository.Youhavetoaddthisrepositorytomaven'sremote repositorypropertiy.

Createafilecalledbuild.propertiesinyouruserhomedirectoryandinsertthisline:
maven.repo.remote=http://www.ibiblio.org/maven/,http://swixat.sourceforge.net/maven/

Page79

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

ThistellsmaventousetheofficialMavenRepositoryandtheSwiXATRepository. Youwillfindmoreinformationsaboutrepositoriesat http://maven.apache.org/using/repositories.html. DownloadandInstalltheSwiXAT'smavenplugin: Youcaneitherdownloadandunzipthe Launchthefollowingcommand(youneedtohaveanactiveconnectiontoInternet):

$mavenplugin:downloadDgroupId=swixatDartifactId=swixatgenappplugin Dversion=X.Y.Z

Theversion'snumber(X.Y.Z)touseintheabovecommandcanbechosenamongtheavailableones intheswixatmavenrepository(http://swixat.sourceforge.net/maven/swixat/plugins).

Createtheapplication'srootdirectory:

$mkdirmyApp $cdmyApp

Createthesampleprojectwiththecommand'mavenswixat:genapp'.Thepluginwillaskfor someinformationsaboutyournewapplication,asinthefollowingexample:

$mavenswixat:genapp ____ |\/|___Apache_____ ||\/|/_`\V/_)'\~intelligentprojects~ |_||_\__,_|\_/\___|_||_|v.1.0.2 Pleasespecifyanidforyourapplication:[app] Pleasespecifyanameforyourapplication:[ExampleApplication] Pleasespecifythepackageforyourapplication:[org.swixat.app] Pleasespecifythefolderforyourapplication(mustbethesameaspackage,onl ywith/insteadof.):[org/swixat/app]

Ifthedefaultvalueproposedwithinthebracketsisright,youcansimplypressenter,otherwiseyou cantypeyourpreferredchoiceandthenpressenter. Attheendoftheaboveprocess,thecompletesourcecodeoftheskeletonofyourapplicationwillbe createdwithinthedirectory'src'havingthefollowingstructure:

Page80

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

Asyoucansee,theproject.xmlfilemakesyourapplicationMavencompatible,soyoucan build/run/deployitbyusingtheMavencommands.

Nowyou'rereadytocompileandruntheapplication...:

$mavenjarrun

...andthemagicisdone...

Youhaveabasicapplicationready,withalltheneededfilesintherightplace. Openyourpreferredtexteditor,editthefilesinthesrc/resourcesdirectoryinorderto implementyourownfunctionalities,andrecompileandrunwiththeabovemavencommand. YourownmavendrivenSwiXATapplicationisready! Page81

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

TheHelloWorldexample
InordertopermiteveryonetolearnhowtouseSwiXAT,wehavepreparedthefollowingtutorial, thatwillexplainallthestepsneededtobuildacompleteSwingapplicationbasedonSwiAXT.

Example1:ThestaticHelloWorldexample
Howtostart,ifnotbyusingtheclassic'HelloWorld'example? First of all, we need to create the directory structure in order to contain all the files of our application. You can either use the mavenplugin provided with SwiXAT, or create manually the needed directories.Astheuseofthepluginhasbeenexplainedintheprevioussection,herewe'llexplain howtocreatemanuallytheenvironmenttocreateanewapplication(evenifouradviceistouse maven). Create the root directory of our application (say 'c:\SwiXAT\samples\hello\' in a Windows environment,or'~/SwiXAT/samples/hello/'onaUnix/Linuxplatform). Cdtothatdirectoryandcreatetwosubdirectoriesnamedrespectively'bsh'and'xml'. WithinthexmldirectorycreateafilenamedhelloWorldFrame1.xmlcontainingthefollowingcode: <?xmlversion="1.0"encoding="UTF8"?> <Frameid="hello"visible="true"size="250,80"title="Myfirst application"layout="BorderLayout"Maximizable="false" Closable="true"Resizable="false"> <panelconstraints="BorderLayout.NORTH"> <labeltext="HelloWorld!"/> </panel> </Frame> Now,createtheapplicationcontextXMLfile,namedcontext1.xml: <?xmlversion="1.0"encoding="UTF8"?> <!DOCTYPEbeansPUBLIC"//SPRING//DTDBEAN//EN" "http://www.springframework.org/dtd/springbeans.dtd"> <beans> <beanid="application"class="org.swixat.framework.Application"> <propertyname="title"><value>HelloWorld</value></property> <propertyname="baseDir"> <value>samples/hello/</value></property> <propertyname="initialFrame"> <value>xml/helloWorldFrame1.xml</value> </property> <propertyname="scriptManager"> <refbean="scriptManager"/></property> </bean> Page82

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

... Wehavelistedhereonlytheapplication'sspecificparameters.For thecompletelistingseethe context1.xmlfilecontainedinthesamplesdirectoryoftheSwiXATexamplesdistribution. Note the baseDir property of the application bean, that contains the value 'samples/hello/'. It representstheprefixusedtocomposealltheabsolutepathsofthedeclaredresources(thismeans thatweneedtoputintheclasspaththeSwiXATdirectory,i.etherootdirwithinwhichourbaseDir resides). Nowwecanlaunchourfirstapplicationsimplybytypinginaconsole:
cdc:\SwiXAT javaorg.swixat.SwiXATsamples/hello/xml/context1.xml

Ofcourseyoumustputalltheneededjarsinyourclasspathbysettingtheenvironmentvariable CLASSPATH3, and the java.exe command must be reachable in the system path. The above commandsareforaWindowsenvironment,buttheUnix/Linuxuserswillbeabletochangethem accordinglytheirplatform. Thefollowingwindowswillappearonthescreen:

Congratulations!YouhavebuildyourownfirstapplicationbasedonSwiXAT.

Example2:InsertingaButton
Nowwe'llbuildaslightlycomplexexamplebyaddingabuttoninordertoshowthehelloworld messagewhenthebuttonispressed. Firstofall,weneedtocreateanewviewcontainingthebutton,asillustratedinthefollowingcode: <Frameid="hello"visible="true"size="250,80"title="Myfirst application"layout="BorderLayout"Maximizable="false" Closable="true"Resizable="false"> <panelconstraints="BorderLayout.NORTH"> <buttonid="b1"text="Greetings"ActionCommand="hello"/> </panel> </Frame>
3 TheCLASSPATHmustbesetto:.;swixat.jar;bsh.jar;commonsjxpath.jar;commons logging.jar;jdom.jar;springcore.jar;swixml.jar.Substitute';'with':'forUnix/Linux environments.

Page83

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

TheabovecodewillbesavedtoafilenamedhelloWorldFrame2.xml. NotetheActionCommandassociatedtothebutton,thatcontainsthevaluehello.Thisisthename ofthecommandtoinvokewhenthebuttonispressed,andit'sdeclaredwithinthetheapplication contextXMLfile,asinthefollowinglisting: <beans> <beanid="application"class="org.swixat.framework.Application"> <propertyname="title"><value>HelloWorld</value></property> <propertyname="baseDir"> <value>samples/hello/</value></property> <propertyname="initialFrame"> <value>xml/helloWorldFrame2.xml</value> </property> <propertyname="scriptManager"> <refbean="scriptManager"/></property> </bean> <!Commands> <beanid="hello"class="org.swixat.commands.CommandBinder"> <propertyname="output"> <value>xml/helloWorldFrame1.xml</value> </property> </bean> ... Theabovecode(storedwithincontext2.xml)issimilartothatcontainedincontext1.xml,exceptfor theinitialFrameproperty,thatthistimepointstothehelloWorldFrame2.xmlfile,andtheaddingof the'hello'commandbean.Thisbeanindicates,intheproperty'output',whichistheframetoopen ('xml/helloWorldFrame1.xml')whenthecommandisinvoked. Nowlaunchthissecondexamplewiththecommands:
$cdc:\SwiXAT $javaorg.swixat.SwiXATsamples/hello/xml/context2.xml

Awindowcontainingthebutton'Greetings'willappear(xml/helloWorldFrame2.xml),andwhen pressed,our'HelloWorld'messagewillbeshowninaseparateframe(xml/helloWorldFrame1.xml):

Page84

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

Example3:AddingaDataSource
Nowwe'lltrytobuildadynamicframe,wherethestrings'Hello'and'World!'willberetrievedbyan externalsource,byusingaScriptingDataSource. CreatewithinthebshsubdirafilenamedgetWords.bshandwriteintoitthefollowingJavaScript code: importjava.util.HashMap; map=newHashMap(); map.put("first","Hello"); map.put("second","World!"); returnmap; Asyoucansee,wefirstcreateanewHashMap,andthenstoreintoittwostrings,Helloand World!,indexedrespectivelybythekeysfirstandsecond.TheHashMapisthevaluereturned bythisscriptcode.Ofcoursethisisjustanexample,becauseinarealapplicationthedatacouldbe retrievedeitherfromabusinessobject,orfromadatabase,or...whateverelsesource. Now,inordertobindtheabovedatatoourview,weneedtomodifytheHelloWorldframeinthis manner(thecodeisstoredwithinhelloWorldFrame3.xml): <Frameid="hello"visible="true"size="250,80"title="HelloFrame" layout="BorderLayout"Maximizable="false"Closable="true" Resizable="false"> <ScriptingDataSourceid="WORDS"script="bsh/getWords.bsh"/> <panelconstraints="BorderLayout.NORTH"> <labelid="label1"origin="$WORDS/first"/> <labelid="label2"origin="$WORDS/second"/> </panel> </Frame> ThefirstdifferenceisrepresentedbythepresenceoftheScriptingDataSourcetag,thatpointstothe bsh/getWords.bshfile,containingthescriptcodetoexecute. Thetwolabelsnowdon'tcontainstaticallythetexttoshow,butinsteadtheypoint,throughthe XPathexpressionwritteninthe'origin'property,tothevaluesreturnedbytheScriptingDataSource. TheJakartaCommonsJXPathlibraryhandlesthekeysstoredwithinaMapexactlyasiftheywere propertiesoftheMapitself,hencewecanrefertoeachstoredvaluesimplybywriting,inthe'origin' property: $DataSourceName/keyName. Thecontext3.xmlfileusedtolaunchthisexamplecontains: <beans> <beanid="application"class="org.swixat.framework.Application"> Page85

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

<propertyname="title"><value>HelloWorld</value></property> <propertyname="baseDir"> <value>samples/hello/</value></property> <propertyname="initialFrame"> <value>xml/helloWorldFrame2.xml</value> </property> <propertyname="scriptManager"> <refbean="scriptManager"/></property> </bean> <!Commands> <beanid="hello"class="org.swixat.commands.CommandBinder"> <propertyname="output"> <value>xml/helloWorldFrame3.xml</value> </property> </bean> ... Theuniquedifferencerespecttocontext2.xmlisrepresentedbytheoutputviewdeclaredinthe 'hello'command,thatpointstothenewlycreatedxml/helloWorldFrame3.xml. Bylaunchingthisexamplewe'llobtainthesameresultoftheexample2,butthistimeweknowthat thetwolabelsshowadynamiccontentobtainedfromaDataSourcetag. Toverifytheaboveassertion,trytochangethescriptingcodeinordertoreturndifferentvalues.

Example4:Passingparametersbetweentwoframes
In this example we'll show you how to pass a value between two frames by using a ContextDataSource. Let'sstartfromthepreviousexample,bymergingthetwoframes,inordertoobtainawindow containingboththe'Greetings'button,andthetwolabelscontainingthedynamictext,asinthe followinglistingcontainedwithinxml/helloWorldFrame4.xml: <Frameid="hello"visible="true"size="250,80"title="Myfirst application"layout="BorderLayout"Maximizable="false" Closable="true"Resizable="false"> <ScriptingDataSourceid="WORDS"script="bsh/getWords.bsh"/> <panelconstraints="BorderLayout.NORTH"> <textFieldid="text1"Columns="6"origin="$WORDS/first"/> <labelid="label2"origin="$WORDS/second"/> <buttonid="b1"text="Greetings"ActionCommand="hello"/> </panel> </Frame> ThistimethefirstlabelhasbeensubstitutedbyaJtextFieldinordertopermittheusertochangeits Page86

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

value;howevernotethatitcontinuestogetitscontentfromthesameScriptingDataSourceusedin thepreviousexample,asthelabel2does,too. Nowwe'llcreatetheframeshownbythecommandassociatedtothebutton,inordertoshowina separatedwindowthetextcomposedbytheconcatenationofthe'text1'and'label2'content. Createanewfilenamedxml/helloWorldFrame4a.xmlcontainingthefollowingXMLcode: <Frameid="hello"visible="true"size="250,80"title="HelloFrame" layout="BorderLayout"Maximizable="false"Closable="true" Resizable="false"> <ContextDataSourceid="WORDS"context="current" source="parent"/> <panelconstraints="BorderLayout.NORTH"> <labelid="label1"origin="$WORDS/text1/text"/> <labelid="label2"origin="$WORDS/label2/text"/> </panel> </Frame> ThisnewframecontainsaContextDataSource,usedtoretrievethecontentoftheUIcomponentsof thepreviousframe(i.e.thecaller).Itpointstothe'parent'keywithinthe'current'context,andas youalreadyknow(seethe'currentcontext'paragraph),the'parent'keypointstotheMapcontaining alltheIDsofthepreviousframe'sUIcontrols.Inthismannerwehaveausefulmechanismto retrievethecontentofwhatevercontrolofthecallerframe. The'origin'propertiesofthetwolabelscontaintheXPathneededtoretrievethecontentofthetext propertyrespectivelyofthe'text1'andthe'label2'controls. Inordertolaunchthisexample,weneedtocreatethecorrespondingcontext4.xmlfile: <beans> <beanid="application"class="org.swixat.framework.Application"> <propertyname="title"><value>HelloWorld</value></property> <propertyname="baseDir"> <value>samples/hello/</value></property> <propertyname="initialFrame"> <value>xml/helloWorldFrame4.xml</value> </property> <propertyname="scriptManager"> <refbean="scriptManager"/></property> </bean> <!Commands> <beanid="hello"class="org.swixat.commands.CommandBinder"> <propertyname="output"> <value>xml/helloWorldFrame4a.xml</value> Page87

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

</property> </bean> ... TheonlychangesarerepresentedbytheinitialFrameandtheoutputviewassociatedtothe'hello' command. Whenlaunched,theapplicationwillshowthefollowingwindow:

NowtrytochangethecontentoftheTextField(bywriting,forexample'Hellodear'),andpushthe 'Greetings' button. A second frame will appear, containing the concatenation of the above two strings,asthefollowingfigureshows:

Example5:Validatingtheuser'sinput
Nowwe'lladdavalidationscriptinordertocheckthevalidityofthevalueinsertedbytheuser. Todoit,firstofallweneedtowritethescriptthatwillvalidatetheinput.Ifwewant,forexample, to control the length of the string inserted in the 'text1' field, we must write in a file called bsh/checkInput.bshthefollowingcode: text=currentContext.getData("idMap").get("text1").getText(); if(text.length()>10) return1; else return0; Asyoucanseeintheabovecode,wefirstreadthecontentoftheJTextFieldnamed'text1'by retrievingfromthecurrentcontexttheframe'sidMap,andthenaccessingtotheUIcomponent identifiedbytheID'text1'. Afterthat,weverifythelengthoftheextractedstring,returningthevalue1incaseitisgreaterthan 10characters. Now we need to define the frame that will display the error message. We'll call that frame Page88

TheSwingXMLAuthoringToolUserGuide

Chapter4:GettingStarted

xml/errorFrame.xml: <Frameid="errorFrame"visible="true"size="180,100"title="Error" layout="BorderLayout"Maximizable="false"Closable="true" Resizable="false"> <panelname="pnl"constraints="BorderLayout.CENTER"> <labelid="msg"text="'Hello'fieldtoolong!"/> <buttontext="Close"ActionCommand="Cancel"/> </panel> </Frame> Afterthat,wemustchangethe'hello'commanddefinitionwithinthecontext4.xml,inthefollowing manner(afterhavingrenamedthecontextfileascontext5.xml): ... <!Commands> <beanid="hello"class="org.swixat.commands.CommandBinder"> <propertyname="type"> <value>bsh/checkInput.bsh</value></property> <propertyname="output"> <value>xml/helloWorldFrame4a.xml</value></property> <propertyname="onError"> <value>xml/errorFrame.xml</value></property> </bean> ... Wehavesimplyaddedtwonewproperties: 1. the'type'propertypointstothe'bsh/checkInput.bsh'filecontainingthecodewrittentovalidate theinputtext 2. the'onError'propertypointstotheerrorFrame.xmlfilecontainingtheoutputviewtoshowin caseoferror(i.e.incasethescriptcodereturns'1') Alltheremainingcontextfileisthesameasfortheexample4. Whenthisexampleislaunched,andatexttoolongisenteredintothetextfield,anerrormessageis shown,asdepictedinthefollowingfigure:

Page89

TheSwingXMLAuthoringToolUserGuide

Chapter5:Extendingtheframework

Chapter5:Extendingtheframework
Howtoaddnewcommands
Ifwewanttoaddanewcommandtoinvokeinresponseofsomeuser'saction,andwewanttoadd permanentlythatnewcommandtotheframeworkinordertobeabletoreuseitwithinwhatever application,wecandoitbyimplementinganewActioninterface. Forexample,ifwewanttoaddthecommandnamedmyCommand,wecanbuildthefollowing newclass: public class MyCommandAction implements Action { public boolean accept(Object caller, AbstractFrame frame, String command, Object arg) { return "myCommand".equalsIgnoreCase(command); } public Object doCommand(Object caller, AbstractFrame frame, String command, Object arg) { // Insert your own execution code here... ... return new Integer(0); } public boolean check(Object caller, AbstractFrame frame, String command, Object arg) { /* Returns true if the command can be executed */ return true; } } Asyoucansee,weneedtofillthreemethods:

accept():calledbytheframework,returnstrueifthisActionimplementationcanhandlethe commandpassedasparameter. check():calledbytheframeworkinordertocheckifthecommandcanbeexecuted. doCommand():containsthecodetoexecuteinresponsetothecommandinvocation. It returnseitheranInteger(containingthevalue0ifallok,otherwise1)oraninstanceof OutputViewinordertoshowanewViewinresponsetothecommandexecution.Nullis usedwhennoactionfoundforthecommand.Theonlycasewherewecanreturnnull,isfor specialcommands,forexampleanActionthatdoesnothing,butlogsallthecommands invokedinSwiXat. Page90

TheSwingXMLAuthoringToolUserGuide

Chapter5:Extendingtheframework

Alltheabovemethodsreceivethefollowingparameters:

caller:theobjectthatcalledthecommandinitially frame:framewherecomefromthecommand command:thecommandtoexecute arg:apossiblespecialeventargument(incaseofaSwingevent,pointstothecausingevent e.g.amouseevent)

Oncewehavebuilttheabovenewclass,wecanaddittotheActionManagerinordertomakeit visibletotheentireframework.Wecanwrite,forexamplewithintheOnStartscript: ActionManager.register(new MyCommandAction()); At this point we can invoke our new command in any actionCommand, like in the following example: <Button text=Clik Here actionCommand=myCommand/> AsnewCommandisinterceptedbytheMyCommandActionclass,wedon'tneedtodeclarethe commandintheapplicationcontextXMLfile. WehavealreadydefinedthefollowingActions(youcanalsoextendoneofthem,ifneeded):

CancelAction:closesthecurrentframe GenericActionAction:ifthecommandcorrespondstotheidofanexisting<Action>tag,the correspondingcommandisexecuted HandleClassMethodAction:supportforstaticjavamethodsinvocation HandleCommandAction:executesanormalcommand HandleScriptFunctionAction:executesafunctiondeclaredinascript NextAction:GotothenextpaneloftheNavigableComponentassociatedwithframe OutputViewAction:opennewview PrevAction:GotothenextpaneloftheNavigableComponentassociatedwithframe RefreshDataAction:refreshdata RefreshViewAction:refreshcurrentframe,orspecificcomponentinframe RefreshViewPatternAction:refreshcomponentthatidmatchpattern ThreadAction:executestheactioninaseparatethread UpdateAction:updatesomeproperty XPathAction:evaluateanXPath

Page91

Anda mungkin juga menyukai