|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
最后我再次声明,我并没有说不看好java,实际上我对java很乐观的,毕竟她正在不断改进中,我相信她总有一天会和.net并驾齐驱的guidEclipseFormsProgrammingGuideInitialcreation:21February2004Addedtablewrapsample:22February2004Introduction
ThisdocumenthasbeenwrittentohelpyouusethenewEclipse3.0featurecalledEclipseForms.ThecontentwilleventuallymovetoEclipsehelp.Inthemeantime,youcanstartexperimentingusingexamplesshownbelowandcodeinEclipse3.0integrationbuilds.
EclipseFormsisaplug-inthatexposesasetofcustomswidgetsandothersupportingclassesthatwerebeforeusedasinternaltoPDEandUpdatecomponents.Theyprovideforcreatingpolished,Web-likeUIsbymodestlyextendingSWTand/ormanipulatingstylebits,colors,fontsandotherpropertiesinordertogetthedesiredbehavior.ThistechnologywasusedthroughoutPDEmulti-pageeditorsandwillnowbeavailableaspublicAPIinEclipse3.0.
ThedocumentrepresentsthestateofAPIatthetimeofwriting.ItispossiblethatsomeaspectsoftheAPIwillslightlychangeuntilfinalrelease.Weanticipateonlymechanicalnamechangesratherthanmorefundamentalchanges.
Problemdefinition
WhenEclipseplatformwasdesigned,thereweretwodistinctcontextinwhichSWTwidgetscouldappear:
Intraditionaldialogs(messageboxes,dialogs,wizards,preferencepages,propertypages)Incontentareas(viewsandeditors)
ControlsindialogstypicallyuseddefaultcolorsandfontsasprovidedbytheoperatingsystemandwerelayedoutusingGridLayoutin9outof10cases.Thegoalwastolooklikeadialogandfillthedialogspaceinbothdirections.
Controlsinviewsandeditorswerestretchyi.e.theyfilledtheentirecontentarea.Stretchycontrolscanscrolltheircontent(trees,tables,textareas,listsetc.).Thecolorsandfontsusedherewerethoseprovidedbythesystemforuseincontentarea(thesecolorscanbeobtainedfromtheDisplayusingSWT.LIST_BACKGROUNDorSWT.LIST_FOREGROUNDkeys).
Whatwasmissingwasthethirdoptionwherewidgetsyouwouldnormallyseeinthedialogcontextarecreatedinviewsoreditors(whereyouwouldexpectstretchycontrols).Severalproblemsneededtobesolved:
SWTcontrolslikebuttons,labels,compositesetc.lookstrangeinthecontentareasas-is(withthedefaultdialogbackground)CompositeswithGridLayoutinthecontentareaareproblematicbecausetheyarenotscrolled.Therefore,itiseasytogetthecontrolstocliporstartridingoneanother.Controlsinthecontentareaarenormallywrappedtofilltheprovidedwidth.WrappingisveryhardtoaccomplishwiththeexistingSWTlayouts.Whenproblems1-3arefixed,theresultlooksverymuchlikeformsinHTMLbrowsers,andanaturalleapistoaddhyperlinksandmixthemwithothercontrols.
EclipseFormsweredesignedtosolvetheseproblems.Theyprovide:
Aconceptofaformthatissuitableforinclusionintothecontentarea(editororview)Atoolkitthatmanagescolors,hyperlinkgroupsandotheraspectsoftheform,aswellasserveasafactoryforanumberofSWTcontrols(thesecontrolsarecreatedandconfiguredtofitintotheformcontext)AnewlayoutmanagerthatlaysoutcontrolsusingthealgorithmsimilartoHTMLtablesCustomcontrolsdesignedtofitintotheform(hyperlink,imagehyperlink,scrollablecomposite,section).Multi-pageeditorwhereeachpageisaform(asinPDE).Setup
InordertobeabletouseEclipseForms,allyouneedtodoisaddorg.eclipse.ui.formsplug-intoyourlistofrequiredplug-ins.Thisplug-insisRCP-friendlyinthatitdoesnothavedependencyonIDEplug-ins(itsonlydependencyisorg.eclipse.ui).
Examples
SourcecodeformostoftheexamplesshowninthisdocumentcanbefoundinEclipserepository(HEAD)asorg.eclipse.ui.forms.examples.CheckthemoutintotheworkspaceandlookinsidethesrcdirectoryinaJavaorPDEperspective.
APIpackages
EclipseFormshasthefollowingpublic(API)packages:
org.eclipse.ui.forms-themainpackageorg.eclipse.ui.forms.editor-classesthatemployEclipseFormsontopoftheMultiPageEditorParttocreatemulti-pageeditorsasseeninPDEorg.eclipse.ui.forms.events-neweventscreatedtosupportcustomwidgetsorg.eclipse.ui.forms.widgets-asetofcustomwidgetsandlayoutscreatedspecificallyforEclipseFormsGettingStarted
WewillstartplayingwithEclipseFormsbycreatinganemptyforminaview.Aswesaidabove,viewsarecontentareasthatrequireflexiblecontent.Hereisthecodesample:
packageorg.eclipse.ui.forms.examples.views;importorg.eclipse.swt.widgets.Composite;importorg.eclipse.ui.forms.widgets.*;importorg.eclipse.ui.part.ViewPart;
publicclassFormViewextendsViewPart{privateFormToolkittoolkit;privateScrolledFormform;
/***Thisisacallbackthatwillallowus*tocreatetheviewerandinitializeit.*/publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Thisisacallbackthatwillallowus*tocreatetheviewerandinitializeit.*/publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Disposesthetoolkit.*/publicvoiddispose(){toolkit.dispose();super.dispose();}}
/***Disposesthetoolkit.*/publicvoiddispose(){toolkit.dispose();super.dispose();}}org.eclipse.ui.forms.examples.views;importorg.eclipse.swt.widgets.Composite;importorg.eclipse.ui.forms.widgets.*;importorg.eclipse.ui.part.ViewPart;
publicclassFormViewextendsViewPart{privateFormToolkittoolkit;privateScrolledFormform;
/***Thisisacallbackthatwillallowus*tocreatetheviewerandinitializeit.*/publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Thisisacallbackthatwillallowus*tocreatetheviewerandinitializeit.*/publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Passingthefocusrequesttotheform.*/publicvoidsetFocus(){form.setFocus();}
/***Disposesthetoolkit.*/publicvoiddispose(){toolkit.dispose();super.dispose();}}
/***Disposesthetoolkit.*/publicvoiddispose(){toolkit.dispose();super.dispose();}}
Inthesnippetabove,wehavecreatedaviewbycreatinganinstanceofatoolkitfirst.Wethenusedthetoolkittocreateaform.Wesetthetitleoftheform.Itisimportantnottoforgetthattoolkitmanagesresourcesthatneedtobedisposedof(hencethedisposemethod).
Whenweregisterthisviewwiththeworkbenchandrun,wegetthefollowing:
Theformwejustcreateddoesthefollowingthings:
ItrendersthetitlewesetusingsetText
Itcanrenderabackgroundimagebehindthetitle
Thetitlewillwrapifthereisnospacetoshowitononeline
Theformwillintroducescrollbarsifthecontentcannotbeshownintheprovidedspace
Thelastiteminthelistneedssomeclarification.Insomeinstances,youwillwanttomaketheformbeachildofamorecomplexlayoutthatisitselfcapableofscrolling.Inthatcase,youmaywanttogetallthecapabilitiesofaform,butwithoutscrolling.InthatcaseyouwouldusetheclassForminsteadofScrolledForm(infact,ScrolledFormhas-aFormasaninternalobjectanddelegatesmostofthemethodslikesetTexttoit).
Addingcontent
Nowthatwehavetheformviewrunning,wecanstartaddingsomecontenttoit.Eclipseformshaveabodyandallthecontentshouldbecreatedthere:
publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");GridLayoutlayout=newGridLayout();form.getBody().setLayout(layout);Hyperlinklink=toolkit.createHyperlink(form.getBody(),"Clickhere.",SWT.WRAP);link.addHyperlinkListener(newHyperlinkAdapter(){publicvoidlinkActivated(HyperlinkEvente){System.out.println("Linkactivated!");}});}
Noticethatwefirstsetlayoutonthebody,thenusedthebodyasaparenttocreateahyperlink.HyperlinkcontrolisoneofthecustomwidgetsinEclipseFormsandactslikealabelthatisclickable.Anewtypeoflistener(HyperlinkListener),itsdefaultimplementation(HyperlinkAdapter)andtheeventypearealldefinedinEclipseFormstosupportthehyperlink.HandlingeventsofthehyperlinkareverysimilartootherSWTwidgets,asshowninthecodeabove.Ourviewnowlookslikethis:
Notehowhyperlinkhasfocusrectanglepaintedaroundit.Whentheviewisactivated,focusistransferredtotheform,whichpassesittothefirstcontrolcapableofacceptingfocus,ourlinkinthiscase.
HyperlinkGroups
Formtoolkithashyperlinkgroupthateachhyperlinkcreatedbyitisaddedto.Hyperlinkgroupsserveseveralroles:
Theycapturecolors(bothnormal,hoverandactive)forallthelinksinthegroup
Theychangecolorsofthemanagedlinksbasedontheirstate
Theychangeunderliningstyleofthemanagedlinksbasedontheirstate
Theymanagecursorsandshowbusycursorbeforelinklistenersprocessthelinkactivation,andchangeitafter.
Youcanchangethedefaultsettingsofthehyperlinkgroupbyobtainingtheobjectfromthetoolkit(getHyperlinkGroup()).
Creatingcommoncontrols
OneofthedesigngoalsofEclipseFormswastoallowcommonSWTcontrolstobecreatedintheeditor/viewcontentspace.Sinceformbodyisanormalcomposite,youcanuseanylayoutandcontrolyouwantinsideit.However,rememberthatrawSWTcontrolsaredesignedtofitinsideadialog.Wewillnowcreatesomeusingtheirconstructorsbycontinuingthemethodabove:
layout.numColumns=2;GridDatagd=newGridData();gd.horizontalSpan=2;link.setLayoutData(gd);Labellabel=newLabel(form.getBody(),SWT.NULL);label.setText("Textfieldlabel:");Texttext=newText(form.getBody(),SWT.BORDER);text.setLayoutData(newGridData(GridData.FILL_HORIZONTAL));Buttonbutton=newButton(form.getBody(),SWT.CHECK);button.setText("Anexampleofacheckboxinaform");gd=newGridData();gd.horizontalSpan=2;button.setLayoutData(gd);
Wearenowusingtwocolumnsandcreatingalabel,atextfieldandacheckbox.Theresultisbelow:
Itiseasytospottheproblem-controlscreateddirectlylookoutofplacebecausetheythinktheyareinadialog.Thisisthereasontherearefactorymethodsonthetoolkittocreatesomeofthecommonlyusedcontrols.Factorymethodssetthecorrectcolorsandalsohookcertainlistenersthatensurecontrolsbehavecorrectlywheninaform.Ifweusethecorrespondingfactorymethodsinstead,thecodewouldlooklikethis:
layout.numColumns=2;GridDatagd=newGridData();gd.horizontalSpan=2;link.setLayoutData(gd);Labellabel=toolkit.createLabel(form.getBody(),"Textfieldlabel:");Texttext=toolkit.createText(form.getBody(),"");text.setLayoutData(newGridData(GridData.FILL_HORIZONTAL));Buttonbutton=toolkit.createButton(form.getBody(),"Anexampleofacheckboxinaform",SWT.CHECK);gd=newGridData();gd.horizontalSpan=2;button.setLayoutData(gd);
Theviewwillnowlookbetter:
Ingeneral,youshouldusetoolkitmethodstocreateallthecontrolsthatyoucan.Incaseofacontrolthatisnotavailablefromthetoolkit,youcanusethemethodadapt.ThismethodtakesanSWTcontrolsandadaptsitforuseintheform.Mostofthetoolkitfactorymethodscalladaptthemselves.
Achievingtheflatlook
OneoftherecongizableattributesofEclipseFormsusedinPDEeditorswastheelegantflatlookofthecontrols.Allthecontrolsusedtherewerewithout3Dbordersthatlooksfineindialogsbutoutofplaceinthecontentspaceofeditorsorviews.ThissupportisbuiltintotheFormToolkitclass.However,onsomeplatformitcomesatapriceofsomecustomrendering.Forexample,lookatthefollowingscreencapturefromPDEeditor(version2.1):
Controlsliketables,textentries,comboboxetc.arerenderedwithflatone-pixelborders.Thesebordersdonotcomefromcontrolsthemselves(SWT.BORDERstyleisnotused).Instead,ifthetoolkitisinstructed,itwilladditselfasapaintlistenertotheirparent,anddrawbordersaroundcontrolsduringpaintevents.Inordertomakethishappen,youneedtocalltoolkitmethodpaintBordersFor(parent)foreachcompositewhereyoucreatedcontrolsliketext,tree,tableetc.
Formtoolkitknowswhichcontrolsrequireacustomborder.However,youmaycreateanewonethatalsoneedtheborderthatisnotonitslist.Youcangiveahinttothetoolkitbymakingthefollowingcall:
ControlmyControl=newMyControl(parent);myControl.setData(FormToolkit.KEY_DRAW_BORDER,FormToolkit.TEXT_BORDER);
or
myControl.setData(FormToolkit.KEY_DRAW_BORDER,FormToolkit.TREE_BORDER);
toolkit.paintBordersFor(parent);
Asyoucanseefromthepictureabove,structuralcontrolsliketrees,tablesetc.haveadifferentborderfromtextareasandyoucanchoosewhichonetorenderforyourcontrol.Notethatthisisnotneededforcontrolcreatedusingtoolkitsfactorymethods.
InEclipse3.0,borderrenderingisnotdoneonWindowsXP.SinceEclipseonWindowsXPcanuseskinnedwidgets,controlsliketext,table,treeetc.arealreadyflatandfurtherfixingisnotneeded.Inordertobeportable,youshouldcallpaintBordersForanyway,andletthetoolkitchoosewhattododependingonthewindowingsystem.
CustomLayouts
EclipseFormsoffertwonewlayoutsoverandabovethoseprovidedbySWT.
TableWrapLayout
Nowthatweknowhowtopopulatetheform,letsthrowitacurve:changethehyperlinktexttobemuchlonger:
link.setText("Thisisanexampleofaformthatismuchlongerandwillneedtowrap.");
Letsseetheresultonscreen:
Whathappened?RememberthatweareusingGridLayout.Whenitaskedthelinkcontroltocomputeitssize,itgaveitthesizeneededtorenderthetextinonelongline.Althoughweinstructedthecontroltowrap,itdidntmatterbecauseGridLayoutrequiresthatacontrolreturnsitssizeinisolation.Thelinkitself(aswellasotherSWTcontrolslikeLabel)iscapableofcomputingtheheightgivenitswidth(ifyoupassthewidthinsteadofSWT.DEFAULTincomputeSize),butGridLayoutisnotpassingit.
WhatwereallyneedisadifferentlayoutalgorithmthatworksmorelikeHTMLtables.Wewantthecontenttotrytofitintheprovidedclientarea,andgrowverticallytocompensate.EclipseFormsprovideanalternativelayoutforjustsuchpurposecalledTableWrapLayout.TherearemanysimilaritiesbetweenGridLayoutandTableWrapLayout.Bothorganizeparentschildreningrids.Bothhavelayoutdatathatinstructsthelayouthowtotreateachcontrol.Bothcanaccepthintsonwhichcontrolshouldgrabexcessspaceetc.
However,theyfundamentallydifferintheapproachtolayout.TableWrapLayoutstartswithcolumns.Itcomputesminimal,preferredandmaximumwidthsofeachcolumnandusesthisinformationtoassignexcessspace.Italsotriestobefairwhendividingspaceacrosscolumnssothatthereisnoexcesswrappingforsomecontrols.
ItispossibletomixGridLayoutandTableWrapLayoutbutthebranchwhereyouuseGridLayoutistheonewherewrappingstops.Thisisquiteacceptableifyoudontwantittowrap(ifthecompositecontainscontrolsthatcannotwrapanyway,liketext,buttons,treesetc.).However,youshouldhaveanunbrokenpathfromtheformbodytoeachtextcontrolthatneedstowrap.
LetsreworkourexampletouseTableWrapLayout(changesarehighlighted);
publicvoidcreatePartControl(Compositeparent){toolkit=newFormToolkit(parent.getDisplay());form=toolkit.createForm(parent);form.setText("Hello,EclipseForms");TableWrapLayoutlayout=newTableWrapLayout();form.getBody().setLayout(layout);Hyperlinklink=toolkit.createHyperlink(form.getBody(),"Clickhere.",SWT.WRAP);link.addHyperlinkListener(newHyperlinkAdapter(){publicvoidlinkActivated(HyperlinkEvente){System.out.println("Linkactivated!");}});link.setText("Thisisanexampleofaformthatismuchlongerandwillneedtowrap.");layout.numColumns=2;TableWrapDatatd=newTableWrapData();td.colspan=2;link.setLayoutData(td);Labellabel=toolkit.createLabel(form.getBody(),"Textfieldlabel:");Texttext=toolkit.createText(form.getBody(),"");td=newTableWrapData(TableWrapData.FILL_GRAB);text.setLayoutData(td);Buttonbutton=toolkit.createButton(form.getBody(),"Anexampleofacheckboxinaform",SWT.CHECK);td=newTableWrapData();td.colspan=2;button.setLayoutData(td);}
Obviously,weusedmore-lessthesameconcepts.Someofthevariableshavedifferentnames(forexample,colspanandrowspan,alignandvalignaretakenfromHTMLTABLEattributes),butyouaredoingthesamething-creatingagridwithtwocolumnswherelinkandbuttonspantwocolumns.SincemarginsarethesameasinGridLayout,theresultwilllooksimilarexceptlinkwillbewrappedasexpected:
Thisismorelikeit.Thewayweconfiguredthelayout,textcontrolwillgrabtheexcessspaceinitscolumn,andboththecheckboxandthelinkwilljustspreadacrossbothcolumns.Inaddition,linkwillnottrytorenderinonelongline-itwilltaketheviewwidthandpushtherestofthecontentdowninordertowrap.
OneofthemaindifferencesbetweenTableWrapLayoutandGridLayoutisthatwiththeformeryoushouldstopthinkingabouttheverticaldimension.InGridLayout,youwouldtypicallylettherigidcontrolsassumetheirnaturalpositionsandletflexiblecontrols(text,tree,table)grabhorizontaland/orverticalexcessspace.Incontrast,TableWrapLayoutworkstop-downandwhenitplacesallthecontrols,itisdone.Theconceptofgrabbingexcessspacestillexistsinhorizontaldimension(asshownabove).However,verticallyyoucanonlychoosetoFILLthecellincaseitistallerthanthecontrol,orpickTOP,MIDDLEorBOTTOMverticalalignment.
Youmaynoticeonethingthatmayseemincontradictionwiththepreviousclaim:TableWrapDatastillhasgrabVerticalvariable.However,thevariableisthereforadistinctpurpose:whenacontrolwithafixedheightspansmultiplerows,itsheightwillcreatealocalcasewhereverticaldimensionisknown,andcontrolsinthespannedcellsneedtodividetheextraspacebetweenthemselves.
InordertohavegoodresultswithTableWrapLayout,ensurethatcontrolsthatneedtowraphavetheappropriatestyle(SWT.WRAP).CompositecustomcontrolsprovidedbyEclipseFormsarewrap-enabledoutofthebox.ThisisachievedbyusinginternallayoutsthatimplementILayoutExtensioninterface:
publicinterfaceILayoutExtension{/***Computestheminimumwidthoftheparent.Allwidgets*capableofwordwrappingshouldreturnthewidth*ofthelongestwordthatcannotbewrapped.*@paramparent*@paramchanged*@return*/publicintcomputeMinimumWidth(Compositeparent,booleanchanged);/***Computesthemaximumwidthoftheparent.Allwidgets*capableofwordwrappingshouldreturnthelength*oftheentiretextwithoutwrapping.*@paramparent*@paramchanged*@return*/publicintcomputeMaximumWidth(Compositeparent,booleanchanged);}
TableWrapLayoutimplementsthisinterfaceitself,whichallowsittohandlecaseswherecompositeswiththislayoutarechildrenofthecompositethatislaidout.Theadditionaltwomethodsallowittocomputethetwoextremecases-theabsoluteminimumwidthandthemaximumwidthifallthecontrolsarespreadaswideaspossible.Thedifferencebetweenthetwoallowthealgorithmtodistributeextraspacefairlybetweencolumnstominimizeexcesswrapping.
Letustakeacloserlookatthespacedistribution.Wewillcommentthecodewewrotesofarintheviewandreplaceitwiththefollowing:
layout.numColumns=3;Labellabel;TableWrapDatatd;label=toolkit.createLabel(form.getBody(),"Sometexttoputinthefirstcolumn",SWT.WRAP);label=toolkit.createLabel(form.getBody(),"Sometexttoputinthesecondcolumnandmakeitabitlongersothatwecanseewhathappenswithcolumndistribution.Thistextmustbethelongestsothatitcangetmorespaceallocatedtothecolumnsitbelongsto.",SWT.WRAP);td=newTableWrapData();td.colspan=2;label.setLayoutData(td);label=toolkit.createLabel(form.getBody(),"Thistextwillspantworowsandshouldnotgrowthecolumn.",SWT.WRAP);td=newTableWrapData();td.rowspan=2;label.setLayoutData(td);label=toolkit.createLabel(form.getBody(),"Thistextgoesintocolumn2andconsumesonlyonecell",SWT.WRAP);label.setLayoutData(newTableWrapData(TableWrapData.FILL_GRAB));label=toolkit.createLabel(form.getBody(),"Thistextgoesintocolumn3andconsumesonlyonecelltoo",SWT.WRAP);label.setLayoutData(newTableWrapData(TableWrapData.FILL));label=toolkit.createLabel(form.getBody(),"Thistextgoesintocolumn2andconsumesonlyonecell",SWT.WRAP);label.setLayoutData(newTableWrapData(TableWrapData.FILL_GRAB));label=toolkit.createLabel(form.getBody(),"Thistextgoesintocolumn3andconsumesonlyonecelltoo",SWT.WRAP);label.setLayoutData(newTableWrapData(TableWrapData.FILL));form.getBody().setBackground(form.getBody().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
Thecodeabovecreatesanumberofwrappinglabelswithtextofvariablelength.Somelabelsspancolumns,somespanrows.Tomakethetesteasier,wewillsettheformbackgroundtowidgetbackgroundsothatcellswillbeeasytospot.Whenweruntheexample,wewillgetthefollowing:
Thekeyinspacedistributionisthatdifferencebetweencontrolminimumandmaximumwidthiscompared.Ifthisdifferenceisgreater,thecontrolwillcausethecolumnwidthtoreceivegreaterallocationofexcesswidth(excesswidthisanywidthgreaterthanthewidthneededtofitallthecontrolswiththeirminimumwidthstakenintoaccount).Noticehowcolumn3isslightlywiderthancolumn2becausetextincolumn2issomewhatlonger.Theoverallgoalistoavoidtoomuchemptyspaceincells.Ifyouwanttoreadmoreaboutthetheorybehindthealgorithm,gotoW3CrecommendationsforHTMLtableauto-layout.
ColumnLayout
AnothercustomlayoutinEclipseFormsisavariationoftheRowLayout.IfyouconfigureRowLayouttoplacechildrenvertically(incolumns),andtomakeallcontrolsthesamewithwithinthecolumn,wewouldgetseveralcolumns(dependingonthewidthofcontrols),butthelastcolumnwouldtypicallynotbecompletelyfilled(dependsonthenumberofcontrols).Again,ifplacedinaform,wewouldgetallthecontrolsinonecolumnbecauseRowLayoutcannotdoverticalwrapping.IfweuseGridLayout,wemustchoosethenumberofcolumnsupfrontandlivewiththechoice.
Therearesituationsinmorecomplexformswherewewantthenumberofcolumnstobeadaptive.Inotherwords,wewouldlikeittochangedependingonthewidthoftheform-usemorewhenpossible,dropthenumberdownifthewidthdecreases.Wewouldalsoliketofilltheformareamore-lessequally(withallthecolumnsroughlythesameheight).AllthiscanbeachievedwithColumnLayout.
ComparedtoTableWrapLayout,ColumnLayoutismuchsimpler.Hardlyanyconfigurationisneeded.Theonlychoiceyouneedtomakeistherangeofcolumnsyouwanttohave(defaultis1to3).Thefollowingexampleshowsaformwithalargenumberofsections(wewilltalkaboutsectionslater)usingColumnLayout.Sincethereisenoughspace,threecolumnsareused
Thesampleexactexamplewilldropthenumberofcolumnstotwowhentheformisnarrowed:
Controlsarelaidouttop-down,lefttoright.Onecolumnisfilled,thenthenthenextoneetc.However,thespacecomputationfirstensuresthateachcolumnisroughlythesameheightsothatspaceisusedrationally.
YoucanstilltweakthesizingoftheindividualcontrolswhenusingColumnLayoutusingColumnLayoutData.Forexample,ifthecontrolisstretchy,youmaywanttolimititswidthorheightbysettingwidthorheighthint.Bydefault,controlsfillthewidthofthecolumn,butyoucanchangethatbychoosingLEFT,CENTERorRIGHT.
ComplexcontrolsExpandablecomposite
Averycommonthemeinsleekwebpagesistheabilitytocollapseaportionofpagecontentusingatogglecontrol.EclipseFormofferssuchacontrol:ExpandableComposite.
ExpandableCompositeec=toolkit.createExpandableComposite(form.getBody(),ExpandableComposite.TREE_NODE);ec.setText("ExpandableCompositetitle");Stringctext="Wewillnowcreateasomewhatlongtextsothat"+"wecanuseitascontentfortheexpandablecomposite."+"Expandablecompositeisusedtohideorshowthetextusingthe"+"togglecontrol";Labelclient=toolkit.createLabel(ec,ctext,SWT.WRAP);ec.setClient(client);td=newTableWrapData();td.colspan=2;ec.setLayoutData(td);ec.addExpansionListener(newExpansionAdapter(){publicvoidexpansionStateChanged(ExpansionEvente){form.reflow(true);}});
Thecompositeacceptsanumberofstylesthatcontrolitsappearanceandbehavior.StyleTREE_NODEwillcreatethetogglecontrolusedinatreewidgetforexpandingandcollapsingnodes,whileTWISTIEwillcreateatriangle-styletoggle.UsingEXPANDEDwillcreatethecontrolintheinitialexpandedstate.IfstyleCOMPACT,controlwillreportwidthinthecollapsedstateenoughtofitinthetitlelineonly(i.e.whencollapsed,itwillbeascompacthorizontallyaspossible).
Controlitselfisresponsibleforrenderingthetogglecontrolandthetitle.Thecontroltoexpandorcollapseissetasaclient.Notethatitisrequiredthattheclientisadirectchildoftheexpandablecomposite.
Weneededtoaddexpansionlistenertothecontrolandreflowtheformonthestatechange.Thisisbecauseexpansioncauseschangesinexpandablecompositesize,butthechangewillnottakeeffectuntilthenexttimetheparentislaidout(henceweneedtoforceit).Ingeneral,everytimeyoudosomethingthatcausesthelayoutoftheformtobeinvalid,youneedtoreflowtheform.ReflowingtheformwillpositionthecontrolsaccordingtothenewsizesANDupdatescrollbars.
Theviewnowlookslikethis:
Whenyouclickonthe+signoronthetitleitself,compositeexpandstorevealtheclient:
Thisisnotbad,butwewouldliketoaligntheclientwiththetitle,notthetogglecontrol.Ifwebitwise-ORCLIENT_INDENTstylewithTREE_NODE,theclientwillreceivethedesiredindent:
ItgoeswithoutsayingthatexpandablecompositeusesinternallayoutthatimplementsILayoutExtension,andcanthereforebeaddedtotheparentthatusesTableWrapLayout.
Section
OneofthemostversatilecustomcontrolsinEclipseForms(andseeninallPDEeditors)isSection.Itextendsexpandablecompositeandintroducedthefollowingconcepts:
Separator-aseparatorcontrolcanbecreatedbelowthetitle
Description-anoptionaldescriptioncanbeaddedbelowthetitleandseparator.
Thecodeisnotmuchdifferentthanincaseoftheexpandablecomposite:
Sectionsection=toolkit.createSection(form.getBody(),Section.DESCRIPTION|Section.TWISTIE|Section.EXPANDED);td=newTableWrapData(TableWrapData.FILL);td.colspan=2;section.setLayoutData(td);section.addExpansionListener(newExpansionAdapter(){publicvoidexpansionStateChanged(ExpansionEvente){form.reflow(true);}});section.setText("Sectiontitle");toolkit.createCompositeSeparator(section);section.setDescription("Thisisthedescriptionthatgoesbelowthetitle");CompositesectionClient=toolkit.createComposite(section);sectionClient.setLayout(newGridLayout());button=toolkit.createButton(sectionClient,"Radio1",SWT.RADIO);button=toolkit.createButton(sectionClient,"Radio2",SWT.RADIO);section.setClient(sectionClient);
Thistime,weusedTWISTIEtogglestyle,addedthedescriptionandalsocreatedcompositeseparator.Theviewnowlookslikethis:
Imagehyperlink
ImagehyperlinkisasubclassofHyperlinkthataddsanimagebeforethelink.Thiscombinationissocommonthatitjustmadealotofsensetomakeonecontroloutofitandsaveonwidgets.Thecontrolcanbeusedasimagelinkonly(whennotextisset),orasacombinationoflinkandimage.Imagesfornormal,hoverandactive(selected)statecanbeset.
Formtextcontrol
Usingthecombinationoflabels,hyperlinks(andimagehyperlinks)andTableWrapLayout,itispossibletocreaterichformcontent:
However,soonyouwillnoticethattherearelimitsinhowcloseyoucangettotheweblook.Ifyouinspectthepictureaboveclosely,youwillnoticethatallelementsareclearlyseparated:imagesfromtext,boldlabelsfromnormallabelsetc.Imagesareallatthebeginningofthetext,nottheinthemiddle.Hyperlinksstandalone-ontheirown.
Toremedytheproblem,EclipseFormsplug-inprovidesaveryrudimentarytextcontrolthatcandothefollowing:
Renderplainwrappedtext
Renderplaintextbutconvertanysegmentthatstartswithhttp://intoahyperlinkonthefly
RendertextwithXMLtags
Inallthreemodes,formtextcontroliscapableofrenderingeitherastringoraninputstream.
Renderingnormaltext(labelmode)
FormTextrtext=toolkit.createFormText(form.getBody(),true);td=newTableWrapData(TableWrapData.FILL);td.colspan=2;rtext.setLayoutData(td);Stringdata="Hereissomeplaintextforthetexttorender.";rtext.setText(data,false,false);
Secondargumentsettofalsemeansthatwewillnotbothertoparsetags,andthethirdthatwewillnottrytoexpandURLsiffound.
AutomaticconversionofURLsintohyperlinks
Nowwewilladdahyperlinkinthetextandturnthethirdargumentintotrue:
FormTextrtext=toolkit.createFormText(form.getBody(),true);td=newTableWrapData(TableWrapData.FILL);td.colspan=2;rtext.setLayoutData(td);Stringdata="Hereissomeplaintextforthetexttorender;thistextisathttp://www.eclipse.orgwebsite.";rtext.setText(data,false,true);
Whenwelookatourview,itnowlookslikethis:
TheURLhasbeenconvertedintoalink.Thelinkispartofthewrappedtext-wedidnthavetocreateaseparateHyperlinkcontrolandtrytosandwichitbetweentwolabels.
Sincerichtextcontrolcanrenderhyperlinks,itacceptshyperlinklisteners.Whencreatedbythetoolkit,itassumeshyperlinksettingsfromthehyperlinkgroupthatbelongstothetoolkit.
Parsingformattingmarkup
Themostpowerfuluseoftheformtextcontroliswhenformattingtagsareaddedtothetext.Theexpectedroottagisform.Itcanoneormorechildrenthatcaneitherbe<p>or<li>.Eitherofthesecanhavenormaltext,textbetween<b>or<span>tags,imagesandlinks.Imagesaredeclaredusing<imghref="imagekey"/>(nocontent),whilelinksareexpressedusing<ahref="href">text</a>.
Ofthetagsshownabove,somehaveadditionalattributes.Tag<a>canacceptnowrap=truetoblockthelinkfrombeingwrappedintothenewline.Tag<p>canhaveattributevspace="false"(truebydefault).Tag<li>hasmoreattributes:
style-canbe"text","bullet"and"image"(defaultis"bullet")
value-notusedfor"bullet";ifstyleis"text",thevaluewillberenderedinsteadinplaceofabullet;ifstyleis"image",valuerepresentsakeyintheimagetableofanimagetoberenderedinplaceofabullet
vspace-thesameasfortheptag.
indent-thenumberofpixelstoindenttext
bindent-thenumberofpixelstoindentthebullet(thisnumberisindependentfromindent-becarefulnottooverlapthem)
Tagsthataffectappearanceofthenormaltextare<b>(worksasexpected),and<span>.Thelaterallowsyoutochangefontand/orcolorofthetextwithinthetag.
Howdoesallthisworkinpractice?Letsmakedatatextthatwilluseallofthesetagstogether:
StringBufferbuf=newStringBuffer();buf.append("<form>");buf.append("<p>");buf.append("Hereissomeplaintextforthetexttorender;");buf.append("thistextisat<ahref="http://www.eclipse.org"nowrap="true">http://www.eclipse.org</a>website.");buf.append("</p>");buf.append("<p>");buf.append("<spancolor="header"font="header">Thistextisinheaderfontandcolor.</span>");buf.append("</p>");buf.append("<p>Thislinewillcontainsome<b>bold</b>andsome<spanfont="text">source</span>text.");buf.append("Wecanalsoadd<imghref="image"/>animage.");buf.append("</p>");buf.append("<li>Adefault(bulleted)listitem.</li>");buf.append("<li>Anotherbulletlistitem.</li>");buf.append("<listyle="text"value="1.">Alistitemwithtext.</li>");buf.append("<listyle="text"value="2.">Anotherlistitemwithtext</li>");buf.append("<listyle="image"value="image">Listitemwithanimagebullet</li>");buf.append("<listyle="text"bindent="20"indent="40"value="3.">Alistitemwithtext.</li>");buf.append("<listyle="text"bindent="20"indent="40"value="4.">Alistitemwithtext.</li>");buf.append("</form>");FormTextrtext=toolkit.createFormText(form.getBody(),true);td=newTableWrapData(TableWrapData.FILL);td.colspan=2;rtext.setLayoutData(td);rtext.setImage("image",ExamplesPlugin.getDefault().getImageRegistry().get(ExamplesPlugin.IMG_SAMPLE));rtext.setColor("header",toolkit.getColors().getColor(FormColors.TITLE));rtext.setFont("header",JFaceResources.getHeaderFont());rtext.setText(buf.toString(),true,false);rtext.addHyperlinkListener(newHyperlinkAdapter(){publicvoidlinkActivated(HyperlinkEvente){System.out.println("Linkactive:"+e.getHref());}});
Onecommonthemethatcanbeobservedisthatthewidgetitselfisnotresponsibleforloadingimages,fonts,resolvinglinksorcolors.Thisisnotabrowseranditismuchbettertoseparateconcernsandsimplyassignimagesandcolorsmanagedelsewhere.Bothlinksandimagessimplyhavehrefattributetoreferencethem.Forlinks,thevalueofthisattributewillbeprovidedinthehyperlinkeventwhenlistenersarenotified.Imagesneedtoberegisteredwiththetextcontrolusingthematchinghrefkey.Thisway,thecontroldoesnotneedtoworryaboutloadingtheimages-ithastheminthehashtableandcanrenderthemimmediately.
Similarapproachhasbeenusedforcolors.Colorsarealreadyhandledbythetoolkit,soyoucanallocateasmanyasyouwantusingauniquekeyandRGBvaluesbycallingtoolkit.getColors().createColor().Whatisleftistosetallthecolorsreferencedinthespantagsothatthecontrolwillbeabletousethemduringrendering.
Whenthecodeaboveisexecuted,theviewnowlookslikethis(sectionhasbeencollapsedtomakeroomfortext):
Ifweexpandthesectionandtheexpandablecomposite,andmakethewindownarrower,theformstillholdsandeverythingwrapsperfectly:
Appropriateusageandlimitations
Althoughtheimageaboveisverypromising,itisveryimportanttocontainexcitement.Aprimedirectiveoftherichtextcontrolis:
"Formtextcontrolisnot,norwilliteverbe,awebbrowser"
Itisveryeasytospotlimitationsofthecontrol.Tagswithinlistitemsorparagraphscannotbenested.Boldissupported,butnotitalic(althoughanyfontcanbesetandassociatedviaspantag).Attributesforverticalalignmentoftextwithrespecttoimagesaremissing.Listsupportisdecidedlylowlevel.AlthoughthecursorturnsintotheI-beamwhenovertext,thetextcannotbeselected.Colorofthetextsegmentscannotbechangedetcetc.ThereisnoBIDIsupport.
Anotherimportantlimitationtoconsiderisperformance.Formtextisneitheraperformancenormemoryhog,butitwaswrittentobesmallandlean,notpowerful.Forthatreason,itdoesnothavesophisticatedpaintingroutines,dirtyregionmanagementetc.Theseroutinesarecost-effectivewhenthecontrolownstheentirewindowandmustbescalable.Incontrast,formtextisbestsuitedforshortsnippetsoftaggedtextthataremixedwithothercontrolsonaform.Thisway,thecontrolisoneofseveralintheparent,allowingnativedirtyregionmanagementfromtheOStoolkittohandlerepaints.ThebestresultsinEclipseformsareachievedwiththemixturethatissimilartoourexampleabove.
Ifyouhaveaproblemwiththeformtextlimitations,youshouldconsideralternatives:
Ifyouneededitingandstyledtext(withdifferentfontsandcolors)willfityourbill,useStyledText(usedbystyledtexteditorslikeJavaeditorinEclipse)Ifyouneedread-onlysupportbuthavecomplextextformattingneeds,useorg.eclipse.swt.browser.Browser.EmbeddedwebbrowserworksonmostplatformsandwillgiveyoufullHTMLsupport.
WhatthiswidgetisforistoprovideformodesttextformattingincombinationwithTableWrapLayoutandothercontrolsinaform.Thepowerliesinthefactthatyouhavefullaccesstoeverycontrolonyourform-akindofdirectaccessthatyoucanonlyachieveinabrowserifyouuseproprietaryDOMaccessmechanisms.Incontrast,EclipseFormsareportable-runeverywherewhereSWTruns.
ColorAndToolkitManagement
Whenusingformsinanon-trivialway,itisimportanttoshareasmuchaspossibletoconserveresources.Forthisreason,colormanagementshouldbeseparatedfromthetoolkitwhentherearemorethanoneformtohandle.
Ofcourse,itispossibletocreateonetoolkitperform,butthatistoowastefuliftherearemanyforms.Instead:
Createonetoolkitforalltheformsthathavethesamelifecycle.Forexample,ifcreatingamulti-pageeditor,createonetoolkitpereditoranddisposeitwheneditorisdisposed.Allthepagesintheeditorshouldsharethistoolkit.
Createonecolormanager(FormColors)perplug-in.Whencreatingthetoolkit,passthecolormanagertothetoolkit.Thetoolkitwillknowthatthecolorsaresharedandwillnotdisposethem.
Useplatformsupportforfontsandifpossible,useJFaceResourcespredefinedfonts.Betweendefault,bannerandheaderfonts,youcanaccomplishalot.Usingmanyfontsisveryconfusingfortheuser,andifyoudomanageyourown,youmustensurealternativesacrossplatforms.ThementionedJFaceformsareguaranteedtoworkonalltheplatformsEclipseshipson.
Disposethecolormanageronplug-inshutdown(dontassumethatplug-insshutdownisplatformshutdown-inEclipse3.0OSGicanuninstallyourplug-indynamically).
Useformcolormanagertoallocateallthecolorsneededbytheforms.
Managedforms
Managedformsarewrappersthataddlifecyclemanagementandnotificationtoformmembers.Managedformisnotaformbyitself.IthasaformandacceptsregistrationofIFormPartelement.ForeachIFormPart,itmanageseventslikedirtystate,saving,commit,focus,selectionchangesetc.InordertoreachtotheWrappedFormwidget,youcallgetfForm()method.
Youshouldviewmanagedformsasviewers-therelationshipbetweenaformandamanagedformissimilartotheonebetweenaTablewidgetandTableViewerinJFace,forexample.
Noteverycontrolontheformneedstobeaformpart.ItisbettertogroupanumberofcontrolsandimplementIFormPartinterfaceforthegroup.SectionisanaturalgroupandEclipseFormprovidesSectionPartimplementation.ItimplementstheinterfaceandcontainsaSectioninstance(eithercreatedoutsideandpassedintoconstructor,orcreatedinthepartitself).
Master/Detailsblock
Master/DetailsisapatternusedthroughouttheUIworld.Itconsistsofalistoratree(master)andasetofproperties(details)drivenbytheselectioninthemaster.EclipseFormsprovidetheimplementationofthepatternasausefulbuildingblockwiththefollowingproperties:
Whiledetailspartiscreated,masterpartfactorymethodisabstractandmustbeimplementedbythesubclass
Masteranddetailspartsarechildrenofthesashformandtheratiooftheformspaceallocatedforeachcanbechangedbymovingthesash.
Throughthenatureofthesashform,masteranddetailspartscanbeorganizedhorizontallyorverticallyintheform.
Theideaofmaster/detailsblockistocreateatreeoratablesectionthatfirestheselectionnotificationviathemanagedform.Ifthedetailspartcanhandletheselectedobject,itshouldswitchtothepageforitanddisplayproperties.Whenbuildingontopoftheprovidedmaster/detailsblock,subclassesshould:
Createthemasterpart(theonethatdrivesthedetails)
Contributeactionstotheformtoolbar(consumesupper-rightportionoftheforminthetitlearea)
Registerdetailspages,oneforeachdistinctinputthatcanarrivefromthemasterpart
Wewillshowhowthislooksinpracticeusingtheexamplefromorg.eclipse.ui.forms.examplesplug-in(availableinEclipserepository).Itcreatesatableforthemasterpartandhooksafewdummyobjectsoftwodistincttypes.Twodetailspagesareregisteredtohandleselectionsofthesetypes.Pagescancontainanynumberofcontrols-theyarecreatedondemandintheprovidedparent.Thedetailsareaisindividuallyscrolled.
publicclassScrolledPropertiesBlockextendsMasterDetailsBlock{privateFormPagepage;publicScrolledPropertiesBlock(FormPagepage){this.page=page;}/***@paramid*@paramtitle*/classMasterContentProviderimplementsIStructuredContentProvider{publicObject[]getElements(ObjectinputElement){if(inputElementinstanceofSimpleFormEditorInput){SimpleFormEditorInputinput=(SimpleFormEditorInput)page.getEditor().getEditorInput();returninput.getModel().getContents();}returnnewObject[0];}publicvoiddispose(){}publicvoidinputChanged(Viewerviewer,ObjectoldInput,ObjectnewInput){}}classMasterLabelProviderextendsLabelProviderimplementsITableLabelProvider{publicStringgetColumnText(Objectobj,intindex){returnobj.toString();}publicImagegetColumnImage(Objectobj,intindex){if(objinstanceofTypeOne){returnPlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);}if(objinstanceofTypeTwo){returnPlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);}returnnull;}}protectedvoidcreateMasterPart(finalManagedFormmanagedForm,Compositeparent){finalScrolledFormform=managedForm.getForm();FormToolkittoolkit=managedForm.getToolkit();Sectionsection=toolkit.createSection(parent,Section.DESCRIPTION);section.setText("ModelObjects");section.setDescription("Thelistcontainsobjectsfromthemodelwhosedetailsareeditableontheright");section.marginWidth=10;section.marginHeight=5;toolkit.createCompositeSeparator(section);Compositeclient=toolkit.createComposite(section,SWT.WRAP);GridLayoutlayout=newGridLayout();layout.numColumns=2;layout.marginWidth=0;layout.marginHeight=0;client.setLayout(layout);Tablet=toolkit.createTable(client,SWT.NULL);GridDatagd=newGridData(GridData.FILL_BOTH);gd.heightHint=20;gd.widthHint=100;t.setLayoutData(gd);toolkit.paintBordersFor(client);Buttonb=toolkit.createButton(client,"Add...",SWT.PUSH);gd=newGridData(GridData.VERTICAL_ALIGN_BEGINNING);b.setLayoutData(gd);section.setClient(client);finalSectionPartspart=newSectionPart(section);managedForm.addPart(spart);TableViewerviewer=newTableViewer(t);viewer.addSelectionChangedListener(newISelectionChangedListener(){publicvoidselectionChanged(SelectionChangedEventevent){managedForm.fireSelectionChanged(spart,event.getSelection());}});viewer.setContentProvider(newMasterContentProvider());viewer.setLabelProvider(newMasterLabelProvider());viewer.setInput(page.getEditor().getEditorInput());}protectedvoidcreateToolBarActions(ManagedFormmanagedForm){finalScrolledFormform=managedForm.getForm();Actionhaction=newAction("hor",Action.AS_RADIO_BUTTON){publicvoidrun(){sashForm.setOrientation(SWT.HORIZONTAL);form.reflow(true);}};haction.setChecked(true);haction.setToolTipText("Horizontalorientation");haction.setImageDescriptor(ExamplesPlugin.getDefault().getImageRegistry().getDescriptor(ExamplesPlugin.IMG_HORIZONTAL));Actionvaction=newAction("ver",Action.AS_RADIO_BUTTON){publicvoidrun(){sashForm.setOrientation(SWT.VERTICAL);form.reflow(true);}};vaction.setChecked(false);vaction.setToolTipText("Verticalorientation");vaction.setImageDescriptor(ExamplesPlugin.getDefault().getImageRegistry().getDescriptor(ExamplesPlugin.IMG_VERTICAL));form.getToolBarManager().add(haction);form.getToolBarManager().add(vaction);}protectedvoidregisterPages(DetailsPartdetailsPart){detailsPart.registerPage(TypeOne.class,newTypeOneDetailsPage());detailsPart.registerPage(TypeTwo.class,newTypeTwoDetailsPage());}}
Thispartcannowbeusedanywhere,buttheexampleitwastakefromwasusingitinsideamulti-pageeditor.Twodistinctobjecttypeswereused(TypeOneandTypeTwo),andtheirclasseswereuseddirectlyaskeys(othermappingbetweendetailspagesandobjectsarepossible).Detailspagesregisteredwiththedetialspartneedtoimplementthefollowinginterface:
publicinterfaceIDetailsPage{voidinitialize(IManagedFormform);voidcreateContents(Compositeparent);voidinputChanged(IStructuredSelectionselection);voidcommit();voidsetFocus();voiddispose();booleanisDirty();voidrefresh();}
Thepageisfirstinitializedwiththemanagedformtogetaccesstothetoolkitandotherobjects.Itisthenaskedtocreatecontentsintheprovidedparent.Itshouldalsosetfocusonthefirstcontrolwhenasked,beabletorefresh,commit,disposeandreacttotheinputchange.Aslongasobjectsinthemasterpartareofthecompatibletype,thepagewillstayvisibleandinputChangedwillbecalled.
Letsseehowallthislooksinpractice(youcanreadthecompleteexamplecodeinthementionedexampleplug-in):
AninstanceofTypeOneobjectisselectedinthemasterpart.Theappropriatepageforthetypeisloadedinthedetailspart.Obviouslythepagecancontainanynumberofcontrolsintroducedintheprecedingtext.Theratioofpartsonthepagecanbechangedbyscrollingthesash(showninthepictureonmousedown).Alsonotetwoactionsintheupper-rightcorneroftheform-thisistheformtoolbar.Inthiscase,tworadiobuttonswerecontributedtocontrolorientationofthepart(horizontalorvertical).
IfwechangetheorientationandalsoselectoneoftheTypeTwoinstances,wegetintothefollowingstate:
Orientationisnowvertical,andadifferentdetailspageisshownforthetype.
Itispossibletoregisterdetailpageproviderinsteadofregisteringpagesupfront.Thisallowsdynamicresolutionoftheobjectthathasbeenselected.
Multi-pageformeditors
Itwasalongwaytothistopic,yetPDEmulti-pageeditorswerethefirsttosparkinterestinEclipseForms.Today,multi-pageeditorsstillrepresentthewidestusersofthetechnology,eventhoughitnowstartstoappearinotherplaces.
EclipseFormsaredesignedtoworkinawidestvarietyofsettings.Forthisreason,theplug-incannotmakeassumptionsofthetypesofeditorinputsyoureditorcanhave.AnumberofconceptsemployedinPDEUIcannotbeusedherebecausewithoutknowingabouttheeditorinputinmoredetail,itishardtoprovidereusablesetofclasses.Nevertheless,EclipseFormsprovidethebasicsupportformulti-pageeditorsyoucanbuildon.
YoushouldstartbuildinganEclipseFormsmulti-pageeditorbyextendingFormEditor:
publicclassSimpleFormEditorextendsFormEditor{/****/publicSimpleFormEditor(){}/**(non-Javadoc)*@seeorg.eclipse.ui.forms.editor.FormEditor#createToolkit(org.eclipse.swt.widgets.Display)*/protectedFormToolkitcreateToolkit(Displaydisplay){//Createatoolkitthatsharescolorsbetweeneditors.returnnewFormToolkit(ExamplesPlugin.getDefault().getFormColors(display));}/**(non-Javadoc)**@seeorg.eclipse.ui.forms.editor.FormEditor#addPages()*/protectedvoidaddPages(){try{addPage(newFreeFormPage(this));addPage(newSecondPage(this));addPage(newThirdPage(this));addPage(newScrolledPropertiesPage(this));addPage(newPageWithSubPages(this));}catch(PartInitExceptione){//}}/**(non-Javadoc)**@seeorg.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)*/publicvoiddoSave(IProgressMonitormonitor){}/**(non-Javadoc)**@seeorg.eclipse.ui.ISaveablePart#doSaveAs()*/publicvoiddoSaveAs(){}/**(non-Javadoc)**@seeorg.eclipse.ui.ISaveablePart#isSaveAsAllowed()*/publicbooleanisSaveAsAllowed(){returnfalse;}
Averysimplewaytogetstartedistocreatepagesandaddthemasabove.EachpageneedtoimplementFormPageandoverridecreateFormContent(ManagedFormmanagedForm)method.Obviouslythereisamanagedformalreadycreatedinthepage,andyoushouldcreatecontentsintheenclosedform,andalsoregisteranyformpartthatneedstobepartofthemanagedlifecycle.
Inadditiontoformpages,youcanaddoneormoretexteditorsasarawsourcealternativetotheGUIpages.Forthis,youshouldcalladdPage(IEditorPart,IEditorInputinput)methodinthesuperclass.
Multi-pageeditorexample
Projectorg.eclipse.ui.forms.examplescontainsanexampleofthemulti-pageeditorsuitableforinclusioninRCPapplicationbecauseitdoesnothaveanydependenciesonIDEplug-ins.
Toruntheexample,customizetheperspectivebycheckingthefollowingcheckbox:
Window>CustomizePerspective...>Commands>EclipseFormsExamples
ThiswilladdamenutothemenubarcalledFormEditors.Themenucontainsoneaction-SimpleFormEditor.Theeditorwillopen.Ithasthefollowingpages:
ThefirstpagecontainsapagewithTableWrapLayoutandsomesamplecontentincludingFormTextwidget.Thepagecontentisfree-forminthatitwillwrapandflowtoptobottom.
Incontrast,thesecondpagecontainsjellycontrols(twotableviews)thatconsumealltheexcessspaceonthepage.Sincethecontrolsarecapableofscrollingthemselves,GridLayoutisused.SeveralPDEeditorpagesareconstructedlikethis.
Thethirdpage(FlowPage)hasalreadybeenshowbeforeinthesectionaboutColumnLayout-itdemonstrateshowtousethislayouttoaccommodatetotheavailablespace.Master/Detailspagehasalsobeenshownabove.
ThelastpageshowshowtoembedCTabFolderinordertoaddanotherdimension.Inthisparticularexample,theactualcontentisnotswitched-thetextcontrolstays,butitscontentisloadedfromdifferentobjectsdependingontheselectedtab.
RecommendedpracticesforEclipseFormsmulti-pageeditors
Therearemanywaysyoucangoaboutwritingaform-basedmulti-pageeditor.Itmostlydependonthetypeofcontentyouareeditingandproficiencyofyourusers.Therearetwowaysyoucanapproachit:
Ifthetypicalusersareusingtheeditorinfrequently,rawsourceishardtoeditbyhandorcomplex,yourusersarenotverytechnicaletc.,youshouldmakeCOMPLETEpagesthatarefullycapableofeditingeveryaspectofthecontentwithouttheneedtoturntotherawsource.Inthisapproach,sourcepageisthereonlyforoccasionalvalidation,ratherthanforregularwork.Inthatrespect,youcangetawaywithabasictexteditor.
Ifyourusersaremoretechnical,havenoproblemeditingthefilebyhandbutwouldappreciatesomehelpfromtimetotime,considerprovidingamixedexperience-makeagoodsourceeditorwithalltheadd-onslikeincrementaloutline,contextassist,syntaxhighlightingetc.Inturn,addcomplexvalue-addfunctionalityintheformpagesthatarehardtoachievefromsource.Wehavelearnedfromexperiencethatitisveryhardtoconvinceseasoneduserstoswitchfromsourceeditingifthevalue-addismarginalordebatable.However,functionthatwasonlyavailableinGUIpagesandwasveryhigh-qualitywasusedreadily.
Acceptingthatuserswillswitchpagesfrequentlyrequiresagoodmodeloftheunderlyingcontent.Modelshouldbedirectlytiedtotheunderlyingdocument(s)sothatitisinsyncbothwhenuserstypeintextdirectlyandwhenchangeitstructurallythroughtheGUIpages.
多谢指点,其实我对.net和ruby也不是很了解,对与java也只是刚起步的阶段,只是在学习中有了点想法就写出来了,现在俺本科还没毕业,所以对大型项目基本上也没有什么经验。 |
|