Professional Documents
Culture Documents
CoverdesignbyFabienBodard ForewordbyFabienBodardandBenotMinisini
1
A Beginner's Guide to Gambas Copyright Notice for the printed version of this work: A Beginner's Guide to Gambas (this work) is copyright 2005 by John W. Rittinghouse, all rights are reserved. Personal use of this material is permitted. However, permission to reprint/republish this material for advertising or promotional purposes or for creating new collective works for resale or redistribution to servers or lists, or to reuse any copyrighted component of this work in other works must be obtained from the the author, John W. Rittinghouse. The author grants a perpetual license to the Gambas user-community for use of the electronic version of this printed work under the terms and conditions of the OpenContent License printed on the following page.
Table of Contents
Acknowledgments........................................................................16 Foreword.......................................................................................17 Chapter1IntroducingGambas.................................................19 GambasArchitecture......................................................19 TheGambasProgrammingEnvironment......................22 GambasIDEComponents.................................................25 Chapter2GambasLanguageConcepts.................................30 GambasVariables,DatatypesandConstants.............30 VariableAssignment..........................................................35 AssignmentUsingTheWITHStatement...........................35 OperatorsandExpressions............................................36 Comparisonoperators......................................................36 ArithmeticOperators..........................................................36 Let'sStartCodingGambas................................................37
END,RETURNandQUITStatements.......................................37
StringOperators................................................................44 Chapter3KeywordsandProgramFlowControl....................46 ThePRINTStatement.......................................................46 TheIFStatement...............................................................47 TheSELECT/CASEStatement.......................................48 GOTOandLABELS..........................................................49 TheFOR/NEXTStatement..............................................49 DO[WHILE]LOOP............................................................51 WHILE[Expression]WENDLoops...................................52 TheREPEATUNTILloop.................................................53 DefiningandUsingArraysinGambas..........................53 Collections.......................................................................55 TheFOREACHStatement...............................................55 Chapter4IntroducingtheGambasToolBox..........................57 TheButtonControl..........................................................61 CommonControlProperties..............................................62 ButtonMethods.................................................................70
4
A Beginner's Guide to Gambas ButtonEvents....................................................................78 ThePictureClass............................................................78 Chapter5ControlsforGatheringInput...................................80 TextLabel..........................................................................82 TextBox............................................................................83 ComboBox........................................................................85 ListBox.............................................................................89 Frame................................................................................92 ToggleButton...................................................................93 Checkbox.........................................................................93 Panel.................................................................................95 RadioButton.....................................................................95 Chapter6Menus,Modules,DialogsandMessageBoxes.....97 TheGambasMenuEditor...............................................98 BuildingMenus..............................................................101 Dialogs............................................................................103 Modules..........................................................................105 MessageBoxes...............................................................112 InformationMessages.....................................................112 Query/ConfirmMessages................................................114 ErrorMessages...............................................................115 WarningorAlertMessages.............................................115 DeleteMessages.............................................................116 DialogClassFilerelatedFunctions.............................117 DialogOpenFileFunction................................................117 DialogSaveFileFunction.................................................118 DialogSelectDirectoryFunction......................................119 CompleteExampleListing............................................120 Module1.modulelisting.................................................123 Chapter7HandlingStringsandConvertingDatatypes.....125 StringFunctions............................................................125 Len...................................................................................126
5
A Beginner's Guide to Gambas Upper$/Ucase$/UcaseandLower$/Lcase$/Lcase........126 Trim$,LTrim$,andRTrim$..............................................127 Left$,Mid$,andRight$..................................................128 Space$............................................................................130 Replace$........................................................................130 String$............................................................................131 Subst$............................................................................131 InStr.................................................................................132 RInStr..............................................................................134 Split..................................................................................134 ConvertingDatatypes..................................................135 AscandChr$..................................................................135 Bin$.................................................................................136 CBool..............................................................................137 CByte...............................................................................138 CDate..............................................................................138 CFloat..............................................................................139 CInt/CintegerandCShort.............................................140 CStr/CString.................................................................140 Hex$................................................................................141 Conv$.............................................................................141 ValandStr$....................................................................142 Str$.................................................................................142 Format$...........................................................................145 Datatypemanagement.................................................147 TypeOf.............................................................................148 Chapter8UsingAdvancedControls.....................................149 IconViewControl...........................................................149 ListViewControl............................................................158 UsingtheGambasIconEditTool................................162 TheTreeViewControl....................................................163 TheGridViewControl....................................................171 TheColumnViewControl..............................................174 LayoutControlsHBox,VBox,HPanelandVpanel. .176 HBoxandVBox...............................................................177 HPanelandVpanel..........................................................177
6
A Beginner's Guide to Gambas TheTabStripControl.....................................................181 Chapter9WorkingwithFiles.................................................188 Access............................................................................188 Dir....................................................................................189 Eof...................................................................................190 Exist................................................................................190 IsDir/Dir?.....................................................................191 Stat.................................................................................191 Temp/Temp$...............................................................192 OPENandCLOSE..........................................................192 LINEINPUT.....................................................................193 READ,SEEK,WRITEandFLUSH.................................194 COPY,KILLandRENAME.............................................195 MKDIR,RMDIR...............................................................196 Chapter10MathOperations..................................................215 PrecedenceofOperations............................................215 Abs..................................................................................216 Acs/ACos......................................................................216 Acsh/ACosh.................................................................217 Asn/ASin.......................................................................217 Asnh/ASinh..................................................................218 Atn/ATan.......................................................................218 Atnh/ATanh..................................................................219 Cos..................................................................................219 Cosh................................................................................220 DegandRad...................................................................221 Exp..................................................................................221 FixandFrac...................................................................222 Int....................................................................................223 Log..................................................................................223 Log10..............................................................................224
7
A Beginner's Guide to Gambas MaxandMin...................................................................224 Pi.....................................................................................225 RandomizeandRnd......................................................225 Round.............................................................................227 Sgn..................................................................................227 Sin...................................................................................228 Sinh.................................................................................229 Sqr...................................................................................229 Tan..................................................................................230 Tanh................................................................................231 DerivedMathFunctions................................................231 Chapter11ObjectOrientedConcepts..................................237 FundamentalsofObjectOrientedProgramming........238 Objects............................................................................239 DataAbstraction..............................................................239 Encapsulation..................................................................240 Polymorphism..................................................................240 Inheritance.......................................................................240 TheGambasApproachtoOOP....................................241 GambasClasses.............................................................241 Sampleprogram:Contacts...........................................242 TheContactclass............................................................242 Contact.GetDataMethod.................................................243 Contact.PutDataMethod.................................................246 Form1.classfile...............................................................247 Form1Constructor...........................................................249 Form_OpenSubroutine...................................................250 AddingControlstoForm1.Form......................................250
TheToolButtons.......................................................................251 TheQuitButton.........................................................................251 AddingtheLabelsandTextBoxes............................................252
UpdateForm()Subroutine................................................253
CodingToolbuttons:First,Prev,Next,andLast.......................254 CodingToolButtons:Addingarecord.......................................256 CodingToolButtons:Clearingdata...........................................258
ValidatingUserInput.......................................................258
8
ToolButtonsagain:UpdatingaRecord............................263 Toolbuttonsagain:DeletingaRecord.............................264 ToolButtonsagain:SavingData......................................265 CreatingaStandaloneExecutable..............................266 Chapter12LearningtoDraw.................................................267 DrawProperties.............................................................267 BackColor/BackgroundandForeColor/Foreground........267 Clip..................................................................................268 FillColor,FillStyle,FillX,FillY..............................................268 Font.................................................................................269 Invert................................................................................269 LineStyle/LineWidth.........................................................270 Transparent.....................................................................270 DrawMethods................................................................270 Text/TextHeight/TextWidth..............................................272 DrawPrimitives:Point/Rect/Ellipse/Line..........................274 DrawPrimitives:PolygonandPolyline............................280 Image/Picture/Tile............................................................284 DrawingwithaDrawingobject........................................292 Chapter13ErrorManagement...............................................298 GeneralConceptsofErrorManagement.....................298 ErrorHandling.................................................................298 BoundaryRelatedErrors.................................................299 CalculationErrors............................................................299 InitialandLaterStates.....................................................300 ControlFlowErrors..........................................................300 ErrorsinHandlingorInterpretingData............................301 RaceandLoadConditions..............................................301 PlatformandHardwareIssues........................................302 Source,Version,andIDControlErrors...........................303 TestingErrors..................................................................303 TestPlanReviews...........................................................303 GambasErrormanagement.........................................304 TRYstatement...IFERROR...........................................304
9
A Beginner's Guide to Gambas CatchandFinallyStatements..........................................306 GambasEventmanagement........................................309 Chapter14Mouse,KeyboardandBitOperations................312 MouseOperations.........................................................312 KeyboardOperations....................................................316 BitOperations................................................................318 Chapter15GambasandDatabases......................................326 ConnectionClass..........................................................327 ConnectionProperties.....................................................328
Charset.....................................................................................328 Databases.................................................................................328 Host...........................................................................................329 Login.........................................................................................329 Name........................................................................................329 Password..................................................................................330 Port...........................................................................................330 Tables.......................................................................................330 Type..........................................................................................330 Users.........................................................................................330 Version......................................................................................330
TheConceptofaTransaction.........................................331 ConnectionClassMethods..............................................332
Open/Close...............................................................................332 Begin/Commit/Rollback............................................................333 Find...........................................................................................333 Create.......................................................................................334 Edit............................................................................................334 Exec..........................................................................................334 Quote........................................................................................335
A Beginner's Guide to Gambas TheDatabaseExampleProgram..................................338 Chapter16GlobalGambas....................................................351 Internationalization........................................................351 Localization....................................................................351 UniversalCharacterSet(UCS).....................................352 Unicode..........................................................................352 UTF8..............................................................................353 HowtotranslateinGambas.........................................355
11
Table of Figures
Figure1GeneraloverviewofGambasarchitecture...........................................20 Figure2theGambasOpeningScreen..............................................................21 Figure3TheGambasProjectCreationWizard.................................................22 Figure4AdialogtoselectthetypeofGambasprojectyouwishtocreate.......23 Figure5ProjectNameSelectionDialog............................................................24 Figure6ProjectDirectorySelectionDialog........................................................24 Figure7NewProjectconfirmationdialog...........................................................25 Figure8TheGambasIDE.................................................................................26 Figure9ProjectExplorerFileMenu...................................................................27 Figure10ProjectMenu......................................................................................27 Figure11ProjectExplorerViewMenu...............................................................27 Figure12ProjectExplorerToolsMenu..............................................................27 Figure13ProjectExplorerMenuandToolbar...................................................28 Figure14ADivisionbyZeroErrorDialog..........................................................40 Figure15TheGambasToolBox........................................................................58 Figure16AdditionalcontrolsforQT...................................................................60 Figure17FirstButtoncoderesults....................................................................65 Figure18Demonstratingfontcapabilities..........................................................67 Figure19Thedottedlineindicatesfocusforacontrol......................................72 Figure20ThelayoutforSecondProjectForm1.form.........................................72 Figure21Apartiallyconstructedformwithourfirstfourcontrols.......................73 Figure22Eventmenu........................................................................................74 Figure23AddingtheFunBtntoourform...........................................................76 Figure24Whatourformlookslikewhenamouseisdetectedovertheform. Notethetextisblankedout...............................................................................77 Figure25TheprogressbarwhentheFunBtnisclickedthreetimes.................77 Figure26ThirdProject(almost)finalresult........................................................80 Figure27UsingHTMLtoformatTextLabeloutput............................................82 Figure28ModifiedTextLabeloutputusingHTMLformatting............................83 Figure29AddingaToolTiptoinformtheuserhowtoshow/hideacontrol.......85 Figure30OurComboBox..................................................................................86 Figure31TheEditlistpropertyeditor................................................................87 Figure32FormattingaTextLabelwithHTML....................................................88 Figure33PlusandminusbuttonstoaltertheComboBoxlist............................88 Figure34WhatourListBoxwilllooklike............................................................90 Figure35ListBoxEditlistpropertyeditor...........................................................90 Figure36Whattheexampleframewebuildwilllooklike..................................92
12
A Beginner's Guide to Gambas Figure37APanelwithRadioButtons................................................................95 Figure38MenuProjectFinalresults..................................................................97 Figure39TheGambasMenuEditorwhenitfirststarts.....................................98 Figure40EditfieldsfortheMenuEditor............................................................99 Figure41Buildingourprojectmenu................................................................101 Figure42Aformattedtextlabeldisplayingthecolorvalue..............................104 Figure43Selectingcolorsandfonts................................................................111 Figure44MakinganewdefaultfontfortheTextLabel1control......................112 Figure45AnInformationMessageBox............................................................113 Figure46Acheckedmenuitem.......................................................................113 Figure47AQuestionMessageBox.................................................................115 Figure48AnErrorMessage............................................................................115 Figure49AWarningmessage.........................................................................116 Figure50Deletemessagewiththreebuttons..................................................117 Figure51TheOpenFileDialog.......................................................................118 Figure52SaveFileDialog...............................................................................119 Figure53TheSelectDirectoryDialog.............................................................119 Figure54ChoosingtheExplorerexample.......................................................149 Figure55LayoutforourListViewexample......................................................159 Figure56CreatinganewIconimageinGambas............................................163 Figure57Oursquareiconimage.....................................................................163 Figure58IconEditorToolBox.........................................................................163 Figure59Ourcircleiconimage.......................................................................163 Figure60TheTreeViewProjectwindow..........................................................164 Figure61WhatourGridViewwilllooklike.......................................................171 Figure62OurColumnViewexample...............................................................174 Figure63Layoutprojecticons.........................................................................178 Figure64Form1designmodeshowinglayoutofourcontrols.........................178 Figure65Layoutprogramwhenitstartsup.....................................................181 Figure66ATabStripcontrol............................................................................182 Figure67TabProjectForm1.formDesign.......................................................183 Figure68Tab0layout......................................................................................183 Figure69Tab1layout......................................................................................184 Figure70Tab2ToolButtonlayoutwithicons...................................................185 Figure71Tab3layoutwithaComboBox.........................................................185 Figure72TheFileOpsprogramatruntime......................................................196 Figure73Form2.formdesignmode................................................................210 Figure74FinishedContactsprogram..............................................................248 Figure75Form1seenindesignmode.............................................................253
13
A Beginner's Guide to Gambas Figure76Contactssearchformdesign...........................................................261 Figure77ContactsManagerrunningstandaloneonmydesktop....................266 Figure78gfxDemoForm1layout.....................................................................271 Figure79ResultsofclickingtheTextButton...................................................274 Figure80ResultsofInvRectbuttonclick.Notethetinyblackcrosshaircenter screen................................................................................................................275 Figure81Ellipsesdemonstratesdrawinglinesandellipses............................278 Figure82OutputafterclickingtheFillRectbutton...........................................280 Figure83UsingDraw.Polygontodrawatriangle............................................282 Figure84UsingDraw.Polylinetodrawlines....................................................284 Figure85UsingtiledimageswiththeTileImgbuttonofourdemoprogram....292 Figure86LoadinganSVGfileinGambas.......................................................295 Figure87ErrorresultscaughtwithTRY..........................................................305 Figure88CATCHtestprogramopeningscreen..............................................307 Figure89DivbyZeroerrorcaughtbyCATCH................................................307 Figure90TheTextLabelupdatedwitherrorinfo.............................................308 Figure91Infomessagethattheerroriscleared..............................................308 Figure92Mainscreenaftererrorhasbeencleared........................................308 Figure93DefaultGambaserrordialog............................................................309 Figure94Oureventwasraised.......................................................................311 Figure95MouseOpsprogramrunning............................................................315 Figure96KbdOpsprogramrunning.................................................................318 Figure97TheBitOpsprogramindesignmode...............................................320 Figure98OurbitOpsprogramrunning............................................................325 Figure99TheFMainformindesignmode......................................................339 Figure100FRequestFormindesignmode.....................................................339 Figure101ChoosingtheTranslateoptioninGambas.....................................356 Figure102TheTranslateDialoginGambas...................................................356
14
Thispageisintentionallyblank.
15
Acknowledgments
Firstofall,averyspecialthanksto BenotMinisini forthecreationofGambas andforhissupportofthisefforttofurtherdocumentthiswonderfullanguage.Without Benot'sinitiative,wewouldallbestrugglingtofindabettertoolthanwhatexiststoday onLinuxplatforms.MuchoftheinitialdocumentationoftheGambaslanguagewasput ontheGambasWikibyBenotandhedeservesspecialcreditformakingthisinformation available. Asitwasthe onlyknownpublishedsourceofdefinitive documentationin existencepriortothiswriting,muchofthereferencematerialhereinwasgleanedfrom thatinitialsetofdocumentation. Aswithanywrittenmaterial,thereisnoguarantee thatthisdocumentationisasaccurateaswhatyoumayfindinthelatestreleaseofthe Gambasproduct. TheauthorwouldliketoextendaspecialthankstoFabienBodardforhishelpin makingthisworkbecomeareality. Fabientirelesslyeditedcode,reviewedthesample projectspresentedherein,andprovidedgreatinsightintotheinnerworkingsofGambas allatthetimeofharvestforhisvineyard.LaurentCarlierandSteveStarrbothalso deservemygratitudefortheirmeticulousworkeditingthecodeandensuringeverything worked as advertised. Their feedback, suggestions and corrections were greatly appreciated. Iwouldalsoliketothank DanielCamposFernndez whowasagreat assetinhelpingmetounderstandsomeofthefinerpointsofGambas. NigelGerrard alsocontributedtothesuccessofthisprojectbyprovidingafinalreviewandeditofthe databasematerial.FromamongtheseGambasHallofFamecoders,whoelsecouldhave doneitbetter? CountlessemailswerereceivedfrommanymembersoftheGambascommunity, all of which provided ongoing encouragement and support which motivated me to completethiseffortandmakeitavailabletoeveryone.Giventhedifficultiesofwritinga bookinthefirstplace,itwasagreatfeelingofsatisfactiontoreceivesuchsupportfrom completestrangerswhoallsharethesinglevisionofmakingGambasasuccess. Ican onlyhopethatthisbookwilldojusticetothateffortandwelcomeanysuggestionsfor change,aswellasanycomplimentsorconstructivecriticism.Ithasbeenalotoffunto learnthiswonderfulnewlanguageandtoexplorethepossibilitiesitoffers.Idedicate thisbooktoallofthoseGambasusersanddeveloperswhohavereliedoneachotherin the Gambasuser/developercommunitytomake this productbecome reality. Shared vision,commongoals,andopensoftwarearepowerfulforcesthatshouldnoteverbe underestimated.Suchforceshavebeenknowntochangetheworldandwillcontinueto dosolongafterthisbookhasbeenreadandforgotten. JohnW.Rittinghouse,Ph.D.,CISM October,2005
16
Foreword
For the last three years, I have plunged headfirst into the Linux programmingenvironment.ConsideringmyfirstinstallationofLinuxwasbackin 1996, it shouldnotbeconsidered agoodfirststart. Asanenthusiastic Basic developer,theLinuxenvironmentlackedatoolthatwould allowmetoeasily programintheLinuxenvironment.Bychance,Istumbleduponasmallproject, thefruitofmorethantwoyearsofworkfromamannamedBenoitMinisini.After figuringouthowtogetpasttheidiosyncrasiesofcompilation,Idiscoveredwhat wastobetheembryonicstagesofoneofthemostfabulousprojectsicouldhave imagined,Gambas!Atthattime,Gambaswasalreadyimplementedwithit'sown IntegratedDevelopmentEnvironment(IDE)andasyntaxhighlighter.Theability ofGambastodynamicallyloadcomponentsandremainfairlytruetotheBasic languageasusedunderWindowswasanaddedbenefit. Today,Gambashasarrivedasamatureproductthat,init'sfirstversion, allowsausertoconstructgraphicalapplicationsorconsolebasedapplications, supportsdatabasemanagement,connectiontotheInternetortosocketservers, utilizesdatacompression,supportsDCOPwithKDEapplications,andmuchmore. AGambasapplicationcanbetranslateddirectlyfromtheIDEandpackagedin binaryformfordifferentLinux distributions.Whatwasinitiallyalluringtome still is Gambas has gone beyond being just another programming language becauseitsupportsallofthefeaturesofa"professional"productwhileretaining itssimplicity. Gambasprovidesarealtoolforthebeginningprogrammerand makesitpossibleforanoviceprogrammertodevelophighqualityapplications. Here,inthisbook,youwillfindthefirstcomprehensivetreatmentofGambas.It makes approaching the Gambas language simple and the reader can easily progressfromthebeginner'sleveltopicstothemoreadvancedtopicsprofessional programmersusedaily. Gambashasandwillcontinuetoevolve.GambasVersion1.0(discussedin thisbook)isthefoundationofalanguagewhichwillevolvetobeevenmore powerful.Forexample,GambasVersion2willmakeitpossibletomakeAPIcalls toa native library. Itwillallowprogrammers to manageevenmore typesof database servers and will work equally well with either Qt or GTK graphics libraries. Gambas2willallowprogrammerstodeveloptheirowncomponents fromwithintheGambasenvironment. Developerswillbeabletocreategames usingSDLandOpenGL.ThescopeoftheGambaslanguageisgrowinglargerand andthesyntaxisbecomingmorecompact. Alloftheseideasforimprovement
17
A Beginner's Guide to Gambas and change do not rest solely in the heads of a stable of chosen developers workingontheGambas2project.TheycomefromallGambasuserswhoprovide theideasthatmakeGambas2evenbetterthanbefore.Alreadyitcandosomuch morethanversion1.0.Istronglyrecommendthatwhileyouarewaitingforthe stablereleaseofGambas2,youbeginyourGambastrainingwithyourmachine and what you will find in this book. It will prepare you for a wonderful programmingexperienceintheLinuxenvironment.
FabienBodardandBenoitMinisini
18
GambasArchitecture
EveryprogramwrittenwithGambasBasiciscomprisedofasetofproject files. Each file within a project describes a class. The class files areinitially compiled and subsequently executed by the Gambas Interpreter. This is very similartohowJavaworks.Gambasismadeupofthefollowingprograms:
1 2 3
Thereaderisencouragedtovisithttp://gambas.sourceforge.net/index.htmltolearnmoreabouttheGambasproject. Forinformationaboutthelicense,visithttp://www.gnu.org/licenses/licenses.html#GPL. SeetheGambasWikiWebSiteIntroductionathttp://gambas.sourceforge.net/index.htmlformoredetails. 19
Figure1below4isanillustrationoftheoverallarchitectureofGambas.In Gambas,aprojectcontainsclassfiles,forms,modules,anddatafiles.AGambas projectisstoredinasingledirectory.Compilingaprojectuses inincremental compilemethodthatonlyrequiresrecompilationofthemodifiedclasses.Every external reference of a class is solved dynamically at runtime. The Gambas archiver transforms the entire project directory structure into a standalone executable.TheGambasdevelopmentenvironmentwaswrittenwithGambasto demonstratethefantasticcapabilitiesofthelanguage.
Figure1GeneraloverviewofGambasarchitecture.
SomeotherfeaturesthatsetGambasapartfromotherlanguagesinclude the fact that Gambas has an extensible component architecture that allows programmerstoextendthelanguage.Anyonecanwritecomponentsasshared libraries that dynamically add new native classes to the interpreter. The componentarchitectureisdocumentedonlineintheGambasWikiencyclopedia5.
4 5 See URL http://gambas.sourceforge.net/architecture.html, for the original graphic. Copyright (c) 1999-2005 by contributing authors. All material on the Gambas Wiki is the property of the contributing 20
A Beginner's Guide to Gambas WewillcoverGambascomponentsingreaterdetaillaterinthisbook.Bydefault, the GambasInterpreter isatextonly(consolebased)program. Thecomponent architectureisusedforthegraphicaluserinterface(GUI)partofthelanguage. BecausetheGUIisimplementedasaGambascomponent,ithastheabilitytobe independentofanyspecificGUItoolkit.WithGambas,youcanwriteaprogram and choosewhichtoolkit,suchas GTK+6, Qt7,etc., touselater. Thecurrent releaseofGambasimplementsthegraphicaluserinterfacewiththe Qt toolkit. TheGUIcomponentsarederiveddirectlyfromtheQTlibrary.Itisrecommended thatthereaderalsoconsultwiththeQTdocumentation8tobetterunderstandthe GUIcontrols.AccordingtoMinisini,a GTK+ componentwithanearlyidentical interfaceastheQtcomponentisplanned.
Figure2theGambasOpeningScreen.
6 7
8
A Beginner's Guide to Gambas Another feature of Gambas that sets it apart from other programming languagesisthecapabilityofanywindowordialogboxtobeusedlikeacontrol. This feature is not directly supported in other programming languages. Also, Gambasprojectsareeasilytranslatable,intoalmostanyotherlanguage.Wewill demonstrate this feature later in the book when we cover Internationalization (i18n).
TheGambasProgrammingEnvironment
For now, let's take a quick tour of Gambas and introduce you to the Gambasprogrammingenvironment.Alloftheexamplesandcodewrittenforthis book were developed using Gambas version 1.0.9 running on Linspire 5.09. TheyshouldworkonanyplatformthatyoucaninstallGambasonsuccessfully. ForLinspireusers,itisassimpleastheclickofabuttonusingtheClickNRun warehousefeatureofthatproduct.Whenyoufirstclickthedesktopicontostart theGambasprogram,youwillbepresentedwithanopeningscreensimilartothat foundinFigure2above.Thewelcomescreenallowsyoutocreateanewproject, openanexistingproject,viewandselectfromrecentprojects,lookatexamples, orquit. ForourquicktourofGambas,wearegoingtoselecttheNewProject optionandcreateourfirstGambasproject.YouwillseeadialogsimilartoFigure 3belowappear.
Figure3TheGambasProjectCreationWizard.
FormoreinfoaboutLinspire,visithttp://www.linspire.com. 22
A Beginner's Guide to Gambas Simplyclickthe Next>> buttonandyouwillbepresentedwithanother dialogthatrequiresyoutochoosethetypeofprojectyouwanttocreate(see Figure4,below). ThisdialogrequiresyoutopickbetweenaGUIprojectora consoleproject.
Figure4AdialogtoselectthetypeofGambasprojectyouwish tocreate.
Forourexample,choosethefirstselection,Createagraphicalprojectand clicktheNext>>buttonatthebottomofthedialog. The next dialog that you willseerequiresyoutonameyourprojectandchoosewhereitwillbelocatedon yourlocalfilesystem.ItisshowninFigure5below. Thissectionofthewizardhasyoutospecifythenameoftheprojectasit willbestoredondisk.Remember,inGambasaprojectisentirelyselfcontained inadirectoryorfolder.Thefoldernameyouchooseasthenamefortheproject iswhatwillbecreatedonyoursystem. Thetitleoftheprojectwillbewhatyouspecifyinthesecondtextinput field of the dialog. Additionally, the Options section allows you to choose whetherornotyourprojectwillbetranslatableandifthecontrolsusedonyour formsaregoingtobemadepubliclyaccessible.Wewilldiscusstheseoptionin moredetaillaterinthisbook.Fornow,justfilloutthedialogasshowninFigure 5andclickNext>>.
23
Figure5ProjectNameSelectionDialog.
Chooseadirectoryappropriateforyourfilesystemandclickthe Next>> button to proceed to the final dialog screen of the wizard, as shown on the followingpageinFigure7. Thisdialogissimplyaconfirmationscreenofthe choicesyouhavemade.Themostimportantthingtorememberaboutthisscreen isthatitisthelastchanceyouhavetobackupandmakechangesbeforeyour newprojectiscreated.
Figure6ProjectDirectorySelectionDialog.
24
Figure7NewProjectconfirmationdialog.
OnceyouhaveclickedontheOKbuttontofinishthiswizard,Gambas will present you with the Gambas integrated development environment (IDE). TheIDEconsistsofseveralcomponentsthatareshowninFigure8onthenext page. GambasIDEComponents TheProjectExploreristhemainGambaswindow.ItshowyouaTreeView ofthetypesoffilesfoundwithinyourproject(i.e.,classfiles,forms,modules,and othertypesoffilessuchasdataandpictureoriconfiles)andtheProjectExplorer allows you to perform most Gambas project management operations, such as opening and saving projects, building executables, running your program or debuggingit,showingorhidingvariousGambasdialogs,etc.FromtheTreeView intheProjectExplorer,youwillseetheitemslistedasfollows:
Classes lists the class files you've created for your project. Classes are basicallytemplatesthatcanbeusedtomakeobjectsoutofatruntime,withcode todefineproperties,methodsandeventhandlersforeachobjectyoucreate.
25
Figure8TheGambasIDE.
Forms liststhevariousformsyoucreateforyourproject. Formsarethe windowstheuseractuallyinteractswith. Modulesdisplaythemodulesyou'vewrittenforyourproject.Modulesare simplysetsofsubroutinesandfunctionstobeusedanywhereinyourprogram. Unlikeclasses,youcan'tmakeobjectsoutofthematruntimeandtheyhaveno eventhandlers. Dataliststheotherfilesinyourproject.Thesecanincludeanyotherkind offileused tobuildyourproject,suchasgraphicfiles,icons,bitmaps,textor HTMLfiles,andevenmediafiles.AtthebottomoftheProjectExploreryouwill findtheStatusBarwhichisusedtoindicatewhatGambasiscurrentlydoing. WhenyoustarttodevelopaprojectinGambas,youwillusuallywantto begin with a main form. The main form is where the program startup and initializationwilloccuranditisusuallythefirstthingyouruserwillseewhen theyexecute(orrun)theapplicationyouhavebuilt.Thisistheformyouwilladd controlstoandspecifywhatactionsaretobetakenwhentheuserinteractswith
26
A Beginner's Guide to Gambas thosecontrols. SuchinteractionbetweentheuserandtheGUIisreferredtoas events. The controls are found in the ToolBox window. You can change the appearanceandbehaviorofthecontrolsbysettingthepropertiesforeachcontrol. Propertiescanbeseeninthepropertieswindow. Now,letstakealookatthemenusandbuttonsfoundatthetopofthe ProjectExplorer.Themenus(seeFigures9through12below)controlallthemain Gambasmanagementtasks.TheFilemenuwillallowyoutoopenaproject,save aproject,createanewproject, opensomeGambasexampleprojects,orquit usingGambas.TheProjectMenuiswhereprogramcompilationoccurs.Youcan also create the program executable, make a source archive, or create an installation package. This menu offers you the option of translating your programintoanotherlanguage.Finally,youcansetGambasIDEpropertiesfrom thismenu.
Figure9ProjectExplorerFileMenu. Figure10ProjectMenu.
Figure12ProjectExplorerToolsMenu.
Figure11ProjectExplorerViewMenu.
27
A Beginner's Guide to Gambas TheViewmenuwillallowyoutobringupthepropertieswindoworthe ToolBox window. You can open a console or use the Icon Editor to create programicons. TheHierarchyoptionwillopenawindowandshowyouyour project'sclasshierarchy.Finally,fromthismenu,youcancloseallofthewindows thatarecurrentlyopenintheIDE. The ToolBar buttons (seeFigure13below) providesingleclickaccesstothemostcommonmenuitems.Hoveringyourmouse cursoroveroneofthebuttonswilldisplayaToolTipthatwilltellyouwhatmenu actionthatparticularbuttonwillperform. Figure13belowshowsyoutheFilemenuandToolBar.FromtheProject ExplorerTreeView youcandoubleclickonaformanditwillpopupforyouto edit.Editingformsissimplyamatterofselectingwhattypeofcontrolyou'dlike toplaceontheformandthenusingthemousetoresize(draw)itonyourform.
Figure13ProjectExplorerMenuandToolbar.
Rightclickingontheformoranyofitschildren(controls)willshowyoua popupmenuthatwillallowyoutoperformoperationsonthecontrol,editits propertiesordeleteit.Thecurrentlyselectedcontrolisindicatedbyfourblack squarescalledhandles. Clickingonahandleandusingthemousetodragthe controlwhereyouwantitwillallowyoutomoveorresizethecontrol.Double clicking on a control will bring up the code editor window and display any existingeventhandlerforthecontrolordisplayadefaulteventhandlerifthere havebeennonespecified. TheGambasCodeEditorenablesyoutowritecodetohandleeventsforthe controlsyou'veplacedonyourform.IntheToolBoxwindow,theSelectionTool istheonlyitemintheToolBoxthatisn'tactuallyacontrol. TheSelectionTool simplygivesyoucontrolofthedefaultmousepointer. Youusethispointerto selectcontrolsandperformpositioningandresizingoperationsonformsandtheir associatedcontrols. FromtheProjectExplorerFileMenu,choosetheQuitoptionandsaveyour project.Whenwereopenit,allyourworkwillbesaved.Inthenextsection,we willbegintocovertheessentialsyouneedtounderstandinordertoprogramwith
28
A Beginner's Guide to Gambas Gambas. Wewillcomebacktothisprojecttodevelopaprogramthatusesthe GUIafterwelearnabitmoreabouttheGambascodingenvironment,theprimary languageconceptsthatarerequiredtouseGambas,andsomebasicsaboutdata typesandvariables. Thatisallcoveredinthenextsectionandconstitutesthe remainderofthisintroductiontoGambasprogramming.Fornow,takeashort breakandwewillcontinuewhenyoucomeback.
29
GambasVariables,DatatypesandConstants
Variablesmustbedefinedatthebeginningofaclass,methodorfunction. Variabledeclarationscaneitherbelocaltoaprocedureorfunctionortheycanbe declaredglobaltoaclass.Aglobalvariableisaccessibleeverywhereintheclass itisdeclared.TheformatofaglobalvariabledeclarationinGambastakesthe followinggeneralform:
[STATIC](PUBLIC|PRIVATE)Identifier[Arraydeclaration]AS[NEW]Datatype
IfthePUBLICkeywordisspecified,itisalsoaccessibletotheotherclasses thathaveanyreferencetoanobjectofthatclass.Ifthe PRIVATE keyword is specified,itisnotaccessibleoutsidetheclass inwhichitwasdefined. Ifthe STATICkeywordisspecified,thesamevariablewillbesharedwitheveryobject oftheclasswhereitisdeclared.IftheNEWkeywordisspecified,thevariableis initializedwith(i.e.,instantiatedwith)anewinstanceoftheclassusingthedata typespecified.Forlocalvariabledeclarations,theformatislikethis:
[DIM]IdentifierASDatatype
30
Boolean datatypes can contain only a single value, either TRUE or FALSE. TRUEisdefinedas1andFALSEisdefinedas0. Thedeclarationofa Booleanvariableoccupies1byteofmemoryandthedefaultvalueisFALSE.An exampleofavariabledeclarationforaBooleanvariablelookslikethis:
STATICPRIVATEbGridASBoolean
Typically, a programmer would use a Boolean datatype when the only valuesforthevariablewouldbeyes/no,TRUE/FALSE,1/0,etc. Ifthevalues usedinyourprogramcouldbeanythingelse,Booleanwouldbeaninappropriate selection for the variable datatype. Another thing to note in the variable declaration above is the placement of the lowercase letter b in from of the variablename. Good programming convention encourages this practice, known as the HungarianNotation11,asitallowstheprogrammerstoknowwhatdatatypethe variableisbysimplyknowingthatthe'b'standsforBoolean.Whathappenswhen a programmer wants to use a Byte datatype instead of a Boolean datatype? Typically,asecondletterisaddedtothevariabledeclarationsoratherthanusing 'b'infrontofthevariablenametheprogrammerwoulduse'by'asbelow:
STATICPRIVATEbySomethingASByte
Theletters'ar' 's', 'i', 'f', 'd', 'st', 'v' and 'o' arecommonlyusednotations whendeclaringvariableswhileprogramminginGambas.Itisgoodprogramming practicetoforceyourselftoadheretothistechniquesothatotherscanpickup yourcodeanduseitwithouthavingtosearcharoundtofindthedatatypefor eachvariableencountered.Someprogrammersevenusemorethanthefirstletter (s) to name their variables. For example, they would code IntMyNumber or ByteSomething.
10 In the second release of Gambas (Gambas2) "Long" and "Single" data types are planned. These data-types are like the C LONG LONG and FLOAT data types. This is a significant improvement because Gambas2 will provide direct programming access to the C API and will also support 64 bit platforms. 11 Hungarian Notation (HN) is a naming convention originated by Charles Simonyi of Microsoft. It was first presented in his thesis and is widely used throughout the source code of the Windows operating system, among other places. 31
A Beginner's Guide to Gambas The Bytedatatype cancontainvaluesfrom0to255andoccupiesone byte of memory when declared. The default value when a Byte datatype is declaredis0.Ifyouarecertainyourvalueswillnotexceed255thenthisdata type is appropriate for use. If it is possible that the values assigned to this variablewouldexceed255,thenthelikelyresultwouldbeaprogramcrashatrun time. Itisbettertousethe Shortdatatype oran Integerdatatype forsuch situations. For a Short datatype, values can range from 32768 to +32767. Shortdatatypesoccupytwobytesofmemoryanddefaulttoazerovaluewhen declared.Integerdatatypesoccupytwiceasmuchmemory,takingupfourbytes. The range of values you can use with the Integer datatype is from 2,147,483,684to+2,147,483,647.ThisissimilartotheLONGdatatypeusedin VB.ExamplesofShortandIntegerdatatypevariabledeclarationsare:
STATICPUBLICsSomeShortASShort STATICPUBLICiSomeIntegerASInteger
Whenintegerswillnotworkforyourpurposes,Gambasprovidesyouwith theFloatdatatype.Thisdatatypeallowsyoutousefloatingpointnumbersfor yourprogram.FloatdatatypesarelikeDoubledatatypesusedinCandVB.The rangeofvaluesfor floatdatatype variablesisfrom1.79769313486232E308to 4.94065645841247E324fornegativevaluesandfrom4.94065645841247E324 to1.79769313486232E308forpositivevalues.Floatvariablesoccupyeightbytes ofmemoryanddefaulttoazerovaluewhendeclared.Asampledeclarationfora floatwouldbeasfollows:
DIMfRadiusASFloat
ThelastnumericdatatypewehaveinGambasistheDatedatatype.Date variablesalsotakeupeightbytesofmemory. Thedateportionofthedateis storedinafourbyteintegerandthetimeportionisstoredinafourbyteinteger. Itisstoredas [Year,Month,Day][,Hours,Minutes,Seconds] andisusually usedwiththeGambasbuiltinDateandTimefunctions,whichwewillexplain about later in this book. The date datatype defaults to a NULL value when initialized.HereishowtodeclareaDatedatatype:
DIMddateASDate DIMdtimeASDate
Strings,VariantsandObjectsarethenonnumericdatatypessupportedin Gambas. A String datatype is a series of zero or more characters that are treatedasasingleentity.Stringscancontainalphanumericdata.Alphanumeric
32
TheVariantdatatypeisusedwhenyoudonotknowwhatkindofdata typethevariablewillbereceiving.Forexample,ifreadingdatafromafile,you couldreadaninteger,astring,asinglecharacter,floatingpointnumbers,etc.To ensure the data is placed in a variable without causing a program crash, the variantdatatypeisused.Youcanthentestthevariantdatausingsomebuiltin functionsofGambastodeterminethedatatypeoryoucanjustconvertthedata tothedatatypeyouneedusingaconversionfunction.Wewilldemonstratethis laterinthebook.Fornow,itisonlyimportantthatyouunderstandthatvariant datatypesexistandthattheyareusedwhenyouarenotsureofthetypeofdata thevariablewillhold. The Object datatype is a special datatype that holds and references objects such as controls and forms. Later, when we begin to discuss OO programming,wewillcovertheuseof objectdatatypesingreaterdetail. The tableshownbelowispresentedasaconvenientreference:
Gambas data-types
Name Boolean Byte Short Integer Float Date String Variant Object Description TrueorFalse 0...255 32768...+32767 2147483648...+2147483647 SimilartothedoubledatatypeinC Date/time,eachstoredina4byteinteger. Areferencetoavariablelengthstring. Canconsistofanydatatype. Anindirectreferencetoanobject. Memorysize 1byte 1byte 2bytes 4bytes 8bytes 8bytes 4bytes 12bytes 4bytes Default FALSE 0 0 0 0 NULL NULL NULL Null
Now that you know about all the different types of data that Gambas supports,wewillstarttolookatwhatyoucandowiththosedatatypes.When usingyourvariablesinGambasprograms,theycanberepresentedbydatathat changes (e.g.,itisavariable) ortheycanberepresentedbydatathatremains
33
A Beginner's Guide to Gambas constantthroughouttheprogram. Thistypeofdataisknownasa Constant in Gambas. GambasconstantsisusedtorepresentaNULLobjectreference,azero lengthstring,aNULLdate,oranuninitializedvariant. Examplesofconstants includethevaluesNULL,TRUEandFALSE.TodeclareaconstantinGambasuse thefollowingformat:
(PUBLIC|PRIVATE)CONSTIdentifierASDatatype=value
This declares a class global constant. This constant is accessible everywhereintheclassitisdeclared. Ifthe PUBLIC keyword isspecified,itis alsoaccessibletotheotherclasseshavingareferencetoanobjectofthisclass. Constant values must be Boolean, integers, floating point or string datatypes. Herearesomeexamplesofconstantdeclarations:
PUBLICCONSTMAX_FILEASInteger=30 PRIVATECONSTMAGIC_HEADERASString="#Gambasformfile"
ThebuiltinconstantsyouwoulduseinGambasarelistedinthetablebelow:
Gambas Constants
Constant Example
TheTRUEvalue. TheFALSEvalue. Integernumbers. Hexadecimalshortsignedintegers. Hexadecimalsignedintegers. Hexadecimalunsignedintegers. Binaryintegers. Floatingpointnumbers. Stringconstants. Stringconstantstobetranslated. NULLconstant/voidstring.
TRUE FALSE 0,562,17,32769 &H100F3,&HF0FF,&FFFF &H1ABF332E,&1CBF302E &H80A0&,&HFCFF& &X1010111101,%101000011 1.1110,5.3419E+4 "Hello,GambasWorld!" ("Thisisvery,verycool") NULL
34
\n \r \t \ \\ \xx
This assignment statement assigns the value of an expression to one of the followingelements: Alocalvariable Afunctionparameter Aglobal(class)variable Anarrayelement Apublicobjectvariableorproperty Herearesomeexampleofvariableassignments:
iMyVal=1984 stMyName="Orwell" fMyNum=123.45
A Beginner's Guide to Gambas isused. Theexpressionwillbeginwith dotnotation,i.e.,.Textcouldbeused. WITHassignsthedottedexpressionontheleftoftheequalsignthevaluefound ontherightsideoftheequalsign. Expression mustbeanobject. Hereisa sampleofhowtheWITHstructurelooks:
WITHExpression .object=something;. ENDWITH
Asanexample,thecodebelowiscodeequivalenttohButton.Text="Exit"
WITHhButton .Text="Exit" ENDWITH
OperatorsandExpressions
Now thatwe know howto declare variables and constantsand how to assignvaluestothesevariablesandconstants,letstakealookattheoperations thatcanbeperformedwiththem.Wewillbeginwithcomparisonoperatorsthen takealookatarithmeticoperatorsandstringoperators. Comparisonoperators Comparison of two variables requires finding answers to questions like doesxequalyorisalessthanb.Thefollowingcomparisonsaresupportedin Gambas:
Operator
= <> < > <= >=
Meaning
Isequalto Isnotequal Islessthan Isgreaterthan Islessthanorequalto Isgreaterthanorequalto
Example
IFa=bTHEN... IFa<>cTHEN... IFa<dTHEN... IFa>eTHEN... IFa<=fTHEN... IFa>=gTHEN...
ArithmeticOperators All of the basic arithmetic operations are supported in Gambas. These
36
A Beginner's Guide to Gambas operators include addition, subtraction, multiplication, and division. The standard symbols for these operations are '+', '', '*', and '/'. For example, Number+Numberwilladdtwonumbers.Whenavalueorvariableispreceded byaminussign, 222, forexample,Gambascomputestheoppositesignofthat number.ThevalueZeroistheoppositeofitself.Now,wewillstarttowritesome Gambas code using the Gambas terminal application feature. The console window will display our output so lets use Gambas to experiment with the operatorsaswelearnaboutthem. Let'sStartCodingGambas Nowthatweknowaboutdatatypesandvariableassignments,letsgetour feetwetwithGambas. StartGambasandfromthe ProjectExplorer FileMenu selectNewProject.AsyougothroughtheNewProjectWizard,selectaTerminal ProjectandclickNext.NamethisprojectTerminalTestandplaceitinadirectory called TerminalTest. Don't worry about any of the other options. Just click Next>>untilthewizardcompletes.OncetheIDEappearswithyournewproject wewillneedtocreateastartupclassinordertorunourcode.FromtheProject ExplorerfindtheTreeViewitemcalledClassesandrightclickthemouse.Choose the New... option and take the default name Class1. The code window will appearandinsidethewindowitshouldlooksomethinglikethis:
'Gambasclassfile STATICPUBLICSUBMain() END
Let'stakealookatsomeGambaskeywordsyoushouldknowabitmoreabout beforeweproceed. END,RETURNandQUITStatements The END keyword indicatestheendofaprocedureorafunction. There aredifferencesfrom VB whenusing END. In VB,the End commandclosesall forms and files and terminates the program. In Gambas, the END command worksmorelike VB's EndFunction combinedwith VB's EndSub. Itclosesthe functionorsubroutine. Forsimilarfunctionalityto VB'sEnd command,usethe QUITcommand.Itendstheprogramimmediately.Allwindowsareclosed,and everythingisfreedupinmemoryascleanlyaspossible. InGambas,whenyou wishtoexitaroutine,youcanusetheRETURNcommand.Usually,RETURNis usedtoreturnavaluetothecallingprocedure.TheformatofRETURNis:
37
WhenGambasexecutestheRETURNcommand,itquitsaprocedureora functionandcompletesitsworkbyreturningthevalueofExpression.Now,enter thefollowing code after the ' Gambas class file line (note thatcomments in Gambasstartwiththe'[akathetickmark]) andbetweenthe STATICPUBLIC SUBMain()andENDstatements.Onceyouhaveenteredthecodebelowinthe Gambas code window, click the green button from the Project Explorer ToolBartoexecuteyourprogram.Hereisthecodeyouwanttotryfirst:
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=3 R=6 PRINT===>;N;"|";R;"and";N;"|";R; END
Ifallgoeswell(anditshould),youwillseetheblueshrimp(a.k.a.,theGambas mascot)danceandtheconsolewindowwillrespondwiththefollowing:
===>3|6and6|3
Theconsolewillrespondwiththefollowing:
==>3
38
A Beginner's Guide to Gambas To multiply numbers, we use the format of Number * Number and Gambaswillmultiplythetwonumbers.Hereisanotherconsoleexampletotry:
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=8 R=5 PRINT"===>";N*R; END
Theconsolewillrespondwiththefollowing:
==>40
Divisionisnodifferentthanmultiplication. Usetheformatof Number/ NumbertohaveGambasdividetwonumbers.Adivisionbyzeroerrorwilloccur if the value of the number to the right of the slash is zero. Try this console example:
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=9 R=3 PRINT"===>";N/R; END
Theconsolewillrespondwiththefollowing:
==>3
Nowtryusingthe\todivideinsteadofthe/character:
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=9 R=5 PRINT"===>";N\R; END
Theconsolewillrespondwiththequotient:
==>1
39
A Beginner's Guide to Gambas If you use a backslash to divide numbers, i.e., Number \ Number Gambas computesthequotientofthetwonumbers.Adivisionbyzeroerrorwilloccurif the value of the number to the right of the backslash is zero. A \ B is the equivalent of INT(A/B). To get the remainder, we can use the builtin MOD functionlikethis:
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=9 R=5 PRINT"===>";N\R;"andtheremainderis:";9MOD5; END
Theconsolerespondswith:
===>1andtheremainderis:4
Gambaswillrespondwiththefollowing:
Figure14ADivisionbyZeroErrorDialog.
NOTE:ClicktheStopbuttonwhenyouseethisdialogappear.
40
Theconsolewillrespondwiththefollowing:
==>8
Gambas also has the ability to support logical arithmetic operations12. Using the format of Number AND Number instructs Gambas to use the AND operator tocomputethemathematical AND ofthebinaryvaluesofbothofthe numbers.Trythis:
STATICPUBLICSUBMain()
DIMNASInteger DIMRASInteger N=0 R=0 PRINT"=>";NANDR;"istheANDresultof";N;"and";R R=1 PRINT"=>";NANDR;"istheANDresultof";N;"and";R N=1 PRINT"=>";NANDR;"istheANDresultof";N;"and";R END
Theconsolewindowrespondswith:
=>0istheANDresultof0and0 =>0istheANDresultof0and1 =>1istheANDresultof1and1
Likewise, Number OR Number used the OR operator and computes the mathematicalORofthebinaryvalueofthetwonumbers.
12 In Gambas2, it will allow the use of concatenated operators. For example, a += 2 or B /= 4 will work just as if you were programming in C or C++. 41
Theconsolewindowrespondswith:
=>0istheORresultof0OR0 =>1istheORresultof0OR1 =>1istheORresultof1OR1
Number XOR Number uses the XOR operator and computes the mathematicalexclusiveORofthebinaryvalueofthetwonumbers.
STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=0 R=0 PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R R=1 PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R N=1 PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R END
Theconsolewindowrespondswith:
=>0istheXORresultof0XOR0 =>1istheXORresultof0XOR1 =>0istheXORresultof1XOR1
Additionally,thefollowingoperatorsmanipulateoneormorenumericvaluesand returnanumericvalue:
DEC|INC|LIKE|NOT
42
Theconsolewillrespondwiththefollowing:
==>4|6
LIKE isusedtoperformaBooleancomparisonofastring. Ittakesthe format of String LIKE Pattern and it returns TRUE if the String matches the Pattern.Thepatterncancontainthefollowingpatternmatchingcharacters: * ? [abc] [xy] [^xy] MatchNnumberofanytypeofcharacter. Matchanysinglecharacter. Matchanycharacterspecifiedbetweenthebracketsymbols. Matchanycharacterthatexistsintheintervalxy. Matchanycharacterthatdoesnotexistintheintervalxy.
Theconsolerespondswith:
TRUE
Theconsolerespondswith:
TRUE TRUE FALSE FALSE
Note:youmustuseadoublebackslashcharacter,\\toprintabackslashorspecial stringsequencecontainingbackslashes. Otherwisethe\willbeinterpretedbythe compilerasaspecialcharacterlike'\n','\t','\*',etc.Alternatively,youcanusethis patternstring:LIKE"G[Aa][*]" TheNOToperatorisusedtoreturnaresultofanexpression.Theformatis asfollows: Result=NOTExpression WhenGambasevaluatesthisexpression,itcomputesthelogicalNOTofthe expression.Iftheexpressionisastringoranobject,GambasreturnsTRUEifthe expressionisNULL.Herearesomeexamplestotryonyourconsole:
STATICPUBLICSUBMain() PRINTNOTTRUE PRINTNOTFALSE PRINTNOT11 PRINTNOT"Gambas" PRINTNOT"" END
Theconsolerespondswith:
False True 12 False True
StringOperators InGambas,whenyouwanttocompareorconcatenatestrings,youcanuse
44
A Beginner's Guide to Gambas thestringoperators. Theseoperatorsallowyoutoconcatenatestringsandfile paths,performLIKEoperationsasexplainedabove,determineifstringsareequal ornotequal,lessthan,greaterthan,lessthanorequalto,orgreaterthanorequal to each other. The following table of string operations is shown for your convenience:
Resulttodetermine
Concatenatetwostrings. Concatenatetwostringsthatcontainfilenames.Addapathseparatorbetween thetwostringsifnecessary. PerformpatternmatchingusingtheLIKEoperator. Determineifthetwostringsareequal. Determineifthetwostringsdifferent. Determineifthefirststringislowerthanthesecondstring Determineifthefirststringisgreaterthanthesecondstring Determineifthefirststringislowerorequaltothesecondstring Determineifthefirststringisgreaterorequaltothesecondstring
Note:allstringoperatorcomparisonsarecasesensitive. HerearesomethingstotryusingGambasconsole:
STATICPUBLICSUBMain() DIMaASString DIMbASString a="ham" b="burger" PRINT"===>";A&B; a="Gambas" b=1 PRINT"===>";A&"isnumber"&B; END
Theconsolerespondswith:
===>hamburger ===>Gambasisnumber1
45
Thebestwaytounderstandwhatthesekeywordsandconditionalsmeanis tograduallyintroducethemwithexamples. Ratherthangothroughthelistof keywordsinalphabeticalorder,let'staketheapproachofintroducingthembased on the type of functionality they support. We will start with the most basic statementsandcommandsandprogressthroughthemorecomplexonesaswe continue.Let'sstartwiththeGambasPRINTstatement. ThePRINTStatement The PRINT statement prints expressions to the standard output. The expressionsareconvertedtostringsbytheStr()function.PRINTtakestheformat of:
PRINTExpression[(;|,)Expression...][(;|,)]
Theconsoledisplaysthefollowingoutput:
===>bis:1 ===>bis:1 ===>bis:1
HereisanexampleusingIFthatyoucantryontheconsole:
STATICPUBLICSUBMain() DIMbASInteger b=1
47
Theconsolerespondswith:
===>Gambasisnumber1
TheSELECT/CASEStatement TheSELECTstatementevaluatesanexpression,comparingittoeachCASE specified,andwillexecutethecodeenclosedinthematchingCASEstatementif theexpressionevaluatedisTRUE.IfnoCASEstatementmatchestheexpression under evaluation, the DEFAULT or CASE ELSE statement is executed. The SELECT/CASEstatement allowsaprogrammertobuildacodeblockcapableof evaluatingmanyexpressionresultswithouthavingtocodeanexcessiveamount ofIF/ELSEIF/ELSEstatements.TheformatoftheSELECTstatementis:
SELECTExpression [CASEExpression[,Expression...] [CASEExpression[,Expression...] [CASEELSE|DEFAULT...] ENDSELECT
HereissomecodetoshowyouhowtousetheSELECTstatement:
STATICPUBLICSUBMain() DIMwASInteger w=1 'START:isaLABEL,usedwithGOTOexplainedbelow. START: PRINT"Thevalueofwis:"&w SELECTCASEw CASE1 INCw GOTOSTART CASE2
48
Theconsoleshouldrespondwiththefollowingoutput:
Thevalueofwis:1 Thevalueofwis:2 Thevalueofwis:3 Thevalueofwis:4 Thevariablewhasnohandlerfor:4 FinalvalueofwIS:4
Becausethevariablewwasincrementedtothevalueof4andtherewasto CASE tohandlethatvalue,the CASEELSE block isexecuted. CASEELSEcan alsobewrittenasCASEDEFAULT.Eitherway,itiswherecodedefaultstowhen nocasesatisfiesthevalueofthevariablebeingchecked. GOTOandLABELS Notetheuseofthe LABEL named START: inthepreviouscodeexample. Thecolonmustbeusedwiththelabelnameanditmustfollowitwithoutany spacesbetweenthelabelandthecolon. Labelsarethetargetswherea GOTO instructionwilldirectprogramflow.WhiletheuseofGOTOshouldbejudicious itissometimesnecessary.Itisusedintheaboveexampletodemonstratehowto useGOTOandLABELS.Later,whenwestudyloopingstructures,wewillrewrite thiscodetouseaGambasloopingmechanism. TheFOR/NEXTStatement Many times when writing code, programmers find the need to iterate throughasetofvalues(calledlooping)toprocessdata.TheFORstatementisa loopingstatementcommonlyusedinprograms.Ittakesthegeneralformof:
FORVariable=ExpressionTOExpression[STEPExpression]...NEXT
49
A Beginner's Guide to Gambas The FOR statement repeats a loop while at each iteration of the loop incrementingavariable.Notethatthevariablemustbeanumericdatatype(i.e., abyte,ashort,anintegerorafloatingpointnumber)anditmustbedeclaredas alocalvariable.Iftheinitialexpressionthe FORstatement evaluatesishigher thantheTOexpression(forpositiveSTEPvalues)oriftheinitialexpressionisless thantheTOExpression(fornegativeSTEPvalues)theloopwillnotbeexecuted atall.TheSTEPkeywordallowstheprogrammertodefinethesizeoftheinterval incrementedbetweenloopiterations.Hereisanexample:
STATICPUBLICSUBMain() DIMIASInteger DIMJASInteger J=1 FORI=1TO21STEP3 PRINT"LOOPiteration:"&J&",Iisequalto:"&I INCJ NEXT PRINT"JIS:"&J&"andIis:"&I END
Thiscoderesultsinthefollowingoutput:
LOOPiteration:1,Iisequalto:1 LOOPiteration:2,Iisequalto:4 LOOPiteration:3,Iisequalto:7 LOOPiteration:4,Iisequalto:10 LOOPiteration:5,Iisequalto:13 LOOPiteration:6,Iisequalto:16 LOOPiteration:7,Iisequalto:19 JIS:8andIis:22
Gambasalsoprovidesa FOREACH loopingstructurethatallowsyouto iteratethroughthevaluesofacollection,array,enumerableclasses,etc.,without theneedtomaintainanintegercounter.WewillfullycoverthedetailsofFOR EACH when we discuss collections later in this book. At this point in your introductiontoGambas,youareencouragedtoplayaroundwiththecodeinthe
50
A Beginner's Guide to Gambas examplesandchangevariablevalues,practiceusingthe PRINTstatement,etc. Get to know the console and you will quickly learn it is a great tool to test expressions,codesegments,etc. DonotbeafraidtoexperimentwithGambas! Theveryworstthingthatcanhappenisyourprogramblowsupandyouhaveto restart your computer unlikely, but indeed possible. Play around and get comfortablewithGambas.Itisthebestwaytolearn. DO[WHILE]LOOP The DO[WHILE]LOOPstructurebeginsexecutionofaloopthatwillnot enduntilaconditionismetorcodewithintheloopstructureforcesanexit.The codeexecutedintheloopisdelimitedbythekeywords DO and LOOP. Ifthe optionalkeyword WHILE isnotspecified, theloopwould executeforever (an infiniteloop)oruntilsomeconditionwithintheloopstructureforcedanexit.If theoptionalkeywordWHILEisspecified,theloopisstoppedoncetheevaluated resultoftheexpressionbecomesFALSE.Inotherwords,whiletheresultsofthis expressionareTRUE,continuetoiterate(do)theloop.IftheexpressionisFALSE whentheloopisstarted,theloopwillnotbeexecutedatall.Hereistheformat oftheDOLOOP:
DO[WHILEExpression] ... LOOP
Thefollowingcodeexampleshouldhelpyoubetterunderstandhowtousethe DO...WHILELOOP:
STATICPUBLICSUBMain() DIMaASInteger a=1 DOWHILEa<=5 IFa=1THEN PRINT"HelloWorld,looping"&a&"time." ELSE PRINT"HelloWorld,looping"&a&"times." ENDIF INCa LOOP DECa PRINT PRINT"GoodbyeWorld,Iloopedatotalof:"&a&"times." END
51
WHILE[Expression]WENDLoops This loop structure begins a loop delimited by the WHILE ... WEND instructions.TheloopisrepeatedwhileExpressionisTRUE.If,oninitialentry,the expression is FALSE, the loop is never executed. The DO WHILE LOOP and WHILE...WENDstructuresareequivalent.Trythiscode:
STATICPUBLICSUBMain() DIMaASInteger a=1 WHILEa<=5 IFa=1THEN PRINT"HelloWorld,WHILE...WENDlooping"&a&"time." ELSE PRINT"HelloWorld,WHILE...WENDlooping"&a&"times." ENDIF INCa WEND DECa PRINT PRINT"Goodbye,WHILE...WENDloopedatotalof:"&a&"times." END
Theconsoleshouldprintthefollowing:
HelloWorld,WHILE...WENDlooping1time. HelloWorld,WHILE...WENDlooping2times. HelloWorld,WHILE...WENDlooping3times. HelloWorld,WHILE...WENDlooping4times. HelloWorld,WHILE...WENDlooping5times. Goodbye,WHILE...WENDloopedatotalof:5times.
52
A Beginner's Guide to Gambas TheREPEATUNTILloop This loop structure begins to execute code that is delimited by the keywords REPEATandUNTIL.Arepeatloopwillalwaysexecuteatleastonce, eveniftheUNTILvalueisinitiallyFALSE.Hereisasampletotryontheconsole:
STATICPUBLICSUBMain() DIMaASInteger a=1 REPEAT IFa=1THEN PRINT"HelloWorld,REPEATUNTILlooping"&a&"time." ELSE PRINT"HelloWorld,REPEATUNTILlooping"&a&"times." ENDIF INCa UNTILa>5 DECa PRINT PRINT"Goodbye,REPEATUNTILloopedatotalof:"&a&"times." END
Theconsoleshouldprintthefollowing:
HelloWorld,REPEATUNTILlooping1time. HelloWorld,REPEATUNTILlooping2times. HelloWorld,REPEATUNTILlooping3times. HelloWorld,REPEATUNTILlooping4times. HelloWorld,REPEATUNTILlooping5times. Goodbye,REPEATUNTILloopedatotalof:5times.
DefiningandUsingArraysinGambas
TherearetwokindsofarraysthatcanbeusedinGambas.Thefirsttypeof Gambasarrayworkslikearraysusedinthe Java programminglanguage. The othertypeofarraythatisusedinGambasisknownasa Nativearray. When using Javalike arrays, you must remember that the arrays are objects of the followingclasses:Integer[],String[],Object[],Date[],andVariant[].Allofthese typesof Javalike arrayscanhaveonlyonedimension. Youdeclarethemlike this:
DIMMyArrayASNEWInteger[]
53
A Beginner's Guide to Gambas Arraysarealwaysinitializedasvoidatstartup. Theyaredynamic,and havealotofusefulmethodsapplyingtothem. Whenusingsingledimension arrays,thesearetherightchoice. Nativearrays ontheotherhandcansupport multidimensionalimplementationsorarrayswitharraysobjectsofthefollowing classes:Integer,String,Object,Date,andVariant.Theyaredeclaredlikethis:
DIMMyArray[Dim1,Dim2,...]ASInteger DIMMyArray[Dim1,Dim2,...]ASString DIMMyArray[Dim1,Dim2,...]ASVariant
Nativearrayscanhaveuptoeightdimensions. TheyareNOTobjects. Theyareallocatedonthestackifyoudeclarethemlocaltoafunction.Theyare allocatedinsidetheobjectdataifyoudeclarethemasglobalinscope. Native arraysareNOTdynamic.Theycan'tgroworshrinkoncetheyaredeclared.You canonlyonlysetorgetdatafromanelementinthesetypesofarrays.Hereisan exampleofusingathreedimensionalnativearrayinGambas. Inthisexample, thearrayisfilledwithintegervaluesrangingfrom0to26. Enterthiscodein yourconsolecodewindow:
STATICPUBLICSUBMain() DIMiASInteger DIMiiASInteger DIMiiiASInteger DIMnarMatrix[3,3,3]ASInteger FORi=0TO2 FORii=0TO2 FORiii=0TO2 PRINTi,ii,iii&"==>"; narMatrix[i,ii,iii]=i*9+ii*3+iii PRINTnarMatrix[i,ii,iii] NEXT NEXT NEXT END
Whenyouexecutethiscode,youroutputintheconsolewindowshouldbesimilar towhatisshownhere:
000==>0 001==>1 ... 221==>25 222==>26
54
Collections
Collections are groups of objects implemented with a hash table. Collectionobjectsusekeysthatareimplementedas stringdatatypes. Thedata valuescorrespondingtoanycollectionkeyisa Variantdatatype. Objectsina collectionareenumerable.NULLisusedwhennothingisassociatedwithagiven key.Consequently,associatingNULLwithakeyhasthesameeffectasremoving itfromthecollection. Thesizeoftheinternalhashtablegrowsdynamicallyas dataisinserted.Thisclassiscreatedusingthisgeneralformat:
DIMhCollectionASCollection hCollection=NEWCollection([ModeASInteger])
NotethewordEACHaftertheFORstatement.TheFOREACHconstructis discussednext.Also,wewillgointomuchgreaterdetailaboutcollectionslaterin thisbookwhenwetalkaboutobjectorientedprogramming.Wewilldevelopan application that makes extensive use of collections. For now, just note that collectionelementsareenumeratedintheorderinwhichtheywereinsertedinto thecollection.However,ifyoureplacethevalueofanalreadyinsertedkey,the originalinsertionorderiskept. TheFOREACHStatement The FOR EACH statement executes a loop while simultaneously enumeratinganobject. The Expression mustbeareferencetoanenumerable object such as a collection or an array. The order of enumeration in not necessarilypredictable.Thegeneralformatofthestatementis:
FOREACHExpression...NEXT FOREACHVariableINExpression...NEXT
ThissyntaxmustbeusedwhenExpressionisanenumerableobjectthatis not a container. For example, an object returned as the result of a database query.Thestatementsabovecreateanewcollectionobject.Enterthefollowing codeintoyourconsolecodewindowandrunit.
STATICPUBLICSUBMain() DIMMyDictASNEWCollection DIMstrElementASString MyDict["absolute"]=3
55
Yourconsoleshoulddisplaythisoutput:
312
56
Button Label TextLabel TextBox TextArea CheckBox ComboBox ListBox RadioButton ToggleButton Frame Panel TabStrip ProgressBar Image Timer Dial SpinBox ScrollBar Slider LCDNumber ListView TreeView IconView GridView ColumnView ScrollView DrawingArea GambasEditor TableView Workspace
Asyoucansee,thereisawideselectionoftoolsforyoutoplaywithin
57
A Beginner's Guide to Gambas Gambas.Ourintroductiontothetools(whicharealsocalledcontrols)willteach youaboutwhateachcontroldoes,whatproperties,methods,andeventsyoucan usetodirectthebehavioroftheinterfaceyouarebuilding,andhowtocodethe controltomakeitworkexactlyasyoudesire.Alongtheway,wewillbebuilding severalsimpleprojectstogetyoumoreexperiencedinusingtheGambasIDE.All of the controls in the ToolBox are builtin using the gb.qt component. This componentimplementstheGraphicalUserInterfaceclasses.ItisbasedontheQT library.Hereisalistofthevariousfunctionalitythegb.qtcomponentprovides:
Clipboard Containers DragandDrop Drawing Fonts IconView KeyboardandMouse Menus ListView,TreeViewandColumnView Printing
Wewillcoverothercomponentslaterinthisbook.AtthetopofFigure15, you see the word Form displayed. This is the default toolkit for the gb.qt component.Fornow,let'stakeaquicklookattheToolBoxagainandreviewthe iconstherein.
Figure15TheGambasToolBox.
58
Onthesecondrowyouwillfind:
Onthethirdrowwehave:
Thefourthrowofcontrolsdisplay:
Figure16AdditionalcontrolsforQT.
TheQTSpecificControlsfoundonthetoprowofFigure2are:
Thesecondrowofcontrolsincludethesetools:
TheButtonControl
ThisclassobjectinheritsitsattributesfromtheControlclass,asdoallthe controlsintheGambasToolBox.Usingthiscontrolimplementsapushbuttonon aform.Apushbuttoncandisplaytext,apicture,orboth.Youhavetheabilityto setonebuttoninsideawindowtobethe Defaultbutton.Then,whentheuser pressestheRETURNkey,itwillactivatethatbuttonautomatically.Also,youcan setonebuttoninsideawindowtobetheCancelbutton.PressingtheESCkey willactivatetheCancelbuttonautomatically. Thisclass iscreatable,meaning thatyoucanwritecodetodynamicallygenerateabuttononaformatruntime. Todeclareabuttonobject,theformatbelowisused:
DIMhButtonASButton hButton=NEWButton(ParentASContainer)
TheContainer,inmostcases,willbetheformwhereyouplacethebutton. Itcould beany container object, however. This code will create a new push buttoncontrol. Notethevariablenameisprecededbythelowercaseletter h. Thisisastandardconventionprogrammersusetorefertothehandle(handlesare really references to something) of an object. Since Gambas supports object orientedprogramming,wewillgraduallyintroduceOO(ObjectOriented)concepts to you as we encounter them. OO will be covered in much greater detail in Chapter11ofthisbook.Generally,objectsarecreatedfromaclassbyassigninga copyoftheobjecttoavariable,inthiscase hButton. Thisprocess,knownas instantiating anobjectoccurswhenhButtonisassignedavalueusingtheNEW
61
A Beginner's Guide to Gambas keyword. WhatthelinebelowmeansishButtonwillbeinstantiatedasaNEW Button object and Parent is the property (read only) that will read a method (thinkofmethodsasfunctionsthatsetorgetavalue)thatisimplementedinside theContainerclass.TheContainerclassisusedbecauseitistheparentclassof everycontrolthatcancontainothercontrols.Now,thislineofcodeshouldmake perfectsensetoyou:
hButton=NEWButton(ParentASContainer)
Notetheformatofthestatementabove.Control.Property=Expressionis thestandardconventionusedforsettingorgettingattributeinformationfroma control.Manyofthepropertiesforcontrolsarecommonamongallcontrols,so wewilltakethetimenowtoexplainallofthebuttonpropertieshere.Laterinthe book,wewillonlyexplainthepropertiesthatareuniquetoagivencontrolwhen weencounterthem. BackColorisdefinedasPROPERTYBackColorASInteger Thisintegervaluerepresentsthecolorusedforthecontrolbackground.It is synonymous with the Background property. Note that PROPERTY is a predefined datatype used internally in Gambas. You can use the Gambas predefinedconstantsforcolortosetcommoncolorvalues:
Black DarkCyan DarkRed Green Pink White Blue Cyan DarkBlue DarkGray DarkGreen DarkMagenta DarkYellowDefault Gray LightGray Magenta Orange Red TransparentViolet Yellow
TosettheBackColorpropertyforhButtontored,youwouldusethiscode:
hButton.BackColor=Color.Red
62
A Beginner's Guide to Gambas Alternatively, if you know the RGB (red, green, blue) or HSV (hue, saturation,value)valuesforaspecificcolor,Gambasprovidesameanstoconvert thosevaluestoanintegervaluethatcanbepassedontotheBackColor(orother colorrelated)property.TheclassColorprovidestwomethods,RGBandHSVthat youcanuse.Hereishowthosefunctionsaredefined:
STATICFUNCTIONRGB(RASInteger,GASInteger,BASInteger[,AlphaAS Integer])ASInteger
The RGB function returns a color value from its red, green and blue components.FortheHSVfunction,usethis:
STATICFUNCTIONHSV(HueASInteger,SatASInteger,ValASInteger)ASInteger
HSVreturnsacolorvaluefromitshue,saturationandvaluecomponents.Touse one of these functions to set the button's background color, here is what you couldcode:
hButton.BackColor=Color.RGB(255,255,255)
Thiswouldsetthebutton'sbackgroundcolortowhite.Thisismostusefulwhen youaretryingtosetcolorswhosevaluesfalloutsidethedefaultcolorconstant valuesprovidedwithGambas. Border This property is another common attribute found on many controls.Thisclassisstatic.TheconstantsusedbytheBorderpropertyinclude thefollowing:Etched,None,Plain,Raised,andSunken.Tosettheborderproperty forourbutton,wecouldusethiscode:
hButton.Border=Border.Plain
63
A Beginner's Guide to Gambas Caption is defined as PROPERTY Caption AS String and the Caption propertyissynonymouswiththeTextproperty.Thefollowingcode
hButton.Caption=OK
isthesameas
hButton.Text=OK
Now, enter this code between the PUBLIC SUB Form_Open() and END statementssoitlookslikethis:
PUBLICSUBForm_Open() DIMhButtonASButton hButton=NEWButton(ME)AS"hButton" hButton.X=215 hButton.Y=60 hButton.Width=200 hButton.Height=40 hButton.Enabled=TRUE hButton.Text="ClickorpressESCtoQuit" hButton.Border=TRUE hButton.Default=TRUE hButton.Cancel=TRUE hButton.Show END
AfterthePUBLICSUBForm_Open()'sENDstatement,addthisroutine:
PUBLICSUBhButton_Click() MainForm.Close END
64
Figure17FirstButtoncoderesults.
Simply click the button or press the ESC key to exit this program. Congratulations!YouhavejustcreatedyourfirstGUIbasedprograminGambas! Yes, it is a little bit ugly but remember, you did it the hard way, using code instead of taking advantage of the Gambas ToolBox. Remember, a good programmerwillalwaystryusepredefinedconstantsiftheyareavailableinstead ofhardcodingnumericvalues. Forexample,keycodesandmousestyleshave thesamenamesastheyaredefinedasconstants,buttheirnumericvaluesare totallydifferent.Theanticpatedgb.gtkcomponentwillnotworkwithgb.qtcode ifyouarenotusingpredefinedconstantssowhenwritingcode,itisimperativeto use these constants instead of numeric values. If not, the code will not be portable.Goodcodeshouldneverusenumericvaluesforthesetasks.Now,save yourprojectandexitGambasfornowandwewillproceedwithlearningmore abouttheToolBox. CursorisdefinedasPROPERTYCursorASCursor andyoucanusethe Cursorpropertyforassigningacustomcursortoacontrol.Thisclassimplements acustommousecursor.Thisclassiscreatable. Hereishowtodeclareacursor objectvariableandinstantiateacursorobject:
DIMhCursorASCursor hCursor=NEWCursor(MyPicASPicture[,XASInteger,YASInteger])
Default is defined as PROPERTY Default AS Boolean and you use the Defaultpropertytoindicatewhetherornotthebuttonisactivatedwheneverthe RETURNkeyispressed.Usingthecodebelow,itwouldforcetheusertoactually clickabuttonratherthanhittheRETURNkeytoactivateit. Generally,when creatinganOK/Canceltypedialog,youwouldwanttosetoneofthebuttonstoa defaultactionusingthisproperty.ThinkaboutjusthittingtheRETURNkeyina wizardtoacceptthedefaultsettingsandmoveon.
hButton.Default=FALSE
DesignisdefinedasPROPERTYDesignASBooleananditindicatesthat thecontrolisindesignmode.ThismeansthatwhentheDesignpropertyissetto TRUE,controlsindesignmodejustdrawthemselvesandwillnotreacttoany inputevent. ThispropertyisusedbytheGambasDevelopmentEnvironment to displaycontrolsintheformeditor.Whatthisreallymeansisyoudonotneedto worryaboutthisproperty. Drop isdefinedas PROPERTYDropASBooleanandisusedtocheckto see if a control accept the drop from a drag and drop operation. The Drop property iseitherTRUEorFALSEandyoucancheckthevaluebeforetryingto dropsomethingontothecontrolbyusingcodelikethis:
IFhButton.Drop=FALSETHEN hButton.ToolTip="NoDropsallowed" ELSE hButton.ToolTip="Dropsomethinghere" ENDIF
A Beginner's Guide to Gambas The Expand property isdefinedas PROPERTYExpandASBoolean and anditindicatesthatthecontrolisabletoexpandifitisincludedinacontainer thatdynamicallyrearrangesitscontents. FontisdefinedasPROPERTYFontASFontanditreturnsorsetsthefont usedtodrawtextinthecontrol. Toset Fontproperty attributes,codelikethis canbeused:
hButton.Font.Name="Lucida" hButton.Font.Bold=TRUE hButton.Font.Italic=FALSE hButton.Font.Size="10" hButton.Font.StrikeOut=FALSE hButton.Font.Underline=FALSE
Theoutputoftheabovecodewouldbeasfollows:
Figure18Demonstratingfontcapabilities.
TosettheForeColorpropertyforhButtontored,youwouldusethiscode:
hButton.ForeColor=Color.Red
AswiththeBackColorproperty,ifyouknowtheRGBorHSVvaluesfora specificcolor,youcanpassthemtotheForeColorpropertywiththiscode:
hButton.ForeColor=Color.RGB(255,255,255)
67
A Beginner's Guide to Gambas Thiswouldsetthebutton'sforegroundcolortowhite. TheXpropertyisdefinedasPROPERTYXASIntegeranditisusedtoset orreturnthexpositionofthecontrol. X isthesameas Leftproperty. The Y propertyisdefinedasPROPERTYYASIntegeranditisusedtosetorreturnthey positionofthecontrol(topleftcorner). TheHeightpropertyisdefinedasPROPERTYHeightASIntegeranditis used to set or returnthe height of the control. Itissynonymous withthe H property and can be used interchangeably. This value describes how tall the controlisfromthexpositionmovingdownHeightpixels.TheWidthpropertyis definedasPROPERTYWidthASIntegeranditisusedtosetorreturnthewidth of the control. It is synonymous with the W property and can be used interchangeably.Thisvaluedescribeshowwidethecontrolisfromthexposition totherightWidthpixels. The Handle property isdefinedas PROPERTYREADHandleASInteger andisusedtoreturntheinternalX11windowhandleofthecontrol.Itisaread onlyattribute.ItissynonymouswiththeId(PROPERTYREADIdASInteger). The Mouse property isdefinedas PROPERTYMouseASInteger andis usedtosetorreturntheappearanceofthecursortoapredefinedimagewhenit hoversinsidetheboundariesofthecontrol. Predefined valuesforthe Mouse propertyareshowninthetablebelow:
CursorShape Default Arrow Cross Wait Text SizeS SizeE SizeNESW SizeNWSE SizeAll Blank SplitV SplitH Pointing Value 1 0 2 3 4 5 6 7 8 9 10 11 12 13
68
A Beginner's Guide to Gambas TheNextpropertyisdefinedasPROPERTYREADNextASControlandit isusedtoreturnthenextcontrolhavingthesameparentwithinaContainer.Itis usefulwheniteratingthroughaseriesofcontrolstosetfocus.Wewilldiscussthis property in more detail when we discuss the SetFocus() method. To get the previouscontrol,onewouldusethe Previous property,defined as PROPERTY READPreviousASControl. Thispropertyreturnsthepreviouscontrolhaving thesameparent. The Parent property isdefinedas PROPERTYREADParentASControl and is used to return the container that holds the control. It is a readonly property. The Picture property is defined as PROPERTY Picture AS Picture and returnsorsetsthepictureshownonacontrol(i.e.,abutton).Wewilldiscussthe Pictureclasslaterinthischapter. TheScreenXpropertyisdefinedasPROPERTYREADScreenXASInteger anditreturnsthepositionoftheleftborderofthecontrolinscreencoordinates. Usually,itisusedinconjunctionwithScreenY. TheScreenYpropertyisdefinedasPROPERTYREADScreenXASInteger andreturnsthepositionofthetopborderofthecontrolinscreencoordinates. TheTagpropertyisdefinedasPROPERTYTagASVariantandisusedto return or sets the control tag. This property is intended for use by the programmer and is never used by the component. It can contain any Variant value. TheTextpropertyisdefinedasPROPERTYTextASStringandreturnsor setsthetextdisplayedinthebutton.Itisalmostalwaysusedandit'svaluecan be changed dynamically. We have already used this property in the example above:
hButton.Text="ClickorpressESCtoQuit"
The ToolTip property is defined as PROPERTY ToolTip AS String and returnsorsetsthetooltip(atooltipisthelittleboxoftextthatpopsupovera controlwhenthemousehoversoveritforafewseconds).
hButton.ToolTip="Clickme!"
69
A Beginner's Guide to Gambas TheToppropertyisdefinedasPROPERTYTopASIntegerandreturnsor setsthepositionofthetopborderofthecontrolrelativetoitsparent. TheValue property isdefinedas PROPERTYValueASBoolean anditis usedtoactivatethecontrol(i.e.,makethebuttonclick).Thisisdoneifyouset thispropertytoTRUE.ReadingthispropertywillalwaysreturnavalueofFALSE. The Visible property isdefinedas PROPERTYVisibleASBoolean andit indicatesifthecontrolisvisibleornot.SettingthispropertytoFALSEwillmake itdisappearfromview.Conversely,settingittoTRUEmakesitappear. The Window property is defined as PROPERTY READ Window AS Windowandreturnsthetoplevelwindowthatcontainsthecontrol. Atthispoint,wehavecoveredallofthepropertiesfortheButtonControl andyoushouldhaveaprettygoodunderstandingofwhattheyareusedforand howtousethem.Rememberthatmostofthesepropertiesarecommontomany controls. Next,wewillcoverthemethods(thingsyoucandowiththebutton) andprovideyousomeexamplesofhowtousethem. ButtonMethods Methodsarethebuiltinroutinesprovidedforacontrolthatallowyouto dothingslikeshowit,hideit,moveit,etc.Herearethemethodssupportedby theButtoncontrol:Delete,Drag,Grab,Hide,Lower,Move,Raise,Refresh,Resize, SetFocus,andShow.Usually,amethodiscalledinresponsetosomeevent.We willdiscusseventsinthenextsection.Let'stakealookatthemethodsusedwith Button: The Delete method is defined as SUB Delete() and when invoked it destroysthecontrol.Itisimportanttoknowthatadestroyedcontrolbecomesan invalidobject. Whatthismeansisthatonceyouhavedestroyedit,ensureno othercodesubsequentlyreferencesit. The Drag method isdefinedas SUBDrag(DataASVariant[,Format ASString])andwheninvokeditstartsadrag&dropprocess.Dataisthedata tobedragged.ItcanbeaStringoranImage.IfDataisatextstring,thenyou canspecifyin Format the MIMETYPE ofthetextbeingdragged.Forexample, MIMETYPEtext/html.
70
A Beginner's Guide to Gambas The Grab method isdefinedas FUNCTIONGrab()ASPicture and it grabsapictureofthecontrolandreturnsit. The Hide method andthe Show method aredefinedas SUBHide() and SUBShow()andtheysimplyhideorshowthecontrol.Hereishowtheywould beused:
IFExpression=TRUETHEN hButton.Hide ELSE hButton.Show ENDIF
The Lower method and Raise method aredefinedas SUBLower() and SUBRaise(). Lowersendsthecontroltothebackgroundofitsparent. Raise bringsthecontroltotheforegroundofitsparent. Asanexampleofhowthese methodswork,let'sgobacktoourproject,FirstProject.Changethecodeinthe hButton_Click()routinetoreadasfollows:
PUBLICSUBhButton_Click() Button1.Hide Label1.Text="Ouch!" WAIT2.0 Button1.Show Label1.Text="Betternow!" END
Onceyouhaveenteredthecode,runtheprogramandseewhathappens. WhenyouclickthebuttonitwilldisappearandLabel1.Textwillchange. After twoseconds, it will reappearand change the label again. Also, notethatwe slippedinanewcommandforyoutotry WAIT. WAITtakesafloatingpoint valueasaparameterthatrepresentssecondsorfractionsofsecondsexpressedas decimalvalues. Numberslessthan1areprocessedasmilliseconds. WAIT1.5 wouldpauseexecutionfor1,500 milliseconds. IfyouspecifyWAITwithouta parameter,itwillrefreshtheinterfaceanditdoesnotallowtheusertointeract withtheapplication. TheMovemethodisdefinedasSUBMove(XASInteger,YASInteger[, WidthASInteger,HeightASInteger])andisusedtomoveand/orresizethe control.
hButton.Move(hButton.X50,hButton.Y20)
71
A Beginner's Guide to Gambas The Refresh method isdefinedas SUBRefresh([XASInteger,YAS Integer,WidthASInteger,HeightASInteger]) and isused toredrawthe control,orinsomeinstances,justaportionofit. TheResizemethodisdefinedasSUBResize(WidthASInteger,Height ASInteger)andisusedtoresizethecontrol. The SetFocus method isdefined as SUBSetFocus( ) and youcallthis methodtogivefocustothecontrol.Focusisroughlyequatedtowherethetext cursorwouldbelocated.Whenacontrolhasfocusitisusuallyindicatedvisually insomemanner.Forexample,abuttonwithfocusmayhaveasmalldottedline aroundittoindicatewherefocuscontrolisontheform:
Figure19Thedottedlineindicates focusforacontrol.
WehavecoveredallofthemethodsavailablefortheButtonclass(control) andwillnowbegindiscussingtheeventsforthatclass.Asachangeofpace,let's trytolearnabouteventswithamorehandsonapproach. Wecandothisby buildinganewprogramandlearningwhattheeventsdoandhowtousethem. CloseGambas(asmallquirkofGambasisthelackofacloseprojectmenuselection) andrestartittoinitiatetheNewProjectWizard.Selectagraphicaluserinterface projectandgothroughthewizardjustlikewedidwiththeprojectFirstProject. NamethisprojectSecondProject. OncetheIDEappears,createanewstartup classformandnameitForm1.Forthisproject,wearegoingtoplacethreeLabel controlsontheform,asshowninFigure20below.
Figure20ThelayoutforSecondProjectForm1.form.
72
A Beginner's Guide to Gambas The first label's text caption is set with the Label.Text property. The setting shouldbeHereistheandthesecondisGambasMascotandthethirdis > which points to a PictureBox control (where the shrimp lives). Name the labelsLabel1,Label2andLabel3respectively.Next,namethePictureBoxcontrol PictureBox1. ToobtainthegraphicoftheGambasmascot,youcangototheofficial Gambaswebsite13andrightclickonthemascot.Choosetosavetheimageand samveitasgambasmascot.pngonyourcomputer. Movethefiletothedata directory in the SecondProject folder. (Another Gambas quirk is that the file explorerdialogsdon'tseemtobedynamic.Oncetheyhaveinitialized,changesmade outside theGambasenvironment arenotupdateddynamically.) Once you have done this, you can set the Picture property for PictureBox1 to the file named gambasmascot.png.Atthispoint,thetopofyourformshouldlooklikethis:
Figure21Apartiallyconstructedformwithourfirstfourcontrols.
Now,selecttheProgressBarcontrolfromtheToolBoxandplaceitonthe form so it looks like that shown in Figure 20 above. Finally, we have three buttonstoaddtotheform.NamethesebuttonsFunBtn,NoFunBtn,andQuitBtn. Allofthenecessarycontrolsforourexamplehavebeenaddedtotheformatthis point. TrytogetthelayouttolookasclosetothepictureshowninFigure3 aboveaspossible. Atthispoint,youmaybeaskingwhatallofthisisgoingto accomplish? Remember, we are going to learn how to use events with these controls. Wehaveplacedthecontrolswherewewantthemandnowthenext stepistodecidewhateventswearegoingtohandle. Forthisexercise,wearegoingtohandlemouseeventswhenthemouse movesoverlabels.Ifthemousemovesoffofthemainwindow(Form1.form)or backontoitwewillhandlethoseevents.Wewillalsohandlebuttonclicksand theESCkeyifitispressed. Let's beginby settingtheProgressBar1.Valuetozerowhentheprogram starts. Thatishandledwiththeinitializationroutinewhenopeningtheformat programruntime,asshownbelow:
13 TheofficialGambassiteishttp://gambas.sourceforge.net/index.html. 73
Whenthemousemovesoverthestartupform(ourGambasprogramonthe desktop),wewanttosetthethreetoplabel'stextpropertiestoblankvaluessoit appearsthatthetextdisappears. Thisrequireschoosingan eventhandler. To chooseaneventfromtheGambasIDE,movethemouseovertheform(butnot directlyoveracontrol)andclickitonce. Next,rightclickthemouseandyou shouldseeamenupopup,similartotheoneshowninFigure22below.Choose theEventselectionitemfromthepopupandpicktheEnterevent.Addthiscode, asshownbelow:
PUBLICSUBForm_Enter() Label1.Text="" Label2.Text="" Label3.Text="" END
Figure22Eventmenu.
74
Thenextthingwewanttodoishandlethesituation(event)thatoccurs whenthemousemovesoveranyofourlabels. Inthisevent,wearegoingto changetheLabel.Textpropertyoftheaffectedlabeltoindicatethatamousehas beendetectedoverthecontrol.Singleclickyourmousecursoronthefirstlabel and whenthehandlesappear,rightclick and choose the Enter eventwhen it appearsontheEventsubmenu. Inthecodewindow,findthe Label1_Enter() subroutineandenterthiscode:
PUBLICSUBLabel1_Enter() Label1.Text="Here'sthe" END
Repeattheprocess,choosingtheLeaveeventandensureyourcodeistypedinthe codeeditorasfollows:
PUBLICSUBPictureBox1_Leave()
75
Figure23AddingtheFunBtntoourform.
Now,doubleclickontheNoFunBtnandaddthis:
PUBLICSUBNoFunBtn_Click() ProgressBar1.Value=ProgressBar1.Value0.01 IFProgressBar1.Value<0.01THEN ProgressBar1.Value=0.0 ENDIF END
76
Figure24Whatourformlookslikewhenamouseisdetected overtheform.Notethetextisblankedout.
Now, click the Click me for more fun button and the progress bar changes.Clickitthreetimesandyoushouldseethis:
Figure25TheprogressbarwhentheFunBtnisclickedthreetimes.
Ifyoumoveyourmouseoverthemascotpicture,youshouldseethelabel textappearanddisappearasyoumovethemouseonandoffthepicture.Finally, youcanhitESCorclicktheQuitbuttontoexittheprogram.Thelasteventwe are going to write code for in this example is the doubleclick event. This requiresyoutoonceagainchooseaneventhandler. FromtheGambasIDE,movethemouseovertheFunBtnandclickitonce. Next,rightclickthemouseandyouwillseethemenupopupallowingyouto
77
RepeatthisprocessfortheNoFunBtnandaddthiscode:
PUBLICSUBNoFunBtn_DblClick() ProgressBar1.Value=ProgressBar1.Value0.1 IFProgressBar1.Value<0.1THEN ProgressBar1.Value=0.0 ENDIF END
Now,savetheprojectandclicktherunbutton.Thistime,whenyouclick the progress bar it works just as it did before, but if you doubleclick, it will incrementthevalueby10unitsratherthanbyone.Onceyouexityourprogram, saveyourprojectandexitGambas.Next,wearegoingtolookatthetheother eventsthatcanusedwiththeButtoncontrol. ButtonEvents The Button events we have used in our previous example include the Click,DblClick,Enter,andLeaveevents. Wewillreserveourdiscussionofthe remaining events, namely Drag, DragMove, Drop, LostFocus and GotFocus for when we deal with drag and drop operations. The Menu, KeyPress and KeyRelease events will be covered when we talk about menu and keyboard operations. Finally, when we cover mouse operations, we will discuss the MouseDown,MouseMove,MouseUp,andMouseWheelevents.
ThePictureClass
Earlier in the chapter, when we used the Picture control to place our mascotontheforminoursecondexample,wementionedthePictureClassand saidwewouldcoveritlater.Well,nowitistimetotalkaboutthePictureClass. Thisclassrepresentsapictureanditscontentsarestoredinthedisplayserver,not inprocessmemorylikeanImagewouldbenormallystored.EvenifXWindows
78
A Beginner's Guide to Gambas does not manage transparency (yet), each picture object can have a mask assignedwithit.Thiscanbesetexplicitlyatthetimethepictureisinstantiated, or it can be set implicitly when loading an image file that has transparency attributes,likeaPNGfile.Whendrawingonapicturehavingamask,boththe pictureandthemaskaremodified.Thisclassiscreatable.Itisdefinedas:
DIMhPictureASPicture
andtheprocessofinstantiatingitusesthisformat:
hPicture=NEWPicture([WidthASInteger,HeightASInteger, TransparentASBoolean])
PropertiesforthiscontrolincludeDepth,Height,Image,Transparent,and Width.ThemethodsprovidedincludeClear,Copy,Fill,Flush,Load,Resize,and Save.Wewillcovertheuseofthesemethodsandpropertiesinlaterexamplesin thisbook.Atthispoint,youshouldhaveasolidunderstandingofhowtousethe Gambas programming environment and it's various tools. In the next few chapters,wewillpresentmorecontrolswithmorecomplexexamplesasthebest waytolearnisbydoing.
79
Hereiswhatourprogramwilllooklikewhenwearefinishedwithit:
Figure26ThirdProject(almost)finalresult.
80
A Beginner's Guide to Gambas Inthisexercise,wewilllearntoputtitlesonourprogramwindow,usean inputboxtogatherHTMLformattedinputfromtheuseranddisplaythatresultin anewtypeoflabel,theTextLabel.Wewillalsolearnhowtogroupandorganize our controls on the form, using panels and frames, and place controls like RadioButtonsandCheckBoxeswithinthoseorganizationalcontrols.Finally,we willlearnhowtouseListBoxesandComboBoxestoallowtheusertoselectfrom oneofmanychoices.Alongtheway,wewilllearnabitmoreabouteventcoding andtrytomakeitinteresting. Let'sgetstartedbycreatinganewProjectwith Gambas.StartGambasandchoosetocreateanewprojectusingaGraphicalUser Interface. Gothroughthewizardmakingtheprojecttranslatableandtheform controlspublic. Selectthename ThirdProject andputitinadirectoryofyour choosing.WhentheIDEstarts,createanew,startupclassform.Doubleclickon the blank form and the code editor window will appear. You should see somethinglikethis:
'Gambasclassfile PUBLICSUBForm_Open() END
Now,wewillstartbyputtingthetitleofourprogramatthetopofthe window when the program runs. To accomplish this, we will set the form's Captionproperty tothetextwewanttouseasthetitle. Enterthislineinthe Form_Open()subroutine:
ME.Caption="***ThirdProject***"
Thattakescareofthetextforthewindowtitle. Now,ifwelookatour finalresultpicture,westillhavetoaddourcontrols. Wewillstartatthetop, addingthecontrolswealreadyknowabout:Label,TextBox,andButton.Place eachcontrolontheformasshowninFigure26above.NamethecontrolsLabel1, TextBox1,and UpdateBtn. Thesecontrolswereusedinthelastchapter,soyou shouldbecomfortableusingtheminyourprograms.Next,wewilladdtheQuit Buttonatthebottomrightcorneroftheform.NamethiscontrolQuitBtn.Now, let'saddthecodeforthesecontrols.DoubleclickthemouseontheQuitBtnand addthiscodetotheQuitBtn_Click()subroutine:
PUBLICSUBQuitBtn_Click() Form1.Close END
81
A Beginner's Guide to Gambas Fortheupdatebutton,wearegoingtotransferthetexttheusertypedinto the TextBoxcontrol totheTextLabel,reflectingany HTML formattingthatthey entered.Hereisthecodeneededforthat:
PUBLICSUBUpdateBtn_Click() TextLabel1.Text=TextBox1.Text END
TextLabel
ThisclassiscreatableanditinheritsitsattributesfromtheControlclass.It implementsacontrolcapableofdisplayingsimpleHTMLtext.YoucanuseHTML entitiessuchas<and>todisplaycharacterslike<and>.ForHTMLthat requirestheuseof quotemarks, avoid the because itwill notwork. For example,entering:
<divalign="center"><b>Thiswon'twork.</b>
Thefigurebelowshowsyouanexampleofhowthisworks:
Figure27UsingHTMLtoformatTextLabeloutput.
Whatwewanttodonowiscodetheupdatebuttontotakeadvantageof thesecool HTML features. Toaccomplishthis,weneedtomodifythecodewe previously entered for the update button's click event. Doubleclick on the
82
Instead of simply assigning the input text from the TextBox to the TextLabel1.Textproperty,wearegoingtomakeitlookfancy.Now,anythingthe user types will automatically be centered in boldface and placed on the TextLabel1.Ifyousaveyourprojectandrunitatthistime,yourresultsshouldbe likethatofFigure28below:
Figure28ModifiedTextLabeloutputusingHTMLformatting.
TextBox
OurnexttaskistolearnmoreabouttheTextboxcontrolwejustused.You alreadyknowthatitisusedtolettheuserenteralineoftextinputandreturn thatinputtotheprogramasastring. TextBoxinheritsitsattributesfromthe Controlclassandthisclassimplementsasinglelinetexteditcontrol.Thisclassis creatableandisdeclaredas:
DIMhTextBoxASTextBox
Let's try something else now. Suppose that we want to streamline our applicationsothattheuserdoesnothavetoclicktheupdatebuttonwhenthey entertext. Also,itwouldbenicetohavethetextfieldclearitselfifthemouse entered the control area and to put back the default prompt when when the mouseismovedawayfromthecontrol. Wewouldwanttopreservewhatever wastypedintothefieldbytheuserwhenthemouseleavesthecontrolsowehave
83
A Beginner's Guide to Gambas toremembertoassignthevaluethatiscurrentlyintheTextBox1.Textfieldtothe TextLabel1.Text field. We want to continue to use the HTMLcapable format capabilitiesoftheTextLabel. Wewillneedtomodifyourcode.First,wemustcreatetheeventhandlers forthemouseenteringthecontrolandleavingthecontrol. Clickonceonthe TextBox1controlontheformandrightclickthemousetoselecttheEventitem. FromtheEventsubmenuchooseEnter.RepeatthisprocessandchoosetheLeave event.Now,gotothecodeeditor,findthefirstsubroutine(TextBox1_Enter()) andinsertthefollowingcodebetweenthefirstandlastline:
TextBox1.Clear
The first line of code will use HTML to format and center the TextBox1.Textstringandsetittoaboldfacefont.Thenextlineofcodeassigns thedefaultpromptstringweinitiallycreatedtotheTextBox1.Textsowhenthe mouse leaves we have saved whatever the user typed and reset it to what it lookedlikebeforethemouseenteredthecontrol. Saveyourworkandrunthe programtoseehowitworks. TherearenotreallyanyTextBoxuniqueMethodstodiscuss,butwhilewe arelearningaboutevents,let'splayaroundwiththecodealittleandlearnabout theShowandHidemethodsandhowtheymaybeusedinaprogram.Clickonce ontheform(becarefulnottoclickonanycontrolontheform)andrightclickthe mousetoselecttheEventitem.FromtheEventsubmenuchooseMouseDown. RepeatthisprocessandchoosetheDblClickevent.Now,gotothecodeeditor, findthesubroutineForm_MouseDown()andinsertthefollowingcodebetween thefirstandlastline:
UpdateBtn.Hide
Right now, you may be asking yourself How the user would ever know this? Goodpoint. Let'sletthemknowwithaToolTipproperty.Clickonthe UpdateBtncontrol. NowgotothepropertywindowandfindToolTip. Onthe rightsideofthatentryisaninputfieldandwithagrayboxwiththreedots(...). Thatmeansanotherdialogwilltakeplacewhenyouclick. Inthiscase,itwill openaneditwindowsoyoucanformatyourToolTipusingHTML.Clickitand whentheeditdialogappears,enterthistext(orcode,asyouwish):
Click<b>(ordoubleclick)</b>ontheformtohide<b>(orshow)</b>me.
Figure29AddingaToolTiptoinform theuserhowtoshow/hideacontrol.
ThereareacoupleofTextBoxuniqueeventswecoulddiscussatthispoint, namely KeyPress and KeyRelease,butwearegoingtoholdoffonthoseuntil laterinthebookwhenwestartworkingwiththekeyboarddirectly. Readyto moveon?Wearegoingtoaddsomeselectorcontrolstoourprogramnext.The ComboBoxandListBoxallowuserstoselectfromamongseveralchoices.Wewill startwiththeComboBoxfirst.
ComboBox
The ComboBox control inherits its attributes from the Control class. It implementsatextboxcombinedwithapopuplistbox. Thisclassiscreatable andisdeclaredusingtheformatbelow:
85
Toinstantiatethevariablewejustdeclared,usethisformat:
hComboBox=NEWComboBox(ParentASContainer)
Thelineofcodeabovewillreturnacomboboxitemfromitsintegerindex. Notethatthe.ComboBoxItem representsaniteminthecomboboxpopuplist box.Thisclassisvirtual.Youcannotuseitasadatatypeanditisnotcreatable. It has a single property, Text which returns a string value representing the ComboBoxitemrepresentedbyIndex. WearegoingtocreateaComboBoxon ourformnow.Hereiswhatourcontrolwilllooklike:
Figure30OurComboBox.
OK,iagreethatitisnothingveryfancyanditprobablyrankskindoflow onthecreativitylist,butitwillgetthejobdoneandteachyouwhatyouneedto knowtouseComboBoxes.Tobuildournewcontrol,wewillgototheGambas ToolBoxand selectthe ComboBoxcontrol. Placeitontheform(refertoour initialFigureattheverybeginningofthischaptertoseewhereitshouldgo)andtry togetitasclosetowhatyouseeinthatpictureasyoucan.Onceyouaredone withthat,clickonitonceifyoudonotseethehandlesandgototheProperties Window.FindtheListproperty.Theinputboxtotherightofthiswillenablea
86
Figure31TheEditlistpropertyeditor.
Toinsertaniteminthelist,typetheitemintheTextBoxatthebottomof theeditor.Thefirstiteminthelististhedefault.Itismostoftenusedtoseta defaultselection(likeNoneorPicksomething,etc.)Inourcase,typePickanitem andclickinsert.AddItem1,Item2,Item3,andItem4tothelist.Makesurethey appearintheordershowninFigure31abovesoitwilllookrightwhenitruns. Onceyouhaveitsetthewayyouwant,justclicktheOKbuttonandtheeditor willcloseandsaveyourwork. Saveyourprojectandruntheprogramtosee whatitlookslikeonyourform.Whenyouhavefinishedlookingattheworkwe havedonesofar,exittheprogramandwewillcontinuebyaddingsomecodeto processComboBoxselections. IftheuserselectssomethingfromtheComboBox,theitemwillchangeand thischangegeneratesaneventthatyoucanhandle. Fromtheform,selectthe ComboBox control and rightclick. Choose Event and select Change from the submenu. Now, go to the code editor and find the subroutine PUBLIC SUB ComboBox1_Change().Addthecodesothesubroutinelookslikethis:
PUBLICSUBComboBox1_Change() DIMresultASString result=Trim(ComboBox1.Text) TextLabel1.Text=result&"wasselectedfromtheComboBox" END
Saveyourprojectandruntheprogramtoseewhathappens.Noticethat whenanitemisselectedtheTextLabel1.Textvalueisupdatedbutdoesnothave
87
Changethecodeandruntheprogramagain.Youshouldseesomethingsimilarto thisintheTextLabel1control:
Figure32FormattingaTextLabelwithHTML.
Sotherealprogrammersouttherearealreadyaskinghowtodothiswith code,eh?Ithoughtyouwouldneverask!Seriously,itisnothard.Let'smodify our program slightly to allow dynamically add or remove items from the ComboBox.Todothis,wearegoingtoneedabuttonthatwillindicateaddingan itemandanotherbuttontoremoveanitem.Addtwobuttons,onecalledPlusBtn andtheothercalledMinusBtntotheform,asshownbelow:
Figure33Plusandminusbuttons toaltertheComboBoxlist.
DoubleclickonthePlusBtnandinsertthiscode:
PUBLICSUBPlusBtn_Click() DIMItemASString DIMNumItemsASInteger ComboBox1.Refresh NumItems=ComboBox1.Count IFNumItems=0THEN Item="PickanItem" ELSE Item="Item"&Str(NumItems) ENDIF ComboBox1.Refresh ComboBox1.Add(Item,NumItems) END
88
A Beginner's Guide to Gambas Inthecodeabove,wedeclaretwovariables,ItemandNumItems.Itemisa stringandNumItemsanInteger.WewilluseNumItemstodeterminehowmany itemsarealreadyinthelist.Thisisdoneusingthe.Countproperty.Ifthereare noitemsinthelist,wewillsetourdefaultpromptofPickanItemasItemzero. ComboBoxarraysarezerobased,meaningthecountingstartsatzero,not one.IttheNumItemsvalueiszerowewillcreateadefaultstring.Otherwise,we aregoingtoconcatenatetheitemnumbertothewordItemsoitwilladdtothe nextopenslotinthelist.WecalltheRefreshmethodtoforcetheComboBoxto refreshitscountpropertysoiftheusertriestoselectagainitwillbecurrent.The lastlineofcodeusesthe.AddmethodtoaddtheitemtotheComboBoxitemlist. Now,doubleclickontheMinusBtnandaddthiscode:
PUBLICSUBMinusBtn_Click() DIMNumItemsASInteger 'Thecomboboxarraystartsatzero ComboBox1.Refresh NumItems=ComboBox1.Count IFNumItems>0THEN DECNumItems IFNumItems<>0THEN ComboBox1.Remove(NumItems) ENDIF ComboBox1.Refresh ENDIF END
Removingelementsfromthelistismuchsimpler.Weonlyneedaninteger variabletodeterminethenumberofelementsinthelist.Onceagain,thisisdone usingthe.Countproperty.Inourexample,Countwillreturnavalueof5thefirst timeitisread.Iftherearenoitemsinthelist,wewillnotdoanything.Because the ComboBoxitems arestoredinazerobasedarray,wemustdecrementthe count by one if it is not already zero. Now, save your project and run the program.Tryremovingalltheitemsinthelistandreinsertingthem.Cool,eh? MorecoolstufftocomewiththeListBox,whichwediscussnext.
ListBox
TheListBoxcontrolalsoinheritsitsattributesfromtheControlclass.The ListBoximplementsalistofselectabletextitems. Thisclassiscreatable. The followingcodewilldeclareaListBoxandcreateit:
89
LiketheComboBox,thisclassactslikeareadonlyarray.
DIMIndexasInteger DIMhListBoxASListBox DIMhListBoxItemAS.ListBoxItem hListBoxItem=hListBox[Index]
Figure34WhatourListBoxwill looklike.
Figure35ListBoxEditlistpropertyeditor.
90
A Beginner's Guide to Gambas ThisisexactlythesameeditorweusedtobuildtheComboBox1control. Thistime,wearegoingtoadditemstothelistandalsolearnabouttheSystem class.The Systemclass ispartofthe Gambas componentlibrary andprovides supportforalltheclassesincludedintheinterpreterbydefault.TheSystemclass is static and provides readonly information about the operating system environment. The properties of this class that you can read include Charset, Domain,Home,Host,Language,Path,andUser.Usetheeditorandenterthe followingitemsinthelist: Charset Domain Home Host Language Path User Next,doubleclickontheListBox1controlontheform.Thiswilltakeyou to the code editor and you should be in the PUBLIC SUB ListBox1_Click() subroutine.Thefollowingcodewillshowyouhowtoaccessthesevalues.Enter itasfollows:
PUBLICSUBListBox1_Click() IFTrim(ListBox1.Text)="System.Charset"THEN TextLabel1.Text=System.Charset ELSEIFTrim(ListBox1.Text)="Domain"THEN TextLabel1.Text=System.Domain ELSEIFTrim(ListBox1.Text)="Home"THEN TextLabel1.Text=System.Home ELSEIFTrim(ListBox1.Text)="Host"THEN TextLabel1.Text=System.Host ELSEIFTrim(ListBox1.Text)="Language"THEN TextLabel1.Text=System.Language ELSEIFTrim(ListBox1.Text)="Path"THEN TextLabel1.Text=System.Path ELSEIFTrim(ListBox1.Text)="User"THEN TextLabel1.Text=System.User ENDIF END
A Beginner's Guide to Gambas easytoimplementanduse. Agreatadvantageofusingthesetypesofselector components is that it virtually eliminates the possibility of a user typing data incorrectly. In the next section, we are going to learn how to organize the controlsonourformtobettermanagethepresentationtocontrolstotheuser. Also,wewilllearnwhyframesandpanelsareagoodthingtoconsiderearlyin thedevelopmentprocess.
Frame
The Frame class inherits its attributes from the Container class. This controlisacontainerwithanetchedborderandalabel.Thisclassiscreatable. DodeclareandinstantiateaFrame,usethisformat:
DIMhFrameASFrame hFrame=NEWFrame(ParentASContainer)
Figure36Whattheexampleframewebuildwilllooklike.
Tocontinuedevelopmentofourproject,wewillfirstaddaFramecontrol totheform(nameitFrame1)andplaceitsimilartothatfoundinFigure24atthe beginningofthischapter.Next,wewilladdtwoToggleButtoncontrols(named ToggleButton1 and ToggleButton2) and three CheckBox controls (named CheckBox1,CheckBox2,andCheckBox3). ArrangethemtolooklikeFigure 33 above.Onceyouhaveeverythingplacedcorrectlyontheform,let'sgotothenext stepandwritecodefortheeventswewillrespondtoinourprogram.
92
ToggleButton
TheToggleButtoncontrolinheritsitsattributesfromtheControlclassand implementsatogglebutton.Thismeansiteithertogglesupordown.Thisclass iscreatable.Todeclareandinstantiatethiscontrol,usetheformat:
DIMhToggleButtonASToggleButton hToggleButton=NEWToggleButton(ParentASContainer)
Doubleclick on the ToggleButton1 control and add this code to the PUBLICSUBToggleButton1_Click()subroutine:
PUBLICSUBToggleButton1_Click() IFToggleButton1.Value=TRUETHEN Frame1.Text="Toggled1down" ELSE Frame1.Text="Toggled1up" ENDIF END
RepeatthepreviousstepfortheToggleButton2controlandenterthiscode:
PUBLICSUBToggleButton2_Click() DIMresultASString IFToggleButton2.Value=TRUETHEN Frame1.Text="Toggled2down" ELSE Frame1.Text="Toggled2up" ENDIF END
Checkbox
TheCheckBoxclassinheritsitsattributesfromtheControlclass.Thisclass implementsacheckboxcontrolanditiscreatable. Declareandinstantiatethe variablelikethis:
DIMhCheckBoxASCheckBox
93
WhenaCheckBoxcontrolisclickedinourprogram,wewanttodetectthe click event and immediately respond. In this case, we will change the Checkbox.TextpropertywhenevertheCheckBox.Valueischeckedandturnsout tobeTRUE.Thiswillshowthatwecaughttheclickeventandrespondedtothe valueofTRUEorFALSE(checkedorunchecked). Iftheboxisunchecked,we willwanttoreturnittotheNormalstate.ForCheckBox1,doubleclickonthe control and enter this code in the code editor for the PUBLIC SUB CheckBox1_Click()subroutine:
PUBLICSUBCheckBox1_Click() DIMoutline1ASString DIMoutline2ASString DIMoutline3ASString IFCheckBox1.Value=TRUETHEN Checkbox1.Text="Iwaspicked" ELSE Checkbox1.Text="Checkbox1" ENDIF END
RepeatthisprocessforCheckBox2andCheckBox3:
PUBLICSUBCheckBox2_Click() IFCheckBox2.Value=TRUETHEN Checkbox2.Text="Iwaspicked" ELSE Checkbox2.Text="Checkbox2" ENDIF END PUBLICSUBCheckBox3_Click() IFCheckBox3.Value=TRUETHEN Checkbox3.Text="Iwaspicked" ELSE Checkbox3.Text="Checkbox3" ENDIF END
Now, save your project and run the program. Once you have satisfied yourselfthattheyworkasweplanned,endtheprogramandwewillcontinueour projectbyaddingthelasttwocontrolsthatwearegoingtocoverinthischapter, thePanelandRadioButton.
94
Panel
The PanelclassinheritsitsattributesfromtheContainerclass.Thisclass implementsa Panelcontrol withachangeableborder. Thisclassiscreatable. Declareandinstantiateapanellikethis:
DIMhPanelASPanel hPanel=NEWPanel(ParentASContainer)
Inourprogram,wearegoingtousethePaneltogroupourRadioButtons insideit.Hereiswhatthispanelwilllooklikewhenwearefinished:
Figure37APanelwithRadioButtons.
WewillfirstneedtoaddaPanelcontroltotheform(nameitPanel1)and placeittolooklikethePanelfoundatthebeginningofthischapter. Next,we will add two RadioButton controls (named RadioButton1 and RadioButton2). ArrangethemtolooklikeFigure37above.
RadioButton
The RadioButtonclass inheritsitsattributesfromtheControlclassandis usedtoimplementaradiobuttoncontrol. RadioButtoncontrolsthatsharethe sameparent(inthiscase,thePanelcontainer)aremutuallyexclusive.Onlyone RadioButton can be selected at once. This class is creatable. Declare and instantiateaRadioButtonlikethis:
DIMhRadioButtonASRadioButton hRadioButton=NEWRadioButton(ParentASContainer)
SelecttheRadioButtoncontrolfromtheToolBoxandplaceitontheform. Namethe firstRadioButton RadioButton1 and repeat thisprocessfor another, namedRadioButton2. Onceyouhaveeverythingplacedcorrectlyontheform, let'sgotothenextstepandwritecode.DoubleclickonthefirstRadioButtonand enterthiscode:
95
Repeatthisprocessforthesecondone:
PUBLICSUBRadioButton2_Click() RadioButton2.Text="HaHaRB1" RadioButton1.Text="RadioButton1" END
Now, save your project and run the program. Once you have satisfied yourselfthateverythingwehavedoneinthischapterwillworkasweplanned, takeawelldeservedbreakandwewillstartfreshonthenextchapter.
96
Figure38MenuProjectFinalresults.
We are going to create four menus. Each menu will be used to demonstratethecontrolsorstandarddialogswearegoingtolearnaboutinthis chapter. Wewillfirstbuildthemenu,asshownabove,thenwewillshowyou howtousethestandardcolorandfiledialogs,MessageBoxes,and,asanadded bonus,wewillshowyouhowtocreateamoduleinGambasanduseit.Tobegin our project, open Gambas and create a new Graphical User Interface project. NameitMenuProjectandsetallthecontrolstranslatableandpublic.Onceyou gettotheIDE,createaform,Form1andmakeitaStartupclass. AddaQuit Buttontotheform,asshownaboveandenterthiscodetobeexecutedwhena userclickstheQuitbutton:
97
Next, add a TextLabel, named TextLabel1 to the window as shown in Figure38above.Thattakescareofthepreliminariesforourproject.Now,let's seehowtobuildthemenuandusethestandarddialogsprovidedbyGambas.
TheGambas MenuEditor
Gambas has a builtin Menu Editor. You can access it from the form windowbypressing CTRLE orbyrightclickingontheformandselectingthe MenuEditor optionfromthepopupthatappears. Eitherway,the MenuEditor willappearandyouwillseesomethinglikethis:
Figure39TheGambasMenuEditorwhenitfirststarts.
98
A Beginner's Guide to Gambas WhenyoufirststarttheMenuEditor,theeditorwindowwill,ofcourse,be blank. It is not anintuitively obvious tool to use, so let's spend a minute to explaintheMenuEditor.First,somecommonterminology.Thetextthatyousee runninghorizontallyacrossthetopofaformisreferredtoasamenu.Amenu cancontainMenuItems(whicharelistedverticallybelowthemenu).MenuItems cancontain subMenus,whicharebasicallynewnestedmenusthatbelongtoa MenuItemand willpopupanddisplay anotherlistof MenuItems. Menus can containseverallayersofnestedsubMenus. ToinsertamenuyouwillhavetousetheInsertbutton.TheNextbutton willmovethecurrentmenucursorpositiontothenextiteminthewindow. It onlymovesdownandthereisnopreviousbutton.Ifyoureachtheendofthelist, itwillstopandtheonlythingyoucandoisclickthemouseonamenuentryor insertanewone.TheDeletebuttonwillremovethemenuentryunderthemenu cursor. Thefirsttwo and arrowbuttons(upanddown)totherightofthe Deletebuttonwillmovetheentryunderthemenucursorupordownthelistof menuentries.Ifyouclickthe or (unindentandindent)arrowbuttons,the will work much likeindentation in an outline works. Theindented itemwill become either a MenuItem or subMenuItem depending on the level of indentation. Indented items with three ... preceding the name indicate MenuItems. More than three dots preceding the name indicates it is a subMenuItemoftheentryatthepreviousindentationlevel. Onceyoubuilda menuortwo,itwillbeeasytounderstand.Onceyouclicktheinsertbutton,you willseeseveralnewfieldsappearatthebottomoftheMenuEditor,namelythese:
Figure40EditfieldsfortheMenuEditor.
99
A Beginner's Guide to Gambas TheNamefieldshouldprobablyhavebeencalledVariable Namebecause thatiswhatthisfieldisusedfor.Thisisthevariablenamethatyourcodeinthe classfilewillusetoreferencethisparticularobject. TheGroupfieldreferstoaControlGroup.ControlGroupsareusedinthe GambasIDEtocreateandhandlegroupsofcontrolsasasingleentity.Whenyou selectanycontrolonaform,inthePropertiesdialog,youshouldnoticeaGroup propertythatdoesn'tcorrespondtoanydocumentedpropertyofthatcontrol.This specialpseudopropertyallowsyoutoassigncontrolgroups.Essentially,whenthat controliscreatedatruntime,itwillbetreatedasthoughyouhadcreateditin codelikeso:
myControl=NEWColumnView(ME)AS"myGroup"
anditseventhandlersmustbenamedlikeso:
PUBLICSUBmyGroup_Click()
You can refer to the control that generated the event with the LAST keyword,oryoucanassignaTagtoeachcontroltodifferentiatethembyusing thetagvalue. Captionisthetextthattheenduserwillseewhentheprogramruns.Tag isreservedforprogrammerstostoredataandisacommonpropertyfornearlyall controls. WewillcoverhowtousetheTagpropertylater. Fornow,youonly needtoknowthatitcancontainANYVarianttypedata. The Shortcut CheckBoxes allow you to define keyboard shortcut key combinationslikeControlAtoautomaticallyinvoketheclickeventforthatmenu entry. Remember, menu entries basically only respond to click events or keyboardshortcuts. The Picture fieldallowsyoutospecifythefilenameofan iconthatwilldisplaywiththemenuentry.Apreviewwindow(a.k.a.,apicture box)appearstotherightofthisfield. The CheckBoxes to the right of the input fields, Visible, Enabled, and Checked refertothe state ofthemenuentry. Bydefault,allmenuentriesare createdtobeenabledandvisible.Youcanspecifyiftheitemischeckedornot. Incode,youcanseeiftheentryischeckedornotbylookingatthemenuentry's Checkedproperty.ItwillreturnaTRUEorFALSEvalueindicatingthestatusof theitem. Hereisanexampleofhowtotoggleacheckmarkonoroffwhena menuitemispicked:
100
TheIFstatementwilltesttheCheckedpropertyoftheMenu2Item1object andiftheBooleanvalueisTRUEwillsetittoFALSE(togglingit).IftheBoolean valueisNOTTRUEtheELSEclauseisexecuted,togglingthe.Checkedvalueto TRUE.ThislogiccanbeusedtotoggleanymenuorsubMenuItem. NOTE:AwordofcautionusethisfeaturesparinglyforgoodGUIdesign. Many users feel overwhelmed when they are presented with too much gadgetry in an interface.
BuildingMenus
Now,let'screateourmenu.Whenyouarefinished,itwilllooksomething likethisfromthemenueditor:
Figure41Buildingourprojectmenu.
(Variable)Name
Menu1 Menu2 Menu3 Menu4
Group
Caption
ColorDialog MessageBoxes FileDialogs Help
(Variable)Name
Menu1Item1 Menu1Item2 Menu1Item3
Group
Caption
ForegroundColor BackgroundColor Font
After you have inserted these items with the editor, ensure they are positionedbelowtheColorDialogentryandindentedonelevel.Now,movethe menucursoroverthesecondmainmenuentry,MessageBoxesandwewillinsert themenuitemsforthismenu. MessageBoxes
InfoMessage AlertMessages ErrorMessage WarningMessage DeleteMessage QuestionMessage
(Variable) Name
Menu2Item1 Menu2Item2 subMenuItem1 subMenuItem2 subMenuItem3 Menu2Item3
Group
Caption
InfoMessage AlertMessages ErrorMessage WarningMessage DeleteMessage QuestionMessage
(Variable)Name
Menu4
Group
Caption
About
102
A Beginner's Guide to Gambas That'sallthereistoit!ClicktheOKbuttontoleavethemenueditorand whenyourreturntotheform,amenuwillbethere.Ifitdoesnotlooklikeour example,gobacktothemenueditorandadjusttheentriesuntilitdoes. After youarecompletelysatisfiedwiththemenu'sformatandappearance,thenextstep istocodeactionsforeachmenuclickevent. However,beforewedothat,we needtolearnaboutthestandarddialogsandMessageBoxesthatareprovidedin Gambas.
Dialogs
TheDialogclassisusedtoimplementalloftheGambasstandarddialogs. Thisclasscontainsstaticmethodsusedtocallthestandard dialogboxes.This classisstatic. TheDialogmethodssupported (i.e.,thestandard dialogs) are: OpenFile,SaveFile,SelectColor,SelectDirectory,andSelectFont.Theproperties supportedbythisclassare:Color,Filter,Font,Path,andTitle. Colorisanintegervaluethatthe SelectColorDialog returnsrepresenting thecolorselected.ItisinterestingtonotethatGambashas32predefinedcolor constantsbutthestandard SelectColorDialog consistsof48colors. Thismeans youcannotusethe predefinedconstants likeRed,Black,etc.,withanysenseof suretyina CASEstatement orelsewhere. Whenacolorischosen,howdoyou determineifitisapredefinedconstantoranothercoloroutsidetherangeofthe 32predefinedinGambas?Youwriteamoduletodeterminethat,ofcourse!We willcomebacktothistopicafterexplaininghowtousetheSelectColorDialog. WhenworkingwiththefilerelatedDialogs,theFilterandPathproperties arereturned. Filterisdefinedas STATICPROPERTYFilterASString[] andit returnsorsetsthefilters(i.e.,categorizebyfileextension,suchasall.docor.png files)usedinthestandardfiledialogs.Thispropertyreturnsorreceivesastring array.Eachelementinthearrayrepresentsonefiltertousewhenthefiledialog callismade.Eachfilterstringmustfollowthefollowingsyntax:
HereisanexamplethatalsodemonstratestheuseoftheDialogTitleproperty:
103
First,wesettheTitleoftheDialogtoChooseaforegroundcolorsothe userhassomeideaofwhattheDialogisusedfor. Wecallthestandarddialog withDialog.SelectColor.Oncetheuserhaspickedacolororcanceledfromthe dialog, we will place the name of the color returned in the TextLabel1.Text control wecreated atthe beginning of ourproject. We choose the TextLabel becauseitallowsustoformatouroutputlikethis:
TextLabel1.Text="<b>Colorselectedwas</b>"&Str$(Dialog.Color)&"."
Figure42Aformattedtextlabeldisplayingthecolorvalue.
104
Modules
Wearegoingtocreateamoduletoreturnthenameofacolorifitisa predefinedconstant.Ifnot,wewantastringthattellsusitis not apredefined colorconstant.Oncewedefineourmodule,wewillcomebackandmodifyour codetousethemodule.FromtheProjectwindow,findModulesintheTreeview andselectanewmodule,namedModule1.Whenthedialogappears,leavethe CheckBoxes blank and just take the default name and click OK. You will be presentedwithanewcodewindowtitledModule1.module. Itshouldstartout withacommentlikethis:
'Gambasmodulefile
Now, we write all the code for our function, which we will call SetColorName.First,wemustdeclarethefunctionandidentifywhatinputand outputparametersitwillprocess.Hereishowwedothat:
PUBLICFUNCTIONSetColorName(iValASInteger)ASString
WedeclareapublicFunctionthattakesanintegerparameterandreturnsa string. Thismodulewillthattheintegervaluethatthe SelectColorDialog has returned,andcheckitagainstthe32predefinedcolorconstantsusedinGambas. Ifitmatchesacolorconstant,wewillsetatemporarystringtothenameofthat color.Ifnot,wewillcreateastringthatidentifiestheconstantvalueandreturn thattothecallingcode.Wewillneedtocreateatemporarystringvariabletodo this,soaddthisvariabledeclarationasthefirstlineofcodeinsidethefunction:
rvalASString
A Beginner's Guide to Gambas Onceyouhavecompletedthiscode,savethismodulefileandreturnback to the code window for Form1. We have to modify our code in the Menu1Item1_Clicksubroutine.Hereisthenewsubroutine:
PUBLICSUBMenu1Item1_Click() Dialog.Title="Chooseaforegroundcolor" Dialog.SelectColor ColorName=Module1.SetColorName(Dialog.Color) TextLabel1.ForeColor=Dialog.Color TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END
Now,whentheprogramexecutes,thevariablewillbeknown.Inthecodebelow, thecallto:
ColorName=Module1.SetColorName(Dialog.Color)
anditwillreturnthestringtoourColorNamevariable.Wewanttosetthecolor oftheforegroundtexttothecolorjustpicked:
TextLabel1.Forecolor=Dialog.Color
Now,wewilltakethestringanddisplayit(formatted,ofcourse)byassigningit totheTextLabel1.Textproperty.
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
ThefinalversionofourMenu1Item1_Clickroutineshouldlooklikethis:
PUBLICSUBMenu1Item1_Click() Dialog.Title="Chooseaforegroundcolor" Dialog.SelectColor ColorName=Module1.SetColorName(Dialog.Color) TextLabel1.ForeColor=Dialog.Color
107
ThefinaloptioninourfirstmenuistochangetheFont. The SelectFont Dialogisusedtoaccomplishthis.Onceagain,gototheformmenuandchoose theFontoptionintheColorDialogmenuofourprojecttogettheclickeventsetin thecodewindow.FontsarehandledinGambaswiththeFontclass.Thisclass representsa font used fordrawing or displaying textincontrols.This class is creatable.Todeclareafontvariable,usethisformat:
DIMhFontASFont hFont=NEWFont([FontASString])
Thecodeabovecreatesanewfontobjectfromafontdescription.Thisclass acts like a readonly array. This code creates a new font object from a font descriptionandreturnsit:
DIMhFontASFont hFont=Font[FontASString]
ThepropertiesthatyoucanusewithFontinclude:
Styles Underline
HereisanexampleofhowtousecodetosettheFontproperties:
Form1.Font.Name="Utopia" Form1.Font.Bold=TRUE Form1.Font.Italic=TRUE Form1.Font.Size="14" Form1.Font.StrikeOut=FALSE Form1.Font.Underline=TRUE
The Font class has three Methods you can call: Height, ToString, and Width.Heightisafunctionthatreturnstheheightofthetextdisplayedwiththe font.Itisdeclaredas:
FUNCTIONHeight(TextASString)ASInteger
ToStringreturnsthefullnameofafontasadescriptionstring.Thisstringisa concatenationofallthefontpropertiesseparatedbycommas.Itisdeclaredas:
FUNCTIONToString()ASString
AnexamplecalltoToStringwouldbe:
PRINTApplication.Font.ToString()
WidthisafunctionjustlikeHeightbutitreturnsthewidthofthetextdisplayed withthefont:
FUNCTIONWidth(TextASString)ASInteger
Now,let'scontinuetoenterourcodeforourMenuProjectprograminthe PUBLIC SUB Menu1Item3_Click() routine. First, we will declare two local variables,fontdataandoldfontdata.Wewanttogetthenewfontfromthecallto the SelectFontDialog,butwealsowanttoretaintheoldfontdataincasewe need it. Next, we declare two string variables, attr and sel (attribute and selection)tobeusedtosetthefontattributestring;selectionisaworkstringwe willbuilddynamically,basedonthevariousselectionstheusercouldmakeinthe dialog.
PUBLICSUBMenu1Item3_Click() DIMfontdataASfont
109
Now,weassignthecurrentTextLabel1.fontpropertytotheoldfontdatavariable:
oldfontdata=TextLabel1.Font
Next,let'ssetthetitleforthedialogandcalltheSelectFontDialogwiththesetwo lines:
Dialog.Title="Pickafont..." Dialog.SelectFont
Atthispoint,wewillchecktoseewhatattributestheuserhaschosenand dynamically build an output string. We could have built this IF THEN ELSE statementtocheckeverypropertysupportedbythe Fontclass,butwearenot interestedinallofthemforthisexercise.
IFfontdata.ItalicTHEN sel="Italic" attr=attr&sel ENDIF IFfontdata.BoldTHEN sel="Bold" attr=attr&sel ENDIF IFfontdata.StrikeoutTHEN sel="Strikeout" attr=attr&sel ENDIF IFfontdata.UnderlineTHEN sel="Underline" attr=attr&sel ENDIF
110
Note that we have jumped the gun a bit and introduced the use of MessageBoxeswithoutexplainingthem. Thatisournexttask,butIwantedto giveyouapreview. Saveyourprojectandexecuteitatthistime. Yourresults shouldbesimilartothis,dependingonthecolorsandfontyouselected:
Figure43Selectingcolorsandfonts.
Andifyoudecidetokeepitasthedefault,youwillseesomethinglikethis:
111
Figure44MakinganewdefaultfontfortheTextLabel1control.
MessageBoxes
MessageBox controls are a quite handy means of communicating informationtotheuserorgettinganswersthatareoftheTRUE/FALSE,YES/NO type. Generallyspeaking,MessageBoxesfallintooneoffourbroadcategories: queryand/or confirmation, information,warning,and error/alertnotifications. TheMessageclassisusedfordisplayingtheseMessageBoxes.Thisclassisstatic anditcanbeusedasafunction.Itisdeclaredas
STATICFUNCTIONMessage(MessageASString[,ButtonASString])ASInteger
TheMethodsthataresupportedbythe Messageclass areInfo,Question, Delete,Error,andWarning.YouhaveseentheMessage.Questionmethodused used already. Each method serves a specific purpose and should be used appropriatelyinyourcode. Let'sstartwiththeeasiestMessageBoxmethod,the Informationmethod. InformationMessages TheInfomethodisdeclaredas:
STATICFUNCTIONInfo(MessageASString[,ButtonASString])ASInteger
anditisusedtodisplayaninformationMessageBox,withonlyonebutton.Since theuserdoesnothavetomakeadecision,theyonlyneedtoacknowledgethe
112
Figure45AnInformationMessageBox.
To continue building our example program, from the form go to the MessageBoxesmenuandclickonInfoMessagemenuitem.Itwilltakeyoutothe codeeditorwindowandyouwillbeinthe Menu2Item1_Clicked() subroutine. Hereitis:
PUBLICSUBMenu2Item1_Click() Message.Info("Hereissomeinformationtoconsider.") END
Figure46Achecked menuitem.
Figure 43 above showsthe checked menu item. Selecting it again will uncheckit. Well,thatwasnottoodifficult,wasit?See,Gambasmakesthings easy.Now,let'smoveontothenextpart.
113
Becausetheindexofthebuttonclickedbytheuserisreturned,itiseasiest toembedthecalltoMessage.QuestioninaSELECT/CASEstatement. SELECT takestheintegerreturnvalueand,becauseweknowitcanonlybereturnedas CASE1,2,or3,wewillnotneedtomakeaDEFAULTsection. Wecould,of course,butitisnotnecessary.Dependingonthevaluereturned,wewilleither takea Yes action,a No action,ora Don'tknow actionbecausethatiswhatwe specifiedinourcalltotheDialog(intheSELECTstatementabove).Let'swrite newcodeforourMessageBoxesMenumenuitemQuestionnow.Chooseitfrom theformwindowandenterthiscode:
PUBLICSUBMenu2Item3_Click() SELECTMessage.Question("Didyoulikethis?","Yes","No","Don'tknow") CASE1 TextLabel1.Text="Likedit." CASE2 TextLabel1.Text="Didnotlikeit." CASE3 TextLabel1.Text="Didnotknow." ENDSELECT END
114
Figure47AQuestionMessageBox.
GototheformandclicktheErrorMessagesubMenuItemtosetupaclickevent andenterthiscode:
PUBLICSUBsubMenuItem1_Click() Message.Error("Wow!Thiswasamistake.") END
Hereiswhatyoushouldseewhenyouruntheprogram:
Figure48AnErrorMessage.
WarningorAlertMessages Warning messages display a warning MessageBox, with up to three buttons. Theindexofthebuttonclicked bytheuserisreturned. Warningis
115
Inourexampleprogram,error,warninganddeletemessagesarepartof the submenu we created to appear when the menu item Alert Messages is activated.Tocodethewarningmessage,weneedtosettheclickeventbygoing tothemenuandclickingontheWarningMessagesubMenuItem.Thiswillputus inthecodewindowwherewewillenterthiscode:
PUBLICSUBsubMenuItem2_Click() Message.Warning("Youhavebeenwarnedaboutthis!") END
Whenyouexecutetheprogram,hereiswhatyoushouldsee:
Figure49AWarningmessage.
DeleteMessages The Delete function displays a deletion MessageBox, with up to three buttons. The index of the button clicked by the user is returned. Delete is declaredas:
STATICFUNCTIONDelete(MessageASString[,Btn1ASString,Btn2AS String,Btn3ASString])ASInteger
SettheclickeventforthesubMenuItemDeleteMessageandenterthiscode:
PUBLICSUBsubMenuItem3_Click() SELECTMessage.Delete("Delete?","Yes","No","Cancel") CASE1 TextLabel1.Text="Deletedit" CASE2 TextLabel1.Text="NotDeleted" CASE3 TextLabel1.Text="Canceled!"
116
Whenyouexecutetheprogram,hereiswhatyoushouldsee:
Figure50Deletemessagewiththreebuttons.
DialogClassFilerelatedFunctions
The standard dialogs provided with Gambas also support file operation suchasopeningafile,savingafile,andchoosingadirectorypath. Theyare prettystandardbutthegreatadvantageisthatyoudon'thavetobuildthemevery time you want to write a program. Consistency in user interface is now demandedfromusersandanythinglessmakesyourprogramlessapproachable and,resulting,lessacceptedbyusersthanitcouldbe.Thissectionwillshowyou howeasyitistouseGambasstandarddialogsforfileoperations. DialogOpenFileFunction TheOpenFileDialogfunctioncallsthefilestandarddialogtogetthename ofafiletoopen. ThisfunctionreturnsTRUEiftheuserclickedontheCancel button,andFALSEiftheuserclickedontheOKbutton.Itisdeclaredasfollows:
STATICFUNCTIONOpenFile()ASBoolean
Figure51TheOpenFileDialog.
CreateaclickeventforourFileSave...menuitemandinthecodewindowenter thiscode:
PUBLICSUBMenu3Item2_Click() Dialog.Title="Savefileto..." Dialog.SaveFile TextLabel1.Text="SAVE:"&Dialog.Path END
Hereistheresult:
118
Figure52SaveFileDialog.
Thisisthefinalclickeventweneedtocodeforourprogram.Choosethe SelectDirmenuitemandenterthiscode:
PUBLICSUBMenu3Item3_Click() Dialog.Title="Pickadir..." Dialog.SelectDirectory TextLabel1.Text="SAVEtoDIR:"&Dialog.Path END
Saveyourprojectandrunthecode.HereiswhatyoushouldseeforSelectDir:
Figure53TheSelectDirectoryDialog.
119
A Beginner's Guide to Gambas Now we have written all the code needed to finish our MenuProject program. Save it and execute the program. The next section presents the completeclassfileforyoutoreview.Itistimeforustomoveontobiggerand betterthings.Inthenextchapter,wewillstartlearninghowtohandleinputand outputfromtheuserbyusingstringsandfiles.
CompleteExampleListing
'Gambasclassfile 'declareaglobalvariabletobeusedwithourSetColorNamemodule ColorNameASString PUBLICSUBForm_Open() ME.Caption="WorkingwithMenus" END PUBLICSUBQuitBtn_Click() Form1.Close END PUBLICSUBMenu1Item1_Click() Dialog.Title="Chooseaforegroundcolor" Dialog.SelectColor ColorName=Module1.SetColorName(Dialog.Color) TextLabel1.ForeColor=Dialog.Color TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END PUBLICSUBMenu1Item2_Click() Dialog.Title="Chooseabackgroundcolor" Dialog.SelectColor ColorName=Module1.SetColorName(Dialog.Color) TextLabel1.BackColor=Dialog.Color TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END PUBLICSUBMenu1Item3_Click() DIMfontdataASfont DIMoldfontdataASFont DIMattrASString DIMselASString attr="" oldfontdata=TextLabel1.Font Dialog.Title="Pickafont..." Dialog.SelectFont
120
122
Module1.modulelisting
'Gambasmodulefile PUBLICFUNCTIONSetColorName(iValASInteger)ASString rvalASString SELECTiVal CASEColor.Black rval="Black" CASEColor.Blue rval="Blue" CASEColor.Cyan rval="Cyan" CASEColor.DarkBlue rval="DarkBlue" CASEColor.DarkCyan rval="DarkCyan" CASEColor.DarkGray rval="DarkGray" CASEColor.DarkGreen rval="DarkGreen" CASEColor.DarkMagenta rval="DarkMagenta" CASEColor.DarkRed rval="DarkRed" CASEColor.DarkYellow rval="DarkYellow" CASEColor.Gray rval="Gray" CASEColor.Green rval="Green" CASEColor.LightGray rval="LightGray" CASEColor.Magenta rval="Magenta" CASEColor.Orange rval="Orange" CASEColor.Pink rval="Pink" CASEColor.Red rval="Red" CASEColor.Transparent rval="Transparent" CASEColor.Violet rval="Violet" CASEColor.White rval="White" CASEColor.Yellow
123
124
StringFunctions
InGambas,thereisarichsetofstringfunctions.Wewillusetheconsole forthischapterandlearnaboutthefollowingfunctions:
Len Upper$/Ucase$andLower$/LCase$ Trim$/RTrim$andLTrim$ Left$/Mid$/Right$ Space$ Replace$ String$ Subst$ InStr RInStr Split
Wewillneedtocreateanewconsoleapplicationtodoourworkinthis chapter.StartGambasandcreateanewterminalapplicationnamedStringTests. When the IDE appears, create a new startup class named Class1. The code windowshouldappearandyoushouldseesomethinglikethis:
'Gambasclassfile STATICPUBLICSUBMain() END
Wenowhaveallthepreliminariesoutofthewayandarereadytobegin
125
Fromthecodewindow,let'stypethefollowing:
STATICPUBLICSUBMain() DIMiStringLengthASInteger DIMsTestStringASString sTestString="12345678901234567890" sStringLength=Len(sTestString) PRINT"==>"&iStringLength&"isthelengthofourteststring." sTestString="12345" iStringLength=Len(sTestString) PRINT"==>"&iStringLength&"isthelengthofourteststring." sTestString="12345678901" iStringLength=Len(sTestString) PRINT"==>"&iStringLength&"isthelengthofourteststring." END
Theconsolewillrespondwiththis:
==>20isthelengthofourteststring. ==>5isthelengthofourteststring. ==>11isthelengthofourteststring.
Itisimportanttoknowthatstringlengthbeginscountingatposition1,not zerolikeinCandsomeotherlanguages. Nowthatwecanfindouthowmany charactersareinastring,let'slearnhowtoconvertthestringfromonecaseto another. Upper$/Ucase$/UcaseandLower$/Lcase$/Lcase Upper$ returnsa stringconverted touppercase. Ucase$ and Ucase are
126
A Beginner's Guide to Gambas synonynmsforUpper$andcanbeusedinterchangeably.Lower$returnsastring convertedtolowercase.Lcase$andLcasearesynonymsforLower$andcanalso be used interchangeably. Note that these functions do not work with UTF8 strings.HereisthestandardGambaslanguagesyntaxforusingthesefunctions:
Result=Upper$(String) Result=UCase$(String)
Typethisinthecodewindowandexecutetheprogram:
STATICPUBLICSUBMain() DIMsStringLengthASInteger DIMsTestStringASString sTestString="abcdefg" PRINT"==>"&sTestString&"isourstartingstring." PRINT"==>"&UCase$(sTestString)&"isnowuppercase." PRINT"==>"&LCase$(sTestString)&"isnowbacktolowercase." PRINT"==>"&Upper$(sTestString)&"isnowbacktouppercase." sTestString="123abc456def789ghiZZZ" PRINT"==>"&sTestString&"isourstartingstring." PRINT"==>"&UCase(sTestString)&"isnowuppercase." PRINT"==>"&LCase(sTestString)&"isnowbacktolowercase." PRINT"==>"&Upper(sTestString)&"isnowbacktouppercase." PRINT"==>"&Lower$(sTestString)&"isnowbacktolowercase." END
Theconsolerespondswith:
==>abcdefgisourstartingstring. ==>ABCDEFGisnowuppercase. ==>abcdefgisnowbacktolowercase. ==>ABCDEFGisnowbacktouppercase. ==>123abc456def789ghiZZZisourstartingstring. ==>123ABC456DEF789GHIZZZisnowuppercase. ==>123abc456def789ghizzzisnowbacktolowercase. ==>123ABC456DEF789GHIZZZisnowbacktouppercase. ==>123abc456def789ghizzzisnowbacktolowercase.
Trim$,LTrim$,andRTrim$ Trim$stripsawayallwhitespacesfromeitherendofastring.Itwillnot
127
A Beginner's Guide to Gambas strip white spaces away after the first nonwhitespace is encountered and basically ignores all whitespace until the last nonwhitespace character is encountered,whereuponitwillbegintotrimtrailingwhitespace.Awhitespace isanycharacterwhoseASCIIcodeisstriclylowerthan32.Trim$isbasicallya calltoLtrim$andRtrim$simultaneously.Itisusedlikethis:
Result=Trim$(String)
TrythisonyourconsoleseehowtheTrim$functionworks:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString DIMiLengthASInteger PRINT"12" PRINT"12345678901234567890" sTestString="<abcdef" iLength=Len(sTestString) PRINTsTestString&">isourstartingstring." PRINT"Itis"&Str$(iLength)&"characterslong" sResult=Trim$(sTestString) PRINTsResult&">istheresultofTrim$call." END
Theconsolerespondswiththis:
12 12345678901234567890 <abcdef>>isourstartingstring. Itis14characterslong <abcdef>istheresultofTrim$call.
Left$,Mid$,andRight$ Left$ returns the first Length characters of a string. If Length is not specified,thefirstcharacterofthestringisreturned.IfLengthisnegative,allof the string except the Length last characters are returned. Standard Gambas languagesyntaxis:
Result=Left$(String[,Length])
Right$ returns the Length last characters of a string. If Length is not specified,thelastcharacterofthestringisreturned.IfLengthisnegative,allof the string except the Length first characters are returned. Standard Gambas languagesyntaxis:
Result=Right$(String[,Length])
Trythisonyourconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString DIMiLengthASInteger PRINT"12" PRINT"12345678901234567890" sTestString="abcdefghi" iLength=Len(sTestString) PRINTsTestString&"isourstartingstring." PRINT"Itis"&Str$(iLength)&"characterslong" sResult=Left$(sTestString,3) PRINTsResult&"istheresultofLeft$call." sResult=Mid$(sTestString,4,3) PRINTsResult&"istheresultofMid$call." sResult=Right(sTestString,3) PRINTsResult&"istheresultofRight$call." END
Theconsolerespondswiththis;
12 12345678901234567890 abcdefghiisourstartingstring. Itis9characterslong abcistheresultofLeft$call. defistheresultofMid$call. ghiistheresultofRight$call.
129
A Beginner's Guide to Gambas Space$ Space$ returns a string containing Length spaces. Standard Gambas language syntaxis:
String=Space$(Length)
Trythisontheconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString PRINT"12" PRINT"12345678901234567890123456" sTestString="a" PRINTsTestString&Space$(24)&"z" END
Replace$ Replace$ replaces every occurrence of the string Pattern in the string StringbythestringReplaceString,andreturnstheresult.IfStringisnull,thena null string is returned. If Pattern is null, then the string String is returned. StandardGambaslanguagesyntaxisasfollows:
Result=Replace$(String,Pattern,ReplaceString)
Trythisprogramonyourconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString sTestString="abc123ghi" PRINTsTestString&"isourstartingstring." sResult=Replace$(sTestString,"123","def") PRINTsResult&"istheresultofReplacecall." sTestString="abcdefghi" PRINTsTestString&"isourstartingstring." sResult=Replace$(sTestString,"","") PRINTsResult&"istheresultofReplacecall." sTestString="\ta\tb\tc\tdef"
130
Theconsolerespondswith:
abc123ghiisourstartingstring. abcdefghiistheresultofReplacecall. abcdefghiisourstartingstring. abcdefghiistheresultofReplacecall. A b c defisourstartingstring. abcdefistheresultofReplacecall.
String$ String$ simply returns a string containing Length times the Pattern. Use this format:
String=String$(Length,Pattern)
Trythisontheconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString PRINT"12" PRINT"12345678901234567890123456" sTestString="a" PRINTsTestString&String(24,".")&"z" END
Theconsolerespondswith: 12
12345678901234567890123456 a........................z
Subst$ Subst$replacesarguments&1,&2,etc.inapatternwiththefirst,second, andsubsequentReplaceStringsrespectively,andreturntheresult. IfPatternis null, then a null string is returned. For C developers, this is not unlike a
131
Trythislittleapplicationonyourconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString sTestString="abcdef" sResult="ghijkl" PRINT"Ourstartstringis:"&sTestString PRINTSubst$("OurSubststringis:&1",sResult) END
Theconsolerespondswith:
Ourstartstringis:abcdef OurSubststringis:ghijkl
Theresultingoutputis:
abcdefghiisourstartstring. Firstspaceisatposition:4 Nextspaceisatposition:8 123456 123456789012345678901234567890123456789012345678901234567890 abcdefghijklmnopqrstuvwxyzisournewtest string. LengthofsTestStringis:51 Firstspaceisatposition:2 Nextspaceisatposition:4 Nextspaceisatposition:6 . . Nextspaceisatposition:46 Nextspaceisatposition:48 Nextspaceisatposition:50
133
Enterthiscodeintheconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMiPositionASInteger sTestString="abcdefabcdefabc" PRINT"12" PRINT"12345678901234567890" PRINTsTestString iPosition=RInstr(sTestString,"abc") PRINT PRINT"lastoccurrenceofabcstartsatposition:"&iPosition END
Theconsolerespondswith:
12 12345678901234567890 abcdefabcdefabc lastoccurrenceofabcstartsatposition:17
Split Splitsplitsastringintosubstringsdelimitedbytheseparator(s)designated asparameters.Escapecharacterscanbespecifiedalso.Anyseparatorcharacters enclosedbetweentwoescapecharactersareignoredinthesplittingprocess.Note thatSplittakes onlythreeargumentssoifyouwanttouseseveralseparators, youshouldpassthemasthesecondparameter,concatenatedinasinglestring. By default, the comma character is the separator, and there are no escape characters. This function returns a string array filled with each detected substring.TheGambaslanguagesyntaxis:
134
Hereisaprogramtotryonyourconsole:
STATICPUBLICSUBMain() DIMaWordArrayASString[] DIMsWordASString 'noteweuseaspacedelimiter aWordArray=Split("ThisisindeedaverycoolfeatureofGambas!","") FOREACHsWordINaWordArray PRINTsWord NEXT END
Theconsolerespondswith:
This is indeed a very cool feature of Gambas!
ConvertingDatatypes
AscandChr$ AscreturnstheASCIIcodeofthecharacteratpositionPositionintheString .IfPositionisnotspecified,theASCIIcodeofthefirstcharacterisreturned.Chr$ returnsthecharacterwhoseASCIIcodeisCode.Awordofcaution:Gambasuses the UTF8 charset internally, soany charactercode greaterthan128 maynot havethesamemeaningastheywouldhavewithanothercharset(forexample, ISO88591).HereistheGambaslanguagesyntax:
Code=Asc(String[,Position]) Character=Chr$(Code)
HereisasampleprogramthatillustratestheuseofbothASCandCHR$:
'Gambasclassfile
135
Inthecodeabove,Chr(9)isusedtorepresenttheTABcharacter.Theresulting outputfromtheconsoleis:
LengthofsTestStringis:16 71ischar: G 97ischar: a 109ischar: m 98ischar: b 97ischar: a 115ischar: s 32ischar: <space> 105ischar: i 115ischar: s 32ischar: <space> 103ischar: g 114ischar: r 101ischar: e 97ischar: a 116ischar: t 46ischar: .
Bin$ Bin$returnsthebinaryrepresentationofanumber.IfDigitsisspecified, the representation is padded with unnecessary zeros so that Digits digits are returned.HereisthecallingconventionforBin$:
136
Examplecodeyoucantryontheconsole:
STATICPUBLICSUBMain() DIMsBinaryCodeASString DIMcounterASInteger FORcounter=0TO15 sBinaryCode=Bin$(counter,4) PRINTsBinaryCode NEXT END
Theoutputshouldlooklikethis:
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Otherwise,theexpressionistrueinallothercases.HereistheGambaslanguage syntax:
137
Hereisanexample:
STATICPUBLICSUBMain() PRINTCBool(0);"";CBool(1) END
Theconsolerespondswith:
FALSETRUE
Example:
STATICPUBLICSUBMain() PRINTCByte("17") PRINTCByte(32769) PRINTCByte(TRUE) END
Theconsolerespondswith:
17 1 255
CDate CDate converts an expression into a date/time value. Be careful! The currentlocalizationisNOTusedbythisfunction.Gambaslanguagesyntaxis:
Date=CDate(Expression)
Example:
138
Theconsolerespondswith:
08/21/200520:52:40isourstarttime. 08/21/200520:52:41isonesecondlater. 08/21/200520:52:40isstillwherewestarted. 08/21/200520:52:42isonesecondlater.
Example:
STATICPUBLICSUBMain() DIMsFloatStringASString DIMfFloatNumASFloat sFloatString="0.99" fFloatNum=0.01 PRINTfFloatNum+CFloat(sFloatString) PRINTCFloat("3.0E+3") END
Theconsolerespondswith:
1 3000
139
CShort converts an expression into a short integer. Expression is first convertedintoaninteger.Then,ifthisintegeroverflowstheshortrange,itis truncated.HereistheGambaslanguagesyntaxforCShort:
Short=CShort(Expression)
Hereisanexamplethatslightlymodifiesthepreviousconsoleexampleto showbothofthesefunctions:
STATICPUBLICSUBMain() DIMsFloatStringASString DIMfFloatNumASFloat sFloatString="0.99" fFloatNum=120.901 PRINTfFloatNum+CFloat(sFloatString) PRINTCInt(fFloatNum);"wasafloat,nowanint." PRINTCShort(fFloatNum);"wasafloat,nowashort." END
Theresultis:
121.891 120wasafloat,nowanint. 120wasafloat,nowashort.
CStr/CString CStr/CStringconvertsanexpressionintoastring.Becareful!Thecurrent localization is NOTused by this function. Here is howthe Gambas language syntaxforCStrworks:
String=CStr(Expression) String=CString(Expression)
140
Consoleoutputis:
120.901isnowastring.
Hex$ Hex$returnsthehexadecimalrepresentationofanumber.IfDigitsisspecified, the representation is padded with unnecessary zeros so that Digits digits are returned.HereistheGambaslanguagesyntax:
String=Hex$(Number[,Digits])
Hereisanexampleprogram:
STATICPUBLICSUBMain() DIMcounterASInteger FORcounter=1TO15 PRINTHex$(counter,2);""; NEXT END
Thisistheresult:
0102030405060708090A0B0C0D0E0F
Conv$ Conv$ converts a string from one charset to another. A charset is represented by a string like "ASCII", "ISO88591", or "UTF8". The GAMBAS interpreter internallyusesthe UTF8charset.Thecharsetusedbythesystemis returnedbyacalltoSystem.Charset.ItisISO88591onMandrake9.2operating
141
Theconversionreliesontheiconv()GNUlibraryfunction.Hereisacode exampletotry:
STATICPUBLICSUBMain() DIMsStrASString DIMiIndASInteger sStr=Conv$("Gambas","ASCII","EBCDICUS") FORiInd=1TOLen(sStr) PRINTHex$(Asc(Mid$(sStr,iInd,1)),2);""; NEXT END
Hereistheoutput:
C781948281A2
StandardGambaslanguagesyntaxis:
Expression=Val(String)
142
Trythis:
STATICPUBLICSUBMain() DIMsDateTimeASString DIMdDateASDate PRINTNow;"iscurrentsystemtime." sDateTime=Val(Str$(Now)) PRINTsDateTime;"isastringrepresentationofcurrentsystemtime." PRINTVal(sDateTime);"isVALconvofthestringrepresentation." dDate=Val(sDateTime) PRINTdDate;"istheDATEvariableconvertedwithVAL." PRINTStr(dDate);"isastringrepresentationofthedatevariable." END
Hereistheoutput:
08/21/200521:42:45iscurrentsystemtime. 08/21/200521:42:45isastringrepresentationofcurrentsystemtime. 08/21/200521:42:45isVALconvofthestringrepresentation. 08/21/200521:42:45istheDATEvariableconvertedwithVAL. 08/21/200521:42:45isastringrepresentationofthedatevariable.
Hereisanothersampleprogramtotry:
'Gambasclassfile STATICPUBLICSUBMain() DIMsInputLineASString DIMvalueASVariant DOWHILEsInputLine<>"quit" PRINT"==>"; LINEINPUTsInputLine IFsInputLine=""THEN sInputLine="<CRLF>" ENDIF
143
Theoutputshouldbesimilartothis:
==>true Youtyped:true trueisBoolean. ==>214 Youtyped:214 214isanInteger. ItcouldalsobeaByte. Itcouldalsobeashort. ==>08/23/0512:23:55 Youtyped:08/23/0512:23:55
144
Format$ Format$convertsanexpressiontoastringbyusingaformatthatdepends onthetypeof theexpression.Formatcan bea predefined format(an integer constant)orauserdefinedformat(astringthatdepictstheformat).IfFormatis not specified, gb.Standard component formats are used. This function uses localization information to format dates, times and numbers. The Gambas languagesyntaxis:
String=Format$(Expression[,Format])
Auserdefinednumberformatisdescribedbythefollowingcharacters:
FormatSymbol "+" "" "#" "0" "." "%" "E" Meaning printsthesignofthenumber. printsthesignofthenumberonlyifitisnegative. printsadigitonlyifnecessary. alwaysprintsadigit,paddingwithazeroifnecessary. printsthedecimalseparator. multipliesthenumberby100andprintsapercentsign. introduces theexponential part of afloat number. The sign of the exponentis always printed.
145
Hereisaprogramthatdemonstratesseveralexamples:
STATICPUBLICSUBMain() PRINT"" PRINT"UserdefinednumericFormatexamples:" PRINTFormat$(Pi,"#.###") PRINTFormat$(Pi,"+0#.###0") PRINTFormat$(Pi/10,"###.#%") PRINTFormat$(11^11,"#.##E##") PRINT"" PRINT"Userdefineddateandtimeformatexamples:" PRINT PRINTFormat$(Now,"mm/dd/yyyyhh:nn:ss") PRINTFormat$(Now,"m/d/yyh:n:s") PRINTFormat$(Now,"dddddmmmyyyy") PRINTFormat$(Now,"ddddddmmmmyyyy") END
146
Datatypemanagement
Manytimeswhencheckingvariables,itisimportanttoknowwhatdata typeyouaredealingwith.Gambasprovidesahostoffunctionsforthatpurpose. Youcancheckforthefollowingdatatypes:
IsBoolean/Boolean? IsDate/Date? IsInteger/Integer? IsNumber/Number? IsShort/Short? IsByte/Byte? IsFloat/Float? IsNull/Null? IsObject/Object? IsString/String?
Each of the functions above are called using the standard Gambas language syntaxof BooleanResult=IsBoolean?(Expression) BooleanResult=IsByte?(Expression) BooleanResult=IsDate?(Expression) BooleanResult=IsFloat?(Expression) BooleanResult=IsInteger?(Expression) BooleanResult=IsNull?(Expression) BooleanResult=IsNumber?(Expression) BooleanResult=IsObject?(Expression) BooleanResult=IsShort?(Expression) BooleanResult=IsString?(Expression) and the given function will return TRUE if an expression is of the datatype queriedorFALSEifitisnot.
147
A Beginner's Guide to Gambas TypeOf TypeOfreturnsthetypeofanexpressionasanintegervalue.Gambashas definedseveralpredefinedconstantsforthedatatypesreturnedbythisfunction. The predefinedconstants Gambassupportsareshowninthetablebelow. The standardGambaslanguagesyntaxforthisfunctionis:
Type=TypeOf(Expression)
That'saboutallwewillcoverinthischapter.Inthenextchapter,wewill return to the Gambas ToolBox and start learning to use some of the more advancedcontrols,suchasiconview,listview,etc.Youshouldnowbeadequately preparedtodealwithmoreadvanceddatahandlingtechniquesrequiredforthose controls.
148
IconViewControl
Firstofall,startGambasandselecttheExplorerprojectfromtheMiscellaneous sectionoftheExampleprograms:
Figure54ChoosingtheExplorerexample.
ThisisthefirstsubroutineGambaswillexecutewhentheprogramisrun:
STATICPUBLICSUBMain()
Now,showtheform:
hForm.Show END
150
Wewillassignthepathpassedin(System.Home)asaparametertoourglobal variable$sPath:
$sPath=sPath
HereistheRefreshExplorer()subroutine.Itisessentiallythemeatofthe program:
PRIVATESUBRefreshExplorer()
First, we declare the local variables. Let's start with a string var to hold file names:
DIMsFileASString
Next,declarepicturevariablesforouriconimages:parentdirectory,folderand file:
DIMhPictDirASPicture DIMhPictParDirASPicture'addedbytheauthor DIMhPictFileASPicture
cDirisanarrayofstrings(representingthenamesoffilesordirectories):
DIMcDirASNEWString[]
sNameisaworkstringusedtorepresentfilenamesfoundinadirectory:
DIMsNameASString
The next statement is either not documented in Gambas or the documentationisunreachableontheGambaswebsite.However,thiscallappears toincrementtheBusyproperty valuethatisdefinedintheApplicationclass.It
151
A Beginner's Guide to Gambas seemstobeusedasasemaphoresootherprocessescantesttheflagbeforetrying to get computer time (remember, most applications use some sort of OS implementedroundrobinCPUschedulingroutinetoshareprocessorresources). Here,itisbasicallyaflagthattellsalltheothercallingprocessesthattheyhaveto waituntiluntilthisprocessisnotbusyanymore(indicatedbydecrementingthe valueoftheBusyproperty).ThisseemstobehowGambassetsflagstoprevent criticalprocessesfrombeinginterrupted.
INCApplication.Busy
Oncethedon'tinterruptmeflagisthrown,wesetthewindowtitletothe systempathandcallthebuiltinConv$14 functiontoconvertthesystemcharset (thesetofcharacterstheoperatingsystemhasprovidedasdefault)towhattheuser hasdefinedasthedesktopcharset(thesetofcharacterstheuserhaschosentosee fromtheirdesktop). Notethat Conv isasynonymfor Conv$ andyoucanuse eitheroneinterchangably.
ME.Title=Conv($sPath,System.Charset,Desktop.Charset)
Now, whatever may exist in the icon view is wiped out by calling the iconview'sClearmethod:
ivwExplorer.Clear
Next,assigniconstothepicturevariableswedeclared.Wehaveaniconto representfoldersandoneforfiles:
hPictDir=Picture["folder.png"] hPictParDir=Picture["ParentFolder.png"]'addedbytheauthor hPictFile=Picture["file.png"]
Thisnextlineofcodeisalittletrickertodecipher.TheStatfunctiontakes afilenamestringasitsparameter. Inthiscase,thecurrentpathheldinglobal variable $sPath is catenated with the work string sFile using the &/ symbol combination. ThisisaspecialcatenationsymbolusedinGambasspecificallyto catenate filenames. The Stat function is called with the catenated filename passedasaparameterandsimultaneouslythe Stat.Hidden propertyischecked. Ifthe Stat.Hidden propertyis set to aTRUE value,the CONTINUE statement executes,forcingprogramflowtothenextiterationoftheFORloop.Thiswhole processbasicallyforcestheprogramtoignoreanyhiddenfilesitencounters.
IFStat($sPath&/sFile).HiddenTHEN'isithidden? CONTINUE'ifso,gotonextloopiteration ENDIF'IFStat ENDIF'IFNOT$bHidden
OnceeverythingisloadedinthecDirarraywiththeFOR/NEXTloopwe callthebuiltinSortmethodandsortthearrayofstrings:
153
Now,wecheckthetagofthefilenameusingthestringfunctionLeft$:
IFLeft$(sFile)="D"THEN
If the 'D' tag is found, it is a directory and we add a directory to the IconViewcontrol usingthe Addmethod andourpictureofafolderasthelast parameterinthecall.
ivwExplorer.Add(sFile,sName,hPictDir) ELSE'otherwiseitwasafileandweadditwithafileicon ivwExplorer.Add(sFile,sName,hPictFile) ENDIF
Ifanerroroccurs,wewillcatchitwiththecatchclausebelow:
CATCH
Ifanyerroroccurs,itshouldpopupaMessageBoxwiththeerrortextdisplayed:
Message.Error(Error.Text) END'ofourRefreshExplorerroutine
Iftheuserchoosesthequitoptionfromthemenu,thenthisroutineexecutes:
PUBLICSUBmnuQuit_Click() ME.Close END
If the user selects the Refresh option, we will call the RefreshExplorer subroutinedescribedpreviously.
PUBLICSUBmnuViewRefresh_Click() RefreshExplorer END
Thissubroutineiscalledwhentheactivateeventistriggeredbyauserby doubleclickingonafolderintheIconViewcontrol:
PUBLICSUBivwExplorer_Activate()
Ifthecontrolkeywashelddown,wewilltogglethevaluebacktoFALSE beforeinstantiatinganewwindow.Then,wewillmoveourcontroltobeoffset 16pixelsrightandbelowthecurrentwindow,havingthesameheightandwidth using the hForm.Move method. Finally, we show the form and refresh the ExplorerwithourRefreshExplorersubroutine.
IF$bCtrlTHEN $bCtrl=FALSE hForm=NEWFExplorer(sNewPath) hForm.Move(ME.X+16,ME.Y+16,ME.W,ME.H) hForm.Show ELSE
Othewise, the control key was not held down so we simply assign the sNewPathvaluetotheglobal$sPathandrefreshtheexplorer:
$sPath=sNewPath RefreshExplorer ENDIF ENDIF
156
When the user clicks this routine, it calls our subroutine to show the hiddenfilesor,iftheyareshowing,turnoffviewingofhiddenfiles:
PUBLICSUBmnuViewHidden_Click() ToggleViewHidden END
Iftheuserchoosestoshowhiddenfilesintheexplorerbyselectingthe ShowHiddenFilesoption,thenthisnextroutineisexecuted.Thefirstlinechecks the value of the mnuViewHidden.Checked property and toggles the value by essentially making $bHidden become whatever the logical NOT value of mnuViewHidden.Checked is at the moment it is checked. It then assigns the oppositevaluetothepropertyandrefreshestheviewbycallingRefreshExplorer. Theresultisthatthehiddenfilesareshown.
PRIVATESUBToggleViewHidden() $bHidden=NOTmnuViewHidden.Checked mnuViewHidden.Checked=$bHidden RefreshExplorer END
This subroutine is executed when the menu's about item is clicked. It simplydisplaysaMessageBoxcreditingthecodetoGambasfounder,B.Minisini:
PUBLICSUBmnuAbout_Click() Message("IconViewexamplewrittenby\nBenotMinisini") END
157
Thefinaltwosubroutinestoggletheglobalvariable$bCtrlwheneverthe controlkeyispressedorreleased.
PUBLICSUBivwExplorer_KeyPress() IFKey.ControlTHEN$bCtrl=TRUE END PUBLICSUBivwExplorer_KeyRelease() IFKey.ControlTHEN$bCtrl=FALSE END
Thereyouhaveit.EverythingyouneedtoknowaboutusingtheIconView controlinacoolapplication.Next,wewilllookattheListViewcontrol.
ListViewControl
The ListView control inheritsControlandimplementsalistofselectable textitemswithicons.ListViewitemsareindexedbyakey.Theydisplayastring andanicon.Thiscontrolhasaninternalcursorusedforaccessingitsitems.You mustusetheMovemethods(MoveAbove,MoveBelow,MoveCurrent,MoveFirst, MoveLast,MoveNext MovePrevious,MoveTo)tomovetheinternalcursor,and youneedtousetheItempropertytogetthetextoftheitemthecursorpointsat. ThisclassiscreatableandthestandardGambaslanguagesyntaxis:
DIMhListViewASListView hListView=NEWListView(ParentASContainer)
158
Figure55LayoutforourListViewexample.
From the left top of the picture, you have our ListView control named ListView1, a Textbox named Textbox1, and the Insert Item button named Button1. TherearetwoRadioButtons,namedRadioButton1andRadioButton2 and the Remove Itembutton named Button2. Atthe botton of the form isa TextLabelnamedTextLabel1andtheQuitbuttonnamedButton3. Onceyou havecreatedtheformandmadeitastartupclass,weneedtoaddthefollowing codetothecodewindowtoseehowtoimplementaListViewcontrol:
'Gambasclassfile sStatusasString PUBLICSUBForm_Open() DIMpicSquareASNEWPicture DIMpicCircleASNEWPicture picCircle.Load("circle.png") picSquare.Load("square.png") 'ThiswilladdanitemtotheListViewwithastartingentry ListView1.Add("ListItem1","ListItem1",picSquare) TextLabel1.Text=ListView1.Item.Text ListView1_Click END
A Beginner's Guide to Gambas IntheListView1_Clicksubroutine,thefirstlineofcodemovestheinternal cursor to the most current item and highlights it by setting the Item.Selected property to TRUE in the second line. Finally, the third line updates our TextLabel1.Textvaluewiththetextofthecurrent(ornewlyadded)selectionand thecurrentstatus(heldinglobalvarsStatusASString)appended. Iftheuser clicks on the Insert item button (we named it Button1), this next routine is executed:
PUBLICSUBButton1_Click()
Declarealocalvariable,picToUse,forouricontobedisplayed:
DIMpicToUseASNEWPicture
Next, check which radioButton has been clicked. If the first button has been clicked,wewillloadtheimageforsquare.png,otherwise,circle.pngisloaded.
IFTextbox1.Text<>NULLTHEN IFRadioButton1.ValueTHEN picToUse.Load("square.png") ELSE picToUse.Load("circle.png") ENDIF
Getthecurrentitem(ordonothing)iftheListViewisempty:
ListView1.MoveCurrent()
Nowwewilladdanewentrywithakeyandnameinthetextbox:
ListView1.Add(Textbox1.Text,Textbox1.Text,picToUse)
Thisemptiesouttextbox:
TextBox1.Text="" sStatus="current."'setstatustocurrent
This call to the ListView1_Click subroutine will update (refresh) our ListView control:
ListView1_Click
Next,wemustensurethenewitemisinthevisibleareaofthecontrol:
160
TheButton2_Clicksubroutineiscalledwhenevertheuserdecidestodelete thecurrentlyselecteditemintheListViewcontrol.
PUBLICSUBButton2_Click()
Ifwereachedthispoint,wehavemovedthecursortoandneedtoremove thecurrentcursoritem:
ListView1.Remove(ListView1.Item.Text)
CleanupourTextLabel1.Textdisplaywiththiscall:
TextLabel1.Text=""
If the user clicks their mouse on an item in the ListView control, this
161
A Beginner's Guide to Gambas routineiscalled. WewillsimplyupdatetheTextLabel1.Textpropertywiththe text of the item selected and refresh the ListView control by calling our ListView1_Clicksubroutine.
PUBLICSUBListView1_Select() TextLabel1.Text=ListView1.Item.Text sStatus=selected. ListView1_Click END
UsingtheGambasIconEditTool
Atthispoint,allthecodeiscreatedforourListViewexampleprogram.We stillneedtocreatethecircle.pngandsquare.pngicons.WewillusetheGambas IconEditor todothat. Tobringuptheiconeditor,wewillgototheProject WindowintheIDE.IntheProjectTreeView,findtheDatafolderandrightclick yourmouse.PicktheNewitemandtheImagesubMenuitem.Youwillseethis dialogpopup:
162
Figure56CreatinganewIconimageinGambas.
SimplytypesquareintheNamefieldandclickok.Now,theiconeditor appears and you can create an icon. Use the rectangle option from the Icon EditorToolBoxandcreateabluesquareandsaveitwiththediskshapedicon.
Figure59Ourcircleicon image.
A Beginner's Guide to Gambas outtothetopofthetree. Thiscontroladdsafewmethodsspecificallyforthe purposeofmanagingthetraversaloftheparent/childtrees. TreeView, like all othercontrols,inheritsitsattributesfromtheControl class. Thiscontrolimplementsatreeviewofselectabletextitemswithicons. Treeviewitemsareindexedbyakey.Theydisplayastringandaniconforeach item. Thiscontrolhasaninternalcursorusedforaccessingitsitems.Usethe Move methods (Move, MoveAbove, MoveBack, MoveBelow, MoveChild, MoveCurrent, MoveFirst, MoveLast, MoveNext, MoveParent, MovePrevious, MoveTo)tomovetheinternalcursor,andtheItempropertytogettheitemit pointsat.Thisclassiscreatable.ThestandardGambaslanguagesyntaxis:
DIMhTreeViewASTreeView hTreeView=NEWTreeView(ParentASContainer)
ThecodeabovecreatesanewTreeViewcontrol.Thisclassactslikeareadonly array:
DIMhTreeViewASTreeView DIMhTreeViewItemAS.TreeViewItem hTreeViewItem=hTreeView[KeyASString]
The line of code above will returns a TreeView item from its key. The internal cursorismoved tothecurrentitem. Now,let'suse another example programfromtheGambasIDE.StartGambasandselecttheExamples|Basic| TreeViewsampleprogram. WhentheIDEopensup,youshouldseesomething similartoFigure60onthefollowingpage.
Figure60TheTreeViewProject window.
164
After adding theitems,we willmovethecursortothe lastitemadded using the TreeView1.MoveCurrent method and highlight it by setting the TreeView1.Item.Selected property to TRUE. Finally, we set the TreeView1.Item.Expanded property to TRUE to allow the item to collapse or expandwhentheuserclicksontheplus/minusicon. (NOTE:the GambasWiki documentationforthispropertylistsitasExpand,notExpanded.UsingExpandwill NOTwork.)
TreeView1.MoveCurrent TreeView1.Item.Selected=TRUE TreeView1.Item.Expanded=TRUE END
165
A Beginner's Guide to Gambas IftheuserclicksonanitemintheTreeView,wewanttorecordtheClick eventinoureventstackandupdatethestackdisplay(TextArea1.Text).Wethen incrementtheeventnumberbyone.NotethatinupdatingtheTextArea1.Text value, we simply take the new event and append everything else in the TextArea1.Textmemoryafterthelinefeedcharacter, Chr(10). Theneteffectof thiscallinaninsertionoftheneweventatthetopofthedisplayedtext.
PUBLICSUBTreeView1_Click() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Click"&Chr(10)& TextArea1.Text intEventNumber=intEventNumber+1
Next, we find out whether the item clicked is a parent (determined by whetherornotithaschildren).Ifthenumberofchildrenisgreaterthanone,we wantourlabel(TextLabel1.Text)tousethepluralformofchild.Ifthereisonly onechild,ourlabelwillsaychildandiftherearenone,wewantittosaytheitem hasnochildren.WeusetheIFTHEN/ELSEstatementtomakethischeck:
'Thislittlecheckjustupdatesourlabelsothatweknowhowmany 'childrenanentryhas. IFTreeView1.item.Children>1THEN textlabel1.Text=(TreeView1.Item.Text&"has"& TreeView1.Item.Children&"children.") ELSEIFTreeView1.item.Children=0THEN textlabel1.Text=(TreeView1.Item.Text&"hasnochildren.") ELSE textlabel1.Text=(TreeView1.Item.Text&"has1child.") ENDIF END
Iftheuserentersdatainthe Textboxcontrol andclickstheInsertName button(Button1),thefollowingclickeventisexecuted.Itfirstdeclarestwolocal variables. ThepicToUsevariablewilldeterminewhichpicturetoloadbasedon whichRadioButtonwasclickedatthetimetheInsertNamebuttonwasclicked. Thestringvariable,sParent,isassignedthevalueofthecurrentitem'skey.Ifthe MoveCurrentmethod triestomovetheinternalcursortothecurrentitemand thereisnoitem,itreturnsTRUE. Otherwise,FALSEwillbereturnedandwe assignthesParentstringthevalueofthekeythatiscurrent.
PUBLICSUBButton1_Click() DIMpicToUseASNEWPicture DIMsParentASString IFTextbox1.Text<>NULLTHEN
166
Now,weneedtoaddthenewentrywithakeyandanameofwhatwasin thetextbox.WewillplaceitintheTreeViewcontrolasachildofthecurrently selected entry. Note that the key names must be unique or it will crash the program.WecouldusetheExistmethodtofindoutifakeyexistswiththename Textbox1.TextbeforemakingthecalltotheAddmethod,butthatwasnotdone here.Ifwedidthat,thecodewouldmakeachecksimilartothis:
IFExist(Textbox1.Text)<>TRUETHEN TreeView1.Add(Textbox1.Text,Textbox1.Text,picToUse,sParent) ENDIF
Thisnextlinewillupdateourlabelandreflectthenewnumberofkids:
TreeView1_Click
If the user wantsto remove a name fromthe TreeView by clicking the RemoveNamebutton(Button2)thenthissubroutineisexecuted:
PUBLICSUBButton2_Click()
167
A Beginner's Guide to Gambas Firstofall,wemustgetthecursorlineduptoourcurrentselectionand makesurethatthecurrentitemisn'tanemptyornullvalue.IftheMoveCurrent method returns a true value, the list was empty and we are done. The code invokestheRETURNcallandwejumpbacktothecallingprocess. Otherwise, whateverthecurrentitemiswillberemovedbycallingtheRemovemethodinthe secondline,below:
IFTreeView1.MoveCurrent()THENRETURN 'Letsremovethecurrentcursoritem TreeView1.Remove(TreeView1.Item.Text)
Now we must move the cursor to the current item (since we are now pointing at a deleted item). Before we do that we need to check the count propertytomakesurewedidn'tdeletethelastiteminthelist.Ifwedid,thenwe obviouslydon'trunthispartofthecode. The IFstatement checksforacount greaterthanzeroand,ifTRUE, willmovetothecurrentitem,selectitsothe cursorishighlighted,andupdatethecontrolwithacalltotheTreeView1_Click subroutine.
IFTreeView1.Count>0THEN TreeView1.MoveCurrent 'Thisselectsor'highlights'ourcurrentitem TreeView1.Item.Selected=TRUE 'Thiswillupdateourlabelandreflectthenewnumberofkids TreeView1_Click ENDIF END
Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa Dbl_Clickevent.ItisbasicallythesameasanActivateevent.Theroutinebelow is called. It simply updates the event stack, as described previously, and
168
This next routine is dead code. It never gets executed because the Button2_Click subroutine takes care of the removal of an item. To use it effectively,itshouldbecalledfromtheButton2_Clicksubroutinejustbeforethe linecallingtheTreeView1_Clicksubroutine.Ifthisisdone,thentheeventstack wouldbeproperlyupdated,firstwiththedeleteandthentheclickevents.
PUBLICSUBTreeView1_Delete() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Delete"&Chr(10)& TextArea1.Text intEventNumber=intEventNumber+1 END
169
Thisnextroutineisalsodeadcode. Itnevergetsexecutedbecausethe nothingcreatesaneventtogethere.Touseiteffectively,amenuitem,Rename should be added to the Help menu and it should be called from the MenuItem.Clickevent.Ifthisisdone,thentheeventwouldbegeneratedandyou couldwriteabitofcodetogetthenewnamefromtheuserandchangeit.The eventstackwouldbeproperlyupdated,firstwiththerenameeventandthenwith theclickevent.
PUBLICSUBTreeView1_Rename() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Rename"&Chr(10)& TextArea1.Text intEventNumber=intEventNumber+1 END
ThatisallthereistotheTreeViewprogram.Youcanplayaroundwiththe code and implement the suggestions made herein. Once you are able to understand how to use these controls effectively, your Gambas interfaces will becomemoresophisticated. Next,wewilltakealookatthelasttwoadvanced viewcontrols,theGridViewandColumnViewcontrols.
170
TheGridViewControl
TheGridViewcontrol,likealltheothercontrolsintheToolBox,inheritsits attributesfromtheControlclass. GridViewimplementsacontrolthatdisplays data in a grid. This class is creatable. Standard Gambas language syntax for GridViewis:
DIMhGridViewASGridView hGridView=NEWGridView(ParentASContainer)
Thelineabovereturnsacellfromitsrowanditscolumn. Ourexample programforthiscontrolwillcreateagridthatisfourrowsofthreecolumns.We willpopulatethefirstthreerowswithtextandthelastrowwithpictures.Wewill takethelastrowoftextanddemonstratehowthealignmentpropertyworksfor textdata.Ourprogramwillhavethreebuttons,Quit,Clear,andReset. The Quit button will simply close the program. Clear will invoke the GridView.Clearmethodtoerasethecontentsofthegridanddisplayemptygrid cells.TheResetbuttonwillrepopulatethecontentsofthegridwiththedatathe program started with (i.e., the data populated when the form's constructor methodwascalled.Ourprogramwilllooklikethis:
Figure61WhatourGridViewwilllooklike.
171
A Beginner's Guide to Gambas To begin, start Gambas and select the New Project option, choosing to createaGraphicalUserInterfaceproject.Maketheprojecttranslatableandform controls public by checking the two boxes in the Wizard. Name the project GridViewExampleandputitintheGridViewdirectory.WhentheIDEappears, wewillneedtogototheprojectwindowandbringuptheICONEditor.Wewill createthreeicons,namedGridPic,GridPic1,andGridPic2,asshownabove.Try togetthemreasonablyclosetowhatyouseeinthepictureaboveifyoucan. Create a new formthat is a startup class form and put the GridView control, namedGridView1 on the formasshown above. Thenadd thethreebuttons, named Button1, Button2, and Button3 to the form. Make the Button.Text propertiesreflectwhatisshowninthepictureabove. Now,wehavetheformdesignedanditlookslikewhatweexpect. Lets startcoding.Doubleclickontheform,butnotonacontrol,andtheForm_Open subroutine will display in the code window. We will set the caption to your programhere:
'Gambasclassfile PUBLICSUBForm_Open() Form1.Caption="GridViewExample" END
Now,wemustinstantiatethepicturevariablesandloadthepictures.
hPic1=NEWPicture hPic1.Load("GridPic.png") hPic2=NEWPicture hPic2.Load("GridPic2.png") hPic3=NEWPicture hPic3.Load("GridPic1.png")
Thenextthingweneedtodoisdefinethedimensionsofthegrid. Our
172
Next, we will populate the grid with some data, simply identifying the row,columnpositionwithtext:
GridView1[0,0].Text="0,0" GridView1[0,1].Text="0,1" GridView1[0,2].Text="0,2" GridView1[1,0].Text="1,0" GridView1[1,1].Text="1,1" GridView1[1,2].Text="1,2"
Forthelasttextrow,wewanttodemonstratehowtousetheAlignmentproperty:
GridView1[2,0].Alignment=Align.Center GridView1[2,1].Alignment=Align.BottomLeft GridView1[2,2].Alignment=Align.TopRight
Aftersettingthealignmentpropertiesforeachcellintherow,wewilladdtext:
GridView1[2,0].Text="2,0" GridView1[2,1].Text="2,1" GridView1[2,2].Text="1,2"
Finally,wewilladdourthreeiconstothegrid:
GridView1[3,0].Picture=hPic1 GridView1[3,1].Picture=hPic2 GridView1[3,2].Picture=hPic3 END
173
The Clear button is next. Doubleclick on the Clear Button to get the Button2_Clickeventsubroutine,wherewewilladdourcodetoresetthegridto blankvalues:
PUBLICSUBButton2_Click() GridView1.Clear END
Theeasiestwaytorepopulatethedataistosimplyinvoketheconstructor onceagain.Addthiscodesothatiswhatwewilldo.
PUBLICSUBButton3_Click() _new END
TheColumnViewControl
Forournextexample,wearegoingtocreateaprogramthatdisplaysdata inaColumnView,asshownbelow:
Figure62OurColumnViewexample.
174
A Beginner's Guide to Gambas Our simple example will create three columns and five rows. We will populatethecolumndatawiththerow,columnidoftheparticularitem.Todo this,wewillneedtosetthewidthofeachcolumntobedynamicallycalculated basedonthewidthofthecontrolandthenumberofcolumnsspecified.Wewill dothisintheconstructor.Whentheprogramstartsup,allwearegoingtodo ontheForm_Opencallissetthewindowcaption,asshownintheForm_Open() subroutine:
'Gambasclassfile PUBLICSUBForm_Open() Form1.Caption="ColumnViewExample" END
Now, we need to set up the outer (row) and inner (column) loops. Basically,wewillloopthrougheveryeveryrowinthecontroland,ateachrow, wewillloopthrougheachcolumn,populatingtheColumnView1[row][column] arrayitemswithadynamicallybuiltstringoftextthatwillrepresentthecurrent positionwithintheinnerandouterloop.
FORirowcounter=0TO4'forallfiveofourrows 'calltheAddmethodwith[row][col]toaddtoColumnView1control
175
The Clear button is next. Doubleclick on the Clear Button to get the Button2_Clickeventsubroutine,wherewewilladdourcodetoresetthegridto blankvalues:
PUBLICSUBButton2_Click() ColumnView1.Clear END
ForourResetbutton,theeasiestwaytorepopulatethedataistosimply invoketheconstructoronceagain.Addthiscodesothatiswhatwewilldo.
PUBLICSUBButton3_Click() _new END
ThatisallthereistobuildingandpopulatingtheColumnViewcontrol.Next,we willtakealookathowtousethevariouslayoutcontrolsinGambas.
LayoutControlsHBox,VBox,HPanelandVpanel
All of the controls in this group are similar in that they try to arrange controls they contain automatically. They do so by using the .Arrangement property which relies upon constants that are defined in the Arrange class. ConstantsusedbytheArrangementpropertyofthesecontainercontrolsinclude thefollowing:Fill,Horizontal,LeftRight,None,TopBottom,andVertical.If youdonotspecifyan.Arrangementpropertyvalue,thenthecontroldefaultsto whatever it is designed to do, i.e., HBox would arrange controls horizontally,
176
A Beginner's Guide to Gambas VBoxvertically,etc. HBoxandVBox Both of these classes are containers that arrange their children either horizontally or vertically. Like all other ToolBox controls, they inherit their attributesfromtheContainerclass.BothofthesecontrolsactlikeaPanelwithout aborderwhoseArrangementpropertywouldbesettoArrange.Horizontal.These classesarecreatable.StandardGambaslanguagesyntaxtocreateanewHboxis:
DIMhHBoxASHBox DIMhVBoxASVBox hHBox=NEWHBox(ParentASContainer) hVBox=NEWVBox(ParentASContainer)
HPanelandVpanel Bothoftheseclassesarecontainersthatarrangestheirchildrenfromtopto bottom,andthenlefttorightfortheHpanelandlefttoright,toptobottomfor theVPanel. Theyarebothlikeanordinary Panelcontrol withoutaborderbut whose Arrangement property would be set to Arrange.TopBottom ( where a containerstacksitschildrenfromtoptobottom;ifthechildrencontrolscan'tfit vertically,anewcolumnofcontrolsisstartedjustafterthepreviouscolumn)or Arrange.LeftRight (whereacontainerstacksitschildrenfromlefttoright;ifthe childrencontrolscan'tfithorizontally,anewrowofcontrolsisstartedbelowthe previous row). Both these types of controls inherit their attributes from the Containerclass.Thisclassiscreatable.StandardGambaslanguagesyntaxis:
DIMhHPanelASHPanel DIMhVPanelASVPanel hHPanel=NEWHPanel(ParentASContainer) hVPanel=NEWVPanel(ParentASContainer)
Figure63Layoutprojecticons.
Figure64Form1designmodeshowinglayoutofourcontrols.
Fromthetopleftofthefigureabove,westartwithaVBoxandaTextLabel. BelowtheTextLabelistheHBox. Whenyoucreatethesecontrols,Gambaswill suggestdefaultnamesforeachcontrol.Takethedefaultnamesforeachcontrol becauseourprogramusesthosedefaults. PlacethreeToolButtonsintheVBox and four ToolButtons in the HBox. Next, set the picture properties of each ToolButtontotheiconsyouchosetouse(hopefullythesameasthoseabove)for ourproject. Onceyouhavetheiconsdisplayed,weneedtostartwiththefirst ToolButtonintheVBoxanddoubleclicktobringupthecodewindow.Youwill
178
ThenextcontrolcontainerwewillcreateistheHPanel,asshowninthe figureabove. WewilladdfourRadioButtonsandthreeregularbuttonstothis containercontrol.Trytoarrangethebuttonsasshowninthefigure.Youwillsee why this is important once you run the program and see how the HPanel rearrangesthecontrols.Onceagain,doubleclickoneachradiobuttonandadd thefollowingcode:
PUBLICSUBRadioButton1_Click() TextLabel1.Text="RadioBtn1clicked." END PUBLICSUBRadioButton2_Click() TextLabel1.Text="RadioBtn2clicked."
179
The last thing we will do is create the VPanel with three CheckBoxes. RemembertoarrangetheCheckBoxesinyourformlikethoseinthepictureabove toseehowthecontrolrearrangesthemautomatically. Addthiscodewhenyou haveplacedtheCheckBoxesintheVPanel:
PUBLICSUBCheckBox1_Click() IFCheckBox1.Value=TRUETHEN TextLabel1.Text="Checkbox1checked." ELSE TextLabel1.Text="Checkbox1unchecked." ENDIF END PUBLICSUBCheckBox2_Click() IFCheckBox2.Value=TRUETHEN TextLabel1.Text="Checkbox2checked." ELSE TextLabel1.Text="Checkbox2unchecked." ENDIF END PUBLICSUBCheckBox3_Click() IFCheckBox3.Value=TRUETHEN
180
Figure65Layoutprogramwhenitstartsup.
NoticehowtheRadioButtonsintheHPanelhavealignedverticallyfrom RadioButton4toRadioButton1and,becausetherewasroom,itplacedthebutton controlstotherightandcontinuedthealignmentfromtoptobottom,lefttoright. For the VPanel, see how the CheckBoxes aligned themselves. These types of controlsareunpredictableinhowtheywilllayouttheirchildren.Itisbesttouse theseincodedynamicallywhenyouhavetocreateformsontheflyanddonot havetheopportunitytolaythemoutinafixedpanelindesignmode. TheVBoxandHBoxcontrolsholdtheToolButtonsandallowyoutocreate nifty little toolbars that work well with iconic driven controls, such as those depictedwithouricons. Onceyouhavefinishedplayingaroundwithourlittle application,closetheprogramandwewillmoveontolearnaboutTabStrips.
TheTabStripControl
TheGambasTabStripcontrolimplementsatabbedcontainercontrol.Like all controls, it inherits its attributes from the Container class. This class is creatable.Thisclassactslikeareadonlyarray.ThestandardGambaslanguage syntaxis:
DIMhTabStripASTabStrip
181
Invoking the code above will return a virtual tab object from its index. TabStripsareusefulfororganizingandpresentinginformationinselfcontained units.TabStripsallowyoutoobtaininputfromusersbypresentingasimple,easy tofollowinterfacethatcanliterallyguidethemthroughaconfigurationorsetup process.HereisasampleofaTabStripinuse:
Figure66ATabStripcontrol.
TodemonstratehoweasyTabStripsaretocreate,wewillbuildasmall applicationthatimplementsthetabbedinterfaceyouseeabove.Ourapplication thatwillshowyouhowtousetabbedcontrolstopresentinformationtoauser andrespondtoitinyourapplications.StartGambasandcreateanewgraphical userinterfaceprogram.NametheprojectTabs,clickthroughtheProjectCreation WizardandwhenyougettotheGambasIDE,makeanewform,Form1thatisa startupclass. Next,youwillneedtoplaceaTabStripcontrolonthenewform.Onceyou place the TabStrip, you will only see one tab displayed. You must go to the propertieswindowandsettheCountpropertyto5tohavethecontrollooklike theoneweshowabove.NotethattabnumberingstartsatzeroinGambas.Each tabactslikeacontainerforthecontrolsyouplaceonit.Wewillalsoneedtoadd aTextLabelandabuttontoourform. TheTextLabelwillbeusedtoshowthe useractionsinresponsetoourtabbedinterface.ThebuttonwillbeaQuitbutton whichwewillusetoterminatetheapplication. Hereiswhatyourformshould looklikeasyoustarttodesigntheinterface:
182
Figure67TabProjectForm1.formDesign.
Youwillalsoneed tocopy theconfigure,help,and exit iconsfromthe LayoutprojecttotheTabsfoldersowecanusethemwiththisproject.Gambasis designtocontainallprojectworkfromtheIDEtothefolderyoucreatewhenyou startaproject. Asaresult,youneedtomoveoutoftheIDEtocopyfilesfrom anotherfoldertothecurrentproject(aquirkbydesign,perhaps?).Anyway,let's get going on this project. For Tab0 we will add a frame and place two RadioButtonsinit,likethis:
Figure68Tab0layout.
Next,doubleclickoneachRadioButtonandenterthiscode:
PUBLICSUBRadioButton1_Click() TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton1" END PUBLICSUBRadioButton2_Click() TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton2" END
183
Figure69Tab1layout.
DoubleclickoneachCheckBoxandenterthiscode:
PUBLICSUBCheckBox1_Click() IFCheckBox1.Value=TRUETHEN TextLabel1.Text="Youhavechecked:<br><center><strong>CheckBox1" ELSE TextLabel1.Text="Youhaveunchecked:<br><center><strong>CheckBox1" ENDIF END PUBLICSUBCheckBox2_Click() IFCheckBox2.Value=TRUETHEN TextLabel1.Text="Youhavechecked:<br><center><strong>CheckBox2" ELSE TextLabel1.Text="Youhaveunchecked:<br><center><strong>CheckBox2" ENDIF END
Thecodeabovewilldeterminewhethertheuserischeckinganitemor uncheckingitbyfirstlookingattheValueproperty.IfitisTRUE,thentheboxis already checked and we will indicate that fact in the update of the TextLabel1.Text.Otherwise,itisbeinguncheckedandwewillupdatethelabelto statethatfact. ForTab2,wearegoingtoplaceaPanelcontrolontheTabandaddthree ToolButtons. DonotmakethemistakeofplacingoneToolButtonandtryingto copyitandmovethecopyintothepanel.Itwillnotberecognizedasachildof thepanel control. Itwill appearonalltabs(I believethisis another quirkof Gambas). Inorderforthe Panelcontrol toaccepttheToolButtonsaschildren, youmustindividuallyclicktheToolButtonontheToolBoxandcreateeachone justasyoudidwiththefirstToolButton.ForeachToolButton,assignthepicture propertythenameoftheiconweareusingforthatbutton,asshownhere:
184
Figure70Tab2ToolButtonlayoutwith icons.
ThenextstepistodoubleclickoneachToolButtonandaddthiscode:
PUBLICSUBToolButton1_Click() TextLabel1.Text="Youclicked:<br><center>the<strong>ConfigureIcon" END PUBLICSUBToolButton2_Click() TextLabel1.Text="Youhaveclicked:<br><center>the<strong>HelpIcon" END PUBLICSUBToolButton3_Click() TextLabel1.Text="Youhaveclicked:<br><center>the<strong>ExitIcon" END
Figure71Tab3layoutwithaComboBox.
Remember,inordertosettheitemsintheComboBox,youneedtogoto thePropertieswindowandselecttheListproperty.Abuttonwiththreedotswill appear(indicatingthatitleadstotheListEditor)andyouneedtoclickthat.Add the following items: Pick something (to display as our default text), This
185
A Beginner's Guide to Gambas thing,Thatthing,andSomeotherthingtothelist.Finally,weneedtosetan eventfortheComboBoxbysingleclickingonthe ComboBoxcontrol thenright clicking themouse. Choose Events and selectthe Change event. Anytimethe ComboBoxchanges,wewanttodisplaythechangedtextonourTextLabel.Now, addthiscodeintheCodeEditorfortheComboBox1_Change()event:
PUBLICSUBComboBox1_Change() DIMcomboitemASString comboitem=ComboBox1.Text TextLabel1.Text="Youpickeditem:<br><center><strong>"&comboitem END
Inorderforthetimertowork,wemustenableitwhentheformfirststarts. Doubleclickontheformsomewhereexceptonacontroland youwillseethe Form_Open() subroutine appear in the code window. Add this code to the routine:
PUBLICSUBForm_Open() Form1.Caption="PlayingwithTabStrips" Timer1.Enabled=TRUE TextLabel1.Text="" END
186
187
Access Dir Eof Exist IsDir/Dir? Lof Stat Temp/Temp$ OPENandCLOSE INPUT,LINEINPUT,andPRINT READ,SEEK,WRITEandFLUSH COPY,KILLandRENAME MKDIRandRMDIR LINK
Access
Accessisafunctionusedtodetermineifafileisaccessibleornot. The Gambaslanguagesyntaxis
Accessible=Access(Path[,Mode])
The Access function call returns TRUE if the file specified by Path is accessible.IfthevalueofModeisgb.Read,thenthefunctionreturnsTRUEifthe filecanberead.Thisisthedefaultvalueforallfiles.IfModeisgb.Write,then AccessreturnsTRUEifthefilecanbewrittento.Whengb.Execisspecifiedfor Mode,thefunctionreturnsTRUEifthefilecanbeexecuted.Thepreviousflags canbecombinedwiththeORoperator.Foradirectory,theexecutionflagmeans thatthedirectorycanbebrowsed.Forexample:
PRINTAccess("/home/rabbit",gb.WriteORgb.Exec)
wouldreturn
188
whilethestatement
PRINTAccess("/root",gb.Write)
willreturn
False
Dir
The Dir function returns a string array that contains the names of files located in Directory that matches the specified File pattern. If no pattern is specified,anyfilenamethatexistsinthedirectoryisreturned.Thepatternmay containthesamegenericcharacterspermittedforthe LIKE operator. Inother words,thosecharactersfoundinthefollowingtable:
Genericcharacter * ? [abc] [xy] [^xy] Matches Anynumberofanykindofcharacter. Anysinglecharacterofanytype. Anycharacterspecifiedbetweenthebrackets. Anycharacterthatlieswithinthespecifiedinterval. Anycharacterthatisnotfoundwithintheinterval.
Hereisanexamplecodesegmenttohelpyou
'Printadirectory SUBPrintDirectory(DirectoryASString) DIMsFileASString FOREACHsFileINDir(Directory,"*.*") PRINTsFile NEXT END
189
Eof
TheEoffunctionreturnsaBooleanvalueofTRUEifweareattheendof thestream.StandardGambaslanguagesyntaxis:
Boolean=Eof(File)
AnexampleofhowEofisusedfollows:
... OPENFileNameFORREADAS#hFile WHILENOTEof(hFile) LINEINPUT#hFile,OneLine PRINTOneLine WEND CLOSE#hFile ...
Exist
The Existfunction returnsTRUEifafileoradirectoryexists.Using~as directoryidentifierdoesnotwork.Ifthepathspecifieddoesnotexist,FALSEis returned.Gambaslanguagesyntaxis:
Boolean=Exist(Path)
HereisanexampleofusingExisttodetermineifafileexistsbeforecallingOPEN toreadthefile:
... DIMsCurrentFileNameASString sCurrentFileName="TheRaven.txt" IFExist(sCurrentFileName)THEN ...'openthefile ELSE Message.Info("File"&sCurrentFileName&"doesnotexist.") ENDIF ...
190
IsDir/Dir?
TheIsDirfunctionreturnsTRUEifapathpointstoadirectory.Ifthepath does not exist or is not a directory, this function returns FALSE. Gambas languagesyntaxforIsDiris:
Boolean=IsDir(Path)
Some examples of how to use IsDir that were provided on the Gambas documentationWikiare:
PRINTIsDir("/etc/password") False PRINTIsDir(Application.Home&/".gambas") True PRINTIsDir("/windows") False
Stat
TheStatfunctionreturnsinformationaboutafileoradirectory.TheFile objectinformationreturnedincludesthetype,size,lastmodificationdate/time, permissions,etc.Thefollowingfilepropertiescanbeobtainedusingthisfunction:
.Group .Mode .Sticky .Hidden .Perm .Time .LastAccess .LastChange .LastUpdate .SetGID .SetUID .Size .Type .User
ThestandardGambaslanguagesyntaxforStatis:
Fileinfo=Stat(Path)
Here is an example of how to use Stat and what will be returned from the console:
WITHStat("/home") PRINT.Type=gb.Directory PRINTRound(.Size/1024);"K" ENDWITH
Theconsolewillrespondwith:
191
Temp/Temp$
TheTemp$functionreturnsauniquefilenameusefultocreatetemporary files. The filename created will be located in the /tmp directory. Gambas languagesyntaxis:
Filename=Temp$()
Example:
PRINTTemp$() /tmp/gambas.0/12555.1.tmp
OPENandCLOSE
OPENandCLOSEworkasateam.OPENopensafileforreading,writing, creatingorappending data. UnlesstheCREATEkeywordisspecified,thefile mustexist.IftheCREATEkeywordisspecified,thenthefileiscreated,orcleared ifitalreadyexists.Ifthefileisopenedforwriting,thepathtoitmustbeabsolute becauserelativepathsare,bydefault,assumedtorefertofilesthatexistinside thecurrentGambasprojectorarchivefolder.GambaslanguagesyntaxforOPEN is:
OPENFilenameFOR[READ][WRITE][CREATE|APPEND][DIRECT] [WATCH][BIG|LITTLE]AS#Variable
IftheBIGorLITTLEkeywordisspecified,allsubsequentREADandWRITE operationsonthisfilewill use bigEndian or littleEndian data representation. Variable receives the object that represents the opened stream. CLOSE is the reciprocalfunctionandsimplyclosesanopenedfile.SyntaxforusingCLOSEis:
192
Hereisanexamplethatopensandclosesafile: 'GambasClassFile
sCurrentFileNameASString sCurrentFileLengthASInteger PUBLICSUBForm_Open() DIMsInputLineASString DIMhFileInASFile sCurrentFileName="TheRaven.txt" IFExist(sCurrentFileName)THEN OPENsCurrentFileNameFORREADAShFileIn sCurrentFileLength=Lof(hFileIn) WHILENOTEof(hFileIn) LINEINPUT#hFileIn,sInputLine'LINEINPUTisexplainedbelow TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine WEND CLOSEhFileIn ELSE Message.Info("File"&sCurrentFileName&"doesnotexist.") ENDIF END
LINEINPUT
LINEINPUTreadsanentirelineoftextonthestandardinput.Itcanbe usedontheconsoleorwithfiles.TheGambaslanguagesyntaxis:
LINEINPUTVariable
or,forfileswherethedataisreadfromthestreamFile:
LINEINPUT#File,Variable
HereisanexampleyoucantrytoseehowLINEINPUTworks:
STATICPUBLICSUBMain() DIMhFileASFile DIMsInputLineASString
193
where 256 isthemaximumnumberofbytesyouwantread(precededwitha dash) symbol. The 256 can be any number, but you should limit it to the maximumsizeofanyvariableyourprogramwillusetoholdthereaddata.
READ,SEEK,WRITEandFLUSH
TheREADfunctionreadsdatafromthestandardoutput.Ittreatstheinput streamasbinarydatawhosedatatypeisspecifiedbythetypeofthevariablethe dataisstoredinduringthereadoperation.Thebinaryrepresentationofthedata shouldbethesamerepresentationcreatedbyuseoftheWRITEinstruction. If Variableisastring,youcanspecifyalengththatindicatesthenumberofbytesto read.IfthevalueoftheLengthparameterisnegative,thenLengthbytesareread fromtheendofstream.IfnoLengthparameterisspecifiedforastring,theentire stringisreadfromthestream.Thestringvaluethenmusthavebeenwrittenwith theWRITEinstruction.StandardGambaslanguagesyntaxforREADis:
READVariable[,Length]
IfREADisusedwithfileoperations,theGambaslanguagesyntaxis:
READ#File,Variable[,Length]
TheWRITEfunctionwritesexpressionstothestandardoutputusingtheir binary representation. If Expression is a string, you can specify a length that indicatesthenumberofbytestowrite.Ifnolengthisspecifiedforastringvalue, theentirestringvalueiswrittendirectly tothestream. HereistheGambas
194
andforwritingtoafile,thisistheconvention:
WRITE#File,Expression[,Length]
TheSEEKfunctiondefines(ormoves)thepositionofthestreampointer, most often in preparation for the next read/write operation. If the position specifiedbythe Length parameterisnegative,thenthestreampointerismoved backwards Length bytesfromtheendofthefile. Tomovethestreampointer beyondtheendofthefile,youmustusethe Lof()function. StandardGambas languagesyntaxis:
SEEK#File,Position
HerearesomeexamplesofusingSEEK:
'Movetothebeginningofthefile SEEK#hFile,0 'Moveaftertheendofthefile SEEK#hFile,Lof(#hFile) 'Move100bytesbeforetheendofthefile SEEK#hFile,100
TheFLUSHfunctioniscalledtoempty(orflush)thecontentsofabuffered data stream.Ifnostreamisspecified,everyopenstreamisflushed. Typically, FLUSHiscalledaftermultiplewriteoperationsandbeforeclosingoutaprogram or routine toensure all data held in a bufferis written out to the file before exiting.HereistheGambaslanguagesyntaxforFLUSH:
FLUSH[#File]
COPY,KILLandRENAME
The COPYfunction willcopyasourcefiletoaspecifieddestinationfile. Thedestinationpathneednothavethesamenamethanthesourcepath. You cannot copy directories recursively with this function. The Gambas language syntaxforthisfunctionis:
195
HereisanexampleofhowtouseCOPY:
'Savethegambasconfigurationfile
COPYSystem.Home&/".gambas/gambas.conf"TO"/mnt/save/gambas.conf.save"
The KILLfunction removesafile. TheGambaslanguagesyntaxis KILL Path and whatever exists in Path is permanently deleted. RENAME simply changesthenameofafileorfolderfrom Oldname to Newname. Hereisan example:
RENAMEOldnameASNewname
MKDIR,RMDIR
TheMKDIRfunctionisusedtocreate(make)afolderonyourfilesystem andRMDIRisusedtoremoveafolder.Bothfunctionstakeasingleparameter,a Filepathandname.TheGambaslanguagesyntaxis:
MKDIRfile:/rittingj/MyDocuments/Gambas/test RMDIRfile:/rittingj/MyDocuments/Gambas/test
Figure72TheFileOpsprogramatruntime.
196
Tostart,loadGambasandcreateanewgraphicaluserinterfaceproject. NameitFileOpsandwhenyougettotheGambasIDE,createanewform,Form1 andmakeisastartupclass.Whentheformdisplaysonyourscreen,wearegoing tobeginbycreatingthemenus. Youcanpress CTRLE tobringupthe Menu Editor.Addthefollowingmenuitemsshowninthetablesbelowusingtheeditor. Fortheicons,youwillneedtocopyiconsfromthesamedirectorywespecifiedin thelastchapter. Most Linuxbaseddistributionshaveiconfilesthatareusually stored in the folders namedfile:/usr/share/icons/defaultkde/32x32/actions orfile:/usr/share/icons/defaultkde/32x32/applications. Your particular system maybeslightlydifferent.Regardlessofwhereyoufindtheicons,pickouticons appropriateforourprogramandcopythemtotheFileOpsfolder.Herearethe17 iconsIchosetouseforthisproject:
FileOpen EditUndo
FileSave EditRedo
FileSaveAs EditCut
FilePrint EditPaste
Exit EditCopy
Format Colors
Format Fonts
HelpAbout
Help Contents
197
A Beginner's Guide to Gambas If you cannot find the exact same icon, simply pick one that is most appropriateandsaveitwiththefilenameforthatoptionasshowninthetables below.Itisnotcrucialthateveryiconbeexactlythesame.Infact,theSelectAll iconwascreatedusingtheGambasIconEditor. FileMenu VariableName FileNewItem FileOpenItem FileSaveItem FileSaveAsItem FilePrintItem FileExitItemMenu EditMenu VariableName EditSelectAllItem EditUndoItem EditRedoItem EditCutItem EditCopyItem EditPasteItem EditPrefsItem FormatMenu VariableName FomatColorItem FormatFontItem HelpMenu HelpContentsItem HelpAboutItem
"Contents" "About"
Picture["contents.png"] Picture["buildingblocks.png"]
198
Whentheprogramstarts,thissubroutineiscalled.Itcallsaconstructor,_new() toinitialize.Theconstructorisexplainedinthenextsection.Whenourprogram starts,wearegoingtohaveitautomaticallyloadourdefaulttextfile,namedThe Raven.txt.ThisfilewascopiedofftheInternetandyoucanplaceanytextfilein theFileOpsprojectfoldertouseforthisproject.Justrememberthatthefilename has to be changed in the code below if you choose not to use our default filename.
PUBLICSUBForm_Open() DIMsInputLineASString DIMhFileInASFile
ThatisallthereistotheForm_Open()subroutine.Hereistheconstructorforthe form:
PUBLICSUB_new() Timer1.Delay=1000 Timer1.Enabled=TRUE END
Theconstructorsimplysetsthetimerdelayto1second(1000ms)andsets theenabledpropertytotrue. Theneteffecthereisthatthetimerwillupdate itselfeverysecond.Wewillimplementthetimercontrollaterinthiscode. Let'snowturnourattentiontotheFile|Newmenuoption.Foranewfile tobecreatedbytheuser,wemustfirstblankoutthetextintheTextArea1.Text property.Wewillprompttheuserforanewfilenameandsavetheblankfileto disktocreateit. Whateverchangestheuserwillmakewillbesavedonexitor whenevertheuserchoosestosavefromthemenu.Thelastthingwedointhis subroutineissettheForm1.Captionpropertytothenewlysavedfilename.
PUBLICSUBFileNewItem_Click() TextArea1.Text="" Dialog.Title="Enternewfilename..." Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"] Dialog.SaveFile Form1.Caption=Dialog.Path END
ThenextroutineisactivatedwhentheuserclickstheFile|Openmenuitem.
200
The filename of the file that was selected by the user is stored in the Dialog.Pathproperty.WewillassignthattotheglobalvariablesCurrentFileName so other parts of the program will have access to it. We will set the Form1.Caption property to the name of the newly opened file and clear the currentTextArea1displaybyinvokingtheClearmethod.
sCurrentFileName=Dialog.Path Form1.Caption=""&sCurrentFileName&"" TextArea1.Clear
Next,wewillopenthefileandreadeachlineintomemoryusingtheLINE INPUTfunctionandourstringvariablesInputLine. Oncethedataisstoredin sInputLine, we will add it to the end of whatever is currently stored in the TextArea1.Textproperty(effectively concatenating ontotheendofthecurrent textvalue)andaddourCRLFcharacters.Oncewereachtheendofthefile,we willexittheloopandclosethefile.
OPENsCurrentFileNameFORREADAShFileIn
201
TheFile | Savemenuitem,whenclicked,willinvokethissubroutine. It worksalmostlikethepreviousoneexceptthatwealreadyknowthenameofthe file held in the global variable sCurrentFileName. When we return from the standarddialogcall,weupdatetheglobalvariablewithwhateverwasreturned notcaringifthefileisthesamenameornot.Whateveritisorhasbecomewill bewhatissaved.
PUBLICSUBFileSaveItem_Click() Dialog.Title="Savetextfile" Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"] IFDialog.SaveFile()THEN RETURN ELSE sCurrentFileName=Dialog.Path File.Save(sCurrentFileName,TextArea1.Text) ENDIF END
ThenextsubroutinewewillcodeistheFileSaveAsmenuitem.Iftheuser wantstosavetheexistingfileunderadifferentfilename,thisistheroutineto handle thatoption. Forthissubroutine,itwillworkalmostidenticallytothe FileSavesubroutinebutwewillneedtochecktoseeifthefilenamereturnedfrom thestandardfiledialogisactuallydifferentthanthecurrentfilename. Ifitis different,thenwewillsavethefileunderthenewname.Ifthenameisthesame, wewillpopupaMessageBoxandinformtheuserthatnosaveactionwastaken becausethenameswereidentical.
PUBLICSUBFileSaveAsItem_Click() DIMsTmpNameASString
WeusethelocalstringvariablesTmpNametomakeourcheck.Firstofall, we need to the the full path to the application and concatenate the current filenametothattogetthefullyqualifiedpathnameforourfile. Weusethe Applicationclassforthatpurpose,checkingthePathpropertytogetthenameand path of the running application. Note the use of the &/ operator which is specificallyusedtocatenatefilenames.
202
Justaswedidpreviously,wewillsetthetitleandfilterproperties,then callthestandardfiledialog.
Dialog.Title="Savetextfileas..." Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]
Ifthefilenamesarethesame,wewillpopuptheMessageBoxandreturn:
ELSEIFsTmpName=Dialog.PathTHEN Message.Info("Filenotsaved:namesameascurrentfile.","OK") RETURN
203
We MUST call the Printer.Setup() subroutine before we actually try to print something.ItismandatorytocallthisfunctioninGambas.
IFPrinter.Setup()THENRETURN
204
The calculation for obtaining iPrinterAreaWidth and iPrinterAreaHeight subtracttheleft/rightandtop/bottommarginsfromthetotalpagewidth/height. ForLettersizedpaper(8.5x11)thewidthvaluewouldbe8.5inchestimes300 dpior2550 and theheightwouldbe11 inchestimes300 dpi or3300. Our calculationsubtracts600(300forleftmargin+300forrightmargin)fromboth thewidthandtheheightvaluesreturnedfromthePrinter.Setupcall. Next,we needtobuildtheoutputstringforourMessage.Infocallanddisplaythatdatato user:
'buildastringforMessageBoxwithdatafromprintersetupcall strMsg="Res:"&Str(Printer.Resolution)&",Width:"&Str (Printer.Width)&",Height:"&Str(Printer.Height) 'showaMessageBoxwithdataobtainedfromtheprintersetupcall message.Info(strMsg)
Next, we need to parse all of the content of the text in the TextArea1 controlintoastringarray.ItisveryeasytodoinGambasandonlytakesasingle line of code. To do this,we willuse theSplitfunction and setthe delimiter parametertothe'\n'characterwhichdesignatestheendofthelineoftext:
'useanarrayofstringstostoreeachlineoftextinTextArea1.Text arsTxtToPrint=Split(TextArea1.Text,"\n")
Inourcodebelow,wehavecalledtheDraw.Rectfunctiontodrawaborderatone inchmarginsaroundourpage.
'makeaborderaroundthepage Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin) 'nowwewillloopthrougheachlineinthearrayandprintit FOREACHsTxtLineINarsTxtToPrint
205
Now,wewillmakethecalltoDraw.Texttoactuallyprintthetext. The firstparameterDraw.TexttakesisthestringobjectsTxtLinerepresentingourline of text to be printed from the array of string arsTxtToPrint. The next two parameters, iLeftMargin and (iTopMargin+iTxtPosY) areused todefine theleft marginandthecurrentverticalTextYposition.Eachlineisincrementedbythe valueheldintheproperty Draw.TextHeight. Optionally,youcanspecifyright andbottommargins,andanalignmentproperty.Inourcasebelow,wespecified the right margin, defined by iPrinterAreaWidth (as we calculated above) and omittedthebottommarginsinceitismaintainedinthecodeoftheFORLOOP above.Finally,wehavespecifiedthealignmentofthetexttobeleftaligned.
'Nowweprintthetextlineatthenewlineposition
Draw.Text(sTxtLine,iLeftMargin,iTopMargin+iTxtPosY,iPrinterAreaWidth,,Align.Left)
NEXT'iterationoftheFORLOOP
Tofinishtheprintprocess,youMUSTremembertocallDraw.End:
Draw.End'Thenprintfinalcontentsandejectlastpage END
Sinceourexampleprogramonlyworkswithtextfiles,thereisanalternate, sometimeseasiermethodofprinting.Youcanusethesystem'sbuiltinpr(print) command. ItisinvokedusingtheGambasSHELLmethod. Thiscallcanallow youtoprintanytextfilefromwithinyourprogramdirectlytothedefaultprinter. Toseehowthismethodworks,let'saddamenuitemtoourprogramandtrythis. GototheForm1.formandpressCTRLEtobringupthemenueditor.Belowthe File|Printmenuitem,addanewitem, FileSysPrintItem andgiveitthecaption Print(systemmethod).Createaclickeventandaddthiscode:
PUBLICSUBFileSysPrintItem_Click() DIMaStringASString
206
Itlooksalotmoredifficultthatitreallyis.Let'sgolinebylinethroughthe code.First,wedeclareastringvariable,aString.Nextweneedtobuildthestring thatwillbepassedofftothesystemasaconsolecommandandassignittoyour aString variable. Becausewemustensurethestringisbuiltexactlyasitwould have to be typed from the console, we must ensure it contains quote marks embeddedinit.Thefirstpartofthestring:
"prh\""
willinvokethesystemcommandpr.Thehparameterspecifiesthatwewantto haveaheaderprintedoneachpage,inthiscase,itwillbethecurrentfilename, heldinthevariablesCurrentFileName,which,inourprogram,isglobalinscope. This filename has to be embedded in quote marks so we need to use the \ characterbeforetheopeningquotemarkandterminatethispartofthestringwith anotherquotemark.Thenextpartofthestring:
&sCurrentFileName&"\""
concatenatesthefilenameandtheterminatingquoteforthefilenamepassedinas astringvariable,onceagainprecededbya \ character. Thenextquotemark terminates this portion of the string. The next part of the command to concatenateis:
&"o10<\""
whichaddstheoparameter(whichspecifiesanoffset)andavalueof10spaces. The<characterisusedonthecommandlinetodesignatetheinputstreamcomes fromthefilenamethatfollowsthe<character.Inthiscase,weneedtodelimit our string with quotes again, so the \ character is used to allow the quote charactertobepartoftheoutputstring. Thenextquotecharacterbeginsthe quotedfilenamestring.Thelastpartofourcommandis:
sCurrentFileName&"\"|lpr"
207
A Beginner's Guide to Gambas Itspecifiesthefiletoread(andprint)andterminatesthefilenamewith quotemarksasexplainedbefore. Thefinalpartofthestringisthe|character which pipes (redirects)theoutputtothelineprinter(lpr). Inall,ittakesone variabledeclarationandthreelinesofcodetoprintafileusingthistechnique. Eithertechniquewillworksochoosetheonethatsuitsyoubest.Anothermethod thatyoucanuseifyouhaveKDEinstalledistoprinttoapostscriptfileandsend the.psfileto'kprinter'.ThiswillprovideyouwithaccesstotheKDEprintdialogs andalloftheCUPSprintersandfeaturesinstalledonyoursystem. IftheuserclicksontheFile|Exitmenuitemwecouldsimplyclosethe program.However,wewanttogivetheuserachancetosavebeforeexitsowe willpopupaquestiondialogtoaskiftheywanttosavethefile. Ifso,wewill saveit.Ifnot,wesimplyexittheprogram.
PUBLICSUBFileExitItem_Click() DIMiResultASInteger iResult=Message.Question("Saveyourwork?","Yes","No","Cancel") SELECTCASEiResult CASE0 File.Save(sCurrentFileName,TextArea1.Text) CASE1 CASE2 CASEELSE ENDSELECT ME.close END
That'sitfortheFileMenu. Now,therealpowerofGambaswillbecome obviousaswebuildthecodefortheEditmenufunctions. Fromthismenu,we wanttheusertobeabletoselectalltext,undo,redo,cut,paste,copyorcalla configurationroutine.Forourpurposes,theconfigurationroutinewillbepretty simple,butitshouldbeenoughtoshowyouhowtoaccomplishthetask. IftheuserclicksontheEdit|SelectAllmenuitem,itwillselectallthetext in the TextArea. This is done be obtaining the length of the text using the TextArea1.Length property and passing that value to the TextArea1.Selection MethodwithastartingpointofzeroandanendingpointLengthcharactersfrom thatstartpoint,asshowninthecodebelow.
PUBLICSUBEditSelectAllItem_Click() DIMilengthASInteger ilength=TextArea1.Length TextArea1.Selection(0,ilength) END
208
Eithermethodwillworkbuttheauthor'spreferenceistousethesecond methodasitreflectsthesimplicityofGambaswhenprogramming.Thissimplicity is seen in the use of the builtin Undo, Redo, Cut, Paste and Copy methods providedbyGambasforTextArea1.Textaswell.Gambasprovidesthesemethods soprovidingthiscapabilityforyourprogramusersisasimplematterofaddinga singlelineofcodeforeachmenuitem'sclickevent,asshownbelow:
PUBLICSUBEditUndoItem_Click() TextArea1.Undo END PUBLICSUBEditRedoItem_Click() TextArea1.Redo END PUBLICSUBEditCutItem_Click() TextArea1.Cut END PUBLICSUBEditPasteItem_Click() TextArea1.Paste END PUBLICSUBEditCopyItem_Click() TextArea1.Copy END
OurEdit|Preferencesmenuoptionwillbeusedtoshowyouhowtobring upasecondforminyourprogram. Wewillsavethedatagatheredfromthe Form2.forminaconfigurationfilenamedFileOps.confandthatwillenableusto passthosesavedvaluesbackandforthbetweenthemainform,Form1.formand thesecondform,Form2.form.Thisistheeasiestwaytoexchangedatabetween classes but it is possible to pass data as parameters between forms. We will discuss that later in this book. The EditPrefsItem_Click() subroutine is pretty simple.Wejustshowthesecondform.
PUBLICSUBEditPrefsItem_Click()
209
HereiswhatForm2.formwilllooklike:
Figure73Form2.formdesignmode.
Asyoucansee,itisprettybasic.ATextLabelisusedtodisplaythedefault path. There are two buttons, one to change the default path by calling the standard Dialog.SelectDirectory routine and the other to return to the calling process,Form1.forminthiscase.Whentheformisopened,wewilldisplaythe captionPreferencesatthetopofthewindow.Theconstructorroutine_new()is calledautomatically.HereisthecodeforourForm2:
'Gambasclassfile PUBLICSUBForm_Open() Form2.Caption="Preferences" END
WhentheuserclickstheChangeDefaultPathbutton,thefollowingroutine iscalled:
PUBLICSUBButton1_Click() Dialog.SelectDirectory TextLabel1.Text=Dialog.Path END
210
A Beginner's Guide to Gambas The subroutine above simply callsthe Gambas standard dialog function Dialog.SelectDirectoryand updatestheTextLabel1.Textpropertywithwhatthe userhaschosenasthedefaultvalue.Whentheuserreturnsfromthissubroutine, theonlyotheroptionontheformistoclicktheReturnbutton,whichexecutes thiscode:
PUBLICSUBButton2_Click() DIMMyPathASString MyPath=application.Path&/"FileOps.conf" WritePrefs(MyPath) Form2.Close END
211
As you can see, it is pretty simple but it can easily be expanded to accommodatealmostanysetofconfigurationdatayourapplicationmayneedto store. YouareonlylimitedbyyourimaginationinGambas. Now,let'slookat ourFormatmenucode. IntheFormatmenu,theonlyoptionswehaveareto change colors or fonts. We are going to use theGambas standard dialogs to accomplishbothtasks.Hereishowitisdone:
PUBLICSUBFormatColorItem_Click() 'first,popupamessagetoexplainhowwearegoingtowork Message.Info("SelectBackgroundcolorfirst,textcolorsecond.","OK") 'setdialogcaptiontoremindtheuserweareselectingBACKGROUND Dialog.Title="SelectBackgroundColor" 'callthestandarddialogroutinetoselectcolor Dialog.SelectColor 'updateourTextArea1.Backcolorwiththevalueselected. TextArea1.BackColor=Dialog.Color
212
Atthebeginningofour program,inthe constructorroutine,wehadto enablethetimer.Toactuallymakethetimerdoanything,youmustprogramit. Doubleclicking on the timer control will take you to the Timer1_Timer() subroutine,shownbelow.Ifyourecall,wearegoingtohaveourprogramdisplay thecurrenttimeononelabelandthecurrentcursorpositionwithinthetextarea onanotherlabel.Hereishowweaccomplishthattask:
PUBLICSUBTimer1_Timer() 'getthetimeforrightnowandconverttoastring 'toputintheTimeLabel.Textproperty TimeLabel.Text=Str$(Now) 'wewillgetlineandcolumndatafromthe.Lineand '.ColumnpropertiesoftheLabelcontrolandupdatethe 'PosLabel.Textpropertywiththeirvalues: PosLabel.Text="Line:"&Str(TextArea1.Line)&"Col:"&Str (TextArea1.Column) END
ThelastmenuisourHelpmenu.Ithastwooptions,ContentsandAbout.
PUBLICSUBHelpContentsItem_Click() SHELL"konqueror\"file:/root/MyDocuments/GambasforBeginners/FileOps/Help.html\"" END
A Beginner's Guide to Gambas demonstrating this feature, simply copy any .html file on your system to the programdirectoryandrenameitashelp.html.Asanalternative,youcancreate yourown.htmlfileifyouknowhowtodothat.Thatiswhatrealprogrammers woulddo.Hereisthelastthingweneedtodo:
PUBLICSUBHelpAboutItem_Click() Message.Info("<b>SimpleTextEditor</b>by<br>J.Rittinghouse","OK") END
Runtheprogramandwhenyouaresatisfied,let'smoveontodosomemath.
214
PrecedenceofOperations
WhenyouusevariousoperatorsinanexpressioninGambas,thereisa specificprecedenceofoperationsthatGambasusestoperformtheoperation.A welldefinedprotocolisfollowed:
Bearinginmindtheorderofoperations(i.e.,theprecedence),youcanuse themathematicalfunctionsinGambastoperformjustaboutanymathematical operationneededforyourprograms.Wewillcovereachfunction,eitherintrinsic orderivedinthischapterandprovideexamplesofhowtheyareused.Thereisa tableprovidedattheendofthischapterthatshowsyoutheofficialdeveloper version of the hierarchy of operations, as defined in the gb_reserved_temp.h Gambassourcefile.
15 See URL: http://en.wikipedia.org/wiki/Intrinsic_function. 215
Abs
Absisanintrinsicfunctionthatreturnstheabsolutevalueofanumber. Theabsolutevalueofanumberisitsunsignedmagnitude.Forexample,Abs(1) and Abs(1) both return 1. The number argument can be any valid numeric expression.IfnumbercontainsNull,anerrorisreturned;ifitisaninitialized variable,zeroisreturned.StandardGambaslanguagesyntaxis:
Abs(number)
ThefollowingexampleusestheAbsfunctiontocomputetheabsolutevalueofa number.Trythisonyourconsole:
STATICPUBLICSUBMain() DIMMyNumASVariant MyNum=Abs(1.03E3) PRINTMyNum MyNum=Abs(2.5+6.5) PRINTMyNum END
Acs/ACos
Acs/ACosisaderived functionthatcomputestheinversecosine(arc cosine)ofanumber.Y=ACos(X)returnsthearccosineforeachelementofX. ForrealelementsofXinthedomain[1,1],ACos(X)isrealandintherange.For real elementsof X outside thedomain [1,1], ACos(X) iscomplex. The ACos function operates elementwise on arrays. The function's domains and ranges includecomplexvalues.Allanglesarereturnedinradians.Syntaxis:
value=ACos(Number)
Example:
PRINTAcs(0.5) 1.047197551197 PRINTAcs(1) 3.14159265359
216
Acsh/ACosh
TheAcsh/ACoshisaderivedfunctionthatcomputesthehyperbolicarc cosine(inversehyperboliccosine)ofanumber X. Itoperateselementwiseon arrays.Allanglesareinradians.ThedomainincludesrealnumbersXsuchthat X >= 1. The range of the hyperbolic arccosine function is limited to non negativerealnumbersYsuchthatY>=0.Gambaslanguagesyntaxisasfollows:
value=Acsh(Number) value=ACosh(Number)
Hereisanexampletotryontheconsole:
STATICPUBLICSUBMain() DIMyASVariant Y=2 PRINTAcsh(Y) END
Theconsolerespondswith:
1.316957896925
Asn/ASin
Asn/ASinisaderivedfunctionthatcomputesthearcsineofanumber. TheASin()functioncomputestheprincipalvalueofthearcsineofx.Thevalueof xshouldbeintherange[1,1]. Uponsuccessfulcompletion,Asn()returnsthe arcsineofx,intherange[p/2,p/2]radians.Ifthevalueofxisnotintherange [1,1]0.0isreturned.TheASin()functionwillfailifthevalueusedforxisnot intherange[1,1].StandardGambaslanguagesyntaxis:
value=Asn(Number) value=ASin(Number)
Hereisanexample:
STATICPUBLICSUBMain() DIMyASVariant Y=0.5 PRINTAsn(Y) Y=1.0 PRINTAsn(Y)
217
Theconsolerespondswith:
0.523598775598 1.570796326795
Asnh/ASinh
Asnh/ASinhisaderivedfunctionthatcomputestheinversehyperbolic sine (hyperbolic arcsine)for eachelementof X. The ASinh function operates elementwise on arrays. The function's domains and ranges include complex values.Allanglesareexpressedinradians.StandardGambaslanguagesyntaxis:
value=Asnh(Number) value=ASinh(Number)
Anexampleisasfollows:
STATICPUBLICSUBMain() DIMyASVariant Y=2 PRINTAsnh(2) END
Theconsolerespondswith:
1.443635475179
Atn/ATan
Atn / ATan is an intrinsic function that computes the arctangent of a number.ForrealelementsofX,ATan(X)isintherange[p/2,p/2].TheATan function operates elementwise on arrays. The function's domains and ranges includecomplexvalues.Allanglesareinradians. Standard Gambaslanguage syntaxis:
value=Atn(Number) value=ATan(Number)
Example:
218
Theconsolerespondswith:
0.463647609001
Atnh/ATanh
Atnh/ATanh is a derived function that computes the inverse hyperbolic tangent(orhyperbolicarctangent)ofanumber.Thefunctionoperateselement wiseonarrays.It'sdomainsandrangesincludecomplexvalues.Allanglesarein radians. TheGambaslanguagesyntaxof Y=ATanh(X) returnsthehyperbolic arctangentforeachelementofX.
value=Atnh(Number) value=ATanh(Number)
HereisanexampleyoucantryontheconsoleusingAtanh():
STATICPUBLICSUBMain() DIMMyResultASFloat DIMMyNumASFloat MyNum=0.5 MyResult=ATanh(0.5) PRINT"Thehyperbolicarctangentof"&MyNum&"is:"&MyResult END
Theconsolerespondswith:
0.549306144334
Cos
Cos()inanintrinsicfunctionthatreturnsthecosineofanangle.TheCos functiontakesanangleandreturnstheratiooftwosidesofarighttriangle.The ratioisthelengthofthesideadjacenttotheangledividedbythelengthofthe hypotenuse.Theresultliesintherange1to1. Toconvertdegreestoradians,
219
Theconsolerespondswith:
Secantofangle1.3(inradians)is:3.738334127075
Cosh
Cosh is a derived function that computes the hyperbolic cosine of a number. The Cosh function operates elementwise on arrays. The function's domainsandrangesincludecomplexvalues.Allanglesareinradians.Standard Gambaslanguagesyntaxis:
Value=Cosh(Number)
Hereisanexampletotryontheconsole:
STATICPUBLICSUBMain() DIMMyAngleASFloat DIMMyResultASFloat MyAngle=1.0'Angleexpressedinradians. MyResult=Cosh(MyAngle) PRINT"Cosh()ofangle"&MyAngle&"(inradians)is:"&MyResult END
Theconsolerespondswith:
220
DegandRad
Degisanintrinsicconversionfunctionthatconvertsradianstodegrees. Rad isa reciprocal conversion function thatconvertsdegreesto radians. The GambaslanguagesyntaxforDegandRadis:
Value=Deg(Angle) Value=Rad(Angle)
Anexampletotryontheconsoleis:
STATICPUBLICSUBMain() PRINTDeg(Pi/2) PRINTRad(90) PRINTRad(180)Pi END
Theconsolerespondswith:
90 1.570796326795 0
Exp
Expisanintrinsicfunctionthatcomputestheexponentialofanumber.It returns e (thebaseofnaturallogarithms,wheretheconstant e isapproximately 2.718282)raisedtoapower.Thenumberargumentcanbeanyvalidnumeric expression.Ifthevalueofnumberexceeds709.782712893,anerroroccurs.The Exp function complements the action of the Log function and is sometimes referredtoastheantilogarithm.TheGambaslanguagesyntaxis:
Value=Exp(Number)
Hereisanexample:
STATICPUBLICSUBMain() PRINTExp(1) END
221
HereisanotherexamplethatusestheExpfunctiontoreturneraisedtoapower:
STATICPUBLICSUBMain() DIMMyAngleASFloat DIMMyHSinASFloat'Defineangleinradians. MyAngle=1.3'Calculatethehyperbolicsine MyHSin=(Exp(MyAngle)Exp(1*MyAngle))/2 PRINTMyHSin END
Theconsolerespondswith:
1.698382437293
FixandFrac
Fixisanintrinsicfunctionthatreturnstheintegerpartofanumber.Frac isanintrinsicfunctionthatcomputesthefractionalpartofanumber.Notethat intheexamplebelow,Frac()returnstheabsolutevalueofthefractionalresultof .ThestandardGambaslanguagesyntaxis:
Value=Fix(Number) Value=Frac(Number)
Example:
STATICPUBLICSUBMain() PRINTFix(Pi) PRINTFrac(Pi) PRINTFix(Pi) PRINTFrac(Pi) END
Theconsolerespondswith:
3 0.14159265359 3 0.14159265359
222
Int
Int(Number)returnsthemathematicalintegerpartofanumber,i.e.,the greaterintegersmallerthanNumber.
Value=Int(Number)
Herearesomeexamplesyoucantryontheconsole:
PRINTInt(Pi) 3 PRINTInt(Pi) 4
Log
Logisanintrinsicfunctionthatcomputesthenaturallogarithmof e.The logarithmhavingbase e.Theconstant eisapproximately2.718282whereeisa unique number with the property that the area of the region bounded by the hyperbola y=1/x,the xaxis, and the vertical lines x=1 and x=e is 1. The notationlnxisusedinphysicsandengineeringtodenotethenaturallogarithm, whilemathematicianscommonlyusethenotationlogx.TheNumberargument canbeanyvalidnumericexpressiongreaterthan0.StandardGambaslanguage syntaxis:
value=Log(Number)
Hereisanexample:
STATICPUBLICSUBMain() PRINTLog(2.71828) PRINTLog(1) END
Theconsolerespondswith:
0.999999327347 0
Youcancreateaderivedfunctiontocalculatebasenlogarithmsforany numberxbydividingthenaturallogarithmofxbythenaturallogarithmofnas
223
Theconsolerespondswith:
3.321928094887istheresultofLogn(10)
Log10
Log10 is a derived function that computes the decimal logarithm of a number.Log10(x)=Log(x)/Log(10).Gambaslanguagesyntaxis:
value=Log10(Number)
Example:
PRINTLog10(10) 1
MaxandMin
Maxreturnsthegreaterexpressionofthelist.Expressionsmustbenumbers ordate/timevalues.Minreturnsthesmallerexpressionofthelist.Expressions mustbenumbersordate/timevalues.
value=Max(Expression[,Expression...]) value=Min(Expression[,Expression...])
224
Theconsolerespondswith:
7 01/01/2100 1 01/01/1900
Pi
Pireturnsp*Number.IfNumberisnotspecified,itisassumedtobeone. StandardGambaslanguagesyntaxis:
Result=Pi([Number])
Examples:
PRINTPi 3.14159265359 PRINTPi(0.5) 1.570796326795
RandomizeandRnd
Randomize initializes a pseudorandom number generator. It uses a methodology that seeds itself with the current date and time. The Gambas languagesyntaxis:
Randomize(Number)
wherethenumberargumentcanbeanyvalidnumericexpression. Randomize uses the parameter Number to initialize the Rnd function's randomnumber
225
A Beginner's Guide to Gambas generator,givingitanewseedvalue.Ifyouomitnumber,thevaluereturnedby thesystemtimerisusedasthenewseedvalue.IfRandomizeisnotused,theRnd function(withnoarguments)usesthesamenumberasaseedthefirsttimeitis called,andthereafterusesthelastgeneratednumberasaseedvalue. Inother words,foranygiveninitialseed,thesamenumbersequenceisgeneratedbecause eachsuccessivecalltotheRndfunctionusesthepreviousnumberasaseedfor thenextnumberinthesequence. Inordertorepeatsequencesofrandomnumbers,callRndwithanegative argumentimmediatelybeforeusingRandomizewithanumericargument.Before callingRnd,usetheRandomizestatementwithoutanargumenttoinitializethe randomnumber generator with a seed based on the system timer. Using Randomize with the same value for number does not repeat the previous sequence. Rndcomputesapseudorandomfloatingpointnumber,usingtheLehmer algorithm.Ifnoparametersarespecified,Rndreturnsapseudorandomnumber intheinterval[0,1].Ifonlyoneparameterisspecified,Rndreturnsapseudo randomnumberintheinterval[0,Min].Ifbothparametersarespecified,Rnd returnsapseudorandomnumberintheinterval[Min,Max].StandardGambas languagesyntaxforRndis:
Rnd([Min[,Max])
The number argument can be any valid numeric expression. The Rnd functionreturnsavaluelessthan1butgreaterthanorequalto0.Thevalueof numberdetermineshowRndgeneratesarandomnumber. Toproducerandom integersthatfallwithinanygivenrange,usethisformula:
Int((upperboundlowerbound+1)*Rnd+lowerbound)
Here,upperboundisthehighestnumberintherange,andlowerboundisthe lowestnumberintherange.Hereisanexampleprogramtotryontheconsole:
STATICPUBLICSUBMain() DIMDiceASInteger PRINT"Between0and1:"; PRINTRnd PRINT"Between0and2:"; PRINTRnd(2) PRINT"BetweenPiandPi*2:";
226
Theconsolerespondswith:
Between0and1:7.826369255781E6 Between0and2:0.263075576164 BetweenPiandPi*2:5.515396781706 Youthrewa6 Youthrewa4 Youthrewa1
Round
RoundroundsanumbertoitsnearestintegerifDigitsisnotspecified.If Digitsisspecified,roundsto10^Digits.
Value=Round(Number[,Digits])
Example:
STATICPUBLICSUBMain() PRINTRound(Pi,2) PRINTRound(1972,2) END
Theconsolerespondswith:
3.14 2000
Sgn
Sgnreturnsanintegerindicatingthesignofanumber. Ifthenumberis zero, it returns zero. If the number is strictly positive, it returns the integer
227
Example:
STATICPUBLICSUBMain() PRINTSgn(Pi) PRINTSgn(Pi) PRINTSgn(0) END
Theconsolerespondswith:
1 1 0
Sin
Sinisanintrinsicfunctionthatcomputesthesineofanangle.Theangleis specified in radians. The sine function sin x is one of the basic functions encounteredintrigonometry(theothersbeingthecosecant, cosine,cotangent, secant,andtangent).Let beananglemeasuredcounterclockwisefromthex axisalonganarcoftheunitcircle.Thensinistheverticalcoordinateofthearc endpoint.Asaresultofthisdefinition,thesinfunctionisperiodicwithperiod2. BythePythagoreantheorem,sinalsoobeystheidentitysin2 + cos2 = 1. The standardGambaslanguagesyntaxforSinis:
Value=Sin(Angle)
Example:
STATICPUBLICSUBMain() PRINTSin(Pi/2) END
Theconsolerespondswith:
1
228
Sinh
Sinhisaderivedfunctionthatcomputesthehyperbolicsineofanumber. StandardGambaslanguagesyntaxforSinhis:
Value=Sinh(Number)
ThefollowingexampleusestheExpfunctiontocalculatehyperbolicsineofan angle:
STATICPUBLICSUBMain() DIMMyAngleASFloat DIMMyHSinASFloat'Defineangleinradians MyAngle=1.3'Calculatehyperbolicsine MyHSin=(Exp(MyAngle)Exp(1*MyAngle))/2 PRINTMyHSin END
Theconsolerespondswith:
1.698382437293
Sqr
Sqrisanintrinsicfunctionthatreturnsthesquarerootofanumber.The numberargumentcanbeanyvalidnumericexpressiongreaterthanorequalto0 (nonnegative).TheGambaslanguagesyntaxis:
Value=Sqr(Number)
Hereisanexample:
PRINTSqr(2) 1.414213562373
Theconsolerespondswith:
2istheresultofSqr(4) 4.795831523313istheresultofSqr(23) 0istheresultofSqr(0)
Tan
Tanisanintrinsicfunctionthatcomputesthetangentofanangle.The angleargumentcanbeanyvalidnumericexpressionthatexpressesananglein radians.Tantakesanangleandreturnstheratiooftwosidesofarighttriangle. Theratioisthelengthofthesideoppositetheangledividedbythelengthofthe sideadjacenttotheangle.Toconvertdegreestoradians,multiplydegreesbypi/ 180. To convert radians to degrees, multiply radians by 180/pi. Standard Gambaslanguagesyntaxis:
Value=Tan(angle)
ThefollowingexampleusestheTanfunctiontoreturnthetangentofanangle:
STATICPUBLICSUBMain() DIMMyAngleASFloat DIMMyCotangentASFloat MyAngle=1.3'Defineangleinradians. MyCotangent=1/Tan(MyAngle)'Calculatecotangent. PRINTMyCotangent PRINTTan(Pi/4) END
Theconsolerespondswith:
0.277615646541 1
230
Tanh
Tanh is a derived function that computes the hyperbolic tangent of a number.ThestandardGambaslanguagesyntaxforTanhis:
Value=Tanh(Number)
Example:
STATICPUBLICSUBMain() PRINTTanh(1) END
Theconsolerespondswith:
0.761594155956
DerivedMathFunctions
Thenonintrinsic(derived)mathfunctionsshowninthetablebeloware providedinGambasfromthebuiltinintrinsicmathfunctions.
Derivedequivalents
ASin(X)=Atn(X/Sqr(X*X+1)) ACos(X)=Atn(X/Sqr(X*X+1))+2*Atn(1) Sinh(X)=(Exp(X)Exp(X))/2 Cosh(X)=(Exp(X)+Exp(X))/2 Tanh(X)=(Exp(X)Exp(X))/(Exp(X)+Exp(X)) ASinh(X)=Log(X+Sqr(X*X+1)) ACosh(X)=Log(X+Sqr(X*X1)) ATanh(X)=Log((1+X)/(1X))/2 Log10(X)=Log(X)/Log(N)
Belowisatablelistingotherderivedmathfunctionsthatcanbebuiltusingthe formulasshowninthetablebelow:
231
Since Gambas does not directly provide you with builtin functions for theseotherderivedfunctions,wearegoingtobuildamodulethatwillextend Gambascapabilitiesbyprovidingallofthefunctionslistedinthetableaboveasa finalexerciseinthischapter.OurmodulewillbenamedDerivedandyouwillbe able to access all of the functions in your code by using the format Derived.function_namewherefunction_namewillbeoneofthefunctionswebuild in the next section. Start Gambas and create a terminal application named MyMath. Createanewclass,Class1fromtheIDEandmakeitastartupclass. NextcreateanewmoduleandnameitDerived.Openthenewcodewindowfor theClass1.classfileandenterthefollowing:
'Gambasclassfile STATICPUBLICSUBMain() DIMmyValASFloat myVal=51.5 WHILEmyVal<>0.0 PRINT"Enteranumber>1orenter0toquit:"; LINEINPUTmyVal IFmyVal=0.0THENBREAK IFmyVal<=1.0THEN PRINT"Numberwas<=1.0" CONTINUE ENDIF
232
Now,openthecodewindowfortheDerived.modulefileandenterthiscode:
'GambasDerived.modulefile PUBLICFUNCTIONSec(xASFloat)ASFloat DIMresultASFloat result=1.0/Cos(x) RETURNresult END PUBLICFUNCTIONCoSec(xASFloat)ASFloat DIMresultASFloat result=1.0/Sin(x) RETURNresult END PUBLICFUNCTIONCoTan(xASFloat)ASFloat DIMresultASFloat result=1.0/Tan(x) RETURNresult END PUBLICFUNCTIONArcSec(xASFloat)ASFloat DIMresultASFloat result=Atn(x/Sqr(x*x1))+(Sgn(x)1)*(2*Atn(1)) RETURNresult END
233
Whenyouruntheprogram,youwillreceiveaprompttoenteranumber> 1or0toquit.Enter4andyoushouldseethefollowingresults:
Enteranumber>1orenter0toquit:4 1.529885656466issecant 1.321348708811iscosecant 0.863691154451iscotangent 0.85707194785isarcsecant 0.801529994232isarccosecant 2.896613990463isarccotangent 0.036618993474ishyperbolicsecant 0.036643570326ishyperboliccosecant 1.000671150402ishyperboliccotangent 1.472219489583ishyperbolicarcsecant 0.247466461547ishyperbolicarccosecant 0.255412811883ishyperbolicarccotangent 2isLogNof:4tobase2 ofmyVal:4 Enteranumber>1orenter0toquit:
Now, you should be able to perform almost any type of mathematical operationnecessaryformostprograms. Youhaveabsorbedalotofmaterialin
235
236
A Beginner's Guide to Gambas much success with that. The ability to maintain a program once it has been writtenandtodolocalizeddebuggingandtodomuchlargerdevelopmentefforts arealso reasonscited assignificant advantagesgained withtheuseofobject oriented programming languages (OOPLs). In the 1990s, overoptimism regarding the benefits of OO programming led businesses to expect miracles. When software developers could not deliver on the outrageous business plans basedonthosepromises,2001sawbusinessesfalllikedominos,leavingtheentire techindustry inarecession. DefunctcompanieslitteredSilicon Valleylikeso manybleachedbonesinadesert. Fortunately, Gambas takes a very pragmatic approach to the implementation of OO concepts, leveraging what works and, unlike C++, avoidingthatwhichwillnoteverworkwell.TheGambasimplementationisan elegant compromise between true OO theory and the business realities programmershavetocontendwithtoday. OOPisoftencalledaparadigmratherthanastyleortypeofprogramming toemphasizethepointthatOOPcanchangethewaysoftwareisdevelopedby changingthewaythatprogrammersandsoftwareengineersthinkaboutsoftware. Much ofthe evolution of any language depends on theOS thatsupports that language. Withtheadventof Linux andthehugegroundswellofsupportfor opensourcesoftware,thefuturelooksverybrightforGambas.Now,let'stakea lookatsomeofthebasicOOconceptsthatGambassupports.
FundamentalsofObjectOrientedProgramming
Objectorientedprogrammingisbaseduponseveralkeyconcepts:objects, data abstraction, encapsulation, polymorphism, and inheritance. One distinguishing feature of OOP is the methods used for handling data types. Objecttypedataisgenerallyrequiredtosatisfyprogrammerdefinedconstraints.A datatyperestrictedtoaspecificobjectisconsideredtobea private datatype. Thistypeoflanguageimposedconstraintrestrictingdatatypestospecificobjects forcesprogrammers(bydesign)tocodewithoutrelyingoncreatingalaundrylist ofvariablesvisibletoeveryobjectintheprogram(globalvariables). Variables canbeusedanddisposedofwithintheobjectorclassinwhichtheyareneeded and they do not affect other parts of a program. The actions taken by the program where such variables are used are referred to as methods. In more traditionallanguages,methodsequatetofunctionsorsubroutines.InOOP,these constraints also may extend to the use of methods and are not exclusive to variables.
238
A Beginner's Guide to Gambas Objectorientedlanguagesprovideinternalmechanismsforensuringthat variablesandmethodsareonlyvisibleandavailablewithinthescopeoftheclass ormethodinwhichtheyaredeclared.Albeit,somevariablesandmethodsare designed to be visible to all other methods or classes of a project. In those instances, they are referred to as public variables and methods. In Gambas, variablesandmethodsthatarepublicareglobalinscopetotheclassinwhichthey aredeclared.Variablesmeanttobevisibleonlytothemethodsinwhichtheyare declaredas private withinagivenclassarecreatedwiththeDIMkeywordin Gambas. Objects Objects arecomprisedofallthedataandfunctionalitythatexistwithin distinct units in a running (executing) computer program. Objects are the foundation of modularity and structure in an OOPL. They have two basic attributes: they are selfcontained and they are uniquely identifiable. Having thesetwoattributesallowsallofthevariousprogramcomponentstocorrelate variablesinaprogramwithvariousrealworldaspectsofaproblemforwhicha programisintendedtosolve. DataAbstraction DataAbstractionDataabstractionisamethodologyusedinOOPLsthat enablesaprogrammertospecifyhowadataobjectisused.Abstractionallowsa programmertoisolatedataobjectsfromtheunderlyingdetailsofhowthedatais created(usuallybyusingevenmoreprimitivedataobjects).Inotherwords,the useofadataobject,comprisedofoneormoreprimitivedataobjects, allowsa programmer to structure his or her code to use data objects that operate on abstractdata. Dataobjectsthatarecomprisedofoneormoreprimitivedataobjectsare called compound data objects. With abstraction, the program can use data withoutmakinganyassumptionsaboutit(i.e.,theunderlyingdetailsofhowor wherethatdatacamefrom)thatisn'tnecessaryforperformingagiventask. A concretedatarepresentationisdefinedindependentofanyprogramsthatusethe data.Theinterfacebetweentheconcreteandabstractdataisasetofprocedures, called constructors, that implement abstract data in terms of the concrete representation.Methods(subroutinesandfunctions)mayalsobesoabstractedin theOOPparadigm.
239
A Beginner's Guide to Gambas Encapsulation EncapsulationEnsuresthatusersofanobjectcannotchangetheinternal state of the object in unexpected ways; only the object's internally defined methodsareallowedtoaccessitsstate(orattributes). Eachobjectexposesan interfacethatspecifieshowotherobjectsmayinteractwithit.Otherobjectswill not know of this object's internal methods and must therefore rely upon this object'sinterfaceinordertointeractwithit. Polymorphism Polymorphismmeanstheabilitytotakemorethanoneform.InOOPLs,it refers to a programming language's ability to process objects differently depending on the datatype or class. More specifically, polymorphism is the abilitytoredefinemethodsforderivedclasses.Anoperationmayexhibitdifferent behaviorsindifferentcircumstances.Thebehaviorisdependentuponthedata type used in the operation. For example, given a base class named shape, polymorphism enables the programmer to define different methods of area calculation for any number of derived classes, such as circles, rectangles and triangles.Nomatterwhatshapeanobjectis,applyingtheareamethodtoitwill return the correct results. Polymorphism is used extensively in OOPLs when implementing inheritance and is considered to be a requirement of any true OOPL. Inheritance Inheritance istheprocessbywhichobjectscanacquirethepropertiesof objectsthatexistinanotherclass.InGambas,allofthecontrolsoftheToolBox inheritthepropertiesoftheclassnamedControl. InOOP,inheritanceprovides reusability and extensibility (adding additional features to an existing class withouttheneedtomodifyit).Thisisachievedbyderivinganewclassfroman existingclassandmakingchangestothenewinstanceofthatclass.Thenewclass willhavecombinedthefeaturesofbothclasses.Inheritanceallowsobjectstobe defined and created that are specialized implementations of alreadyexisting objects. They can share (and extend) the existing object's behavior without havingtoreimplementit.
240
TheGambasApproachtoOOP
AnOOprogramisgenerallydesignedbyidentifyingalloftheobjectsthat willexistinasystem.Thecodewhichactuallydoestheworkisirrelevanttothe objectduetoencapsulation. ThebiggestchallengeinOOPisofdesigningan objectsystemthatisunderstandableandmaintainable. Itshouldbenotedthat therearedistinctparallelsbetweentheobjectorientedparadigmandtraditional systems theory. While OOP focuses on objects as units in a system, systems theory focuses on the system itself. Somewhere in between, one may find software design patterns or other techniques that use classes and objects as building blocks for larger components. Such components can be seen as an intermediate step from the objectoriented paradigm towards the more pragmaticallyorientedmodelsofsystemstheory.SuchappearstobetheGambas approachtoOOP.Itisanelegant,pragmaticsolutionthattakesthebestofboth approachesandmakesprogrammingeasyandsimple. Gambashastriedtokeepsimplicityattheforefrontofanapproachthat leverages OO concepts and compromises with systems theory where it makes goodsense. Inthatregard,Gambashastakena classbasedapproach toOOP. TheclassbasedOOPapproachisanOOPparadigmwheretheconceptofaclassis central.Inthisapproachencapsulationpreventsusersfrombreakinginvariantsof theclass.Classinvariantsareestablishedduringconstructionandareconstantly maintained between calls to public methods. Temporarily breaking class invariancebetweenprivatemethodcallsispossible,althoughitisnotencouraged. Sometimes,itisusefulbecauseitallowstheimplementationofaclassofobjects to be changed for aspects not visible to or exposed inside the class interface withouthavinganimpactonusercodethatmayhaveimplementedfeaturesof thatclass. ThedefinitionofencapsulationinaclassbasedOOPparadigmfocuseson groupingandpackagingofrelatedinformation(cohesion).OOPlanguagesdonot normallyofferformalsecurityrestrictionstotheinternalobjectstate. Usinga methodofaccessisamatterofconventionfortheinterfacedesign.Inheritanceis typicallydonebygroupingobjectsintoclassesanddefiningclassesasextensions ofexistingclasses. Thisgroupingofclassesissometimesorganizedintotreeor latticestructures,oftenreflectingacommonsetofbehaviors. GambasClasses InGambas,youcandefineyourownclasses. Rememberthataclassis
241
Instantiatinganobjectmeanstocreateanewinstanceofthetemplateandassign that instance the name on the left side of the equal sign. In GB, this is accomplishedusingtheNEWkeyword:
object_name=NEWClass_name
Whenobject_nameisinstantiatedasanewcopyofthetemplatedefinedby Class_name,theprogramminglanguageallows object_name toinheritallofthe methods and attributes of Class_name. When the new object is created, it automaticallyinvokesaconstructortoinitializeitselfwithdefaultvariables.Itis important to note that the current version of Gambas does not support the concept of virtual dispatch. In other words, when you invoke a method (or set/get a property value) for an object reference using the dot notation (i.e., class.object.method),themethodthatisactuallyexecutedisthemethodbelonging tothedatatypeofthevariablethatownstheobjectreference,notthemethodof therealdatatypeoftheobject.InGambas2,thisissuehasbeencorrected.
Sampleprogram:Contacts
ToillustratetheuseofaclassinGambas,wearegoingtocreateasample programthatimplementsacontactsbook.Itisgoingtobefairlysimplebutwill beusefultomaintaincontacts.Tobegin,createanewprojectnamedClassesand whenyougettotheIDE,createaclass(notastartupclass)namedContact.This iswherewewillstartwithourprogram,buildingaclassdefinitionforaContact. TheContactclass
'GambasContact.classfile PUBLICFirstNameASString PUBLICLastNameASString PUBLICInitialASString PUBLICSuffixASString PUBLICStreet1ASString
242
Wewantourclasstoprovidetwomethods,onetoretrieveourcontactdata fromthefileitisstoredinandonetoputdataintothatfile.Appropriately,the twomethodswillbenamedContact.GetDataandContact.PutData. Contact.GetDataMethod Let's start with the GetData method, which is decleared as a function becauseitwilltakeacollectionvariableasaparameterandreturnacollection filledwithdatafromthecontacts.datafileifthatdataexists.Wewilldeclarelocal variableswithinourmethodsbyusingtheDIMkeyword. Notethatwecould declare these variables as PRIVATE outside of the method definitions and it wouldrenderthemvisibleonlytothemethodswithinthecontactclass.However, declarationslocaltothemethodthemselvesfurtherrestrictsthescopeandmakes theentireclassfilecleanerinappearancefromauserperspective.Theywillsee allthepublicmethodsandvariablesandnothingmore. Thecollectionvariableispassedinasaparameterfromtheconstructorcall inForm1.classsoitisnotnecessarytodeclareitseparately. Thefunctionwill returnacollectionvariablesoweadd ASCollection totheendofthefunction declaration.WewillshowhowthecollectionvariablecTheDataispassedtothis functionwhenitiscalledfromtheForm1.classfile.
PUBLICFUNCTIONGetData(cTheDataASCollection)ASCollection 'thisstringvarwillholdeachlineofdatareadfromthefile DIMsInputLineASString 'weneedafilehandleandtwostringvarsforbuildingfilenames DIMhFileInASFile DIMfilenameASString DIMfullpathASString 'thisclassvariableisusedtoconvertthestringdatawereadin 'fromfileintoacontactrecord.Wedeclarethevariablehereand
243
245
A Beginner's Guide to Gambas Contact.PutDataMethod The reciprocal routine to GetData is PutData, where we will store the collectionofdata that isconsidered mostcurrent. Whatevereditsorchanges havebeenmadewillbereflectedinthissaveoperation.Wewillsavethedateto afile,storingtherecordasacommadelimitedstring. Eachlineofoutputwill representonecontactrecord. ThePutDatamethodisdeclaredasasubroutine sinceitdoesnotreturnavariable. Ittakesoneparameter,thecollectionobject wewishtostore.cTheDataisthecollectionpassedtothissubroutine.
PUBLICSUBPutData(cTheDataASCollection) 'thisstringvarwillholdeachlineofdatareadfromthefile DIMsInputLineASString 'weneedafilehandleandtwostringvarsforbuildingfilenames DIMhFileOutASFile DIMfilenameASString DIMfullpathASString 'thisclassvariableisusedtoconvertthestringdatainto 'acontactrecord.Wedeclarethevariablehereand 'willinstantiateitbelow DIMMyContactRecordASContact 'alocalintegervartokeeptrackofhowmanyrecordsweadded DIMRecordNumASInteger 'instantiateanewrecordthatisblank.Notethatsincewearenot 'addingthisrecordtoacollection,itisnotnecessarytorenew 'itbyreinstantiatingiteachtime. MyContactRecord=NEWContact 'startatrecord1 RecordNum=1 'wehaveahardcodedfilenamesoweonlyneedthepathtotheprogram 'becausewewillstorethedatawheretheprogramresides. filename="contacts.data" fullpath=Application.Path&/filename 'wehavetospecifyWRITECREATEwhenweopenthefile.Ifthefile 'exists,itwillbeopenedforWRITE.Ifitdoesnotexist,thenwe 'willcreateanewfileandwritetothat. OPENfullpathFORWRITECREATEAS#hFileOut 'now,weloopthrougheachrecordinthecollection.Notethatwe
246
Form1.classfile Save the Contact.class file and close it. Our contact class definition is completesonowwewillneedtocreateaformnamedForm1.Form1willserve asthemaininterfacebetweentheuserandtheprogramandit'sdata. Hereis whatourfinishedformwilllooklike:
247
Figure74FinishedContactsprogram.
Ourprogramwillallowausertoadd,changeordeleteacontactandstore thatdatatoadatafile.Contactdataismanagedinourprogramasacollectionof objectsthatareoftypeContact,whichwedefinedintheContact.classfileabove. Wewillallowtheusertomovetotheveryfirstiteminthecollection,scrollto nextorpreviousitems,gotothelastitem,updatedataonthecurrentform,save thecurrentdatatofile,andexit.Allinall,itdoesmostofthebasicsnecessaryfor contactmanagement. Wewillalsoaddasearchfeature(usingamodule)that willfindthefirstinstanceofacontactbysearchingforalastname.Amazingly,to accomplishallofthistakesverylittlecodeinGambas! Now,let'slookattheprogramthatwillusethecontactclass.Theprogram willrequirefourpublicvariables,asshownbelow. Our constructorroutine will automatically look for and load the default contact file, which we named contacts.data.Itisnotnecessaryfortheusertoknoworusethisfilenamesoitis hardcodedintothemethodswhereitisused.Iftheconstructorroutine_new() cannotloadafile,itwillcreateonedummyrecordsotheuserneverseesablank startupscreen.
'GambasForm1classfile 'Contactswillrepresentthecollectionofrecordsfortheaddrbook PUBLICContactsASCollection 'representsasinglecontactrecordusedbyallsubroutines PUBLICContactRecordASContact 'indexthatpointstothecurrentrecord PUBLICRecordPointerASInteger 'wewillneedastringvartousewhentheusersearchesbylastname PUBLICSearchKeyASString
248
249
Form_OpenSubroutine Our program will automatically open the form using the Form_Open() subroutine below. Since Form1.form is defined as a startup form, it is not necessarytocalltheForm1.Showmethod.Allwearegoingtodohereissetthe captiontodisplayatthetopofthewindowwhentheprogramrunsandgetthe recordpointedtobythecurrentrecordpointer.Inthiscase,thepointershould pointtothelastrecordloadedfromthecontactsfileafterprogramflowreturns fromtheconstructor.
PUBLICSUBForm_Open() 'settheprogramcaption Form1.Caption="ContactsManager" 'startwiththerecordpointedtoaftertheconstructorcall 'whichshouldbethelastrecordinthecollection ContactRecord=Contacts[CStr(RecordPointer)] 'thissubroutinewillrefreshallfieldswithcurrentrecorddata UpdateForm END
AddingControlstoForm1.Form Itistimetoputallofthecontrolsontheformandgivethemnames.We willbeusingnineToolButtons,oneregularButton,14labelsand13TextBoxes. We will also need to use nine icons, which we can obtain from the usr/share/icons/defaultkde/32x32folder(NOTE:yoursystemmaybedifferentso browsearoundtofindwheretheiconsarestoredifneeded).TheiconsIusedfor thisprogramareasfollows:
250
Startofdata
Prev
Next
Endofdata
Clearfields
Updatefields
Addnew
Deletecurrent
Savetofile
The ToolButtons
The nine ToolButtons that use these icons in their Picture property are named:
FirstRecordBtn LastRecordBtn AddBtn PrevRecordBtn ClearBtn DeleteRecordBtn NextRecordBtn Update SaveAllBtn
CreatenineToolButtonsandarrangethemontheformasshowninthe figureatthebeginningofthischapter. Assignthenamesshownabovetothe ToolButtonsandsettherespectivebuttonPicturepropertiestothenamesofthe icons you chose for your program, based on what your system distribution provides. Worst case scenario is that you can use the builtin icon editor in Gambastocreateyourownicons.
The Quit Button
251
Probablythemosttediouspartofdevelopingthisprogramisnext,adding theLabelandTextBoxcontrolstotheform.Trytoarrangethemasyouseein Figure74above.FortheLabelcontrols,youcantakethedefaultvariablenames providedbyGambasforallofthelabelsexcepttheoneatthebottomoftheform where we will display our Record n of n data. That label should be named StatusLabel. TheTextboxfields,asshownfromtoplefttobottomrightonthe form,shouldbenamedasfollows:
FirstName MI LastName Suffix Street1 Street2 City State Zip5 Zip4 AreaCode DialPrefix DialLast4
Hopefully, the names should be selfexplanatory (i.e., selfdocumenting code)andyouhavenoproblemscreatingtheform.Becarefultousethecorrect caseandtypethenamesexactlyasshownabove,otherwiseyouwillbetracking downundeclaredvariableswhenyoutrytoruntheprogram.Atthispoint,your form,indesignmode,shouldlooklikethis:
252
Figure75Form1seenindesignmode.
UpdateForm()Subroutine TheUpdateForm()routinewillbecalledeverytimedataontheformhas changedandneedstoberefreshedsotheuserwillseetheupdatesastheyoccur. This routine posts each field on the form with the current data found in the collection based on the current record pointer. Also, the label StatusLabel is updatedwiththecurrentrecordnumberofnrecordsinthecollectionfromhere. Let'swalkthroughthecode:
PUBLICSUBUpdateForm() 'checktoensuretherearerecordsbeforewedoanything IFContacts.Exist(CStr(RecordPointer))THEN 'wefoundrecordssonowwemovetotherecordatcurrentpointer ContactRecord=Contacts[CStr(RecordPointer)] 'fordebugonly PRINT"InUpdateFormwithRecordPointerof:"&RecordPointer 'assignTextbox.Textvalueswhateverisstoredinthecontactrecord FirstName.Text=ContactRecord.FirstName MI.Text=ContactRecord.Initial LastName.Text=ContactRecord.LastName Suffix.Text=ContactRecord.Suffix Street1.Text=ContactRecord.Street1 Street2.Text=ContactRecord.Street2 City.Text=ContactRecord.City
253
The first ToolButton we will code is the one that will move us to the beginningofthedata. DoubleclickonthefirstToolButtonandyoushouldbe takentothecodewindowwheretheFirstRecordBtn_Click()routineawaits.Add thiscode:
PUBLICSUBFirstRecordBtn_Click() 'movetothefirstrecord RecordPointer=1 'retrievethatrecordfromthecollection ContactRecord=Contacts[CStr(RecordPointer)] 'updatetheformdisplaywiththenewdata UpdateForm END
Asyoucansee,movingtothefirstrecordwasprettysimple.Now,wewill codethePrevandNextbuttons.DoubleclickonthesecondToolButton()and
254
ValidatingUserInput WhentheuserentersdataintheInitialfield,andalsointheSuffix,State, Zip5,Zip4,AreaCode,DialPrefixandDialLast4fields,wewanttoensurethatthe data fits and they cannot enter extraneous letters or characters. Each of the routinesbelowareactivatedonachangeevent.Inotherwords,ifthetextinthe TextBox.Textfieldchanges,itwillgototherespective_Change()routinebelow. Eachroutineworksalmostidenticallytolimitthenumberofcharacterstheuser can type. If they type more, the extra characters are truncated at the length specifiedbytheprogram.Forexample,anareacodecanbenomorethanthree digits.Wecouldalsoaddcodetoensureonlydigitsareenteredinnumericfields, etc.,butthatisnotwhywearebuildingthisprogram.WIwillleavethattoyou toaddasanexerciseattheendofthischapter.Foreachcheckbelow,wewill need a temporary string var, sTemp. If the length of the TextBox.Text data exceedsthelengthweallow,weuseMID$tocopythefirstnletterstosTempand thencopythatvaluebackintotheTextBox.Textproperty.
PUBLICSUBMI_Change() DIMsTempASString
258
Asyoucansee,lotsofrepetitivebutnecessarycode.Youcangobacklater andbulletprooftheinputofthisprogrambyaddingadditionalvalidationchecks foreverypossiblethingyoucanthinkofbutIwillshowyoulaterinthisbooka better way, building a customized InputBox that will perform the validation processautomatically. AddingaSearchFeature Wewanttheusertobeabletofindacontactbysearchingforalastname. There are so many controlson ourformnow that adding another onewould detractfromtheoverallaestheticsandmakeitappearlessthanelegant.Abetter solutionistouseamouseclickanywhereontheformitself.Itgeneratesanevent andwillallowustocapturethateventandinitiateasearchprocess.Whenthis happens,wearegoingtopopupacustomizedsearchformandprompttheuser toenteralastnametowhichwewilluseasakeyforoursearch.Createanevent forMouseDownontheform.HereisthecodefortheMouseDownevent:
PUBLICSUBForm_MouseDown() SearchForm.ShowModal Message.Info("Backtomainformwith:"&SearchKey,"Ok") DoFind END
NotethatweshowtheformusingtheShowModalmethodinsteadofjust
260
Figure76Contactssearchformdesign.
Prettybasic,justalabel,aTextbox,andabutton.FromtheIDEcreatea newform,named SearchForm and add thelabel and buttonas shown below. NamethebuttonSearchBtnandtheTextBoxshouldbenamedSearchInput.Here isallthecodethatisneededfortheSearchForm:
'GambasSearchFormclassfile PUBLICSUBSearchBtn_Click() 'thisisacalltoourcustommodule,search,whichhas 'asinglemethod,SearchOn,thatisexplainedbelow Search.SearchOn(SearchInput.Text) 'fordebugonly PRINT"returning:"&SearchInput.Text 'assignthesearchkeytotheglobalvarwenamedinForm1 Form1.SearchKey=SearchInput.Text 'nowcloseoursearchform SearchForm.Close END PUBLICSUBForm_Open() 'setthecaptionforthesearchwindow SearchForm.Caption="Findbylastname" 'highlightandselecttheSearchInputTextbox 'sincethereisonlyoneinputfield,ithasfocusalready SearchInput.Select END
261
A Beginner's Guide to Gambas Atthispoint,youmightbewonderingwhatexactlyisgoingon.Basically, in Gambas, public variables are public to a class file. When we want to pass parameters between classes,wecanusethemethodofpassingparameterswith functions like we did when we started the program and passed an empty collectionvariabletotheGetDatamethod. Another waytoaccomplishthisisby using modules. Thekey pointto rememberisthatpublicvariablesinmodulesarepublictoallclasses.Essentially, allwehavedoneiscreateaconduittopassoursearchkeyfromthesearchform backtothemainprogramviathemodule.Notethattheonlycodeneededinthe moduleisastatementthattakestheparameterpassedfromthesearchformand returnsittothemainprogram.Assoonasitcomesbackfromthemodule,itis assignedtotheForm1classpublicvariableSearchKey. Alsonotethatwefully qualified the variable name, specifying Form1.SearchKey to ensure it resolves correctly. This is necessary because the SearchButton_Click() subroutine that invokedthemoduleisinadifferentclassfilethantheForm1classfilethatcalled it.
'Gambasmodulefile PUBLICFUNCTIONSearchOn(sKeyASString)ASString RETURNsKey END The DoFind Subroutine
ToolButtonsagain:UpdatingaRecord Iftheuserhappenstoeditdataonanexistingrecordwhenitisdisplayed, wewantthedatatobesavedtothesamerecord. Toaccomplishthisusinga collectionobjectiscomplicatedbythefactthateachobjectinthecollectionmust haveauniquekey.Togetaroundthis,wewilldeletetheobjectwiththecurrent keyusingthebuiltinmethodRemove,andreaddtheobjectusingthesamekey butwithupdateddata. Sortofsneaky,butitgetsthejobdonewithoutmuch effort.Hereishowitworks:
PUBLICSUBUpdate_Click() 'declarealocalcontactobjectforustoworkwith DIMMyContactRecordASContact 'instantiateit MyContactRecord=NEWContact 'nowremovetheexistingrecordinthecollection Contacts.Remove(CStr(RecordPointer)) 'thenwepopulateourworkrecordwiththeformdata MyContactRecord.FirstName=FirstName.Text MyContactRecord.LastName=LastName.Text MyContactRecord.Initial=MI.Text MyContactRecord.Suffix=Suffix.Text MyContactRecord.Street1=Street1.Text MyContactRecord.Street2=Street2.Text MyContactRecord.City=City.Text
263
265
A Beginner's Guide to Gambas Thatisallwehavelefttodo.Runtheprogramandentersomedata.Be suretotryalltheoptionsandcreateafewrecords. Saveyourdatatofileand reloadit.Whenyouaresatisfiedthatitworksasweplanned,itisoktogoback andcommentoutalltheconsoleoutput(thePRINTstatements)sotheywillnot displayatruntime. Foralltheotherprogramswehavecreated,wehavebeen contenttosimplyexecutethemfromwithintheIDE.Sincethisprogramcanbea usefuladditiontoyourdesktop,wewillnowshowyouhowtocreateastand aloneexecutableandallowittorunindependentoftheGambasprogramming environment.
CreatingaStandaloneExecutable
Itisveryeasytocreatetheexecutable.Simplymakesureyourprogramis readyforrelease(testitfirst!)andthengototheProjectmenuandchooseMake Executable.TheGambasIDEwillcreateanexecutionscriptthatwillinvokethe GambasInterpreterandallowyoutoexecuteyourcode.Icreatedadesktoplink totheprogramandusedthisfortheapplicationpathonmysystem:
'/rittingj/MyDocuments/GambasforBeginners/Classes/Classes'
Ofcourse,yoursystemwillbedifferent.Youwillneedtopointthedesktoplink totheapplicationtowhereeveryouhadtheIDEsavetheexecutablefile.Onthe LinuxdistributionIusedforthisprogram,itwouldnotworkuntilIenclosedthe fullpathwithtickmarks,asshownabove. Becausethe GambasInterpreter is invokedasasystemcall,theticksareneededtokeepthesystemfromthinkingit ispassingparametersto /rittingj/My (wherethefirstspacecharacteroccurs). Here is the final result, our program executing in standalone mode on the desktop:
Figure77ContactsManagerrunningstandaloneonmydesktop.
266
DrawProperties
EachitemyouwishtodrawinGambasissupportedwithseveralcommon attributes,suchasbackgroundcolorandforegroundcolor,afillcolor,fillstyle, etc. SomepropertiesinGambas,suchasClip,arereadonlyandsimplyreturn datatoyouforuseinyourcode. BackColor/BackgroundandForeColor/Foreground As we explained in Chapter 4, many of the properties for controls are common among all controls, so we will only explain the properties that are uniquetoagivencontrolinthischapter.
BackColorisdefinedasPROPERTYBackColorASInteger ForeColorisdefinedasPROPERTYForeColorASInteger
This integer value represents the color used for the current drawing background or foreground color. It is synonymous with the Background/Foregroundproperties. Notethat PROPERTY isapredefineddata typeusedinternallyinGambas.YoucanusetheGambaspredefinedconstantsfor colortosetcolorvalue:
Black DarkCyan DarkRed Green Pink White Blue Cyan DarkBlue DarkGray DarkGreen DarkMagenta DarkYellowDefault Gray LightGray Magenta Orange Red TransparentViolet Yellow
267
Alternatively,aswestatedpreviously,ifyouknowtheRGBorHSVvalues foraspecificcolor,GBprovidesameanstoconvertthosevaluestoaninteger valuethatcanbepassedtotheBackColor(orothercolorrelated)property.The Colorclass providestwomethods,RGBandHSVthatyoucanuse. The RGB functionreturnsacolorvaluefromitsred,greenandbluecomponents. HSV returnsacolorvaluefromitshue,saturationandvaluecomponents.Touseone ofthesefunctionstosetthebutton'sbackgroundcolor,hereiswhatyoucould code:
Draw.BackColor=Color.RGB(255,255,255)
ThiswouldsettheDrawobject'sbackgroundcolortowhite.Thisismostuseful whenyouaretryingtosetcolorswhosevaluesfalloutsidethedefaultconstants valuesprovidedinGB. Clip The Clipclass isstatic.Clipisareadonlypropertythatreturnsavirtual object(.DrawClip)thatisusedformanagingtheclippingareaofadrawing.The virtualclass.DrawClip isusedfordefiningthe clippingarea ofadrawing. The Gambas drawing methods never draw outside the boundaries of the defined clippingarea. Youcannotusethisvirtualclassasadatatype. Thestandard Gambaslanguagesyntaxis:
STATICPROPERTYREADClipAS.DrawClip
Thisclasscanbeusedasafunction.Toinvokethefunctiontodefineaclipping area,usethisGambaslanguagesyntax:
STATICSUB.DrawClip(XASInteger,YASInteger,WASInteger,HASInteger)
Properties that are returned by this function include Enabled, H, Height, W, Width,XandY. FillColor,FillStyle,FillX,FillY The FillColorproperty returnsorsetsthecolorusedbydrawingmethods
268
GambaslanguagesyntaxforFillColorandFillStyleisasfollows:
STATICPROPERTYFillColorASInteger STATICPROPERTYFillStyleASInteger
The FillX property and the FillY property are used to return or set the horizontal/vertical origin of the brushes used by drawing methods capable of fillingapolygonwithacolororpatternorboth. Gambaslanguagesyntaxfor FillXandFillYis:
STATICPROPERTYFillXASInteger STATICPROPERTYFillYASInteger
Font The Font class returns or sets the font used for rendering text on the drawingsurface.Gambaslanguagesyntaxis:
STATICPROPERTYFontASFont
Tosetcontrolfontattributes,thiscodecanbeused:
Draw.Font.Name="Lucida" Draw.Font.Bold=TRUE Draw.Font.Italic=FALSE Draw.Font.Size="10" Draw.Font.StrikeOut=FALSE Draw.Font.Underline=FALSE
Invert The Invert property is used to stipulate that all drawing primitives will combinetheirpixelcolorswiththepixelcolorsofthedestinationusinganXOR operation.Gambaslanguagesyntaxis:
269
LineStyle/LineWidth The LineStyle property returns or sets the style used for drawing lines. LineWidthreturnsorsetsthewidthusedfordrawinglines.TheLineclassisstatic anddefinestheconstantsusedbytheDraw.LineStyleproperty.Theseconstants include:
Dash DashDotDot Dot None DashDot Solid
StandardGambaslanguagesyntaxis:
STATICPROPERTYLineStyleASInteger STATICPROPERTYLineWidthASInteger
Transparent
The Transparent property indicates that some drawing methods like Draw.Text do not fill their background with anything (hence, they are transparent).Gambaslanguagesyntaxis:
STATICPROPERTYTransparentASBoolean
DrawMethods
OneofthebestwaystolearnhowtouseGambasdrawingmethodsisto writecodethatdemonstratestheuseofeachmethod. Inthismanner,youcan seehowtoprogramthemethodandgetimmediategratificationbyseeingthe results.Wearegoingtobuildademoapplicationthatwillshowyouhowtouse nearlyallofthemethodsthataresupportedbytheDrawclass. Wewillstartbecreatinganewgraphicaluserinterfaceapplication.Name theprojectgfxDemoandwhentheIDEappears,createaform,Form1.Makesure youspecifyitasastartupclassandensurethecontrolsarepublic.Hereiswhat theForm1layoutwilllooklikeatruntime:
270
Figure78gfxDemoForm1layout.
Settheformwidthto530andtheheightto490.Thedefaultsettingsfor allotherpropertiesshouldbefineforourpurposes. Createeightbuttonsand label them as shown in the picture above. The button names are TextBtn, InvRectBtn, EllipseBtn, FillRectBtn, PolygonBtn, PolyLineBtn, TileBtn, and QuitBtn.Eachbuttonshouldhaveawidthof60andaheightof25.Placethem aslowontheformasyoucanwithoutcuttingoffthebottomofthebutton.For eachbuttonyouhavecreated,wewillneedtocreateaclickeventbydouble clickingonthebutton. Aswegothroughtheexplanationsofeachofthefollowingmethods,we willbeaddingcodewhereappropriate.Beforewegettothemethodsthemselves, thereareacoupleofthingsweneedtodowithourprogram.First,weneedto addaDrawingAreacontrol,nameddatotheform.Placeitatthetopleftcorner ofForm1andmakeitabout1inchby1inch.Wewilldynamicallyresizeitinour program.Next,wewilluseaconstructortostartthedrawingprocess,invoking the Draw.Begin method and setting the parameters that will be used for our program.Hereistheconstructorsubroutineyouneedtoadd:
PUBLICSUB_new() 'establishwidthofthedrawingarea da.W=form1.W10 'establishheightofthedrawingarea da.H=form1.H45 'makethemandatorycalltostartdrawoperations Draw.Begin(da)
271
When the form opens at program start, it will first call the constructor above,thenexecutethecodeintheForm_Opensubroutine.Allwearegoingto doforthissubroutineissetthecaptionatthetopoftheform:
PUBLICSUBForm_Open() Form1.Text="DrawingExamples" END
ThefinalroutinewewillcreatebeforeexploringtheDrawmethodsisthecode neededtostopourprogram.DoubleclickontheQuitbuttonandaddthiscode:
PUBLICSUBQuitBtn_Click() Draw.End'closedrawingoperations ME.Close'closeForm1 END
Now,wearereadytobeginaddingcodetoexploreourvariousdrawingtools,the methodsoftheDrawclass. Text/TextHeight/TextWidth We will begin with Draw.Text and the two readonly text properties, TextHeightandTextWidth.TheTextHeightpropertyreturnstheheightofatext drawing while the TextWidth property returns the width of a text drawing. StandardGambaslanguagesyntaxis:
STATICFUNCTIONTextHeight(TextASString)ASInteger STATICFUNCTIONTextWidth(TextASString)ASInteger
DoubleclickontheTextbuttonandaddthiscode:
PUBLICSUBTextButton_Click() 'thisvarwillbeusedforourloopcounter DIMcounterASInteger 'clearthecurrentdrawingarea da.Clear 'setforegroundcolortoblack
272
Onceyouhaveaddedthecodeabove,saveyourworkandclicktheRUNbutton. Hereiswhatyoushouldsee:
273
Figure79ResultsofclickingtheTextButton.
WearegoingtousetheInvRectbuttontoillustratehowthesemethodsareused. DoubleclickontheInvRectbuttonandenterthefollowingcode:
PUBLICSUBInvRectBtn_Click() 'usethisvarforourloopcounter DIMcounterASInteger 'clearthedrawingarea da.Clear 'makesurefillstyleissettoNone draw.FillStyle=fill.None 'setcolortocyan draw.ForeColor=color.cyan 'thiswillmakethecyanrectangleappearred draw.Invert=TRUE FORcounter=0TO15'loop16times 'drawarect,incthestartx,yandendx,ypositions5*counterval
274
Saveyourworkandruntheprogram.WhenyouclicktheInvRectbutton, youshouldseesomethingsimilartothis:
Figure80ResultsofInvRectbuttonclick.Note thetinyblackcrosshaircenterscreen.
275
A Beginner's Guide to Gambas TheDraw.Linemethoddrawsaline.Thex1,y1pointsrepresentthestart vertexoftheline,x2,y2representtheendvertexoftheline. Thelinemethod uses properties from the Line class to establish line style and thickness. The constantsusedbytheDraw.LineStyleproperty are Dash,DashDot,DashDotDot, Dot,None,andSolid.LinethicknessissetusingtheDraw.LineWidthpropertyand widthissetinpixels.TheGambaslanguagesyntaxforthismethodis:
STATICSUBLine(X1ASInteger,Y1ASInteger,X2ASInteger,Y2ASInteger)
XandYrepresentthecenterpointofthecircleorellipse. Widthcanbe thoughofasaradiusalongthehorizontalplane, heightisaradiusalong the verticalplane. Ifyouspecifytheoptionalparametersofstartandlength,these representstartingangles(indegrees)wherethedrawingwillstartandstop.We willillustratethisinourexamplebelowusingtheEllipsesbutton.Doubleclickon theEllipsesbuttonandenterthiscode:
PUBLICSUBEllipseBtn_Click() 'declaresomevariablestoworkwith DIMx1ASInteger DIMx2ASInteger DIMy1ASInteger DIMy2ASInteger 'wewillneedacountervariable DIMiASInteger 'andavartoholdthevalueoflinewidthaswechangeit DIMlwidthASInteger 'clearourdisplaybeforewebegin da.Clear 'setinitialvectors x1=50 y1=50 x2=100 y2=100
276
277
Saveyourworkandruntheprogram.WhenyouclicktheEllipsesbutton, youshouldseesomethingsimilartothis:
Figure81Ellipsesdemonstratesdrawinglinesand ellipses.
278
A Beginner's Guide to Gambas OurnextcodesegmentwillusetheFillRectbutton.Wearerevisitingthe Draw.Rect method to show you how to use the Draw.FillStyle to create filled objects.Createaclickeventandenterthefollowingcode:
PUBLICSUBFillRectBtn_Click() 'createsomelocalvarstoworkwith DIMx1ASInteger DIMx2ASInteger DIMy1ASInteger DIMy2ASInteger 'clearthedrawingarea da.Clear 'settherecttopleftcorner x1=20 y1=80 'settherectbotrightcorner x2=x1+50 y2=y1+50 'setfgdcolortored draw.FillColor=color.Red 'specifyahorizstylefillpattern draw.FillStyle=fill.Horizontal 'drawarect,ifafillpatternisspecified,itisautofilled Draw.Rect(x1,y1,x2,y2) 'settherecttopleftcorner x1=220 y1=180 'settherectbotrightcorner x2=x1+50 y2=y1+50 'setfgdcolortoblue draw.FillColor=color.Blue 'specifyacrossstylefillpattern draw.FillStyle=fill.Cross 'drawarect,ifafillpatternisspecified,itisautofilled Draw.Rect(x1,y1,x2,y2)
279
Saveyourworkandruntheprogram.WhenyouclicktheFillRectbutton, youshouldseesomethingsimilartothis:
Figure82OutputafterclickingtheFillRectbutton.
The Points parameter is an array of Integer containing the coordinates of the polygonvertexes.Sotheremustbetwointegersinthearrayforeachvertex.We will use the FillPoly button on our Form1 to demonstrate the use of the Draw.Polygonmethod.DoubleclickontheFillPolybuttontocreateaclickevent andwhenthecodewindowappears,enterthiscode:
PUBLICSUBPolygonBtn_Click() 'declaresomeworkvariablestocreateapolygon DIMx1ASInteger DIMy1ASInteger DIMx2ASInteger DIMy2ASInteger DIMx3ASInteger DIMy3ASInteger 'wearegoingtocreateatriangleforourpolygon 'andstoretheverticesintheintegerarraytriangle DIMtriangleASInteger[] 'clearthedisplayarea da.Clear 'settheverticesforeachlegofthetriangle 'startingwiththetoppartofanequilateraltriangle x1=da.w/2'setthehorizaxistomidscreen y1=10'setverticalaxistotop+10pixels 'now,wewilldotheleftlegofthetriangle 'startingontheextremeleftedgeplus10pixels x2=da.Left+10 'andsettingourypositiontodrawingareaheight200pixels y2=da.H200 'therightlegsetshorizpositionfarright20pixelsin x3=da.W20 'andthevertaxiswillbesameasthesecondleg y3=y2 'allverticesdefined,loadtheintegerarraywiththetriangle
281
Saveyourworkandruntheprogram.WhenyouclicktheFillPolybutton, youshouldseesomethingsimilartothis:
Figure83UsingDraw.Polygontodrawa triangle.
283
Figure84UsingDraw.Polylinetodrawlines.
Image/Picture/Tile The Image class draws anImage, or part of it. The image contentsare storedintheprocessmemory,notinthedisplayserverlikeaPicture.Thisclassis creatable. If Width and Height are not specified, then the new image is void. Gambaslanguagesyntaxis:
STATICSUBImage(ImageASImage,XASInteger,YASInteger[,SrcX ASInteger,SrcYASInteger,SrcWidthASInteger,SrcHeightAS Integer])
Thefollowingcodewouldcreateanewimage:
DIMhImageASImage hImage=NEWImage([WidthASInteger,HeightASInteger])
ThecodeabovewillreturnthecolorofanimagepixelatX,Ywhilethefollowing
284
Image allows you to use the following properties: Depth, Height, Picture, and Width. Depth returnsorsetsthedepthoftheimage. Whensettingdepthvalues,you mustonlyusethefollowingvalues:2,8,16,and24.Itisdeclaredas:
PROPERTYDepthASInteger
Heightisareadonlyattributethatreturnstheheightoftheimageasaninteger. Itisdeclaredas:
PROPERTYREADHeightASInteger
Widthisareadonlyattributethatreturnsthewidthinpixelsoftheimage.Itis declaredas:
PROPERTYREADWidthASInteger
Picture (readonly) converts the image into a picture, and returns it. It is declaredas:
PROPERTYREADPictureASPicture
Fillfillstheimagewithaspecifiedcolor.Gambaslanguagesyntaxis:
SUBFill(ColorASInteger)
285
Mirrorreturnsamirroredcopyoftheimage.Themirroredcopyiscreatedusing theverticalaxisoftheimage.
FUNCTIONMirror()ASImage
ReplaceswapsanexistingOldColorvaluewiththecolorspecifiedbyNewColor,as shownbelow:
SUBReplace(OldColorASInteger,NewColorASInteger)
ResizeResizestheimagetothesizespecifiedbythewidthandheightparameter given:
SUBResize(WidthASInteger,HeightASInteger)
Rotate returns a rotated copy of the image. Gambas language syntax is as follows:
FUNCTIONRotate(AngleASFloat)ASImage
A Beginner's Guide to Gambas ThePictureclassdrawsapicture,orpartofapicture.Thepicturecontents arestoredinthedisplayserver,notintheprocessmemorylikeanImage.Evenif XWindowdoesnotmanagetransparencyyet,eachpicturecanhaveamask.This featurecanbesetexplicitlyatpictureinstantiation,orimplicitlywhenloadingan imagefilethathastransparencylikePNG.Whendrawingonapicturehavinga mask, the picture and the mask are modified accordingly. Gambas language syntaxis:
STATICSUBPicture(PictureASPicture,XASInteger,YASInteger[, SrcXASInteger,SrcYASInteger,SrcWidthASInteger,SrcHeightAS Integer])
Thisclassiscreatable.ThefollowingcodeshowsyouhowtocreateaPicture:
DIMhPictureASPicture hPicture=NEWPicture([WidthASInteger,HeightASInteger, TransparentASBoolean])
Thecodeabovewillreturnapictureobjectfromtheinternalpicturecache. If the picture is not present in the cache, it is automatically loaded from the specifiedfile. Inordertoinsertapictureintheinternalpicturecache,usethis code:
DIMhPictureASPicture Picture[PathASString]=hPicture
Heightisareadonlyattributethatreturnstheheightofthepictureasaninteger. Itisdeclaredas:
287
Widthisareadonlyattributethatreturnsthewidthinpixelsofthepicture.Itis declaredas:
PROPERTYREADWidthASInteger
Imageisareadonlypropertythatconvertsthepictureintoanimageandreturns it.Itisdeclaredas:
PROPERTYREADImageASImage
Wewilluseaverysimpleexampletoshowyouhowthisworks.Wewill showyouhowtotakeascreenshotwithcodeandsavetheimage.Theimageof thedesktopistakenasapictureobjectwhenthebuttonontheformisclicked. Thispictureobjectissubsequentlyconvertedintoanimageobjectanddisplayed asanimageinaDrawingArea. Start Gambas and create a new graphical user interface project, named gfxDemo2.MaketheprojecttranslatablewithpubliccontrolsandwhentheIDE appears,createastartupclassformnamedForm1.Fromthepropertieswindow forForm1,settheresizepropertytoTruesoyoucanstretchtheformtoseethe imagewhenitisadded.AddabuttonnamedButton1andaDrawingAreanamed DrawingArea1. Place theDrawingArea atthetopleft cornerof theformand makeitaboutoneinchwideand oneinchhigh. Now,putthebuttonatthe bottom right corner of the form. Add the caption Snapshot to the button. Doubleclickonthebuttontocreateaclickeventandaddthiscode:
'Gambasclassfile PUBLICSUBButton1_Click() 'declareavarforourpicture pASNEWPicture 'andoneforourimage iASNEWImage 'getthepictureojbectfromthedesktopusing.Grabmethod p=Desktop.Grab() 'assignthepictureusingtheimagepropertyto 'convertscreenshottoanimage i=p.image
288
289
FlushFlushestheinternalpicturecache.Themethodtakesnoparametersandis calledusingthisconvention:
STATICSUBFlush()
Resizeresizestheimagetothesizespecifiedbythewidthandheightparameter given:
SUBResize(WidthASInteger,HeightASInteger)
The Tile method draws a tiled picture in the DrawingArea. Gambas languagesyntaxisasfollows:
STATICSUBTile(PictureASPicture,XASInteger,YASInteger,Width ASInteger,HeightASInteger)
290
Thelastthingweneedtodoisgetanimagetouseforourprogram.For ourprogarm,IhavechosentheGambasmascot,whichweusedfromanearlier project.YoucancopythisimagefromourFirstProject.Fromtheprojectwindow, ontheTreeViewDatafolder,selectNewImage.Whenthewindowappears,you canselecttheExistingtabandbrowsetothefolderFirstProject(assumingyou named your projects as we specified in the book) and choose the Gambas mascot.pngimage.SaveittothegfxDemoprojectasGambasshrimp.pngand thatisallthereistoit.If,forsomereason,youcannotfindtheimageonyour
291
Figure85Usingtiledimageswiththe TileImgbuttonofourdemoprogram.
DrawingwithaDrawingobject In Gambas, a drawing object is based on the use of Scalable Vector Graphics,or SVG. Accordingtothe SVGspecification16, SVGisalanguagefor describingtwodimensionalgraphicsinXML.SVGallowsforthreetypesofgraphic objects:vectorgraphicshapes(e.g.,pathsconsistingofstraightlinesandcurves), images and text. Graphical objects can be grouped, styled, transformed and composited into previously rendered objects. The feature set includes nested transformations, clipping paths, alpha masks, filter effects and template objects. SVG drawings can be interactive and dynamic. Animations can be defined and triggeredeitherdeclaratively (i.e.,byembeddingSVGanimationelementsinSVG content)orviascripting. Inkscape17isapopularprogramusedintheLinuxcommunityforcreating SVGimagesandiswhatthisauthorhaschosentousewiththisbooksinceitis freelyavailableontheInternet.Inkscapeisanopensourcevectorgraphicseditor, withcapabilitiessimilartoIllustrator,Freehand,CorelDraw,orXaraXusingthe W3CstandardScalableVectorGraphics(SVG)fileformat.
16 See URL http://www.w3.org/TR/SVG/intro.html for more details on SVG. 17 See URL http://www.inkscape.org/ for more details on Inkscape. 292
A Beginner's Guide to Gambas In Gambas, you can load, save, clear, or copy an SVG image. The properties that you have available to you are the most basic, namely width, height,anddepth. GambasisnotdesignedtobeanSVGeditor. Itsimplyhas provisions for you to use SVG images in your program. Once you have the drawinginyourprogram,itisuptoyoutodosomethingwithit.Asanexample, wewillcreateanewprogramtosimplyloadanSVGimageanddisplayit.First, wewillneedtofindanSVGimage.Ihavedownloadedafreelyavailablepublic domainlicensedimagefromtheInternetathttp://openclipart.orgtouseforour demo.Youcanchooseanyimageyouwishforthisdemo,solongasitisanSVG formatted file. Now, we will create a new graphical user interface project in Gambas named gfxDemo3. Make the project controls public and translatable. Next,createanewstartupclassform,namedForm1.Wearegoingtoaddseveral controls: Scrollview, DrawingArea, HBox, and two buttons. Your form should looklikethisindesignmode:
A Beginner's Guide to Gambas Start with the ScrollView control, naming it ScrollView1. Next, add a DrawingAreaontopofthe ScrollViewcontrol. NametheDrawingAreadaSVG. AddtheHBox,namedHBox1andthetwobuttonsnamedLoadBtnandQuitBtn. Don'tforgettoaddthetextcaptionstothebuttons. Next,doubleclickonthe Quitbuttonandaddthiscode:
PUBLICSUBQuitBtn_Click() ME.Close END
Now,doubleclickontheLoadBtnandaddthis:
PUBLICSUBLoadBtn_Click() 'declareourDrawingobjectfortheSVGfile DIMdraASDrawing 'instantiateit dra=NEWDrawing 'nowloaditusingtheLoadmethod dra.Load("floppy.svg") 'setcachedpropertytoTRUEtocacheitinmemory daSvg.Cached=TRUE 'setvisiblepropertytoTRUEsowecanseethepicture daSvg.Visible=TRUE 'movethedrawingareaobjecttostartattopleft(0,0)origin dasvg.Move(0,0,dra.Width,dra.Height) 'callthemandatoryDraw.Begintostarttodraw draw.Begin(daSvg) 'dothedraw draw.Drawing(dra,0,0) 'calltheDraw.Endmethodtoquitdrawing draw.end 'refreshourformtoseewhatwasdone Form1.Refresh END
Onceyouhavedownloadedorcreatedthefloppy.svgfile,saveittothe
294
Figure86LoadinganSVGfileinGambas.
295
297
A Beginner's Guide to Gambas duringtheinitialdevelopmentofthetestplansbecauseitcancomebacktohaunt youformany,manybuildandretestiterations.Finally,iftheerrordoesoccur, whatcanbedonetogettheprogrambacktothestateofusabilityitwasinbefore theerroroccurred? Most errors are the result of inadequate design, poor programming practices,andpoortesting.Poorprogrammingpracticesincludecodingonlythe method of achieving the desired results without accounting for user error, mistakesininput,validationerrors,etc.Allprogrammersknowhowtodevelop datavalidationchecksand usuallytrytoputthemoffuntiltheygetthecode working.Makingdatavalidationarequirementbumpsthepriorityofdoingthis workupanotchonthelistofthingstheprogrammerhastodo.Poortestingis epitomizedbytestteamsfailingtoaccountforthesetypesoffactorsinthedesign andconstructionoftheproducttestplansandtestcases. BoundaryRelatedErrors Whenaprogramexecutes,theprogramcursormovesfromonepartofthe programtothenextexecutingthecodedinstructionssequentially.Thetransition fromoneareatothenextintheprogramisdefinedbytheexitofoneboundary condition and theentrytothenext. Thistransitional state,or boundary, can includenumeric,text,andoperatorboundaries. Iftheuserisaskedtoentera numberfrom0to99inaprogram,whathappensiftheuserenterstheletterB ortypesin123instead?Whatiftheuserentersthenumber84andthesystem tellsyouthenumberistoolarge,promptingtheusertotryenteringanumber from099onceagain?Doestheprogramfailtovalidateinputandattemptto processbadinput?Haveallpossibleboundaryconditionsbeenaccountedforin designandtest?Really? CalculationErrors There are an infinite number of conditions that can cause calculation errors. Theprogrammerlogicmayhavebeeninerrororhisorherformulafor the calculation may be coded incorrectly. Rounding or truncation errors can significantly alter desired results. A good design process should incorporate pseudocodeforanyandallcalculatedresultstoshowhowtheseformulasare intendedtobeimplementedorusedinproduction.Codereviewswouldcheckto seethattheyareindeedimplementedasdesigned.Testcaseswouldexecuteall boundaryconditionsagainstthecodeandverifytheimplementationisasrock solidasitcanbebeforeturningitovertoproductionforgeneraluse.
299
A Beginner's Guide to Gambas InitialandLaterStates Whenaprogramexecutessubroutinesandusesvariables,thesevariables oftenmustbeinitializedwithdefaultvalues.InGambas,suchdefaultsgenerally take the form of a zero value or a NULL value. If initialization is not done specifically by a developer, it is anyones guess as to what the value of that variablewillbewhenfirstcalledunlessthevariableisoneofthedatatypesthat Gambasinitializesautomatically.Remember,thesetypesoferrorsarearesult ofprogrammersnotdoingthejobcorrectly.Asanexample,letusassumethat inthepreviousexampleabovenovariable initialization iswhathashappened when a routine calls for a variable to increment. The program processed 50 records,incrementingthevalueofthevariableeachtimetheroutineisexecuted. When the value is output at the end of processing, it should be equal to 50. However,theuninitializedvariablehadavalueof122(orsomeotherrandom number) and the output shown to the user was 172. This describes what constitutesaninitialstateerror. Todemonstratelaterstateerrors,considerthesamesituationasabove,but instead of passing the expected value of 50 to another module to use for processing,thevalueof172ispassedalong. Theseerrorsareabitharderto detectbecausetheoutputfromthecalledmoduleiswheretheuserthinksthe error occurred. Programmers assigned to debug this problem have to trace throughtheexecutionpathandfollowthechangingstateofthevariableuntilitis discoveredtobeaprobleminthecallingmodule,notthecalledone.Theresult ofthisisagreatdealoftimeandeffortwentintodiscoveringaproblemthatwas avoidable. If the user reported this from a production system, project team credibilityagaintakesahit.Asaprogrammanager,youmustensurethesetypes of situations are prevented by facilitating adequate, indepth discussion in the designphase. ControlFlowErrors Previously,westatedthatwhenaprogramexecutes,theprogramcursor movesfromonepartoftheprogramtothenext,executingthecodedinstructions sequentially. Someexecutioninstructionsforcetheprogramtojumpfromone routine to another. This movementin execution isreferred to as programor control flow. When a program does something wrong in control flow, it is generallyaproblemwiththeprogramlogicoraprogrammererrorincodingthe design. Such logic errors are often uncovered during code reviews in the implementationphase.Sometimes,intestingtheyarediscoveredbybuildingtest
300
A Beginner's Guide to Gambas cases to validate program flow based on the design specifications built in the designphaseandthetestplansbuiltintheimplementationphase.Anyofthese typesoferrorsdiscoveredbyauserwhenasystemisinproductionreflectsa failureofthetestteamtoadequatelytesttheproduct. Asaprojectleader,you areultimatelyresponsibleforpreventingthissituationfromoccurring. TRYto workwiththedesignteamandtestcasedevelopersasearlyintheprocessas possible to set proper expectations for the type of testing and the level of thoroughnessyouexpect. ErrorsinHandlingorInterpretingData There are many ways data can become chock full of errors in a developmentprocess.However,almostallofthesemyriadwaysdatacangoawry are attributed to human error. These types of errors can be a result of miscalculation, errors in logic, parameter passing errors, use of incorrect data types,etc. Almostanythingthataprogrammercandotomakeamistakecan causeanerrorindata.Thebestmeansofpreventingsucherrorsisacontinual checkoflogic,reviewofexpectedandactualvalues,reviewofinputandoutput data,etc.Thisisanongoingprocessanditinvolvesbothuseranddeveloper. Fromtheuserperspective,thedatashouldbebenchmarkedagainstcurrent meansofproducingthedata. Theusershouldcontinuallyreviewtheresultsof outputtoensuresomethinghasnotrunafoulandcauseddatatobecomebad. Fromthedeveloperperspective,basiccodingdisciplineshouldbeenforced;range andboundaryconditionsneedtobechecked,parametricvaluesneedvalidation, datatypevalidationmustoccur,anduseoftestdatamustbevalidatedtobeof the right format, current and in sync with production data, and usable for productionoutput. Itisalwaysgoodforteamleadstoreinforcetheseconcepts withdevelopersandensureperiodiccodereviewstakeplace. Itisessentialto teamsuccess. RaceandLoadConditions Araceconditionisbestdefinedasoneeventprecedinganother.Thetrick ismakingsurethefirstconditionshouldbefirstorthelastconditionissupposed to be last. Few programmers think about or even check for race conditions. Theseconditionsaresometimesidentifiedonlyaftergreatmanpowerhasbeen expended in doing traces into executable code, step by step, to see what is happening.Whenyouhearthewordsirreproducibleastestersaretalkingabout thistypeofbug,interpretittomeanapossibleraceconditionandasksomeoneif
301
A Beginner's Guide to Gambas theyhavecheckedforit. Loadconditions arecommonandaretheresultofputtingmoreworkon thecomputerthanitcanbeartohandle.Asimplepointofillustrationishavinga computerprocessmillionsofrecords. Itistheperfectjobforacomputerbut, whenthetimetoprocesseachrecordismorethanafewmilliseconds,themillion recordstobeprocessedcantakeagreatdealoftime.Forexample,letsassume an ideal situation where your application does some complex validation, necessary to properly process a record, and that it takes 10 milliseconds to process each of these records in a perfectly managed test environment. This translatestoaprocessingrateof100recordsasecond.Notbad,butwhenyou divide100into1,000,000 records,youquicklyfindoutthatthisjobwilltake 10,000 secondsor2.7 hourstoruntocompletion. Again,acceptable inmost cases,exceptthatyoumustrememberthemachineiscompletelytiedupwith processing. Noreportscanbeproduced,noqueriescanberun,etc. Intodays moderncomputingenvironment,thisisnotacceptable. Letstakeanotherviewwhererealworldconditionsareapplied.Inatest environment,wherethe10millisecondsareidealcomputingconditions,wewill compoundtheproblemwithuserinteractionandsystemoverhead.Letslookat recordretrievaltimesandfactorthatintotheequation.Your10millisecondsare now 14.5 milliseconds per record. User queries and other user interactions interactioncouldeasilyaddanother10orsomillisecondsperactivityandnow weareat25millisecondsofprocessingtimeforjustasinglerecord.Wearenow lookingat6.75hourstorunthesamejobthatranin2.7hoursinthetestlab. The point here is that testing should account for such load conditions before releaseintoproduction.Ifauserknowsbeforekickingoffaproductionjobthatit willtake7hourstorun,theycangooffanddootherthingsorrunthejobat night. However, if the EXPECTATION is a 2.5 hour job, they will always be dissatisfiedwithperformancebecauseitisnotwhattheyexpected. PlatformandHardwareIssues Hardwareissuesareamongthemostfrustratingausercanencounter.An examplewouldbehavingauserselecttoprintareportandwatchitscrollbyon thescreen,atamillionwordsasecond. Theprinterdevicewasnotspecified correctly or not specified at all. The user assumed a printer would print the reportbutdeviceerrorsorlackofdevicehandlingcausedthesituationabove. Therearemanytypesofdeviceswhichaprogrammermustaccountforandthe testingprocessneedstoaccountforuserinteractiononallofthem.Asidefrom
302
A Beginner's Guide to Gambas theconditioncitedabove,programscansendthewrongcodestotherightdevice, overrunthedevicewithdata,etc. Programmersandtestersareresponsiblefor ensuring these conditions are accounted for and tested before your user communityareexposedtothem.Allthesetypesoferrorscandoisgiveyouabad markincredibilityasyourusersrateyourperformance. Source,Version,andIDControlErrors Thesetypesoferrorsaregenerallyduetopoorconfigurationmanagement and an internal lack of enforcement of existing configuration management policiesandprocedures.Anexampleofthisishavinganewprogrammerinserta betaversionofcodeintoaproductionstablereleaseforanormalbugfixandthen nottellinganyoneachangehasbeenmadeinthatmodule.Normaltestingofthe maintenancereleasewilllikelynotcatchtheproblemanditmaygounnoticed forseveralsubsequentreleases. Asanotherexample,thissituationcould besomethingasinsidiousas a dataerrorthatonlyshowsuponlywhenquarterlyfinancialsareproduced.When thereisnoreasontobefoundastowhythecompanybalancesheetisoffby several hundred thousand dollars, much effort is expended in having senior developers perform code traces to find a problem. Someone will eventually discoverthatthereissomebetacodeinaproductionmodulethathaserrantly roundedeverythingtothenearestdollarorsomeothersimilarstupidmistake. Good intentions aside, the best cure for these types of problems is good programmerdisciplineforconfigurationmanagementandtohavestrongpolicy enforcementingrainedintoanorganizationscorporateculture. TestingErrors Eventestersmakemistakes. Theycaninterpretthelogicofatestcase improperly,theycanmisinterprettestresults,failtoreportglitches,etc.Testers mayforgettoexecutetestcasesorreportbugsthatreallydontexist.Thesefolks arehumantoo.Thatmeanstheirresultsarealsosubjecttoquestioning.When yourteamshaveworkedhardtodevelopsomethingand thetestresultscome backskewedbadlyonewayoranother,questionthetestprocess. TestPlanReviews Forallbutthemostsimpletypesofprojects,aformalreviewprocessis generally required. This also requires participation from the users, the
303
A Beginner's Guide to Gambas developers, the systems analysts, data analysts, and testers. It is best for all concerned if the formal test review include the most experienced users and developers present in an organization. Some users may not have the proper experiencewithasystemtoproperlyidentifyproblemsbeforetheyoccurandthis addedexperiencecanonlybenefitareviewprocess. Ensureparticipationina formaltestplanreviewisbased lesson theavailability ofuserand developer personnelandmoreonthecontributionsthebestqualifieddevelopersandusers canbringtothetable.Nowthatwehaveagoodunderstandingofthehowand whyoferrors,letstalkabouthowwecanmanagesucherrorsinGambas.
GambasErrormanagement
Gambas provides builtin mechanisms to assist the programmer in error management. Suchmechanismsaretoolsataprogrammer'sdisposal thatare oftenoverlookedand,inmanyinstances,notusedatall.Gambaswasdesigned withtheconceptsofsimplicityandavoidanceoferrantlogicinmind. Gambas programsyouwriteshouldtrytoadheretotheseconceptsbyusingallofthe meansavailabletopreventerrors.Thismeanstakingthetimetowritevalidation routines,workingyourcodetotrackflowandprovideoutputlogs,etc.Itisreally not that much more work and will make a huge difference in the long run. Gambascanonlyprovideanenvironmentinwhichtodevelop,but,intheend,it isyou,thecoder,thatisresponsibleforyourproduct.Let'stakesometimenow tolearnhowtousetheGambasfeaturesforerrormanagement. TRYstatement...IFERROR TheTRYcommandprovidesaprogrammerwiththemeanstoperforman errorcheckanywhereheorshesuspectsanerrormayoccur.Itis,ineffect,away totestthewaterbeforejumpingin.Youcantrytoexecutethestatementand,if anerroroccurs,itwillberecordedbythe Errorclass. Thisisdonebysetting propertyvaluesthatyoucancheck.Thesepropertyvaluesinclude:
TheError.Classpropertywillreturntoyouthenameoftheclasswherethe erroroccurredandthe Error.Codeproperty willtellyouwhatthespecificerror code was. Thetextassociated withtheError.Code isstored inthe Error.Text
304
A Beginner's Guide to Gambas property andthe Error.Whereproperty willtellyoutheoffendinglineofsource code(ifpossible). Theerrorclassalsoprovidestwomethods, Error.Clear and Error.Raise thatyoucanusetohelptrackdownproblems. Wewilldiscussthe useofthesetwomethodsalittlebitlaterinthischapter. The TRYstatement isusedtotestforspecificerrorswhereasthe CATCH statement (described below) is more of a general purpose error catching mechanism.ThegenerallogicusedforTRYisshowninthepseudocodebelow:
TRYaStatement ifERRORTHEN Message.Error(error.text) endif 'endoftry
Saveyourworkandexecutetheprogram.ClicktheExitbuttonandyoushould seesomethingsimilartothis:
Figure87ErrorresultscaughtwithTRY.
305
A Beginner's Guide to Gambas CatchandFinallyStatements Catch is a general purpose error trap. Itis executed when an error is raisedanywherebetweenwhereafunctionstartstoexecuteandwhereitends. Catchprovidesamenstodealwitherrorsthatmayoccurinagivenfunctionand stillallowtheusertokeepusingtheprogram. Anerrorcanberaisedbythe functionitself,orbyanyotherfunctionitmaycallduringexecution.Ifthecalled functionhasaCatchblock,themorenestedtheCatchblockis,themorepriority ithas. Inotherwords,ifanyerroroccurredinthenestedsectionofcode,the Catchinthatsectionwouldbeexecuted,nottheCatchfromthecallingfunction. Ifanerrorisraisedwhiletheprogramisexecutingwithinthecatchblockitself, theerrorwillnormallybepropagatedoutsidethecatchblockbecausecatchhas nomeansofprotectingitself. Ifthereisa Finally partinthefunction,itmust precedethecatchpart.Let'screateasimpleprogramtodemonstratethisfeature. Createanewprojectnamed Chap13 asaGUIbasedprojectandwhentheIDE appears,createastartupclassformnamedForm1.Addtwobuttons,Errorand Quit,namedErrBtnandQuitBtn.Placethebuttonsonthebottomrightcornerof theform.CreateaTextLabelandnameitTextLabel1.Putitatthetopleftcorner oftheformandstretchitallthewayacrossandmakeitaboutoneinchinheight. Doubleclickontheformandenterthiscode:
'Gambasclassfile PUBLICSUB_new() TextLabel1.Text="<center><strong>Noerrorspresent." END STATICPUBLICFUNCTIONRun()ASBoolean DIMhFormASForm hForm=NEWForm1 RETURNhForm.ShowModal() END PUBLICSUBQuitBtn_Click() ME.Close(TRUE) END PUBLICSUBErrBtn_Click() DIMaASInteger DIMbASInteger a=2 b=0 PRINTa/b'willgenerateadividebyzeroerror
306
Whenyouruntheprogram,youshouldseethisastheopeningscreen:
Figure88CATCHtestprogramopeningscreen.
Now,clicktheerrorbuttontogenerateourerrorandyoushouldseethis:
Figure89DivbyZeroerrorcaughtbyCATCH.
YoushouldalsonoticethatthemainscreenTextLabelhaschangedtothis:
307
Figure90TheTextLabelupdatedwitherrorinfo.
OnceyouclicktheOkbuttonfortheErrorMessagedialog,youwillseethis:
Figure91Infomessagethattheerroris cleared.
Now,clicktheOKbuttonontheInfomessageandtheTextAreaisupdatedlike this:
Figure92Mainscreenaftererrorhasbeencleared.
Now,runtheprogramagainandclicktheErrorbutton.Hereiswhatyouget:
Figure93DefaultGambaserrordialog.
GambasEventmanagement
Gambas is built around an eventdriven programming paradigm. Traditionalcomputerprogramminglanguagesweredesignedtofollowtheirown control flow changing flow direction (course) at branch points. In an event drivenparadigm, the control flowis largely driven by external eventssuch as mouse movements, button clicks, etc. Generally, an eventdriven system is preprogrammedusinganeventloopwhichsystematicallypollsthesystemtolook forinformationtoprocess(whichcouldbeanytypeofevent,eventhepassageof time).Ifaneventisdetected,ittriggersaflagthatcanbecheckedintheevent loop. Thisallowsprogrammerstocheckforandrespondtoeventsbywriting
309
A Beginner's Guide to Gambas subroutinesorfunctiontoprocessthem. How information on events is acquired by the system is not really importanttotheprogrammer.Commontypesofeventinputdatacanbepolled intheeventloop.Complexorproprietaryeventsmayrequiretheuseofinterrupt handlersthatreacttohardwareevents,suchassignaldatatraversinganetwork interfacecard(NIC).Mosteventdrivensystemsusebothtechniques.Algorithms writtenbytheprogrammertorespondtoeventsensurethatwhenagiveneventis triggered, code to handle the event in a manner acceptable to the user is provided.Thiscreatesalayerofsoftwareabstractionthatemulatesaninterrupt drivenenvironment.Eventdrivenprogramstypicallyconsistofanumberofsmall programscalledeventhandlers.Eventhandlersarecalledinresponsetoevents. A dispatcher is used to call the event handler. Most often, the dispatcher is implementedbyusinganeventqueuetoholdunprocessedevents. Sometimes, eventhandlerscantriggereventsthemselves.Thiscanpossiblyleadtoanevent cascade(notgood). Gambas, like most common graphical user interface programs, is programmed in an eventdriven style. In Gambas, you have the capability of creatingeventsforuseinyourprograms.Youcandeclareaneventlikethis:
EVENTIdentifier([Parameter#1[,Parameter#2...])[ASBoolean]
Thisdeclarationwilldeclarea classevent. Aclasseventisraisedbya functioncall.Additionally,youcanspecifywhetherornottheeventhandlerwill returna (Boolean)value. If areturnvalueisspecified, a TRUEreturn result wouldindicatethattheeventwascanceled. AuniquefeatureofGambasisthatanobjectcanraiseanevent.Inorder toraiseanevent,theobjectmustbegivenaname(orhandle)atthetimeitis createdwiththeNEWkeyword.Withoutbeingassignedaname,eventsraisedby anobjectareignored.Eventsarecaughtbytheparentofanobject.Theparentis actuallyanobject'suniqueeventobserver.Theparentactsasthedefaultobserver fortheobjectwhenaneventisraised.Thisparentcanbeaclass,inwhichcase theeventhandlermustbeastaticmethod.Inthiscase,thehandleandtheparent bothcanbechangedatruntimeusingtheObject.Attach()andObject.Detach() methodsoftheObjectclass.Thehandleoftheobjectisnotstoredwithanobject andthereforecannotberetrieved. InGambas,thestandardcallingconventionforaneventhandlerwouldbe
310
Figure94Oureventwasraised.
311
MouseOperations
In Gambas, we can use the Mouse class to obtain information about a mouseevent. Thisclassdefinestheconstantsusedwiththemouseproperties. Theclassisstaticandthepropertiessupportedare:
Alt Meta ScreenX Button Middle ScreenY Control Normal Shift Delta Orientation X Left Right Y
Mostofthesepropertiesareselfexplainedbytheirname,butafewneed furtherexplanation. The Alt, Control, Meta and Shift propertiesall returna TRUEvalueifthoserespectivekeysarepressed.Normalcanbechecked(tested) toseeifanyotherspecialkeywaspressed. Button canbeusedtoseeifany buttonispressedbutyoucanuse Left,Right,and Middle todetermineifany specificmousebuttonhasbeenpressed.AllofthesepropertiesreturnTRUEifa button is pressed. Delta returns the (offset) value of the mouse wheel while Orientation can be used to check the direction (forward, backwards) of the wheel'sturn.ScreenXandScreenYreturntheabsolutevalueofthecursorbased onthedesktopwhileXandYreturnthepositionrelativetothewindow. ThereisonlyonemethodfortheMouseclass,Move.TheMovemethod simply repositionsthemousecursor totheX,Y coordinatesspecified. Mouse eventsyoucanmonitorinyourprogramareMousemove,MouseDown,Mouseup,
312
A Beginner's Guide to Gambas andMousewheel. Anychangeinthecurrentstateofthoseeventsallowyouto create a coded response for that event. When coding mouse (or keyboard) operations,itisveryimportanttoalwaysusethepredefinedconstants. Usingany other method of getting or setting properties is not guaranteed to be upward compatible from one Gambas version to the next. The Mouse class uses the followingconstantstospecifytheshapeofthemousecursor:
Arrow Horizontal SizeN SizeS SplitH Blank Pointing SizeNE SizeSE SplitV Cross SizeAll SizeNESW SizeSW Text Custom SizeE SizeNW SizeV Vertical Default SizeH SizeNWSE SizeW Wait
Let'screateashortGambasprogramtodemonstratehowtousethemouse now.FromtheGambasIDE,createanewprojectnamedMouseOpsandmakeit agraphicaluserinterfaceproject,translatablewithpubliccontrols.Createanew form,Form1andmakeitastartupclassform.Next,addadrawingareanamed da tothetopleftcorneroftheForm1window. Resizeittobeaboutoneinch square. Now,let'saddsomecode. Firstofall,whentheprogramrunsandthe windowopens,wewanttosetacaptionthattellstheuserhowtoclearorexitthe window.Wealsoneedtoresizethedrawingareatofittheformfullyandsetthe cachedbufferpropertytoTRUEsoourdrawingcanbeseenbytheuser.Hereis howtodothis:
'Gambasclassfile 'whenformopensatruntime,setacaptionandresizethedrawingarea PUBLICSUBForm_Open() ME.Caption="Pressspacetoclear,mousewheelexits..." da.W=ME.W5 da.H=ME.H5 da.ForeColor=color.Black'settheforegroundcolortoblack 'setcachedpropertytotruesowecanstorethedrawingbuffer da.Cached=TRUE draw.Begin(da)'starttodraw 'wewilldrawahorizandvertlinetosectionfourquadrants draw.Line(1,da.h/2,da.W1,da.h/2) draw.Line(da.W/2,1,da.W/2,da.H1) draw.End END
Nowthatwehavesetthecursorshape,wewillchecktoseeiftheuseris pressing a mouse button to draw. If the left buttonis pressed, we will draw points.Ifitistherightbutton,wewilldrawtinyboxes.
'checkmousebuttonispressedtoseewhichoneispressedand 'drawpointsforleftbtn,boxesfortheright IFMouse.LeftTHEN 'starttodraw Draw.Begin(da) 'littletinydots Draw.Point(Mouse.X,Mouse.Y) Draw.End ELSE'ifitisrightbutton Draw.Begin(da) Draw.Rect(Mouse.X,Mouse.Y,3,3) Draw.End ENDIF END
Whenevertheusermovesthemousewheel,wewillterminatetheapplication.
'iftheusermovesthemousewheel,wewillterminatetheapplication PUBLICSUBda_MouseWheel() ME.Close END
314
Finally,iftheuserpressesanykey,wewillresetthedrawingareabyclearingit andredrawthequadrantbycallingthesameroutineusedtoopentheform:
'checkkbdeventstoclearthedrawingareaandredrawthequadrants PUBLICSUBForm_KeyPress() da.Clear Form_Open() END That'sit.Whenyouruntheprogram,youshouldseesomethinglike this:
Figure95MouseOpsprogramrunning.
315
KeyboardOperations
This class is used for getting information about a keyboard event. It containsallofthepredefinedconstantsGambasusestorepresentthekeysfound on your keyboard. As we pointed out previously, you should never use the integer key values directly. You should always use the Gambas predefined constants.Thisclassisstaticanditactslikeareadonlyarray.Youcandeclare an integer variable and obtain the value of a key constant using this calling convention:
DIMMyIntegerASInteger MyInteger=Key[KeyASString]
PropertiesthataresupportedfortheKeyclassincludeAlt,Code,Control, Meta,Normal,Shift,StateandText.Statecanbeusedtotestwhetherornota specialkeyispressedandTextwillreturnthesinglecharacterrepresentationfor agivenkey. AlltheotherpropertiesworklikethoseusedwiththeMouseclass we described in the previous section. The Key class supports the following predefinedconstants: Forcursorkeys: Up,Down,Left,andRight
Let'screateanothershortGambasprogramtodemonstratehowtousethe keyboard.FromtheGambasIDE,createanewprojectnamedKbdOpsandmake itagraphicaluserinterfaceproject,translatablewithpubliccontrols. Createa newform,Form1andmakeitastartupclassform.Wewillonlyneedtousetwo labelsinthisprogram,aTextLabelandaLabel.First,createaTextLabelnamed TextLabel1andmakeitabout1/2highandstretchitacrossthewidthofthe form. SettheTextLabel1.Alignmentpropertyto center. Now,createaLabel named Label1 and place it below the TextLabel1 control. Make it about two
316
As you can see, the code above is pretty straightforward and simple. Whenyouruntheprogram,youshouldseesomethinglikethis:
Figure96KbdOpsprogramrunning.
BitOperations
Bits are the smallest elements used in computer operations. They are indivisibleatomsofmemoryclusteredingroupscalledbytes.Abyteiscomposed of n number of bits, which is dependent upon the machine word size. For example,inaneightbitsystem,onebyteiscomposedofeightbits.Formodern computingsystemsusedtoday,theoperatingsystemisbuiltusing32or64bit word sizes. The word size increases in order to accommodate a larger addressablememoryspace.Inanoldereightbitsystemforexample,thesystem canonlyaddressmemorythatcanbeexpressedinbinaryformas11111111.In
318
A Beginner's Guide to Gambas otherwords,thememoryspaceislimitedtoasizethatcanbeexpressedwith thoseeightbits.Foraneightbitsystemsmemoryrangesextendfromthesingle bytedecimalrepresentationof65537to+65538.Inamodern32bitsystem,it takesthebinaryformof11111111111111111111111111111111 whichcanbe expressedindecimalnotationas2,147,483,648to+2,147,483,647.Asyoucan see,theaddressablerangeofmemorywith32bitsystemsishuge! Inapplicationslevelprogramming,thereisgenerallynotmuchoccasionto operate at the bitlevel when but occasionally the need does arise. Gambas providesallofthetoolsyouneedtotestabit,clearit,change(invert)it,orsetit. Additionally,bitwiseoperationsyoucanperformincluderotatingabitrightor leftandshiftingabitrightorleft.Thetablebelowsummarizesthebitoperations youcanperforminGambas:
Syntax
Value=BClr(Number,Bit) Value=BSet(Number,Bit) Value=BChg(Number,Bit) Value=Shl(Number,Bit) Value=Shr(Number,Bit) Value=Rol(Number,Bit) Value=Ror(Number,Bit)
Actiontaken
Clearaspecificbitinoperand1usingoperand2 ReturnTRUEifthethebitspecifiedinoperand2ofoperand1isset. Returnsoperand1withthebitspecifiedinoperand2inverted. Returnsoperand1withthebitspecifiedinoperand2shiftedleftonebit position. Returnsoperand1withthebitspecifiedinoperand2shiftedrightonebit position. Returnsoperand1rotatedleftoperand2bitpositions. Returnsoperand1rotatedrightoperand2bitpositions.
Boolean=BTst(Number,Bit) Testtoseeifabitissetinoperand1usingoperand2
Now, we will create yet another short Gambas program todemonstrate howtousethebitfunctions.FromtheGambasIDE,createanewprojectnamed BitOps. Make it a graphical user interface project, translatable with public controls. Create a new form,Form1 and make itastartup class form. Our programwilltakeanintegernumberfrom0255anddisplaythehexadecimal andbinaryvaluesforthatnumber.Itwillallowyoutoselectanyoneoftheeight bitsusedtorepresenttheintegernumberandperformwhateveroperationthe buttonyouclickrepresents.Thebinaryvalueofthatintegerwillbedisplayedso you can compare that binary value to the value of the integer as originally specified. Forthisprogram,wewillneedsevenTextLabels,namedTextLabel1 through Textlabel7. We will need two TextBoxes, TextBox1 and TextBox2. Finally, we will add nine buttons named RolBtn, RorBtn, ShlBtn, ShrBtn, ClearBtn, TestBtn, SetBtn, ChangeBtn, and the QuitBtn. Layout the controls
319
Figure97TheBitOpsprogramindesignmode.
Once you have finished laying out the controls as shown in the figure above,doubleclicksomewhereontheformandthecodewindowwillappear. AddthefollowingcodefortheForm_Opensubroutine:
'Gambasclassfile PUBLICSUBForm_Open() ME.Caption="bitOpns" END
Now,theprogramwilldisplaythecaptionbitOpnswhenitisexecuted. Let's code an exit procedure so the user can terminate the application next. DoubleclickontheQuitbuttonandaddthis:
PUBLICSUBQuitBtn_Click() ME.Close'closethewindow END
320
Whentheuserpressestheclearbutton,wewanttoclearthebitspecifiedforthe integerrepresentedbythefirstparameter.
PUBLICSUBClearBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger 'convertourstringtextvaluetoanint myInt=CInt(textbox1.text) 'iftheintegerisbetween0and255process,otherwiseignore IFInt(myInt>=0)AND(myInt<256)THEN 'convertstringvaluetoanint result=CInt(TextBox2.Text) 'clearthebit i=BClr(myInt,result) 'updatethelabeldisplays label5.Text="Bclr:"&Bin(i) label7.Text=Str$(i) ENDIF END
The Shl function is will shift the value of MyInt n bits left where n is specifiedbythesecondparameter.WhenouruserclickstheShlbutton,wewill executethiscode:
PUBLICSUBSHLBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=Shl(myInt,result) label5.Text="SHL:"&Bin(i) label7.Text=Str$(i) ENDIF END
Inolder8bitsystems,itwasimpossibletoprocessnumberslargerthan 255unlesstheyweresplitupinto8bitchunks.Operationswerethenperformed oneachpieceofanumber.Aftertheoperationswerecompleted,itwasnecessary toreassembleeachnumberbacktogethertorecreatethewholenumber. Allof thiswasaccomplishedbyusingonetinybit,thecarrybit.TheGambasfunctions ROL(rotateleft)andROR(rotateright)areusedtoshiftbitsinbinarynumbers. Thesefunctionsworkconceptuallylikethis: The ROL Instruction 7 6 5 4 3 2 1 0 C The ROR Instruction 7 6 5 4 3 2 1 0 C
ROLandRORworksuchthatthecarrybitisshiftedintotheendbitthatis leftemptybytherotationprocessinsteadofinsertingazerovalue.ROLshiftsthe contentsofabyteoneplacetotheleft. ROLdoesnotplaceazerointobit0. Instead,itmovesthecarrybitfrombitposition7intobitposition0ofthenumber beingshifted. The0bitpositionwasvacatedbytheshiftrotationandtheROL instructionplacesbit7intothecarrybitposition.RORworksjustlikeROL,but intheoppositedirection.Itmoveseachbitofabyterightoneposition,placing thecarrybitintobit7andbit0intothecarrybit.
323
Ifyouwantyourprogramtocheckifabithasbeenset,youcancallBtst.This functionwillreturnTRUEifthebitspecifiedinoperand2ofoperand1isTRUE.
PUBLICSUBTestBtn_Click() DIMiASBoolean DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=BTst(myInt,result) label5.Text="Btst:"&i ENDIF END
That is all we have to do for our bitfiddling program. Save your work and
324
Figure98OurbitOpsprogramrunning.
Whenyouaresatisfiedthattheprogramworksasweplanned,saveyour work.Itwouldbeagoodexerciseatthistimetogobackandmodifythecodeto ensureonlyintegervaluesareinputintothetwoTextboxfields.Also,youcould allownegativenumberstobeenteredtoseewhatresultswouldbeproduced.I willleavethatexercisetothoseamongyoueagerandambitiousenoughtotryit isreallynotverydifficultandwehavealreadyshownyouhowtodovalidation routines(remember,backinthecollectionschapter?). Inthenextchapter,we willcoverbasicdatabaseoperationswithGambas.Theabilitytoworkwithdata in your programs is essential and we cannot overlook this vital aspect of programminginourjourneythroughGambas.
325
A Beginner's Guide to Gambas familiarwithhowbasicSQLoperationsworkwithintheMySQLenvironment,you arereadytocontinuewiththischapter,whichfocusesmoreonhowtoaccomplish thesametypesofthingsthe MySQL tutorialdemonstrated, but fromwithina Gambasprogram. InordertoaccessdatabaseswithintheGambasenvironment,youneedto ensureyourprojectusesthegb.dbcomponent.Whenyoucreateanewproject, you need to go to the project properties dialog and you will find a tab for components.Fromwithinthistabbeddialog,youcanselectthecomponentsyou needforyourprogram. Inthecaseofdatabases,youwillneedtocheck gb.db beforeyoucanuseanyoftheclassesdefinedbythiscomponent. Aswestated previously, the gb.db component allows you to access the following database managementsystems:PostgreSQL,MySQLandSQLite.BecausePostgreSQLand MySqlareclient/serverdatabases,itmeansyourprogramwillneedtomakea connectiontoadatabaseserver.SQLiteisaflatfilebaseddatabasesothereisno serverprocessforyourprogramtoconnectwith.However,thisalsomeansthat yourprogrammayneedtousefullyqualifiedpathnamesforanydatabasefileit usesifthedefaultpath(i.e.,theapplicationpath)isnotused. The gb.db component has been designed to create an intermediate (abstracted)layerbetweenthedatabaseserverandyourprogram. Thisallows youtousethesamecoderegardlessofthedatabasebackendyoudecidetouse. Thereareacoupleofcaveats,ofcourse.Thisabstractedapproachonlyworksif youhavecreatedyourdatabasebyusingthedatabasemanagerorbyusingthe gb.dbcomponent.Furthermore,youmustusetheFind,CreateandEditmethods providedwiththegb.dbcomponent. YoucannotputSQLvaluesdirectlyina requestyoumustusethesubstitutionfeatureoftheaforementionedmethodsto accomplishthat.Finally,youcannotusetheExecmethodtosendSQLrequests directlytotheservertoaccessserverspecificfeatures. Whilethissoundsfairly restrictive, in reality it is not a hindrance to your program. Given these few caveats,youcanaccomplishalmostanydatabaseoperationneededfromwithin theGambasenvironment.Theclassesthataresupportedinthegb.dbcomponent areConnection,DB,Database,Field,Index,Result,ResultField,Table,andUser.
ConnectionClass
TheConnectionclassestablishesyourconnectiontothedatabase.Inorder tosuccessfullyconnecttoadatabase,youmustfirstcreatea connectionobject andsetthenecessarypropertiesthatwillbeusedbythedatabase.Nextyoumust calltheOpenmethod.IfyouareconnectingtoaSQLitedatabaseandtheName
327
A Beginner's Guide to Gambas propertyisnull,adatabaseisopenedinmemory. IftheNamespecifiedisan absolutepath,thepathnameisused.IftheNamespecifiedisarelativepathand theHostpropertyisnull,thedatabaseislocated intheapplicationtemporary directory /tmp/gambas.$UID/sqlite. Otherwise, Host will contain the database directorynameandthedatabasefilepathistheresultofconcatenatingtheHost andNamepropertyvalues.Thisclassiscreatableandthecallingconventionis:
DIMhConnectionASConnection hConnection=NEWConnection()
ConnectionProperties When the hConnection object is instantiated, it creates a new void connection object. You will then need to set properties for this object. The propertiesthatyoucanusewithaconnectionobjectincludeCharset,Databases, Host,Login,Password,Name,Port,Tables,Type,Usersand Version. Wewill explaineachoftheseinthefollowingsections.
Charset
Charset is a readonly property that returns the charset used by the database. Itispossibleforyoutostoreyourstringsinthedatabasedirectlyin UTF8format. However,youcanalsocanusethispropertycombinedwiththe Conv$()subroutinetoconvertfromUTF8formattothedatabasecharsetformat. Using the database charset comes at a cost in performance however. This is becauseyoumustusetheConv$()subroutineeachandeverytimeyoureador writestringdatatothedatabasefields.Fornow,thisistheonlywayyoucando thisifyouwanttousethestringbasedSQLfunctionsandbuiltinsortroutinesof theunderlying databasemanagementsystem(MySQL,PostgreSQL,orSQLite). Future versions of Gambas may automatically make the conversion between Gambasstringsandthedatabasecharset.
Databases
The Databasesproperty canbecheckedtoobtainacollectionobjectthat will contain names of all databases that are managed by the database server. Syntaxis:
PROPERTYDatabasesAS.ConnectionDatabases
The resulting collection of data (which is enumerable using the FOR EACH
328
Youcanusethe Hostproperty tosetorgetthehostnameofwherethe databaseserverislocated.ThehostnamecanbeeitheramachinenameoranIP address. The default host is named localhost. In SQLite, host name is not relevant since SQLite is not a client/server database sytstem. However, from version0.95forward,itispossibleforyoutosetthehomepathfortheSQLite databasebyusingthisproperty.SyntaxforusingtheHostpropertyis:
PROPERTYHostASString Login
The Name property setsor gets the name of the database you want to connectto.Ifyoudonotspecifyaname,adefaultsystemdatabaseisused.For PostgreSQLthedefaultdatabaseisnamed template1andformySQLitisnamed mysql.ForSQLite,thedefaultnameis/tmp/sqlite.db.Foranydatabaseaccess, however,theuserneedstohaveatleastreadandconnectaccessprivilegestouse these databases. Sqlite will locate the database first by trying to use the full pathnameifithasbeengiven.Ifnot,itwillchecktoseeiftheHostvariablehas beenset.Ifthatisthecase,SQLitewilllookatthepathnamethatwassetinthe variable.IftheenvironmentvariableGAMBAS_SQLITE_DBHOMEhasbeenset, thenSQLitewillusethatasthecurrentworkingdirectory.Itisalsopossibleto create and use a database in memory by setting the Name property to :memory:ratherthanmysqlorpostgresqlorsqlite.Syntaxis:
329
ThePasswordpropertywillreturnorsetthepasswordusedforestablishing aconnectiontothedatabase.Callingconventionis:
PROPERTYPasswordASString Port
TheTablespropertyisusedtoobtainavirtualcollectionthatcanbeused formanagingallofthetablesofadatabase.Syntaxis:
PROPERTYTablesAS.ConnectionTables Type
The Users property returns a collection of all users registered in the databaseserver.Likeanyothercollectionobject,itcanbeenumeratedwithFOR EACH.Syntaxis:
PROPERTYUsersAS.ConnectionUsers Version
TheConceptofaTransaction Therearetimeswhentheorderinwhichdatabaseactions(orqueries)are executedisimportant.Sometimes,aprogrammustensureallqueriesinagroup arerunsuccessfullyandinorderorprocessnoneofthematall.Aclassicexample is taken from the banking environment. If a given amount of money (for example,100dollars)istakenfromoneaccountandpostedtoanotheraccount, wewouldexpectthefollowingactionstooccur:
UPDATEaccount1SETbalance=balance100; UPDATEaccount2SETbalance=balance+100;
Bothqueriesmustexecutesuccessfullyorneithermustexecute. Money cannot be transferred out of one account and fail to be posted to the other account.Bothofthesequeriesformasingletransactionthatiscomposedoftwo separate actions (debit 100 from account1 and credit 100 to account2). A transaction issimplyoneormoreindividualdatabasequeriesgroupedtogether between BEGIN and COMMIT statements. WithoutaCOMMITstatement,the transactionisnotpermanentandcanbereversedwiththeROLLBACKstatement. MySQLautomaticallycommitsstatementsthatarenotpartofatransaction process. The results of any SQL UPDATE or INSERT statement that is not preceded with BEGIN will immediately be visible to all connections to the database because the commit is automatically performed. Within MySQL, transactionsareonlyknownwithtransactionsafetables(i.e.,BDBandInnoDB). The other table types COMMIT immediately. Mostdatabasesthat are able to accomplishthisaresaidtobe ACIDcompliant. TheACIDmodelisoneofthe oldestandmostimportantconceptsofdatabasetheory.Thefourgoalsthatmust be met for any database to be considered reliable are Atomicity, Consistency, Isolationand Durability(ACID).Letsexamineeachofthesefourcharacteristics indetail. Atomicity meansdatabasemodificationsmustfollowanallornothing rule. Every transaction is considered an atomic unit. If any part of the transactionfails,theentiretransactionfails.ItiscriticaltheDBMSmaintainthe atomicnatureoftransactionsinanycircumstance.
331
A Beginner's Guide to Gambas Consistency states only valid data will be written to a database. If a transaction is executed that violates database consistency rules, the entire transaction will be rolled back and the database will be restored to a state consistentwiththoserules. Conversely,ifatransactionexecutessuccessfully,it willmaintainastateofconsistency. Isolation requires multiple transactions that occur simultaneously not impacteachother.Forexample,ifUserAissuesatransactionagainstadatabase atthesametimeUserBissuesatransaction,bothtransactionsshouldoperateon the database in isolated bliss. The database should perform one transaction before the other. This prevents a transaction from reading intermediate data producedasasideeffectofanothertransaction.Isolationdoesnotensureeither transactionwillexecutefirst,justthattheywillnotinterferewitheachother. Durabilityensuresanytransactioncommittedtothedatabasewillnotbe lost. This is accomplished via database backups and transaction logs that facilitaterestorationofcommittedtransactionsdespiteanysubsequentfailures. Now,let'stakealookatGambasConnectionclassmethodsavailabletoyouin yourprograms. ConnectionClassMethods The Connection class provides most of the methods you will need to establishaconnectiontoadatabaseandexecuteoneormoretransactionstofind, add,change,ordeletedata.
Open/Close
Toclosetheconnection,simplyinvoketheClosemethod.Inourexampleabove, youcouldusethiscode:
$hConn.Close
andtheconnectionwouldbeclosed.Inordertosubsequentlyuseanydatastored inthedatabase,youwouldneedtoreopenthedatabaseusingtheOpenmethod.
Begin/Commit/Rollback
Aswestatedpreviously,atransactionisoneormoreindividualdatabase queries that are grouped together between BEGIN and COMMIT statements. Without a COMMIT statement, the transaction is not permanent and can be reversed with a ROLLBACK statement. Remember thatMySQL automatically commitsstatementsthatarenotpartofatransactionprocess(definedbyBEGIN andCOMMIT).InGambas,itisrecommendedthatyouusetheFind,Create,and Edit methods to make changes to the database. This helps to maintain code independenceanditallowsyoutowriteasinglepieceofcodethatwillworkwith anydatabasesupportedbyGambas. Gambasusesa resultobject toreturnthe resultsofaSQLquery.
Find
The Find method returns a readonly Result object used for querying recordsinthespecifiedtable.ThecallingconventionforFindis:
FUNCTIONFind(TableASString[,RequestASString,ArgumentsAS,...])ASResult
Request representsa SQLWHEREstatement thatisusedforqueryingthe table. Arguments are quoted as necessary (dictated by SQL syntax), and substitutedinsidetheRequeststring. ItworksliketheSubst()functioninthis
333
TheCreatemethodisusedtobuildaread/writeResultobjectwhichcan usedtocreaterecordsinatable.Standardcallingconventionis:
FUNCTIONCreate(TableASString)ASResult Edit
HereisacodesampletoshowhowEdit()works:
DIMMyResultASResult DIMsQueryASString DIMiParmASInteger sQuery="id=&1" 'wewillinsertaparametervalue(12)attheendofthequerystring iParm=12 $hConn.Begin MyResult=$hConn.Edit("tblDEFAULT",sQuery,iParm) MyResult!Name="MrRittinghouse"'Setafieldvalue $hConn.Update'Updatewiththenewvalue $hConn.Commit'makethechangespermanent $hConn.Close'closethedatabaseconnection Exec
TheExecmethodexecutesaSQLrequestandreturnsareadonlyResult objectcontainingtheresultoftherequest.Standardcallingconventionis:
FUNCTIONExec(RequestASString,ArgumentsAS,...)ASResult
334
A Beginner's Guide to Gambas Request is a SQL WHERE clause and Arguments should be quoted as requiredbySQLsyntax.
Quote
Thequotingmechanismisdependentupontheparticulardatabaseserver driver which makes this method necessary if you need to write database independentcode.HereisanexampleofhowtouseQuote:
'Returnsnumberofrecordsinaquery 'sDBTableisthenameofthetable.Sincethenamecanincludereserved 'charactersitneedstobesurroundedbyquotemarks
rResult=$hConn.Exec("SELECTCOUNT(*)ASiNumRecsFROM"&DB.Quote(sDBTable))
PRINTrResult!iNumRecs
Thecodesnippetbelowshowshowyoucangetthevalueofafieldinthecurrent recordofaResultobject:
DIMMyResultASResult DIMMyVariantASVariant MyVariant=MyResult[FieldASString]
TheResultFieldclassrepresentsoneofthefieldsofaResultobject.You canusetheFindmethodtoselectaparticularfieldbeforeusingit.Theproperties
335
A Beginner's Guide to Gambas this class supports are Length, Name, Result andType. It is also possible to enumeratetheResultFielddatawiththeFOREACHkeyword. Thisclassisnot creatable. Thecodebelowshowsyouhowtomodifythevalueofafieldinthe currentrecordofaResultobject:
DIMMyResultASResult DIMMyVariantASVariant MyResult[FieldASString]=MyVariant
Properties that you can use with a result object include Available, Connection,Count,Fields,Index,andLength.AvailablewillreturnaTRUE valueiftheresultpointstoanexistingdatabaserecord.Connectionreturnsthe parentconnectionobject.Counttellsyouthenumberofrecords(rows)returned withtheresultobject. Fieldsreturnsacollectionofthefieldsinthedatabase table returned with the result object. Index returns the index (current row pointerorcursor)ofthecurrentrecord,startingatzero. Lengthisthesameas countandisusedinterchangeably. Methods supported by the result object class include Delete, MoveFirst, MoveLast,MoveNext,MovePrevious,MoveTo,andUpdate.Mostoftheseareself explanatory,buttheUpdatemethodisusedtorewritethecurrentrecordtothe databasewithanydatachangesthatarespecified.IfyouuseMoveToandspecify anindexthatisvoidorinvalid,itwillreturnaTRUEvalueindicatinganerror. Nowthatwehaveabasicunderstandingofwhataresultobjectisandhowtouse it, let's see how Gambas allows you to find data in a database with the Find method.
DBClass
Thisclassrepresentsthecurrentdatabaseconnection.Thisclassisstatic andallofitsmembersarealsostatic.Mostofthepropertiesofthisclassarethe same as those of the Connection class so we will only cover those that are different, namely Current, Databases, and Debug. Current returns or sets the currentconnection.Databasesreturnsacollectionofallofthedatabasesthatare managedbythedatabaseserver. DebugsetsorreturnsTRUE ifthedatabase componentisindebuggingmode.Whenthedebugflagisset,eachquerysentto any database driver is printed on the standard error output (generally, the console). ThemethodsusedintheDBclassarethesameasthoseusedinthe Connectionclass(Begin,Close,Commit,Create,Edit,Exec,Find,Open,Quote andRollback)sowewon'trepeatthatinformationhere.
336
Database
The Database class is used to represent information pertaining to a database. Thisclassisnotcreatable. Thepropertiesthatyoucanusewiththis classincludeConnection,Name,andSystem.Connectioncanbeusedtoobtain theparentconnectionobject. Namewillreturnthenameofthedatabaseand System will return a TRUE value if the database is a system database. The databaseclassonlyhasonemethod,Delete,whichwilldeleteadatabase.
Field
TheFieldclassisusedtorepresentdataforatablefield.Thisclassisnot creatable. PropertiesthatthisclasssupportsareDefault,Length,Name,Table, andType. Defaultreturnsthedefaultvalueofafield. Lentghwillreturnthe maximum length of a text field. If the text field being checked has no limit specified,azerovalueisreturned. NamewillreturnthefieldnameandTable returnsthetableobjectinwhichthefieldwascreated.Typereturnsthedatatype thatthefieldrepresents.Gambaswillreturnoneofthefollowingconstants:
gb.Booleangb.Integergb.Floatgb.Dateorgb.String
Index
TheIndexclassrepresentsatableindex.Thisclassisnotcreatable.The properties this class supports are Fields, Name, Primary, Table, and Unique. Fieldsreturnsacommaseparatedlistofstringsrepresentingthefieldsthatmake uptheindex. NamereturnstheindexnamewhilePrimarywillreturnaTRUE valueifanindexistheprimaryindexofthetable. Tablewillreturnthetable objectthatownsthisindex.UniquereturnsTRUEiftheindexisunique.
Table
TheTableclassrepresentsthedefinitionofadatabasetable.Thisclassis not creatable. The properties that are supported by the Table class include Connection,Fields,Indexes,Name,PrimaryKey,SystemandType. Connection canbeusedtoobtaintheparentconnectionobject.Fieldswillreturnacollection ofthefieldsofthetablewhileIndexeswillreturnacollectionoftheindexesof thetable.Namewillreturnthenameofthetable.PrimaryKeywillreturnorset theprimarykeyofthetable. Theprimarykeyisastringarraycontainingthe
337
A Beginner's Guide to Gambas nameofeachprimarykeyfield.SystemwillreturnaTRUEvalueifthedatabase isasystemdatabase. Typereturnsorsetsthetypeofatable. Thispropertyis uniquetoMySQLandisonlyusedwithMySQLdatabases. Thisclassonlyhas onemethod,Update,whichiscalledtoactuallycreatethetableinthecurrently connecteddatabase.
User
TheUserclassisusedtorepresentusersofadatabase. Thisclassisnot creatable. The properties User class supports are Administrator, Connection, NameandPassword.AdministratorisareadonlypropertythatreturnsTRUEif a user is a database administrator. Connection returns the parent connection objectoftheuser.NamewillreturnthenameoftheuserandPasswordwillget orsetthepasswordassociated withauser. Whenyoureadtheproperty,you should get the password in an encrypted form. The User class has a single method,Deletewhichisusedtodeleteauserfromthedatabase.
TheDatabaseExampleProgram
The previous sections of this chapter have explained about the Gambas database component and the features provided therein. However, nothing substitutesworkingwithrealcodeinarealapplication. Gambasshipswithan example database program that we are going to explore. Writtenby Gambas founderBenoitMinisini,thisprogramisanexcellentexampleofhowtocodeyour program to use database within the Gambas environment. To begin, start GambasandchoosetheDatabaseprogramfromtheExamplesmenu.Whenthe IDE appears, you will see that the program contains two forms, FMain and FRequest.FMainshouldlooklikethefigurebelow. Thisprogramwillallowyoutochoosewhatdatabaseplatformtouse(i.e., PostgreSQL,MySQL,orSQLite)andspecifythehostname,databasename,user ID and password. An option to automatically create a database exists and is activated whenever the checkbox is checked. Once you have successfully connectedtothedatabase,youhavetheoptionofcreatingatable,deletingit,or fillingitwithsometestdata.TheSQLrequestboxatthebottomoftheformwill allowyoutoperformSQLqueriesagainstthedatabase. Allinall,thisprogram demonstratesalmosteverythingyouneedtoknowtoconnecttoanydatabase usingGambas.
338
Figure99TheFMainformindesignmode.
TheFRequestformismuchsimplertobuild.Itisshowninthefigurebelow:
Figure100FRequestFormindesignmode.
$hConn isdeclaredasaprivatevariableandwillbeusedbyallsubroutinesin
339
340
If,afterthedatabaseconnectionisestablished,theuserwouldclickthe Createtabletestbutton,thissubroutinewouldbeexecuted.Ihavemodifiedit slightly to avoid using hardcoded strings and to use the same name as the database.Theoriginalcodeiscommentedoutsoyoucanuseeithermethod.
PUBLICSUBbtnCreate_Click() 'declarealocalTablevariable DIMhTableASTable 'addthetabletothedatabaseusingtheAddmethod 'hTable=$hConn.Tables.Add("test") 'thisisthecodeIchangedtoavoidhardcodingthestring 'aswasdoneinthepreviouslineofcode hTable=$hConn.Tables.Add(txtName.text) 'nowaddthefieldsofthetabletothetablewejustadded 'notethatwespecifythefieldnameanddatatypeforeach 'ofthefieldsweinsertintothetable.Forstringdata, 'wealsospecifythemaximumlengthofthestringfield.
341
This following segment of code was added by the author to enable or disablethebuttonsdependingonthestateofthedatabase.Forexample,ifthere isdataalready in thedatabasetable,itdoesnotmakesensetofillthattable again,sothatbuttonwouldbedisabled.However,thedeletebuttonwouldbe enabledsothedatacouldberemoved. Ifthedatabasetableisdeleted,thenit wouldbereenabledandifthetableiscreatedandnodataexists,thefillbutton would again be enabled, etc. This prevents errors from clicking on a button whereanactioncouldnotbeperformedsuccessfully.
btnFill.Enabled=TRUE btnDelete.Enabled=TRUE btnCreate.Enabled=FALSE 'next,weaddsomedefaulttexttotheSQLquerybox txtRequest.Text="ShowTABLES" 'theCATCHstatementwoulddisplayanERRORdialogwiththetextof 'theerrormessageifanyerroroccursinthissubroutine. CATCH Message.Error(Error.Text) END'ofthecreatebuttonsubroutine
If,afterthedatabaseconnectionisestablished,theuserwouldclickthe
342
A Beginner's Guide to Gambas Delete table test button, this subroutine would be executed. I have also modifieditslightlytoavoidusinghardcodedstringsandtousethesamenameas thedatabase.Theoriginalcodeiscommentedoutsoyoucanuseeithermethod.
PUBLICSUBbtnDelete_Click() 'removethetable '$hConn.Tables.Remove("test") $hConn.Tables.Remove(txtName.Text) 'putupamessagetoinformtheuserthetableisgone Message.Info("Table"&txtName.Text&"hasbeenremoved") 'enableordisablethebuttonstomakesense.Ifthetable 'hasbeenremoved,itcannotbedeletedagainanditcannot 'befilledsinceitdoesnotexist.Allthatisleftisto 'recreateitandthatbuttonisenabled. btnDelete.Enabled=FALSE btnFill.Enabled=FALSE btnCreate.Enabled=TRUE 'notableexiststoquerysoblankouttheSQLquerytext. txtRequest.Text="" 'ifanerroroccursinthesubroutinecatchithereandshowadialog 'messagetotheuser. CATCH Message.Error(Error.Text) END'thedeletebuttonsubroutine
Ifthedatabaseconnectionhasbeenestablishedandtheuserhascreated thetable,thereneedstobesomedataaddedtomakeituseful.Thissubroutineis executedandwilladdsemiarbitrarydatatothetable.Itwillrandomlyselecta firstnamefromthearrayoffivenamesprovidedand concatenatethecounter numbertothestringName#toserverasthelastname. Thebirthdateis createdrandomlybypickingavaluethataddsarandomnumberfrom110,000 tothebasedateofJanuary1st,1970.Therecordhasanactiveflag,randomlyset aswell.Salaryfiguresarerandomlyselectedwithintherangeof1,000to10,000. Finally, the Update method will put all the data in the table and make the COMMITtothedatabase.Let'slookateachlineofcodetoseehoweasythisis accomplishedinGambas:
PUBLICSUBbtnFill_Click() 'weneedanintegercounteriIndtobeourindexandwe
343
344
Whenever our program runs and the FMain form opens, we need to instantiateourconnectionvariable$hConn.Whenevertheformisclosed,wewill closetheconnection.
PUBLICSUBForm_Open()
345
Next,weneedtotakealookattheFRequestformandseehowthatcode displaystheresultobjectdatawhenitisinvoked.Hereisthecodeforthat:
'Gambasclassfile 'fRequest.classdeclarestwoprivatevariablestouseinthisclass 'onefortheconnection,onefortheresultdata. PRIVATE$hConnASConnection PRIVATE$rDataASResult 'aconstructorroutinewillbeusedtoreceivetheconnectionhandle 'andtheresultsofaqueryasparameterswhenFRequestiscalledby 'theFMainform. PUBLICSUB_new(hConnASConnection,rDataASResult) 'assignthehConnparametertoourprivate$hConnvariable $hConn=hConn 'assigntherDataparametertoour$rDataprivatevariable 'theseassignmentsaremadesothe$prefixedvariablesare 'visibletotheentireclass,notjusttheconstructorroutine. $rData=rData 'callourlittlesubroutinetodisplaythetitleintheformwindow RefreshTitle 'theReadDatasubroutineisusedtopopulateourTableViewcontrol ReadData 'resizethewindowtocenteronthedesktop ME.Move(Int(Rnd(Desktop.WME.W)),Int(Rnd((Desktop.HME.H)))) END'oftheconstructor 'thissubroutinesimplyupdatesthewindowcaption PRIVATESUBRefreshTitle() 'weneedalocalstringvariable DIMsTitleASString 'wewillconcatenatetheconnectionnametothetextforthecaption sTitle=("SQLQueryResults")&""&$hConn.Name
346
The ReadData() subroutine is used to define the structure of the data passed in fromthe results object to the TableViewcontrol. It determines the numberoffieldsfromtheresultsobjectand setsupthecolumnsinthetable, assigning the proper column (field) name and data type. The data type is determined by calling another subroutine, WidthFromType() to get that information. The QT librarybased TableView control is obsolete in the QT library, havingbeenreplacedwiththeQTablecontrol. However,inGambas,itisstill usableandwewillshowyouhowitisdone. Beaware,however,thatitis not recommendedforuse as Trolltech,theownersofthe QTlibrary,havepublicly declaredtheTableViewcontrolobsolete.TheGambasTableViewisbasedupon QTableandQtableItem,bothofwhichwillbecomeobsoleteinQt4.0.TableView willmorethanlikelythenbebaseduponQTableVieworQTableWidgetinstead.
PRIVATESUBReadData() 'thisvariableisdeclaredbutneverused,youcancommentitout DIMhTableASTable DIMhFieldASResultField 'thisvariableisdeclaredbutneverused,youcancommentitout DIMsFieldASString DIMiIndASInteger 'thisvariableisdeclaredbutneverused,youcancommentitout DIMiLenASInteger 'settheapplicationbusyflagtoavoidinterruptions INCApplication.Busy 'resetrowcountoftheTableViewcontroltozero tbvData.Rows.Count=0 'setthenumberofcolumnstobethesamenumber 'asthenumberoffieldsintheresultobject tbvData.Columns.Count=$rData.Fields.Count 'nowwewilliteratethrougheachfieldoftheresultobjectand 'getthenameofthefieldandthedatatypeandsettheTableView 'columnheadingsandfieldtype/sizeasappropriate
347
Thenextbitofcodeisactivatedwheneverdataispresent.TheDataevent oftheTableViewcontrolisusedasthedriverforactivationofthissubroutine.It insertsarowofdatafromtheresultsobjectintothecurrentrowandcolumnof the TableView control. Bear in mind that you don't ever call the data event directly.ThereisverylittledocumentationavailablefortheTableViewcontrolso nothingstatedhereinshouldbeconsideredasthedefinitiveanswerforusingit. However,thegeneralapproachtousingtheTableViewcontrolistofirstloadall datathatistobedisplayedintoanarrayandpreparetheTableViewcontrolwith rows and columns as was done in the ReadData subroutine above. The very processoffillingthearrayanddefiningthecolumnsinthismannerforcestheQt widgetthatisusedintheTableViewcontroltomakeaninternalcalltotheData eventthatactuallydoesfillthecellswithdatafromyourarray.Itisuptoyouto codetheassignmentstatement(s)thatmovedatafromtheresultsobjecttothe TableViewrowandcolumnwhereyouwantthedatadisplayed.Thekeythingto remember is that you must have an event handler, tbvControl_Data( ... ) somewhereinyourclassfiletodothis.InaTableViewcontrol,thedatathatis
348
Iftheformisresizedbytheuser,weneedtoresizethecontrol.Thissubroutine willdothetrick.
PUBLICSUBForm_Resize() tbvData.Resize(ME.ClientW,ME.ClientH) END
Whendataisbeingreadfromtheresultsobject,thissubroutineiscalledto determinewhatthedatatypeisforeachfieldofarow.Thepropertiesfromthe Field class are passed as parameters to this function and used in the select statement.ThisensuresthedataplacedintheindividualcellsoftheTableView controlisnottruncatedandwilldisplayproperly,regardlessofthefontproperty settingestablishedbytheTableViewcontrolitself.
PRIVATEFUNCTIONWidthFromType(hCtrlAScontrol,iTypeASInteger, iLengthASInteger,sTitleASString)ASInteger DIMiWidthASInteger SELECTCASEiType CASEgb.Boolean iWidth=hCtrl.Font.Width(Str(FALSE))+32 CASEgb.Integer iWidth=hCtrl.Font.Width("1234567890")+16 CASEgb.Float iWidth=hCtrl.Font.Width(CStr(Pi)&"E+999")+16 CASEgb.Date iWidth=hCtrl.Font.Width(Str(Now))+16 CASEgb.String
349
Finally,iftheuserclicksonthexatthetoprightcornerofthewindowto closetheprogram,wecometothisroutineandclosethingsdown.
PUBLICSUBForm_Close() ME.Close END
When you execute the example Database program, it requires that you haveadatabasesystemlikePostgreSQLorMySQLinstalledonyoursystem.You musthaveauseraccountandpasswordtousethedatabasesystems.Giventhose caveats,runtheprogramandlogintothedatabase.Youcanplayaround,create andfillthetesttable,andmakequerieswiththeprogram.Atthispoint,youhave learnedallthebasicsforconnectingtoandusingadatabaseinGambas.Inthe nextchapter,wewillcovertheessentialsofmakingyourprogramavailableto users globally, a process of globalization that involves two processes, internationalization(I18N)andlocalization(L10N).
350
Internationalization
Internationalization istheprocessofdesigninganapplicationsothatit canbeadaptedtovariouslanguagesandregionswithoutengineeringchanges. Sometimestheterminternationalizationisabbreviatedasi18n,becausethereare 18lettersbetweenthefirst"i"andthelast"n."Aninternationalizedprogram,with theadditionoflocalizeddata,canusethesameexecutableworldwide.Textual elements,suchasstatusmessagesandGUIcomponentlabels,arenothardcoded inthe program.Instead theyarestoredoutsidethesourcecode and retrieved dynamically. Support for new languages does not require recompilation. Culturallydependentdata,suchasdatesandcurrencies,appearinformatsthat conform to the end user's region and language. In this manner, an internationalizedapplicationcanbelocalizedveryquickly.
Localization
Localization istheprocessofadaptingsoftwareforaspecific regionor language by adding localespecific components and translating text. The term localizationisoftenabbreviatedasL10N,becausethereare10lettersbetweenthe "L" and the "N." Usually, the most timeconsuming portion of the localization processistranslationoftext.Othertypesofdata,suchassoundsandimages,may requirelocalizationiftheyareculturallysensitive. Localizationengineersverify theformattingofdates,numbers,andcurrenciesconformstolocalrequirements.
351
UniversalCharacterSet(UCS)
ISO/IEC 10646 defines a very large character set called the Universal Character Set (UCS), which encompasses most of the world's writing systems. Thesamesetofcharactersisalsodefinedbythe Unicode standard. Todate, changesinUnicodeandamendmentsandadditionstoISO/IEC10646havebeen madeinunisonsothatthecharacterrepertoiresandcodepointassignmentshave stayedsynchronized.Therelevantstandardizationcommitteeshavecommittedto maintainthisapproach. Both UCS and Unicode arecodetablesthatassignanintegervaluetoa character.Thereareseveralalternativesforhowastringofsuchcharacters(or their integer values) can be represented as a byte sequence. The two most obviousencodingformsstoreUnicodetextassequencesofeither2or4bytes. TheseencodingschemesaredesignatedasUCS2andUCS4. Inbothofthese schemes, the most significant byte comes first (Big Endian format). The CharactersinUnicodeareidentifiedbytheirnumberorcodepointwhichis usuallygiveninhexadecimalnotation.Forexample,inHebrew,theletterheis codepoint5D4whichisusuallywrittenwiththeconventionofprefixingaU+ in front of the code point and padding it with leading zeros as needed, i.e., U+05D4.
Unicode
Unicodecurrentlydefinesjustunder100,000characters,buthasspacefor 1,114,112codepoints19.Thecodepointsareorganizedinto17planesof216 (65,536) characters, numbered 0 through 16. Plane 0 is called the Basic MultilingualPlaneorBMPandcontainssymbolsfoundtobeuseful.Generally speaking,itcontainseverycharacteravailabletoaprogrammerbeforeUnicode came along. The characters in the BMP are distributed in a West to East fashion,withtheASCIIcharactershavingtheirfamiliarASCIIvaluesfrom0to 127,theISOLatin1charactersretainingtheirvaluesfrom128to255.Then,the charactersetsmoveeastwardacrossEurope(Greek,Cyrillic),ontotheMiddle East(Arabic,Hebrew,etc.)andacrossIndiaonwardtoSoutheastAsia,endingup withthecharactersetsfromChina,Japan,andKorea(CJK). BeyondthisBMP existsplanes1through16.Theyaresometimesreferredtoastheastralplanes because they are typically used for exotic, rare, and historically important characters.
19 The reader is encouraged to visit http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF for a full explanation. 352
A Beginner's Guide to Gambas ASCIIfilescanbeconvertedintoaUCS2filebyinserting0x00infrontof everyASCIIbyte. Tomakea UCS4 formattedfile,youmustinsertthree0x00 bytesbeforeeveryASCIIbyte. UsingeitherUCS2orUCS4onUnixplatforms can lead to some very significant problems. Strings used with these encoding schemescancontainpartsofmanywidecharacterbyteslike\0or/thathave specialmeaninginfilenamesandotherClibraryfunctions.Thevastmajorityof UNIXtoolsexpecttooperatewithASCIIbasedfilesandsimplycannotread16bit wordsascharacters. Simplyput,UCS2/UCS4arenotsuitableforUnixwhen usedwithfilenames,textfiles,environmentvariables,codelibraries,etc. ThereareseveralotherencodingformscommontobothUCSandUnicode, namelyUTF8,UTF16,andUTF32. Ineachoftheseencodingformats,each character is represented as one or more encoding units. All standard UCS encodingformsexceptUTF8haveanencodingunitlargerthanoneoctet. For manyapplicationsandprotocols,anassumptionofan8bitor7bitcharacterset makestheuseofanythingotherthanUTF8nearlyimpossible.SinceUTF8hasa oneoctetencodingunit,itusesallbitsofanoctetbutcanstillcontainthefull rangeofUSASCIIcharacters,allofwhichhappentobeencodedinasingleoctet. AnyoctetwithsuchavaluecanonlyrepresentaUSASCIIcharacter.
UTF8
UTF8 wasinventedbyKenThompson20. AccordingtothestorybyRob PikewhowaswithKenatthetime,itwasdevelopedduringtheeveninghoursof September2ndin1992ataNewJerseydiner.Kendesigneditinthepresenceof Rob Pike on a placemat (see Rob Pikes UTF8 history21). The new design replaced an earlier attempt to design a File System Safe UCS Transformation Format(FSS/UTF)thatwascirculatedinanX/OpenworkingdocumentinAugust ofthesameyearbyGaryMiller(IBM),GregerLeijonhufvudandJohnEntenmann (SMI)asareplacementforthedivisionheavyUTF1encodingpresentedinISO 10646122.Withinaweekofthattime,PikeandThompsonmadeAT&TBellLabs Plan 9 the first operating system in the world to use UTF8 encoding. They reportedthisattheUSENIXWinter1993TechnicalConference23.FSS/UTFwas brieflyalsoreferredtoasUTF2andlaterrenamedUTF8andpushedthroughthe standardsprocessbytheX/OpenJointInternationalizationGroup(XOJIG).
20 http://www.cs.bell-labs.com/who/ken/ 21 http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt 22 http://64.233.167.104/search?q=cache:U4zV7dcaq0EJ:www.faqs.org/ftp/rfc/pdf/rfc2279.txt.pdf+Greger+Leijonhufvud&h l=en 23 USENIX Technical Conference held in San Diego, CA, January 25-29, 1993, published in the Conference Proceedings, pp. 43-50. 353
A Beginner's Guide to Gambas UTF8encodesUCScharactersasavaryingnumberofoctets.Thenumber of octets and the value of each depend on the integer value assigned to the characterinISO/IEC10646(thecharacternumber,a.k.a.,it'scodeposition,code point or Unicode scalar value). This encoding form has the following characteristics24(valuesinhexadecimal):
CharacternumbersfromU+0000toU+007F(USASCIIset)correspond tooctets00to7F(7bitUSASCIIvalues).Adirectconsequenceisthat aplainASCIIstringisalsoavalidUTF8string. USASCII octet values do not appear otherwise in a UTF8 encoded characterstream.Thisprovidescompatibilitywithfilesystemsorother software(e.g.,theprintf()functioninClibraries)thatparsebasedon USASCIIvaluesbutaretransparenttoothervalues. RoundtripconversioniseasybetweenUTF8andotherencodingforms. Thefirstoctetofamultioctetsequenceindicatesthenumberofoctets inthesequence. TheoctetvaluesC0,C1,F5toFFneverappear. Character boundaries are easily found from anywhere in an octet stream. ThebytevaluelexicographicsortingorderofUTF8stringsisthesame asiforderedbycharacternumbers.Ofcoursethisisoflimitedinterest sinceasortorderbasedoncharacternumbersisalmostneverculturally valid. TheBoyerMoorefastsearchalgorithmcanbeusedwithUTF8data. UTF8 strings can be fairly reliably recognized as such by a simple algorithm,i.e.,theprobabilitythatastringofcharactersinanyother encoding appears as valid UTF8 is low, diminishing with increasing stringlength.
TheUTF8encodingisformallydefinedinISO106461:2000AnnexD.It isalsodescribedinRFC3629aswellassection3.9oftheUnicode4.0standard.
24 See URL http://www.faqs.org/rfcs/rfc2279.html. 354
A Beginner's Guide to Gambas InordertouseUnicode underUnixstyleoperatingsystems,UTF8isthebest encodingschemetouse. ThisisbecauseUCScharactersU+0000toU+007F (ASCII)areencodedasbytes0x00to0x7F(forASCIIcompatibility).Thismeans files and strings that contain only 7bit ASCII characters will have the same encodingunderbothASCIIandUTF8.AllUCScharactersthatfallintherange greaterthanU+007Fareencodedasamultibytesequence,eachofwhichhas themostsignificantbitset.Therefore,noASCIIbyte(0x000x7F)canappearas partofanyothercharacter. The first byte of a multibyte sequence that represents a nonASCII characterwillalwaysfallintherangeof0xC0to0xFDanditindicateshowmany byteswillfollowforthischaracter. Anyfurtherbytesinamultibytesequence willbeintherangefrom0x80to0xBF.Thisallowseasyresynchronizationand makesencodingstatelessandrobustagainstmissingbytes.Allpossible231UCS codescanbeencoded.UTF8encodedcharactersmaytheoreticallybeuptosix byteslong.ThesortingorderofBigEndianUCS4bytestringsispreserved.The bytes0xFEand0xFFareneverusedintheUTF8encoding.Thefollowingbyte sequencesareusedtorepresentacharacter.Thesequencetobeuseddependson theUnicodenumberofthecharacter:
U-00000000 U-00000080 U-00000800 U-00010000 U-00200000 U-04000000 U-0000007F: 0xxxxxxx U-000007FF: 110xxxxx 10xxxxxx U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
HowtotranslateinGambas
TotranslateGambasintoyourownlanguage,opentheGambasprojectin theIDE,and click onTranslate...in theProjectmenu,asshowninthefigure below:
355
Figure101ChoosingtheTranslate optioninGambas.
Next,youmustselectthetargettranslationlanguageinthecomboboxof thetranslatedialogbox,asshownbelow:
Figure102TheTranslateDialoginGambas.
Selectastringfromthelistofuntranslatedstringsandenteritstranslation inthetextfieldshownatthebottomofthedialog. Youneed torepeatthis processuntileverystringinyourapplicationhasbeentranslated.Whenyouhave finished, click on the Closebutton. Itis not necessary to complete all of the strings at one sitting. You can translate the projectin several attempts. The toolbariconsyouseeatthetopoftheTranslatedialogallowyouto:
356
Therearecertainoccasionswhereyoumaynotwanttoevertranslatea string.InGambas,youcanindicateastringshouldnotbetranslatedbyentering aminussigncharacterasthetranslatedstring. Yourtranslationisstoredina *.pofileinthe.langdirectoryoftheproject.Thenameofthe.pofiledependson thelanguagetranslated.Forexample,theFrenchtranslationfileisnamedfr.po. WheneverthelatestGambasversionchanges,anyuntranslatedstringsin yourprogramcouldchange.However,anystringsyouhavetranslatedstringswill bepreserved.Ifanuntranslatedstringdisappearscompletely,thetranslationwill alsodisappearandifanewuntranslatedstringisadded,itgetsanemptyornull translation string assigned to it. All other untranslated stringswillkeep their correspondingtranslationstrings.WhilethestringtranslationfeatureofGambas allowsyoutoeasilymaintainstringconversions,otherlocalespecificthingssuch as dates, number formats, etc. are left to you to manage. It is hoped that Gambas2willaddressthesefeatureswhenitisreleased.Untilthattimearrives, hereisashort,generalizedchecklistforhelpingyoulocalizeyourapplication:
Ensureallmessages,icons,andhumanreadablecontentarestoredin externalresourcefilesandcanbeeasilytranslated. Thetranslatedmessageorresourcefilesshouldbedynamicallyloaded by the application, depending on the current language and locale settingsforthesession. Date/time,sortorder,numericandmonetaryformattingetc.areinthe targetlanguage.Thesortordershouldbeconfigurable,dependingon
357
AccordingtoHuanget.al.,25youshouldconsidercreatinganI18Ntesting checklist for your application. Some of the questions they recommend you considerincludethefollowing: 1.Doesprogramdesignaccountforinternationalconsiderations? 2.Canauserentertext,accelerators,andshortcutkeycombinationsonan internationalkeyboard? 3. Can a user enter dates, times, currencies, and numbers using internationalformats? 4.Canausersuccessfullycut/pastetextwithaccented (ordoublebyte) characters? 5.Cantheapplicationworkcorrectlyondifferenttypesofhardwaresoldin thetargetmarket? 6.Doestheapplicationworkcorrectlyonlocalizedoperationssystems? 7.CanausertypeEuropeanaccented(orAsiandoublebyte)charactersin documentsanddialogboxes? 8. Can documents created in a target language be opened in other languagesandviceversa? 9.Canuserssaveandprintfileswithaccented(ordoublebyte)characters? Whilethereisnosinglechecklistthatcanaccountforthewidedegreeof variationfromapplicationtoapplication,considerationofthesebasicissueswill likelygofarinhelpingyoutoreachaglobalaudience.TheInternethasmadethe worldamuchsmallerplaceandtheaudienceforapplicationshavebecomemuch
25 Huang, E., Haft, R. and Hsu, J. Developing a Roadmap for Software Internationalization, Whitepaper dated October 2000, retrieved fromURL www.symbio-group.com/doc/Developing a Roadmap for Software Internationalization.pdf on October 5th, 2005. 358
A Beginner's Guide to Gambas larger. Youcannotsimplyassumeeveryoneusing yourapplicationisEnglish speakingandusesthesamekeyboardorwillunderstandyouricons. Different pictograms mean different things depending on the locale in which your user resides. Most important of all, make the effort to accommodate the broadest audiencepossibleandyouruserswillmostlikelyallowforafewmistakeshere and there. Not making such an effort will generally leave them with the impressionthatyoucould carelessand theywill probably feelthesame way aboutusingyourprogram.
359
360
Alphabetical Index
Accessfunction................................................................(188) ACIDcompliant..............................................................(331) Activateevent..........................................(155,162,168,170) Addmethod...............................(89,152,154,159,167,175) ANDoperator.....................................................................(41) APPENDkeyword...........................................................(192) Applicationpath..............................................................(327) Arithmeticoperators..........................................................(36) Assignmentstatement........................................................(35) Atomicity.........................................................................(331) BackColorproperty.............................................(62,67,268) Backgroundproperty.........................................................(62) BenotMinisini..............................................(1,19,149,157) BigEndian.......................................................................(192) Bitfunctions.....................................................................(319) Bits...................................................................................(318) Booleandatatypes.............................................................(31) Borderproperty..................................................................(63) Builtinconstants...............................................................(34) Busyproperty................................................................(151p.) Byte......................................................................... .........(318) Bytedatatype.................................................................(31p.) Cachedproperty...............................................................(267) Cancelbutton.....................................................................(61) Cancelproperty..................................................................(63) Captionproperty..........................................................(64,81) Carrybit...........................................................................(323) CASEELSEblock.............................................................(49) CASEstatement.................................................(48,103,114) CASEStatement................................................................(48) CATCHstatement............................................................(305) CheckBoxclass..................................................................(93) CheckBoxcontrol.........................................................(92pp.) Checkedproperty..................................................(100p.,157) Chr(10)......................................................................... ....(166) Chr(13)......................................................................... ....(199) Chr(9).......................................................................(136,194) Classevent.......................................................................(310) Classhierarchy...................................................................(28) Classinvariants................................................................(241) ClassbasedOOPapproach..............................................(241) Clickevent.........................................................................(76) ClickNRun....................................................................(22) Clipclass..........................................................................(268) Clippingarea....................................................................(268) Cohesion..........................................................................(241) Collections.........................................................................(55) Colorclass........................................................................(268) ColumnViewcontrol.......................................(170,174,176) ComboBoxarrays..............................................................(89) ComboBoxcontrol............................................(85pp.,185p.) ComboBoxitems...............................................................(89) Commandlineinterface...................................................(326) COMMITstatement.........................................................(331) Comparisonoperators........................................................(36) Conditionals.......................................................................(46) Connectionclass......................................................(327,332) Connectionobject............................................................(327) 361 Consistency......................................................................(332) Constant.............................................................................(34) Constructorroutine...............................(150,210,213,248p.) Containerclass...................................................................(62) Controlclass.......................................................................(61) ControlGroups................................................................(100) Controls..............................................................................(58) COPYfunction.................................................................(195) Copyrightnotice..................................................................(3) CopyrightNotice..............................................................(2p.) Cursorproperty..................................................................(65) Dataabstraction...............................................................(239) Databasesproperty...........................................................(328) Datedatatype....................................................................(32) Dblclickevent...................................................................(78) DECoperator.....................................................................(43) Defaultbutton....................................................................(61) Defaultproperty.................................................................(66) Deletemethod....................................................................(70) Designproperty..................................................................(66) Desktop.Charset.......................................................(142,152) Dialogclass...................................................................... (103) DialogTitleproperty.......................................................(103) Dirfunction...................................................................... (189) DIRECTkeyword............................................................(192) Divisionbyzero..............................................................(39p.) DivisionbyZero................................................................(40) DO[WHILE]LOOP..........................................................(51) Dotnotation.......................................................................(36) Doubleclickevent.............................................................(77) Dragmethod.......................................................................(70) Drawclass.......................................................................(267) Draw.Ellipsemethod.......................................................(276) Draw.FillStyle..................................................................(279) Draw.Linemethod...........................................................(276) Draw.LineWidthproperty................................................(276) Draw.Pointmethod..........................................................(274) Draw.Polygonmethod..................................................(280p.) Draw.Polylinemethod.............................................(280,282) Draw.Rectmethod..................................................(274,279) DrawingAreacontrol.......................................................(271) Dropproperty.....................................................................(66) Durability.........................................................................(332) Enabledproperty................................................................(66) Encapsulation...................................................................(240) ENDkeyword....................................................................(37) ENDWITHinstruction......................................................(35) Enterevent.........................................................................(74) Eoffunction.....................................................................(190) Errorclass........................................................................(304) Errormanagement............................................................(298) Error.Classproperty.........................................................(304) Error.Clear........................................................................(305) Error.Codeproperty........................................................(304) Error.Raise.......................................................................(305) Error.Textproperty..........................................................(304) Error.Whereproperty.......................................................(305) Errorsinlogic..................................................................(301)
362
363
364