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
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
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)
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
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
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
<ItemEvents>
TheSwingXMLAuthoringToolUserGuide
Chapter1:TheMVCParadigm
Attributes
(*)ThepropertyNameattribute mustbesetwiththenameof thecomponent'spropertyto monitor (ex:propertyName=text) AppliesonlytoSwing componentsthatinheritthe JTextComponentclass. (*)Ifdeclaredalongwithother specificeventattributes,it's calledafterallothers.Example: ifonChangeUpdateand onModifiedareusedtogether, theonModifiedactionis invokedafteronChangeUpdate.
<VetoableChangeEvents> <DocumentEvents>
<CaretEvents>
onCaretUpdate
<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
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",...);
TheSwingXMLAuthoringToolUserGuide
Chapter1:TheMVCParadigm
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:
TheSwingXMLAuthoringToolUserGuide
Chapter1:TheMVCParadigm
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
source :astringcontainingtheIDoftheDOMobject,declaredwithintheSpringapplication context.Itmustpointtoabeanbelongingtooneofthefollowingclasses: String(containingavalidURI) java.net.URL java.io.InputStream :astringcontainingtheXPathusedtogettheneededvalue.ItusesasroottheDOM path instancepointedbythedeclared'source'object. iterate :abooleanvalueindicatingifalltheinstancesfoundmustbereturned(falsebydefault)
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
andthen,toputakeyvaluepairwithinit:
newContext.setData(newKey,value);
or:
context.getContext(contextName).setData(newKey,value);
toremoveacontext'skey,use:
context.removeData(key)
toremoveanentirecontext,instead,use:
context.setContext(contextName,null)
Useinsteadthecurrentcontext,asdescribedinthenextsection.
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
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) {...
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:
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
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.
Sowecaninstantiateandusethelistenerwithinaview'sframe(orinternalframe)inthismanner:
<Frame...> <!Thesourcebusinessobject> <ContextDataSourceid="getStock"context="current"source="stockPicker"/>
Page39
TheSwingXMLAuthoringToolUserGuide
Chapter1:TheMVCParadigm
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
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
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:
The<NestedTreeModel>and<TreeNode>tags
WehaveimplementedanewTreeModel,namedNestedTreeModel,topermittodisplaymoreeasily abusinessmodel'streeofobjectsinsituationswheresomenodesrepresentsimplythecategory's name(notderivedbyrealobject'sinstances)withinwhichsomechildnodesmustbegrouped. Ifwehaveanobject'Person'likethis:
TheSwingXMLAuthoringToolUserGuide
Chapter2:SpecialFeatures
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:
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:
Forexample,ifwehaveaDataSourcenamedCUSTOMERSthatreturnsthefollowing2Darray ofStrings: RalphWhite SamBlack TomYellow PaulGreen WhiteStreet,44London BlackStreet,55NewYork YellowStreet,66Paris GreenStreet,77Rome
TheSwingXMLAuthoringToolUserGuide
Chapter2:SpecialFeatures
thefollowingTableChooserwillbeshown:
SupportforJTablecomponent
AsforSwiXAT0.5.5wehaveaddedthepossibilitytoeasilyfillaTablebydeclaringthesourceof datawiththe'origin'attributeandaTableModeltag. Example1: <table origin="$DS/datas" renderer="name"/>
Example2: <table origin="$DS/selected"> <tableModel origin="$DS/list" columns="name, firstname, address/city" columnNames="Name, Firstname, City" columnEditables="false, false, true"/> </table>
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>
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>
TheSwingXMLAuthoringToolUserGuide
Chapter2:SpecialFeatures
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:
Page56
TheSwingXMLAuthoringToolUserGuide
Chapter2:SpecialFeatures
The<WizardPanel>tag
SwiXATprovidesapowerfulandeasytousemechanismtodefinewizards,i.e.sequentialpanels thatdrivetheusertocompletesomekindoffunctionalitiesbyaskinghimtheneededinformations inauserfriendlymanner.Anautoinstallersetupprogramisaclassicalexampleofawizard. Normallyawizardmustrespectsomesimplerules:
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
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:
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
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:
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>
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
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>
TheSwingXMLAuthoringToolUserGuide
Chapter3:TheApplicationContextXMLfile
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
:(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
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.
Createafilecalledbuild.propertiesinyouruserhomedirectoryandinsertthisline:
maven.repo.remote=http://www.ibiblio.org/maven/,http://swixat.sourceforge.net/maven/
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
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.
Createafilecalledbuild.propertiesinyouruserhomedirectoryandinsertthisline:
maven.repo.remote=http://www.ibiblio.org/maven/,http://swixat.sourceforge.net/maven/
Page79
TheSwingXMLAuthoringToolUserGuide
Chapter4:GettingStarted
$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]
Page80
TheSwingXMLAuthoringToolUserGuide
Chapter4:GettingStarted
Asyoucansee,theproject.xmlfilemakesyourapplicationMavencompatible,soyoucan build/run/deployitbyusingtheMavencommands.
Nowyou'rereadytocompileandruntheapplication...:
$mavenjarrun
...andthemagicisdone...
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
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:
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