You are on page 1of 364

A Beginner's Guide to Gambas

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.

A Beginner's Guide to Gambas


Copyright Notice for the electronic (online) version of this work, based on the OpenContent License (OPL), Version 1.0, July 14, 1998.
This document outlines the principles underlying the OpenContent (OC) movement and may be redistributed provided it remains unaltered. For legal purposes, this document is the license under which OpenContent is made available for use. The original version of this document may be found at http://opencontent.org/opl.shtml . LICENSE Terms and Conditions for Copying, Distributing, and Modifying Items other than copying, distributing, and modifying the Content with which this license was distributed (such as using, etc.) are outside the scope of this license. 1. You may copy and distribute exact replicas of the OpenContent (OC) as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the OC a copy of this License along with the OC. You may at your option charge a fee for the media and/or handling involved in creating a unique copy of the OC for use offline, you may at your option offer instructional support for the OC in exchange for a fee, or you may at your option offer warranty in exchange for a fee. You may not charge a fee for the OC itself. You may not charge a fee for the sole service of providing access to and/or use of the OC via a network (e.g. the Internet), whether it be via the world wide web, FTP, or any other method. 2. You may modify your copy or copies of the OpenContent or any portion of it, thus forming works based on the Content, and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified content to carry prominent notices stating that you changed it, the exact nature and content of the changes, and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the OC or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License, unless otherwise permitted under applicable Fair Use law. These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the OC, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the OC, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Exceptions are made to this requirement to release modified works free of charge under this license only in compliance with Fair Use law where applicable. 3. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to copy, distribute or modify the OC. These actions are prohibited by law if you do not accept this License. Therefore, by distributing or translating the OC, or by deriving works herefrom, you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or translating the OC. NO WARRANTY 4. BECAUSE THE OPENCONTENT (OC) IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE OC, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE OC "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK OF USE OF THE OC IS WITH YOU. SHOULD THE OC PROVE FAULTY, INACCURATE, OR OTHERWISE UNACCEPTABLE YOU ASSUME THE COST OF ALL NECESSARY REPAIR OR CORRECTION. 5. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MIRROR AND/OR REDISTRIBUTE THE OC AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE OC, EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 3

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas AddingaSearchFeature.................................................260


TheDoFindSubroutine.............................................................262

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

ResultObjects.................................................................335 DBClass.........................................................................336 Database.........................................................................337 Field................................................................................337 Index...............................................................................337 Table...............................................................................337 User.................................................................................338


10

A Beginner's Guide to Gambas TheDatabaseExampleProgram..................................338 Chapter16GlobalGambas....................................................351 Internationalization........................................................351 Localization....................................................................351 UniversalCharacterSet(UCS).....................................352 Unicode..........................................................................352 UTF8..............................................................................353 HowtotranslateinGambas.........................................355

11

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

Thispageisintentionallyblank.

15

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

Chapter 1 - Introducing Gambas


GambaswasinitiallycreatedbyBenotMinisini,aresidentofthesuburbs ofParis.AccordingtoBenot,GambasisaBasiclanguagewithobjectextensions. The name itself is a play on the words "Gambas almost means Basic" and, accordingtotheauthor,Gambasevolvedbecauseofhispersonalprogramming experiences with the Microsoft Visual Basic software product1. Rather than contendwiththehorrendousnumberofbugsand idiosyncrasiesfound inthat product,hedecidedtocreateGambas. GambasislicensedundertheGNUPublicLicense2andhastakenonalife ofit'sownduetoitsimmensepopularity. Gambasrunsonmostofthemajor Linux platforms and the current (at the timeof this writing) stable version is Release1.0.9. MinisinimakesitveryclearthatGambasisnotcompatiblewith Visual Basic and itwill never bemade compatible. The syntax and internal workingsofGambasarefarbetterandmoreuserfriendly. Minisinistated[sic] that he took from Visual Basic what he found useful: the Basic language, the developmentenvironment,andtheabilitytoquickly[andeasily]makeprograms with[graphical]userinterfaces.3 Minisini disliked the overall poor level ofprogramming that iscommon amongmanyVisualBasicprograms.Manybelievethatthisproblemmaybedue totheenforceduseofquirkyprogrammingpracticesimposedondevelopersasa resultofthewiderangeofbugsandthestrangeidiosyncrasiesoftheproprietary VBlanguage.Gambashasbeendevelopedtobeascoherent,logicalandreliable aspossible. Becauseitwasdevelopedwithanapproachdesigned toenhance programmingstyleandcapturethebesttheBasicprogramminglanguagehasto offer,theadditionofobjectbasedprogramminghasallowedGambastobecomea popular,modern,stable,usableprogrammingenvironmentforLinuxdevelopers.

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

A Beginner's Guide to Gambas


Acompiler Aninterpreter Anarchiver Agraphicaluserinterfacecomponent Adevelopmentenvironment

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

authors. FormoreinfoaboutGTK+,visithttp://www.gtk.org/. FormoreinfoaboutQt,visithttp://www.trolltech.com/products/qt/. http://doc.trolltech.com/3.3/index.html 21

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

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 Forms Modules Data

Classes lists the class files you've created for your project. Classes are basicallytemplatesthatcanbeusedtomakeobjectsoutofatruntime,withcode todefineproperties,methodsandeventhandlersforeachobjectyoucreate.

25

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

Chapter 2 Gambas Language Concepts


Inthischapter,wewillbegintolearnthebasicconceptsneededtomaster the Gambas programming language. The topics we will cover in this chapter includelearningabout Gambasdatatypes,constants,andvariablesandhowto declareandassignvaluestothoseconstantsandvariables.Wewilllearnabout thebasicarithmeticoperators,comparisonoperators,andstringoperators.

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

Thiswilldeclarealocalvariableinaprocedureorfunction.Thisvariableis onlyaccessibletotheprocedureorfunctionwhereitisdeclared.Anexampleof severallocaldeclarationsisshownbelow:


DIMiValueASINTEGER DIMstMyNameASSTRING DIMfMyMatrix[3,3]ASFLOAT DIMoMyObjectASOBJECT

30

A Beginner's Guide to Gambas Therearecurrentlyninebasicdatatypesaprogrammercanusetowrite programcodeinGambas10.Thesedatatypesincludethefollowing:


Boolean Integer String Byte Float Variant Short Date Object

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

A Beginner's Guide to Gambas meansthatthedatacancontainanycombinationoflettersandintegersorspecial characterssuchas$%^&*.Strings,whendeclaredtakefourbytesofmemory. Thismeansthemaximumsizeforastringis4bytes*8bitsperbyte,or32bits squared(1,024bytes).StringvariablesdefaulttoaNULLvaluewhendeclared. Declareastringvariablejustlikeyouwouldanyothervariable:


STATICPUBLICstSomeStringASString

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

A Beginner's Guide to Gambas Stringconstantscanalsocontainthefollowingescapecharacters:


Escapecharacter ASCIIequivalent

\n \r \t \ \\ \xx

CHR$(13) CHR$(10) CHR$(9) Doublequote Backslash CHR$(&Hxx)

Youcanwriteastringconstantinseveralsuccessiveparts.Forexample, "Myson""is""sixteen"isseenbyGambasas"Mysonissixteen". VariableAssignment AprogrammercanassignanyvaluetoavariableinGambasbyusingthe followinggeneralformat:


Variable=Expression

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

AssignmentUsingTheWITHStatement Thisstatementismostcommonlyusedtosetpropertiesforcontrols.The expressionthatexistsbetweentheWITHkeywordandtheENDWITHinstruction


35

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

A Beginner's Guide to Gambas


RETURN[Expression]

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

NotethatthevalueofvariableNchangedfromapositive3to3andthe valueof6changedtoapositivevalueof6.Don'tworryaboutthesyntaxofthe PRINTstatementortheuseofthekeywordDIMusedtodeclareourvariablesfor now.Wewillcoverthesekeywordslaterinthebook. Tosubtractvalues,usetheformat NumberNumber andGambaswill subtractthesecondnumberfromthefirst.


STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=8 R=5 PRINT"===>";NR; END

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

UsingNumberMODNumbercomputestheremainderofthequotientof thetwonumbers.Adivisionbyzeroerrorwilloccurifthevalueofthenumberto therightoftheMODoperatoriszero.Finally,wecantesttheDivisionbyZero errorbytypingthisexample:


STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=9 R=0 PRINT"===>";N/R; END

Gambaswillrespondwiththefollowing:

Figure14ADivisionbyZeroErrorDialog.

NOTE:ClicktheStopbuttonwhenyouseethisdialogappear.
40

A Beginner's Guide to Gambas Inordertoraiseanumbertoagivenpower(exponent),usetheformatof Number^PowerandGambasraisesNumbertothepowerthePoweroperator specified.Trythis:


STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=2 R=3 PRINT"===>";N^R; END

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

A Beginner's Guide to Gambas


STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=0 R=0 PRINT"=>";NORR;"istheORresultof";N;"OR";R R=1 PRINT"=>";NORR;"istheORresultof";N;"OR";R N=1 PRINT"=>";NORR;"istheORresultof";N;"OR";R END

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

A Beginner's Guide to Gambas TheDECoperatorisusedtodecrementavaluebyone.TheINCoperator willincrementthevaluebyone.Thevariablecanbeanytargetofanassignment butmustbeanumericvalue.


STATICPUBLICSUBMain() DIMNASInteger DIMRASInteger N=5 R=5 DECN INCR PRINT"===>";N;"|";R; END

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.

STATICPUBLICSUBMain() PRINT"Rittinghouse"LIKE"R*" END

Theconsolerespondswith:
TRUE

Thespecialcharacter\preventsthenextcharacterfollowingitinastring frombeinginterpretedasagenericpartofthestring.Thinkofthe\characteras acontrolcode.Trythis:


STATICPUBLICSUBMain() PRINT"Samson"LIKE"S*"
43

A Beginner's Guide to Gambas


PRINT"Gambas"LIKE"?[Aa]*" PRINT"Leonard"LIKE"G[Aa]\\*" PRINT"Alfred"LIKE"G[^Aa]*" END

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:

Gambas String Operations


StringOperation
String&String String&/String StringLIKEPattern String=String String<>String String<String String>String String<=String String>=String

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

A Beginner's Guide to Gambas

Chapter 3 - Keywords and Program Flow Control


InGambas,theprogrammercontrolstheprogrambyusingkeywordsand conditionalexpressions.Gambasisaneventdrivenlanguage.Theprogrammer has the ability to direct what happens whenever any event occurs. The programmerusesGambaskeywords(whicharereservedwordswithveryspecific syntax) to create instructions that guide what the program will do in a given circumstance. Conditionals are testsof an expression or a variable. The test couldbeanevaluationoftheresultofanoperationorcomparisonofequality,for example. The following table shows all of the Gambas keywords currently supported: BREAK END FOR QUIT TO CASE CONTINUE ENDIF END FOREACHGOTO REPEAT RETURN UNTIL WAIT DEFAULT SELECT IF SELECT WEND DO END LOOP STEP WHILE ELSE WITH NEXT THEN WITH

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...][(;|,)]

Bracketsusedinthesyntaxdefinitionaboveindicateoptionalparameters. Ifthereisnosemicolonorcommaafterthelastexpression,anewlinecharacteris automaticallyprintedafterthelastexpression. Ifacommaisusedinsteadofa semicolontoseparateexpressions,thenatabcharacter(ASCIIcode9)isprinted betweenoutputvaluestoseparatetheexpressions.PRINTcanalsousedtodirect outputtoafile. Wewilldiscussprintingtofileswhenwegettothesectionon


46

A Beginner's Guide to Gambas InputandOutput. WhenusingPRINTtowriteoutputtoafile,expressionsare senttothestreamFileandthisformatisused: PRINT#File,Expression[(;|,)Expression...][(;|,)] HereissomethingtotryusingPRINT:


STATICPUBLICSUBMain() DIMbASInteger b=1 PRINT"===>"&"bis:"&B PRINT"===>","bis:",B PRINT"===>";"bis:"&B END

Theconsoledisplaysthefollowingoutput:
===>bis:1 ===>bis:1 ===>bis:1

TheIFStatement TheIFstatementisusedtomakeadecision.IFisoneofthemostcommon structuresusedbyprogrammerstomakecomparisonsanddecisionsbasedonthe resultofthatcomparison.UsingIFlogic,yourprogramcanperformcomparisons usingoperatorsyouhavelearnedaboutandsubsequentlymakedecisionsbased ontheresultofsuchcomparisons.IFtakesthegeneralformof:


IFExpressionTHEN dosomething... [ELSEIFExpressionTHEN dosomethingelse...] [ELSE dosomethingcompletelydifferent...] ENDIF

HereisanexampleusingIFthatyoucantryontheconsole:
STATICPUBLICSUBMain() DIMbASInteger b=1
47

A Beginner's Guide to Gambas


IFb=1THEN PRINT"===>"&"Gambasisnumber"&B; ELSEIFb<>1THEN PRINT"Shouldnotprintme!"; ELSE PRINT"Somethingbadishappening" ENDIF END

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

A Beginner's Guide to Gambas


INCw GOTOSTART CASE3 INCw GOTOSTART CASEELSE PRINT"Thevariablewhasnohandlerfor:"&w ENDSELECT PRINT"FinalvalueofwIS:"&w END

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

NotethatoncethevalueofJexceedsthetestof21intheloop,theloop stopsandcode flowmovespastthe NEXTstatement. ThevalueofJremains unchangedwhenexitingtheloop.Experimentwiththecodeabove,changingthe STEPvaluefrom3to1,forexample.TrytomodifytheFORstatementlikethis:


FORI=21to1STEP1

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

A Beginner's Guide to Gambas Theconsoleprintsthefollowing:


HelloWorld,looping1time. HelloWorld,looping2times. HelloWorld,looping3times. HelloWorld,looping4times. HelloWorld,looping5times. GoodbyeWorld,Iloopedatotalof:5times.

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


MyDict["basic"]=1 MyDict["carpet"]=2 FOREACHstrElementINMyDict PRINTstrElement&""; NEXT END

Yourconsoleshoulddisplaythisoutput:
312

Atthispoint,youshouldbegettingaprettygoodfeelforthesyntaxand structureofGambas.Wearegoingtomoveawayfromconsolebased(terminal) applicationsandreturntoourfirstprojecttobeginexploringtheGambasToolBox andlearnhowtodevelopaGUIbasedprogram. Itistimetotakeabreakand whenyoucomebacktothenextchapter,youwillberefreshedandreadytocode. Ah,heck.Ifyoujustcannotwaittojumpin,goaheadandturnthepage!

56

A Beginner's Guide to Gambas

Chapter 4 Introducing the Gambas ToolBox


ThedefaultGambasToolBoxconsistsofmanycontrols.Asofthiswriting usingrelease(1.0.9),thefollowingcontrolsarecurrentlysupported:

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

A Beginner's Guide to Gambas FromthetopleftofFigure1,thecontrolsintheToolBox(Row1)are:


Select Label TextLabel PictureBox ProgressBar Button CheckBox

Onthesecondrowyouwillfind:

RadioButton ToggleButton ToolButton TextBox ComboBox TextArea ListBox

Onthethirdrowwehave:

ListView TreeView IconView GridView ColumnView HBox VBox

Thefourthrowofcontrolsdisplay:

HPanel VPanel Frame Panel TabStrip ScrollView DrawingArea Timer


59

A Beginner's Guide to Gambas AtthebottomoftheToolBoxwindow,thewordQTisseen.Ifyouclickon that,youwillseethecontrolsspecifictotheQTuserinterfaceappear,similarto Figure2below:

Figure16AdditionalcontrolsforQT.

TheQTSpecificControlsfoundonthetoprowofFigure2are:

Selector LCDNumber Dial SpinBox ScrollBar Slider MovieBox

Thesecondrowofcontrolsincludethesetools:

TableView HSplit VSplit Workspace TextView

ThegeneralapproachtoprogrammingGambasistodesignthelayoutof yourforms,placethecontrolsthatmakeupyourinterfacetotheuseronthe form,determineandhandlethevariouseventsthatcanoccurwitheachcontrol usingacombinationofbuiltinGambasmethodsandyourowncode,anddirect theoperationsoftheprogramusinginput/outputdata.Ifitsoundssimple,itis


60

A Beginner's Guide to Gambas becauseonceyouunderstandthemechanicsofitall,itissimple.Onceyouget usedtoprogrammingeventdrivenapplicationsinGambas,itwillbecomesecond naturetoyou. Thefirstgroupofcontrolswearegoingtolearnaboutaretextorientedin natureandservetoeitherdisplayorgathertextdataortogenerateaneventthat youcanwritecodefor,suchaspushingabutton.Thesecontrolsare:


Button Label TextLabel TextBox InputBox TextArea

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)

CommonControlProperties Buttonpropertiesareattributesthatyoucansetorreadusingtheproperty windoworbyusingcodeinyourprogram.Forexample,thelineofcodebelow willsettheTextpropertyofabutton:


hButton.Text=OK

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

Cancel isdefined as PROPERTY CancelASBoolean and itisused to stipulatewhetherornotthebuttonisactivatedwhentheESCkeyispressed.The followingcodewouldtriggerthisbuttoniftheuserpressedtheESCkeyontheir keyboard.


hButton.Cancel=TRUE

IftheCancelpropertyisusedinyourprogram,itwouldallowyoutohandlethe eventandgracefullyexittheformjustasiftheuserhadclickedaQuit,Exitor Cancelbutton.

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

andcanbeusedinterchangeably.Let'strysomecode.StartGambasandopenup theprojectwecreatednamedFirstProject.FromtheTreeView,doubleclickyour mousecursorontheMainFormformandtheblankformwillopenup.Double clickanywhereontheblankformandyouwillseethecodewindow. Itshould looklikethis:


'Gambasclassfile PUBLICSUBForm_Open() END

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

A Beginner's Guide to Gambas Onceyouhaveenteredthecodeabove,clickthegreenprogramrunbutton andyoushouldseesomethingsimilartothefollowing:

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])

ThecodeformatabovecanbeusedtocreateanewcursorfromaPicture objectandsetanoptionalhotspot.Ifitisnotspecified,thedefaulthotspotisthe topleftofthepicture.Cursorhastwoproperties,XandY,thatcanbeusedtoset orgetthecurrentmouseposition.Hereisanexamplethatshowsyouhowtouse aCursorobjectinyourprogram:


65

A Beginner's Guide to Gambas


DIMhPictASPicture DIMhCursorASCursor hPict=Picture["torric.png"] hCursor=NEWCursor(hPict) ME.Cursor=hCursor

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

Enabled isdefinedas PROPERTYEnabledASBoolean and itindicates thatthecontrolisenabled.Todisableacontrol,simplysetit'sEnabledproperty toFALSE.


IFExpression=FALSETHEN hButton.Enabled=TRUE ELSE hButton.Enabled=FALSE ENDIF
66

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.

ForeColorisdefinedasPROPERTYForeColorASIntegerandthisinteger valuerepresentsthecolorusedforthecontrolforeground.Itissynonymouswith theForegroundproperty.YoucanusetheGambaspredefinedconstantsforcolor tosetcolorvalue:


Black DarkCyan DarkRed Green Pink White Blue Cyan DarkBlue DarkGray DarkGreen DarkMagenta DarkYellowDefault Gray LightGray Magenta Orange Red TransparentViolet Yellow

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

A Beginner's Guide to Gambas


'Gambasclassfile PUBLICSUBForm_Open() ProgressBar1.Value=0.50 ProgressBar1.BackColor=Black ProgressBar1.ForeColor=Yellow END

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.

Repeatthisprocesstochooseanotherevent,theLeaveevent,sothatwhen themousemovesofftheprogramwindowwecandetectthatanddosomething aboutit.Addthiscode:

74

A Beginner's Guide to Gambas


PUBLICSUBForm_Leave() ProgressBar1.Value=0.50 Label1.Text="Wasn'tthat" Label2.Text="somereal" Label3.Text="funstuff?" END

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

RepeatthesameprocessfortheLabel2.TextandLabel3.Textproperties. Your codeshouldlooklikethis:


PUBLICSUBLabel2_Enter() Label2.Text="GambasMascot" END PUBLICSUBLabel3_Enter() Label3.Text=">" END

Wealsowanttodetectandrespondtoeventswhenthemousemovesover ourmascotpictureaswell.ClickonceonthePictureBox1controlandchoosethe EnterEvent.Gotothecodewindowandmakethecodelooklikethis:


PUBLICSUBPictureBox1_Enter() Label1.Text="" Label2.Text="" Label3.Text="" PictureBox1.Border=Border.Plain END

Repeattheprocess,choosingtheLeaveeventandensureyourcodeistypedinthe codeeditorasfollows:
PUBLICSUBPictureBox1_Leave()
75

A Beginner's Guide to Gambas


Label1.Text="Wasn'tthat" Label2.Text="somereal" Label3.Text="funstuff?" PictureBox1.Border=Border.Sunken END

ThenextcontrolthatwewanttotakecareofistheQuitbutton.Double clickonitandthecodewindowdisplaystheQuitBtn_Click()subroutine,which respondstoaClickevent.AddtheForm1.Closeline,asshownbelow.


PUBLICSUBQuitBtn_Click() Form1.Close END

Figure23AddingtheFunBtntoourform.

Now,wehavetowritecodefortheProgressBar.Forourexample,wewill incrementitwhentheFunBtnisclickedanddecrementitwhentheNoFunBtnis clicked.DoubleclickontheFunBtncontrolandaddthiscode:


PUBLICSUBFunBtn_Click() ProgressBar1.Value=ProgressBar1.Value+0.01 IFProgressBar1.Value>0.99THEN ProgressBar1.Value=0.0 ENDIF END

Now,doubleclickontheNoFunBtnandaddthis:
PUBLICSUBNoFunBtn_Click() ProgressBar1.Value=ProgressBar1.Value0.01 IFProgressBar1.Value<0.01THEN ProgressBar1.Value=0.0 ENDIF END

76

A Beginner's Guide to Gambas Thatisnearlyallthereislefttodo!Now,savetheprojectandclicktherun button.Youshouldseethisonprogramstart:

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

A Beginner's Guide to Gambas chooseEvents. FromtheEventssubmenu, pickthe Dblclick event.Addthis code,asshownbelow:


PUBLICSUBFunBtn_DblClick() ProgressBar1.Value=ProgressBar1.Value+0.1 IFProgressBar1.Value>0.90THEN ProgressBar1.Value=0.0 ENDIF END

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])

Thecodeabovewillcreateanewpictureobject.IftheWidthandHeightarenot specified,thenewpictureisempty(void). Youcanspecifyifthepicturehasa maskwiththeTransparentparameter. Thepictureclassactslikeanarray.For example:


DIMhPictureASPicture hPicture=Picture[PathASString]

willreturnaPictureobjectfromtheinternalpicturecache.Ifthepictureisnot presentinthecache,itisautomaticallyloadedfromthespecifiedfile.Toinserta pictureinthecache,usethiscall:


Picture[PathASString]=hPicture

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

A Beginner's Guide to Gambas

Chapter 5 Controls for Gathering Input


Inourintroductiontocontrols,welearnedaboutthemostbasictypesof controlsandevents,namelypictures,labels,buttons,andaprogressbar.Wealso learnedhowtodetectwhenthemouseisoveracontrolandwhatactionswecan takewhenitmovesonoroffthecontrol.Thesetypesofcontrolsallpresentdata orrespondtoeventslikethemouseorabuttonclick,buttheydonotallowusers tochoosefromamongalternativessuchaspickingitemsfromalistortypingin theirname,etc.Inthischapter,wewilladdtoourarsenalofGambasknowledge bylearninghowtoaccomplishthosetasksandrespondtoevenmoreevents.We aregoingtobuildaprogramthatwillintroduceyoutothefollowingcontrolsand teachyouhowtousethem:

TextLabel TextBox ComboBox ListBox ToggleButton Panel Frame Checkbox RadioButton

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

Fromthispointon,wewillbelearningtousenewcontrolsandfeaturesof Gambas.WehavealreadywrittencodetoassigninputdatatotheTextLabel,so let'stakethetimenowtolearnallwecanaboutit.Beforewestart,itisprobably agoodideatogoaheadandclickthesavebuttonontheIDEtosaveyourwork.

TextLabel
ThisclassiscreatableanditinheritsitsattributesfromtheControlclass.It implementsacontrolcapableofdisplayingsimpleHTMLtext.YoucanuseHTML entitiessuchas&ltand&gttodisplaycharacterslike<and>.ForHTMLthat requirestheuseof quotemarks, avoid the because itwill notwork. For example,entering:
<divalign="center"><b>Thiswon'twork.</b>

Thefigurebelowshowsyouanexampleofhowthisworks:

Figure27UsingHTMLtoformatTextLabeloutput.

TextLabelisdefinedas DIMhTextLabelASTextLabel andyoudeclareitlike this:


hTextLabel=NEWTextLabel(ParentASContainer)

Whatwewanttodonowiscodetheupdatebuttontotakeadvantageof thesecool HTML features. Toaccomplishthis,weneedtomodifythecodewe previously entered for the update button's click event. Doubleclick on the
82

A Beginner's Guide to Gambas UpdateBtncontrolandchangethecodetolooklikethis:


PUBLICSUBUpdateBtn_Click() TextLabel1.Text="<divalign=center><b>"&TextBox1.Text&"</b>" END

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

Tocreateandinstantiateanew TextBoxcontrol inyourcode,youcanusethis format:


hTextBox=NEWTextBox(ParentASContainer)

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

That'sitforthisroutine.WejustcallthebuiltinmethodtocleartheTextBoxand wearedone.Now,westillneedtogototheTextBox1_Leave()subroutineand enterthiscode:


TextLabel1.Text="<divalign=center><b>"&TextBox1.Text&"</b>" TextBox1.Text="<Entertexthere>"

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

ThatisallweneedtodotohidetheUpdateBtncontrol.Ifyouuseropts nottousethebuttonnow,alltheneedtodoisclicktheformanditwillhidethe button.Howdowebringitback?Doubleclickwilldothetricknicely.Fromthe


84

A Beginner's Guide to Gambas codeeditor,findtheForm_DblClick()subroutineandenterthiscode:


UpdateBtn.Show

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.

Now,saveyourworkandruntheprogramtoseehowitworks.Hoverthe mouseovertheUpdateButtonandthenicelyformattedToolTipwillappear. It shouldlooklikethefigurebelow.Cool,huh?

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

A Beginner's Guide to Gambas


DIMhComboBoxASComboBox

Toinstantiatethevariablewejustdeclared,usethisformat:
hComboBox=NEWComboBox(ParentASContainer)

ThiswillcreateanewComboBoxcontrol.Thisclassactslikeareadonly array. Inotherwords,declaringthevariable,instantiatingit,andretrievinga valuefromcodedirectlywouldworklikethis:


DIMhComboBoxASComboBox DIMhComboBoxItemAS.ComboBoxItem DIMIndexasInteger hComboBoxItem=hComboBox[Index]

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

A Beginner's Guide to Gambas selectordialogifyouclickinsideit.Clicktheselectordialogbutton(remember, withthethreedots?)anditwillbringuptheEditlistpropertyDialog:

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

A Beginner's Guide to Gambas anyfancyformattingthatitiscapableof.Well,thatiseasytofix.Let'schange thecodelikethis:


PUBLICSUBComboBox1_Change() DIMresultASString result="<divalign=center><b>"&Trim(ComboBox1.Text)&"</b>" TextLabel1.Text=result&"wasselected." END

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

A Beginner's Guide to Gambas


DIMhListBoxASListBox hListBox=NEWListBox(ParentASContainer)

LiketheComboBox,thisclassactslikeareadonlyarray.
DIMIndexasInteger DIMhListBoxASListBox DIMhListBoxItemAS.ListBoxItem hListBoxItem=hListBox[Index]

ThelineofcodeabovewillreturnaListBoxitemfromitsintegerindex. Notethatthe.ListBoxItemrepresentsanitemintheListBoxpopuplistbox.This classisvirtual.Youcannotuseitasadatatypeanditisnotcreatable.Ithasa singleproperty,TextwhichreturnsastringvaluerepresentingtheListBoxitem representedbyIndex.WearegoingtocreateaListBoxonourformnow.Here iswhatournewcontrolwilllooklike:

Figure34WhatourListBoxwill looklike.

Inordertobuildournewcontrol,wewillgototheGambasToolBoxand selecttheListBoxcontrol.Placeitontheform(refertoourinitialpictureatthe verybeginningofthischaptertoseewhereitshouldgo)andtrytogetitascloseto whatyouseeinthatpictureasyoucan.Onceyouaredonewiththat,clickonit onceifyoudonotseethehandlesandgotothePropertiesWindow.FindtheList property. Theinputboxtotherightofthiswillenableaselectordialogifyou clickinsideit.Clicktheselectordialogbutton(remember,withthethreedots?) anditwillbringuptheEditlistpropertyDialog:

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

Now,saveyourprojectandruntheprogram.Tryselectingalltheitemsin thelistandseewhatinformationisreturned. ListsandComboBoxesarevery


91

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)

Thegreatthingaboutaframeisthatitworkssortoflikeawindowwithin awindow.Anycontrolyouplaceintheframebecomesapartoftheframe,ina mannerofspeaking. Whatthismeansisthatifyouput CheckBoxcontrolsor buttonsorwhateverintheframeanddecidetomovetheframe,theyallmove withit.Theycanberearrangedwithintheframe,butiftheframemoves,hides, etc.,sodothey.Hereiswhatourframeandthecontrolswewilladdtoitlook like:

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

A Beginner's Guide to Gambas

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

WhatwehavedonewiththecodeaboveischecktheToggleButton.Value propertytoseeifitisTRUE,indicating thatthebuttonwasclickeddown. If FALSE,anotherclicktoggledittotheupposition.Regardlessofthepositionitis at,wewanttheFrame1.Texttodisplaythestatusofthebuttonlastclicked.Now, let'smoveontolearnabouttheCheckBoxcontrols.

Checkbox
TheCheckBoxclassinheritsitsattributesfromtheControlclass.Thisclass implementsacheckboxcontrolanditiscreatable. Declareandinstantiatethe variablelikethis:
DIMhCheckBoxASCheckBox
93

A Beginner's Guide to Gambas


hCheckBox=NEWCheckBox(ParentASContainer)

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


PUBLICSUBRadioButton1_Click() RadioButton1.Text="HaHaRB2" RadioButton2.Text="RadioButton2" END

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

A Beginner's Guide to Gambas

Chapter 6 Menus, Modules, Dialogs and Message Boxes


AlmosteveryGUIbasedprogramyouencounterwillusesomecombination of menus,MessageBoxes, and standard dialogstocommunicate with theuser. Gambasisnotanydifferent.Additionally,thereisnoprogramminglanguagethat provideseverythingthataprogrammerwoulduseasaprebuiltcomponent.That iswhatmodulesareusedforwritingwhatyouneedoutsidethescopeofwhat Gambasprovides.Forexample,ifyouneedafunctionthatreturnsthenameofa colorbasedonwhatischoseninastandardcolorselectiondialog,youaregoing tohavetowriteone,andwewilldojustthatinournextsampleproject.Inthis chapter, we will learn how to use each of these controls and build another exampleprogramtohelpyoulearntomasterGambas.Hereisascreenshotofthe finalversionofwhatourprojectwilllooklike:

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

A Beginner's Guide to Gambas


PUBLICSUBQuitBtn_Click() Form1.Close END

Doubleclickontheformanywhereoutsideacontrolboundaryandyou willgetthePUBLICSUBForm_Open()subroutinetoappearinthecodeeditor. Insertthiscodeinthatemptysubroutine:


ME.Caption="WorkingwithMenus"

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

A Beginner's Guide to Gambas


IFMenu2Item1.CheckedTHEN Menu2Item1.Checked=FALSE ELSE Menu2Item1.Checked=TRUE ENDIF

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.

Tobegin,clicktheInsertbutton.First,wewillinsertthetoplevelmenus, ColorDialog,MessageBoxes,FileDialogs,andHelp. Tomakethiseasy,usethe


101

A Beginner's Guide to Gambas tablebelowtofillintheinputfielddata: MainMenu


ColorDialog MessageBoxes FileDialogs Help

(Variable)Name
Menu1 Menu2 Menu3 Menu4

Group

Caption
ColorDialog MessageBoxes FileDialogs Help

Now,let'sputthemenuitemsintothefirstmenu.Thesemenuitemswillbelong totheColorDialogmenu: ColorDialog


ForegroundColor BackgroundColor Font

(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

Ensure theError,Warning,andDeleteentriesareindented TWO levels belowthemenuentryforAlertMessages.Now,thelastmenuitemfortheHelp menuneedstobeadded. Help


About

(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:

Thefiltername. Aspace. Anopeningbracket. Oneormorefilepatterns,separatedbysemicolons. Aclosingbracket.

HereisanexamplethatalsodemonstratestheuseoftheDialogTitleproperty:

103

A Beginner's Guide to Gambas


Dialog.Title="Chooseafile" Dialog.Filter=["Pictures(*.png;*.jpg;*.jpeg)","Allfiles(*.*)"] Dialog.OpenFile

ThefilerelatedDialogcalls(SelectDirectory,OpenFileDialogandSaveFile Dialog)allreturnthePathproperty,whichisastringthatcontainsthefilepath selected.InthecaseoftheSelectDirectoryDialogcall,thestringistruncatedat thedirectorylevel.Now,let'sstartcodingourfirstmenuitem,ForegroundColor. Fromtheformwindow,choosetheForegroundColoritemfromthemenuwejust builtandyouwillbetakentothecodewindowinasubroutinecalled PUBLIC SUBMenu1Item1_Click()whereyouwillwanttoinsertthiscode:


PUBLICSUBMenu1Item1_Click() Dialog.Title="Chooseaforegroundcolor" Dialog.SelectColor TextLabel1.ForeColor=Dialog.Color TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END

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)&"."

ThelineofcodeabovewillsettoboldfacetheColorselectedwaspartof thestring,concatenatetheColorvaluetothestringafterconvertingtheintegerto astringusingtheStr$conversionfunction,andthenconcatenatetheterminating punctuationtothestring(wedowantittolookprofessional,don'twe?).Nowrun thecodeandyoushouldseesomethinglikethis:

Figure42Aformattedtextlabeldisplayingthecolorvalue.

104

A Beginner's Guide to Gambas Well,21760isnotveryusefulinformation. Thisnumberistheinternal representationofthatgreenishcolorIselected.Weneedtodevelopsomemethod ofknowingifthecolorisred,blue,green,i.e.,anamedcolorconstant.Thisis whatwewerealludingtointheprevioussectionabouttheproblemwithcolors. Hereisweremodulescomeintoplay.

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

Now,wehavetoaddourCASESELECTstatement.Itwillusetheinteger parameteriValthatispassedintothefunctionfromthecallingsubroutine.Here isthefulllistingforyoutoenter:


'Gambasmodulefile PUBLICFUNCTIONSetColorName(iValASInteger)ASString
105

A Beginner's Guide to Gambas


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 rval="Yellow" DEFAULT rval=Str$(ival)&"anditisnotapredefinedcolorconstant" ENDSELECT RETURNrval END
106

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

WehaveaddedthelineColorName=...buthavenotdeclaredColorName yet.Thisvariablemustbeglobalbecausewearecallingamoduletoreturnthe valueColorName. AttheverybeginningoftheForm1.classcodefile,addthis codejustbeforethePUBLICSUBForm_Open():


'Gambasclassfile 'declareaglobalvariabletobeusedwithourSetColorNamemodule ColorNameASString

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

A Beginner's Guide to Gambas


TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END

Wewillwanttodothesamethingforthebackgroundcolor.Thesecond menuitemintheColorDialogmenuisBackgroundColorsolet'sclickonthat fromtheIDEandcodethefollowing:


PUBLICSUBMenu1Item2_Click() Dialog.Title="Chooseabackgroundcolor" Dialog.SelectColor ColorName=Module1.SetColorName(Dialog.Color) TextLabel1.BackColor=Dialog.Color TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"." END

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:

Ascent Bold Descent Fixed Italic Name Resolution Size StrikeOut


108

A Beginner's Guide to Gambas


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

A Beginner's Guide to Gambas


DIMoldfontdataASFont DIMattrASString DIMselASString

Atthispoint,youmaybeaskingyourselfifyoucouldnotsimplyusethe ToStringpropertytodothis.Yes,butyouwouldnotlearnasmuch.Bearwith meandcodealong.Thefollowinglineofcodesimplyblanksoutourattrstring:


attr=""

Now,weassignthecurrentTextLabel1.fontpropertytotheoldfontdatavariable:
oldfontdata=TextLabel1.Font

Next,let'ssetthetitleforthedialogandcalltheSelectFontDialogwiththesetwo lines:
Dialog.Title="Pickafont..." Dialog.SelectFont

Whentheuserselectsafontfromthe SelectFontDialog,wewanttoassignthe fontselectedtothefontdatavariable:


fontdata=Dialog.Font

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

A Beginner's Guide to Gambas Next,wewillsetthefontintheTextLabel1controltobewhattheuser selectedanddisplaythedynamicallycreatedstringoffontdatatotheuser:


TextLabel1.Font=fontdata
TextLabel1.Text="Font:"&fontdata.Name&","&Str(Round(fontdata.Size))&attr

Wewillwaitfivesecondstoletthetakealookattheresult,thengivethem achoiceastowhetherornottheywanttokeepthesesettingsorrevertbackto theprevioussettings.


WAIT5.0 SELECTMessage.Question("Keepthenewfont?","Yes","No","Don'tknow") CASE1 TextLabel1.Text="Thisisnowthedefaultfont." CASE2 TextLabel1.Font=oldfontdata TextLabel1.Text="Revertedtopreviousfontsetting." CASE3 TextLabel1.Font=oldfontdata TextLabel1.Text="Nochangewasmadetodefaultfont." ENDSELECT END

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

A Beginner's Guide to Gambas

Figure44MakinganewdefaultfontfortheTextLabel1control.

Atthispointinyourlearningjourney,youknowhowtodoquiteabitin Gambas. Wemustcontinuethisjourneybyexpandingourabilitytodealwith inputandoutputfromtheuser.TheMessageBoxesareanothervaluabletoolin ourGambasarsenal.Let'sfindoutmoreaboutusingthem.

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

A Beginner's Guide to Gambas message.Hence,onlyonebuttonisneeded.Hereiswhatourcodewillproduce:

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

Prettysimple,eh?Whatifwewantedtotogglethecheckedpropertyvalue fromTRUEtoFALSEorviceversaeachtimethismenuitemwasselected.Modify thecodeaboveasfollows:


PUBLICSUBMenu2Item1_Click() IFMenu2Item1.CheckedTHEN Menu2Item1.Checked=FALSE ELSE Menu2Item1.Checked=TRUE ENDIF 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

A Beginner's Guide to Gambas Query/ConfirmMessages QuestionandDeletefallintothiscategory.Questionisdefinedas:


STATICFUNCTIONQuestion(MessageASString[,Button1ASString, Button2ASString,Button3ASString])ASInteger

InvokingitdisplaysaquestionMessageBoxwithuptothreebuttons.Theindex ofthebuttonclickedbytheuserisreturned.Let'sgobacktoourpreviouscode andexamineitindetail:


SELECTMessage.Question("Keepthenewfont?","Yes","No","Don'tknow") CASE1 TextLabel1.Text="Thisisnowthedefaultfont." CASE2 TextLabel1.Font=oldfontdata TextLabel1.Text="Revertedtopreviousfontsetting." CASE3 TextLabel1.Font=oldfontdata TextLabel1.Text="Nochangewasmadetodefaultfont." ENDSELECT

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

A Beginner's Guide to Gambas Whenyouexecutetheprogram,hereiswhatyoushouldsee:

Figure47AQuestionMessageBox.

ErrorMessages TheErrorfunctiondisplaysanerrorMessageBox,withuptothreebuttons. Theindexofthebuttonclickedbytheuserisreturned.Errorisdefinedas:


STATICFUNCTIONError(MessageASString[,Btn1ASString,Btn2ASString,Btn3 ASString])ASInteger

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

A Beginner's Guide to Gambas declaredas:


STATICFUNCTIONWarning(MessageASString[,Btn1ASString,Btn2AS String,Btn3ASString])ASInteger

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

A Beginner's Guide to Gambas


ENDSELECT END

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

Fromtheexampleprogramformwindow,clickonthemenuFileDialogs andselecttheFileopen...menuitem. Thissetsuptheclickeventandwewill enterthiscode:


PUBLICSUBMenu3Item1_Click() Dialog.Title="Openfile..." Dialog.OpenFile TextLabel1.Text="OPEN:"&Dialog.Path END
117

A Beginner's Guide to Gambas Thecodeabovesimplysetsthetitleandcallsthestandarddialog.When theuserfinishesthestringreturnedfromtheOpenFileDialogfunctionisassigned totheTextLabel1.Textvariable. Hereiswhatitshouldbringupwhenyourun thecode:

Figure51TheOpenFileDialog.

Prettyeasystuff.Savingfilesisjustaseasy. DialogSaveFileFunction The SaveFileDialog functionalsocallsthefilestandarddialogtogetthe nameofafiletosave.ItreturnsTRUEiftheuserclickedontheCancelbutton, andFALSEiftheuserclickedontheOKbutton.SaveFileisdeclaredas:


STATICFUNCTIONSaveFile()ASBoolean

CreateaclickeventforourFileSave...menuitemandinthecodewindowenter thiscode:
PUBLICSUBMenu3Item2_Click() Dialog.Title="Savefileto..." Dialog.SaveFile TextLabel1.Text="SAVE:"&Dialog.Path END

Hereistheresult:

118

A Beginner's Guide to Gambas

Figure52SaveFileDialog.

DialogSelectDirectoryFunction TheSelectDirectoryDialogfunctioncallsthefilestandarddialogtogetan existingdirectoryname.ItreturnsTRUEiftheuserclickedontheCancelbutton, andFALSEiftheuserclickedontheOKbutton.SelectDirectoryisdeclaredas:


STATICFUNCTIONSelectDirectory()ASBoolean

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

A Beginner's Guide to Gambas


fontdata=Dialog.Font 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 TextLabel1.Font=fontdata TextLabel1.Text="Font:"&fontdata.Name&","&Str(Round (fontdata.Size))&attr WAIT5.0 SELECTMessage.Question("Keepnewfont?","Yes","No","Don'tknow") CASE1 TextLabel1.Text="Thisisnowthedefaultfont." CASE2 TextLabel1.Font=oldfontdata TextLabel1.Text="Revertedtopreviousfontsetting." CASE3 TextLabel1.Font=oldfontdata TextLabel1.Text="Nochangewasmadetodefaultfont." ENDSELECT END PUBLICSUBMenu2Item1_Click() IFMenu2Item1.CheckedTHEN Menu2Item1.Checked=FALSE ELSE Menu2Item1.Checked=TRUE ENDIF Message.Info("Hereissomeinformationtoconsider.") END PUBLICSUBsubMenuItem1_Click() Message.Error("Wow!Thiswasamistake.") END PUBLICSUBsubMenuItem2_Click()
121

A Beginner's Guide to Gambas


Message.Warning("Youhavebeenwarnedaboutthis!") END PUBLICSUBsubMenuItem3_Click() SELECTMessage.Delete("Delete?","Yes","No","Cancel") CASE1 TextLabel1.Text="Deletedit" CASE2 TextLabel1.Text="NotDeleted" CASE3 TextLabel1.Text="Cancelled!" ENDSELECT END PUBLICSUBMenu2Item3_Click() SELECTMessage.Question("Didyoulikethis?","Yes","No","Don'tknow") CASE1 TextLabel1.Text="Likedit." CASE2 TextLabel1.Text="Didnotlikeit." CASE3 TextLabel1.Text="Didnotknow." ENDSELECT END PUBLICSUBMenu3Item1_Click() Dialog.Title="Openfile..." Dialog.OpenFile TextLabel1.Text="OPEN:"&Dialog.Path END PUBLICSUBMenu3Item2_Click() Dialog.Title="Savefileto..." Dialog.SaveFile TextLabel1.Text="SAVE:"&Dialog.Path END PUBLICSUBMenu3Item3_Click() Dialog.Title="Pickadir..." Dialog.SelectDirectory TextLabel1.Text="SAVEtoDIR:"&Dialog.Path END PUBLICSUBMenu4Item1_Click() Message.Info("Thisisallabout<br><b>GambasProgramming</b>!") END

122

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


rval="Yellow" DEFAULT rval=Str$(ival)&"anditisnotapredefinedcolorconstant" ENDSELECT RETURNrval END

124

A Beginner's Guide to Gambas

Chapter 7 Handling Strings and Converting Data-types


Oneofthemostimportantthingsaprogrammerneedstoknowishowto handle strings and use the builtin functions provided by the development languageheorshemaybeworkingwith. Manipulatingstringsandconverting fromonedatatypetoanotherisalmostalwaysrequiredwhenprogramming.The moreadeptaprogrammerisatusingthebuiltinfunctions,themorelikelyitis theirprogramwilloperateefficiently.

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

A Beginner's Guide to Gambas learningaboutthestringsinGambas.Youmayrememberfromanearlierchapter thatinGambasastringdatatypeisareferencetoavariablelengthstring.Itis fourbytesininitialsizeandwhenitiscreateditisinitializedwithaNullvalue. Len Lenreturnsthelengthofastring.ThereturnvalueisanInteger.Hereis howLenwouldbeusedincode:


Length=Len(String)

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])

Mid$ returnsasubstringcontainingthe Length charactersfromthefirst


128

A Beginner's Guide to Gambas position.IfLengthisnotspecified,everythingfromthestartpositionisreturned. If Length isnegative,everythingfromthestartpositionexceptthe Length last charactersisreturned.StandardGambaslanguagesyntaxis:


Result=Mid$(String,Start[,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

A Beginner's Guide to Gambas


PRINTsTestString&"isourstartingstring." sResult=Replace$(sTestString,"\t","") PRINTsResult&"istheresultofReplacecall." END

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

A Beginner's Guide to Gambas simplifiedsprintf.Thisfunctionisveryusefulwhenyoumustconcatenatestrings thatmustbetranslated.Donotusethe&operator,astheorderofconcatenation mightchangewiththelanguage.StandardGambaslanguagesyntaxis:


Result=Subst(Pattern,ReplaceString[,ReplaceString])

Trythislittleapplicationonyourconsole:
STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString sTestString="abcdef" sResult="ghijkl" PRINT"Ourstartstringis:"&sTestString PRINTSubst$("OurSubststringis:&1",sResult) END

Theconsolerespondswith:
Ourstartstringis:abcdef OurSubststringis:ghijkl

InStr InStrreturnsthepositionofthefirstoccurrenceofSubstringinString.If Startisspecified,thesearchbeginsatthepositionStart. Ifthesubstringisnot found,InStr()returnszero.


Position=InStr(String,Substring[,Start])

Thefollowingcodeisabitmoreinvolvedandwilldemonstratethepower ofthisfunction.Wewanttofindeveryspace(setinthestringatevennumbered positions)andprintoutthepositionwhereeachspaceoccurs.Enterthiscodein theconsolecodewindow:


'Gambasclassfile STATICPUBLICSUBMain() DIMsTestStringASString DIMsResultASString DIMiLengthASInteger DIMiPositionASInteger DIMiNextCharPosASInteger
132

A Beginner's Guide to Gambas


DIMiCounterASInteger sTestString="abcdefghi" iPosition=Instr(sTestString,"") PRINTsTestString&"isourstartstring." PRINT"Firstspaceisatposition:"&iPosition iNextCharPos=iPosition+1 iPosition=Instr(sTestString,"",iNextCharPos) PRINT"Nextspaceisatposition:"&iPosition PRINT sTestString="abcdefghijklmnopqrstuvwxyz" PRINT"123456" PRINT"123456789012345678901234567890123456789012345678901234567890" PRINTsTestString&"isournewteststring." PRINT iLength=Len(sTestString) PRINT"LengthofsTestStringis:"&iLength iPosition=Instr(sTestString,"") PRINT"Firstspaceisatposition:"&iPosition FORiCounter=iPositionTOiLength/2 iNextCharPos=iPosition+1 iPosition=Instr(sTestString,"",iNextCharPos) PRINT"Nextspaceisatposition:"&iPosition NEXT END

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

A Beginner's Guide to Gambas RInStr RInStrreturnsthepositionofthelastoccurrenceofSubstringinString.If Startisspecified,thesearchstopsatthepositionStart. Ifthesubstringisnot found,RInStr()returnszero.StandardGambaslanguagesyntaxis:


Position=RInStr(String,Substring[,Start])

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

A Beginner's Guide to Gambas


Array=Split(String[,Separators,Escape])

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

A Beginner's Guide to Gambas


STATICPUBLICSUBMain() DIMiAsciiCodeASInteger DIMsTestStringASString DIMiLengthASInteger DIMcounterASInteger sTestString="Gambasisgreat." iLength=Len(sTestString) PRINT"LengthofsTestStringis:"&Str$(iLength) FORcounter=1TOiLength iAsciiCode=Asc(sTestString,counter) IFiAsciiCode<>32THEN PRINTiAsciiCode&"ischar:"&Chr(9)&Chr$(iAsciiCode) ELSE PRINTiAsciiCode&"ischar:"&Chr(9)&"<space>" ENDIF NEXT END

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

A Beginner's Guide to Gambas


String=Bin$(Number[,Digits])

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

CBool CBoolconvertsanexpressionintoaBooleanvalue.Anexpressionisfalseif anyofthefollowingconditionsaremet:


AfalseBooleanvalue Azeronumber Azerolengthstring Anullobject

Otherwise,theexpressionistrueinallothercases.HereistheGambaslanguage syntax:
137

A Beginner's Guide to Gambas


Boolean=CBool(Expression)

Hereisanexample:
STATICPUBLICSUBMain() PRINTCBool(0);"";CBool(1) END

Theconsolerespondswith:
FALSETRUE

CByte CByteconvertsanexpressionintoabyte.Expressionisfirstconvertedinto aninteger.Then,ifthisintegeroverflowsthebyterange,(32767to32768)itis truncated.


Byte=CByte(Expression)

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

A Beginner's Guide to Gambas


STATICPUBLICSUBMain() DIMsDateStringASString sDateString=CDate(Now) PRINTsDateString;"isourstarttime." WAIT1.0 PRINTCDate(Now);"isonesecondlater." PRINTCDate(sDateString);"isstillwherewestarted." WAIT1.0 PRINTNow;"isonesecondlater." END

Theconsolerespondswith:
08/21/200520:52:40isourstarttime. 08/21/200520:52:41isonesecondlater. 08/21/200520:52:40isstillwherewestarted. 08/21/200520:52:42isonesecondlater.

CFloat CFloatconvertsanexpressionintoafloatingpointnumber. Becareful! Thecurrent localization isNOTusedbythisfunction. Gambaslanguagesyntax is:


Float=CFloat(Expression)

Example:
STATICPUBLICSUBMain() DIMsFloatStringASString DIMfFloatNumASFloat sFloatString="0.99" fFloatNum=0.01 PRINTfFloatNum+CFloat(sFloatString) PRINTCFloat("3.0E+3") END

Theconsolerespondswith:
1 3000

139

A Beginner's Guide to Gambas CInt/CintegerandCShort CIntissynonymouswithCInteger.Eithercallconvertsanexpressioninto aninteger.ThestandardGambaslanguagesyntaxis:


Integer=CInt(Expression) Integer=CInteger(Expression)

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

A Beginner's Guide to Gambas Example:


STATICPUBLICSUBMain() DIMsFloatStringASString DIMfFloatNumASFloat fFloatNum=120.901 sFloatString=CStr(fFloatNum) PRINTsFloatString;"isnowastring." END

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

A Beginner's Guide to Gambas system,butitisUTF8onaRedHatLinuxoperatingsystem.Inthefuture,nearly allLinuxsystemswillprobablybeUTF8based.Thecharsetusedbythegraphical userinterfaceisreturnedbyacallto Desktop.Charset.ItisUTF8withthe Qt component.TheGambaslanguagesyntaxis:


ConvertedString=Conv$(StringASString,SourceCharsetASString, DestinationCharsetASString)

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

ValandStr$ ValconvertsastringintoaBoolean,anumberoradate,accordingtothe contentofthestring. Thecurrent localization isusedtoconvertnumbersand dates.Theconversionalgorithmusesthefollowingorderofprecedence:


Ifstringcanbeinterpretedasadate&time(withdateortime separators),thenthedate&timeisreturned. Elseifstringcanbeinterpretedasafloatingpointnumber,then afloatingpointnumberisreturned. Elseifstringcanbeinterpretedasaintegernumber,thenan integernumberisreturned. ElseifstringisTRUEorFALSE,thematchingBooleanvalueis returned. ElseNULLisreturned.

StandardGambaslanguagesyntaxis:
Expression=Val(String)

142

A Beginner's Guide to Gambas Str$convertsanexpressionintoitsprintablestringrepresentation.Itisthe exactcontraryofVal().Thecurrentlocalizationisusedtoconvertnumbersand dates.Gambaslanguagesyntaxis:


String=Str$(Expression)

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

A Beginner's Guide to Gambas


PRINT"Youtyped:";sInputLine value=Val(sInputLine) PRINT IFIsBoolean(value)THEN PRINTsInputLine;"isBoolean." ELSEIFIsDate(value)THEN PRINTsInputLine;"isadate." ELSEIFIsInteger(value)THEN PRINTsInputLine;"isanInteger." IFvalue=0ORvalue=1THEN PRINT"ItcouldalsobeBoolean." ENDIF IFvalue>0ANDvalue<255THEN PRINT"ItcouldalsobeaByte." ENDIF IFvalue>32767ANDvalue<32768THEN PRINT"Itcouldalsobeashort." ENDIF PRINT"" ELSEIFIsFloat(value)THEN PRINTsInputLine;"isafloat." ELSEIFIsString(value)THEN PRINTsInputLine;"isastring." ELSEIFIsNull(value)THEN PRINTsInputLine;"isNULL." ELSE PRINTsInputLine;"issomethingelse." ENDIF LOOP PRINT PRINT"Wearedone!" END

Theoutputshouldbesimilartothis:
==>true Youtyped:true trueisBoolean. ==>214 Youtyped:214 214isanInteger. ItcouldalsobeaByte. Itcouldalsobeashort. ==>08/23/0512:23:55 Youtyped:08/23/0512:23:55

144

A Beginner's Guide to Gambas


08/23/0512:23:55isadate. ==>John Youtyped:John Johnisastring. ==>32756 Youtyped:32756 32756isanInteger. Itcouldalsobeashort. ==>quit Youtyped:quit quitisastring. Wearedone!

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

A Beginner's Guide to Gambas


Auserdefineddateformatisdescribedbythefollowingcharacters:
FormatSymbol "yy" "yyyy" "m" "mm" "mmm" "mmmm" "d" "dd" "ddd" "dddd" "/" "h" "hh" "n" "nn" "s" "ss" ":" printsyearusingtwodigits. printsyearusingfourdigits. printsmonth. printsmonthusingtwodigits. printsmonthinanabbreviatedstringform. printsmonthinit'sfullstringform. printsday. printsdayusingtwodigits. printsweekdayinanabbreviatedform. printsweekdayinitsfullform. printsdateseparator. printshour. printshourusingtwodigits. printsminutes. printsminutesusingtwodigits. printsseconds. printssecondsusingtwodigits. Printsatimeseparator. Meaning

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

A Beginner's Guide to Gambas Hereistheoutput:


UserdefinednumericFormatexamples: 3.142 +03.1416 31.4% 2.85E+11 Userdefineddateandtimeformatexamples: 08/21/200521:55:14 8/21/0521:55:14 Sun21Aug2005 Sunday21August2005

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)

Predefined data-type constants


Datatype gb.Null gb.Boolean gb.Byte gb.Short gb.Integer gb.Float gb.Date gb.String gb.Variant gb.Object Value Nullvalue Booleanvalue Byteintegernumber Shortintegernumber Integernumber Floatingpointnumber Dateandtimevalue Characterstring Variant Objectreference

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

A Beginner's Guide to Gambas

Chapter 8 Using Advanced Controls


Inthischapter,wearegoingtostudyafewofthemoreadvancedcontrols, suchastheIconView,ListView,GridView,ColumnViewandTabstripcontrolsand learnhowtousethem.FortheIconViewcontrol,wearegoingtotakeadifferent approachthistime,usingoneoftheexampleprogramsprovidedbyGambas.We are going to review the Explorer program written by Gambas creator Benot Minisiniandgothrougheachandeverylineofcodetounderstandexactlywhatis goingonintheprogramandhowtheIconViewcontrolisused.

IconViewControl
Firstofall,startGambasandselecttheExplorerprojectfromtheMiscellaneous sectionoftheExampleprograms:

Figure54ChoosingtheExplorerexample.

Once youselecttheExplorerproject,theIDEwillopenupandwewill needtogettothecode.Youcandothisbydoubleclickingontheclassfileorif theformisalreadyup,doubleclickonacontrolandthenmovetothetopofthe


149

A Beginner's Guide to Gambas codewindow. Eitherwaywillworkaslongasyoustartatthetopofthecode windowwhereyouseethefirstline:


'Gambasclassfile

Thefirstthingweseedoneinthiscodeisthedeclarationoftheprogram's globalvariables.Notethattheyareprefixedwitha'$'characterforclarity.The $sPathvariableisdeclaredasPRIVATEandusedtoholdthenameofthecurrent filepath.


PRIVATE$sPathASString

$bHiddenisaPRIVATEBooleanvariablethatwillactasaflagtobeusedto determineIFafileishiddenornot. Wewillusethe Stat function tocheckits status.


PRIVATE$bHiddenASBoolean

$bCtrlisaPRIVATEBooleanusedasaflagwhenaCTRLkeyispressed.If theuserholdsdowntheCTRLkeywhendoubleclickingonafolderitwillopen upinanewwindow.


PRIVATE$bCtrlASBoolean

ThisisthefirstsubroutineGambaswillexecutewhentheprogramisrun:
STATICPUBLICSUBMain()

Thenexttwolineswilldeclarealocalvariablefortheformwewantto displaytotheuserandcreateaninstanceoftheformnamed FExplorer,passing theparameterSystem.Hometoaconstructorroutine,whichisidentifiedas_new ()),andwhichtakesastringparametersPath(System.Home)thevalueofwhich weobtainedfromtheSystemclass.


DIMhFormASForm hForm=NEWFExplorer(System.Home)

Now,showtheform:
hForm.Show END

150

A Beginner's Guide to Gambas ThisnextsubroutineistheconstructorthatiscalledwhentheMain()subroutine isactivatedandtheFExplorerformisinstantiated:


PUBLICSUB_new(sPathASString)

Wewillassignthepathpassedin(System.Home)asaparametertoourglobal variable$sPath:
$sPath=sPath

Finally, we must call the subroutine RefreshExplorer() to populate the iconviewcontrolnamedivwExplorertorefreshthedisplayforthenewcontrol:


RefreshExplorer END

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"]

Iftheglobalpathvariableisnotsettothehighestlevel(i.e.,theparent) indicatedbythe"/"string,thenwewanttocreateafolderthattheusercanclick togototheparentdirectoryofthecurrentchild. Weaddthisfolderthethe iconviewcontrolnamedivwExplorerbyusingitsAddmethod:


IF$sPath<>"/"THENivwExplorer.Add("D..","..",hPictParDir)

Inthestatementabove,the.Addmethodtakesthreeparameters.Thefirst isthenameofthekey,inthiscaseD..whichisourkeyfordirectories. The secondisthetextplacedbelowtheiconintheIconViewcontrol,andthefinal


14 Common string functions do not deal with UTF-8 very well. In UTF-8, a character can have 1-3 bytes. The Gambas String class methods are able to handle UTF-8 so they should be used whenever possible. 152

A Beginner's Guide to Gambas parameteristhenameofthevariablethatisahandletothefilenameoftheicon wewanttodisplaywiththisentry.Now,wewillbegintoloopthrougheveryfile inthecurrentdirectorytoseeifitisahiddenfileornotandtotageachfilename aseitheradirectoryorafile.


FOREACHsFileINDir($sPath)

Gambasinitializesstringstonullwhencreated,sotheveryfirsttimewe comehere,the$bHiddenvaluewillnotbeTRUEandtheIFstatementwillbe executedinthecodebelow:


IFNOT$bHiddenTHEN

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

Ifwereachedthispointinthecode,thefilewasnothidden.Now,wewill usethebuiltinfilemanagementfunctionIsDirtoseeifthecurrentpathandfile string(catenatedintheStatcall)isafolderorafile.Ifwehaveafolder,wewill addittothecDirstringarray,firsttaggingitwithaletter'D'fordirectoryor'F'for fileandthenappendingthefilenameheldintheworkstringsFiletothe'D'or'F' tag:


IFIsDir($sPath&/sFile)THEN'itwasadirectory cDir.Add("D"&sFile)'weaddittothedirectorieskey ELSE'notadirectoryandweaddittothe"F"keyasafile cDir.Add("F"&sFile) ENDIF NEXT'thisistheendoftheFORloop...

OnceeverythingisloadedinthecDirarraywiththeFOR/NEXTloopwe callthebuiltinSortmethodandsortthearrayofstrings:
153

A Beginner's Guide to Gambas


cDir.Sort

NowthatthecDirarrayissorted,wewillloopthroughthearrayusingthe FOREACHstatementwhichisusedspecificallyforenumeratedobjectsinarrays orcollections.


FOREACHsFileINcDir

ForeverystringinthecDir array,wewillfilltheworkstring sName with thenameofthefile.However,wehavetoremovethetagfirst.Wewillusethe Mid$builtinstringfunctiontotakeallthelettersofthestringafterthefirst(our tag)startingatposition2inthestring:


sName=Mid$(sFile,2)

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

WealsowanttosettheIconView .EditpropertytoTRUEsotheusercan renameitems:


ivwExplorer.Item.Editable=TRUE NEXT'exittheFOREACHLoop

Thestatementsbelowwerecommentedoutbutappeartohavebeenused toalterthesortorderofthe IconViewcontrol. Wewillsimplyskipoverthese commentsandgototheFINALLYstatement:


'ivwExplorer.Sorted=FALSE 'ivwExplorer.Ascending=TRUE 'ivwExplorer.Sorted=TRUE FINALLY'thisisthelastinstructiontoexecuteinthesubroutine
154

A Beginner's Guide to Gambas ThelastthingweneedtodoissettheApplication.busyflagbacktonormalstate:


DECApplication.busy

Ifanerroroccurs,wewillcatchitwiththecatchclausebelow:
CATCH

Ifanyerroroccurs,itshouldpopupaMessageBoxwiththeerrortextdisplayed:
Message.Error(Error.Text) END'ofourRefreshExplorerroutine

ThissubroutineiscallediftheFExplorerformisresizedgeneratingaresize event.ItwillmoveourIconViewcontroltothetopleftcornerandadjustwidth andheighttoaccommodatethenewsizeofthewindow:


PUBLICSUBForm_Resize() ivwExplorer.Move(0,0,ME.ClientW,ME.ClientH) END

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()

Asalways,wemustdeclareourlocalvariables.WedeclaresNewPathasa stringtoholdthefilepathforthetargetpaththeuserclicked(eitheranewfolder ortherootfolder).Also,wedeclareanewformtoshowthedestinationcontents, hForminaseparatewindowifthecontrolkeyispressedwhenthedestinationis


155

A Beginner's Guide to Gambas selected.


DIMsNewPathASString DIMhFormASForm

Thisifchecklooksatthetagweputonthestringtoseeifthedestinationis adirectoryortherootlevelofthesystem. Ifweareattherootlevel,thenwe simplyreturn.Otherwise,thecodewillassignthecatenatedvaluesof$sPathand thevalueheldbytheLAST.Current.KeyoftheIconViewcontrol.Thisisobtained withtheMid$callstartingatposition2(tobypassourtagcharacter).


IFLAST.Current.Key="D.."THEN IF$sPath="/"THENRETURN sNewPath=File.Dir($sPath) ELSE sNewPath=$sPath&/Mid$(LAST.Current.Key,2) ENDIF

Wecheckthenewlyassignedstringvaluedatatypetoensureitis,infact, adirectoryand,ifitis,wewillsubsequentlychecktoseeiftheuserhelddown thecontrolkey. Remember,holdingdownthecontrolkeyinourprogramwill activateanewwindow,whichiswhywedeclaredthelocalhFormvariable.


IFIsDir(sNewPath)THEN

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

A Beginner's Guide to Gambas


END

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

Thenextsubroutineisexecutedwhentheusersingleclicksonanitemin theexplorerandoptstorenametheitem.Asitwasoriginallywritten,itdoesnot checktoseeiftherenameactuallychangedtheitem. Forexample,iftheuser pressedESC,theitemwouldreverttoitsoriginalname.


PUBLICSUBivwExplorer_Rename() Message("'"&Mid$(LAST.Item.Key,2)& "'hasbeenrenamedto'"&LAST.Item.Text&"'") END

157

A Beginner's Guide to Gambas Wecanremedythisoversightbysimplychangingthecodetoreadlikethis:


PUBLICSUBivwExplorer_Rename() IFMid$(LAST.Item.Key,2)<>Last.Item.TextTHEN Message("'"&Mid$(LAST.Item.Key,2)& "'hasbeenrenamedto'"&LAST.Item.Text&"'") ELSE Message('&Mid$(LAST.Item.Key,2)&'wasleftunchanged.') ENDIF END

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)

Theabovecodecreatesanew ListViewcontrol thatactslikeareadonly array.Let'screateaprogramthatwillimplementtheListViewcontrol.Createa newprojectnamedListViewthatisagraphicaluserinterfacetypeproject.When theIDEappearsafteryougothroughtheprojectwizard,createsimpleformthat lookslikethis:

158

A Beginner's Guide to Gambas

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

Whentheprogrambeginsandtheformisfirstdisplayed onscreen,the routineaboveisexecuted.Wecreatetwolocalvariablesforouriconsthatwillbe usedinthelistandloadthemintomemory.Next,weaddadefaultkeyanditem tothelistusingtheListView1.Addmethod,specifyingthepicSquareicontobe associatedwiththisitem.Don'tworryabouttheiconsfornowwewillcreate themlast.Next,weneedtocreateaneventtorefreshthelistanytimeanitemis addedoritisclickedonbytheuser.


PUBLICSUBListView1_Click() ListView1.MoveCurrent ListView1.Item.Selected=TRUE TextLabel1.Text=ListView1.Item.Text&sStatus END
159

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

A Beginner's Guide to Gambas


ListView1.Item.EnsureVisible ENDIF END

TheButton2_Clicksubroutineiscalledwhenevertheuserdecidestodelete thecurrentlyselecteditemintheListViewcontrol.
PUBLICSUBButton2_Click()

Thisnextlineofcodegetsoutcursorlineduptothecurrentselection.The MoveCurrentmethodmovestheinternalcursortothecurrentitem.Itreturnsa TRUEvalueifthereisnocurrentitem,inwhichcasewewillsimplyreturnas thereisnothingtodelete:


IFListView1.MoveCurrent()THENRETURN

Ifwereachedthispoint,wehavemovedthecursortoandneedtoremove thecurrentcursoritem:
ListView1.Remove(ListView1.Item.Text)

CleanupourTextLabel1.Textdisplaywiththiscall:
TextLabel1.Text=""

Now,weneedtoupdatethecursorpositiontothenewcurrentitem(since wearenowpointedatadeleteditem). Butfirst,weneedtocheckthe.Count propertytoseeifwehavejustdeletedthelastiteminthelist. Ifthecountis greaterthanzero,thenwehaveitemsleftinthelist.Otherwise,theIFstatement willnotbetrueandthecodewillbebypassed:


IFListView1.Count>0THEN ListView1.MoveCurrent ListView1.Item.Selected=TRUE'Selectsthecurrentitem sStatus=selected. ListView1_Click'thiswillforceanupdate ENDIF END

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

IftheuserdoubleclickstheirmouseonanitemintheListViewcontrol,it willraisethe Activateevent,indicatingtheuserhaspickedthisitemforsome actiontooccur.Inthiscase,wewillsimplyupdatetheTextLabel1.Textproperty withthetextoftheitemselected,appendedwiththewordactivated,andrefresh theListViewcontrolbycallingourListView1_Clicksubroutine.


PUBLICSUBListView1_Activate() TextLabel1.Text=ListView1.Item.Text&activated. sStatus=activated. ListView1_Click END

IftheuserclickstheirmouseontheButton3(Quit)button,thisroutineis called.Wewanttoexitcleanlysoweinvoketheclosemethodfortheformusing theME.Closecall.


PUBLICSUBButton3_Click() ME.Close END

UsingtheGambasIconEditTool
Atthispoint,allthecodeiscreatedforourListViewexampleprogram.We stillneedtocreatethecircle.pngandsquare.pngicons.WewillusetheGambas IconEditor todothat. Tobringuptheiconeditor,wewillgototheProject WindowintheIDE.IntheProjectTreeView,findtheDatafolderandrightclick yourmouse.PicktheNewitemandtheImagesubMenuitem.Youwillseethis dialogpopup:

162

A Beginner's Guide to Gambas

Figure56CreatinganewIconimageinGambas.

SimplytypesquareintheNamefieldandclickok.Now,theiconeditor appears and you can create an icon. Use the rectangle option from the Icon EditorToolBoxandcreateabluesquareandsaveitwiththediskshapedicon.

Figure57Oursquareicon image. Figure58Icon EditorToolBox.

Figure59Ourcircleicon image.

Repeatthisprocess,creatinganothericonnamedcircle.pngandsavethat too.Thatisit!Yourprogramisreadytorun.TryitoutandseehowtheListView controlworks.

The TreeView Control


TheTreeViewcontrolworksalmostidenticallytotheListViewcontrol.The chiefdifferenceisthattheTreeViewsupportsnestedchildrenandallowsyouto traversefromaninner(child)leveloutwardtotheparentofthechild,alltheway
163

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

A Beginner's Guide to Gambas Next,doubleclickontheTreeViewExampleformandbringuptheform. Doubleclickontheformtoopenupthecodeeditwindowandyouwillseethe followinglisting,whichwewilldissectlinebylinetounderstandhowitworks:


'Gambasclassfile PUBLICintEventNumberASInteger

TheglobalvariableintEventNumber isusedtotrackthenumberofevents thatoccurforoureventstack.Eachtimeweprocessanevent,wewillincrement thisvariable.WedeclaretwolocalPicturevariables,picMaleandpicFemaleand loadthemintomemoryfortheprogrambyusingthePicture.Loadmethod.


PUBLICSUBForm_Open() DIMpicMaleASNEWPicture DIMpicFemaleASNEWPicture picFemale.Load("Female.png") picMale.Load("Male.png") 'ThiswillpopulateourTreeViewwithourstartingentries 'Note:I'llkeeptheentriestextanditskeythesametokeep 'itsimple

Next,wewilladdthestartingvaluesofourTreeViewcontrol.Wewilladd fouritemstothecontrol.Eachitemkeywillbethesameastheitemname.The itemsTedandSallywillbechildrenofitemBill,whileitemFrankwillbeachild ofSally.


TreeView1.Add("Bill","Bill",picMale) TreeView1.Add("Ted","Ted",picMale,"Bill") TreeView1.Add("Sally","Sally",picFemale,"Bill") TreeView1.Add("Frank","Frank",picMale,"Sally")

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

A Beginner's Guide to Gambas


IFRadioButton1.ValueTHEN picToUse.Load("Male.png") ELSE picToUse.Load("Female.png") ENDIF 'Getstheparentitem:thecurrentitem,ornothingistheTreeView 'isvoid IFNOTTreeView1.MoveCurrent()THEN sParent=TreeView1.Key ENDIF

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

However,thecodeintheprogramsimplyforcesthe Addmethod totake theTextbox1.Textandputitinthelist:


TreeView1.Add(Textbox1.Text,Textbox1.Text,picToUse,sParent) TextBox1.Text=""'Thisemptiesouttextbox

Thisnextlinewillupdateourlabelandreflectthenewnumberofkids:
TreeView1_Click

ThiscalltoEnsureVisiblewillmakesurethattheitemwejustaddedtothe listisinthevisibleareaofthecontrol.Ifnecessary,thecontrolwillscrollsothe itemisvisible.


TreeView1.Item.EnsureVisible ENDIF END

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

Iftheuserclicksontheminusiconinthe TreeViewcontrol,itsetsoffa Collapseevent.Theroutinebelowiscalled.Itsimplyupdatestheeventstack,as describedpreviously,andincrementstheeventcounter,intEventNumber,byone.


PUBLICSUBTreeView1_Collapse() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Collapse"&Chr(10) &TextArea1.Text intEventNumber=intEventNumber+1 END

Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa Dbl_Clickevent.ItisbasicallythesameasanActivateevent.Theroutinebelow is called. It simply updates the event stack, as described previously, and
168

A Beginner's Guide to Gambas incrementstheeventcounter,intEventNumber,byone.


PUBLICSUBTreeView1_DblClick() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):DoubleClick"&Chr (10)&TextArea1.Text intEventNumber=intEventNumber+1 END PUBLICSUBTreeView1_Select() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Select"&Chr(10)& TextArea1.Text intEventNumber=intEventNumber+1 END

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

Iftheuserclicksontheplusiconinthe TreeViewcontrol,itsetsoffan Expandevent.Theroutinebelowiscalled.Itsimplyupdatestheeventstack,as describedpreviously,andincrementstheeventcounter,intEventNumber,byone.


PUBLICSUBTreeView1_Expand() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Expand"&Chr(10)& TextArea1.Text intEventNumber=intEventNumber+1 END PUBLICSUBButton3_Click() TextArea1.Text="" 'IntEventNumber=0 END

169

A Beginner's Guide to Gambas TheHelp | Aboutmenuitemgeneratesaclickeventthatcallsthisnext subroutine.Itsimplygivescredittotheauthorofthisexample,C.Packard.


PUBLICSUBAbout_Click() Message.Info("TreeViewexamplebyC.Packard."&Chr(10)&"Aug2004") END

Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa Activateevent.ItisbasicallythesameasaDblClickevent.Theroutinebelowis called.Itsimplyupdatestheeventstack,asdescribedpreviously,andincrements theeventcounter,intEventNumber,byone.


PUBLICSUBTreeView1_Activate() 'Thisjustupdatesoureventstack TextArea1.Text="Event("&intEventNumber&"):Activate"&Chr(10) &TextArea1.Text intEventNumber=intEventNumber+1 END

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

A Beginner's Guide to Gambas

TheGridViewControl
TheGridViewcontrol,likealltheothercontrolsintheToolBox,inheritsits attributesfromtheControlclass. GridViewimplementsacontrolthatdisplays data in a grid. This class is creatable. Standard Gambas language syntax for GridViewis:
DIMhGridViewASGridView hGridView=NEWGridView(ParentASContainer)

ThecodeabovewillcreateanewGridView.Thisclassactslikeareadonly array. Toretrievethecontentsofacellinthegrid,usethiscodetodeclarea GridCellvariablethatcanreadtheGridViewarray(theGridCellisavirtualclass):


DIMhGridViewASGridView DIMhGridCellAS.GridCell hGridCell=hGridView[RowASInteger,ColumnASInteger]

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

Whentheprogramstarts,ifaconstructorexists,itisexecutedfirst. Our constructorwillloadourthreeiconsandpopulatethegrid. First,declarethree localvariablesforthepictures,hPic1,hPic2,andhPic3,asshownbelow:


PUBLICSUB_new() DIMhPic1ASPicture DIMhPic2ASPicture DIMhPic3ASPicture

Now,wemustinstantiatethepicturevariablesandloadthepictures.
hPic1=NEWPicture hPic1.Load("GridPic.png") hPic2=NEWPicture hPic2.Load("GridPic2.png") hPic3=NEWPicture hPic3.Load("GridPic1.png")

Thenextthingweneedtodoisdefinethedimensionsofthegrid. Our
172

A Beginner's Guide to Gambas gridwillhavethreecolumnsandfourrows,sowesettheColumnsandRows propertiesusingtheirvirtualclassgridcolumnandgridrowproperty,counttoset therowsandcolumnsasshownbelow:


GridView1.Columns.Count=3 GridView1.Rows.Count=4

Wecanalsodefinethewidthandheightdimensionsofthegridcolumns androws.Bearinmindthatitispossibletosetdifferentheightvaluesforevery rowanddifferentwidthvaluesforeverycolumn. WewillsetthetheWandH propertiesforourrowsandcolumnsasshownbelow:


GridView1.Columns.Width=72 GridView1.Rows.Height=36

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

A Beginner's Guide to Gambas Theconstructoriscomplete.Now,doubleclickontheQuitButtontoget theButton1_Clickeventsubroutine,wherewewilladdourMe.Closecalltoshut downtheprogram:


PUBLICSUBButton1_Click() ME.Close END

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

Ourprogramiscomplete. Runitandseehowitworks. Afteryouare satisfiedthatitworksasadvertised,closeitdownandnextlet'slearnaboutthe ColumnViewcontrolnext.

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

Theconstructormethodiswherealltheworktopopulatethecontrolis done.Weneedtodeclarethreelocalintegervariables,iwidthtoholdthevalueof thecalculatedcolumnwidth,irowcounterandicolcounter,whichareusedforour loopstructures.


PUBLICSUB_new() 'declareourlocalvars DIMiwidthASInteger DIMirowcounterASInteger DIMicolcounterASInteger 'setthenumberofcolumnsto3 ColumnView1.Columns.Count=3 'calculatethecolumnwidthbasedonthenumberofcolumnsset iwidth=ColumnView1.Width/ColumnView1.Columns.Count 'forthefirstcolumn,setthecolumnwidthandaddacolumntitle ColumnView1.Columns[0].Width=iwidth ColumnView1.Columns[0].Text="FirstCol" 'forthesecondcolumn,setthecolumnwidthandaddacolumntitle ColumnView1.Columns[1].Width=iwidth ColumnView1.Columns[1].Text="SecondCol" 'forthethirdcolumn,setthecolumnwidthandaddacolumntitle ColumnView1.Columns[2].Width=iwidth ColumnView1.Columns[2].Text="ThirdCol"

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

A Beginner's Guide to Gambas


ColumnView1.Add(irowcounter,icolcounter)'startouter(row)loop FORicolcounter=0TOColumnView1.Columns.Count1 'addtexttothe[row][col]item ColumnView1[irowcounter][icolcounter]="Col:"&icolcounter&" Row:"&irowcounter NEXT'column NEXT'row END'ourconstructor

TheQuitButtonhereworksjustlikeinthepreviousexample.Togetthe Button1_Clickeventsubroutine,doubleclickandaddtheMe.Closecalltoshut downtheprogram:


PUBLICSUBButton1_Click() ME.Close END

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)

Let'screateasimpleprogramthatwilldemonstrateeachofthese layout controlsandshowhowtheycanbeusedinanapplication.Forthisapplication, startGambasandcreateagraphicaluserinterfaceprogram.NameitLayoutsand createastartupclassform,Form1.Forthisapplication,wewillneedtousesome icons.MostLinuxbaseddistributionshaveiconfilesstoredinthefoldernamed: file:/usr/share/icons/defaultkde/32x32/actions Yoursystemmaybedifferent.Regardlessofwhereyoufindthem,pickoutseven


177

A Beginner's Guide to Gambas iconsandcopythemtotheLayoutfolder. Forourpurposes,anysevenwilldo butifyoucanfindundo,redo,help,configure,colorize,printer,andexittype iconsitwillbeeasier.HerearetheiconsIchosetouseforthisproject:

Figure63Layoutprojecticons.

Ourprogramisquitesimple.WearegoingtocreateanHBox,aVBox,an HPanel,andaVPanelandputsomesimplecontrolsineachcontainer. Wewill simplyupdateatextlabeltoshowwhensomethinghasbeenclicked.Hereishow ourformwilllookindesignmode:

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

A Beginner's Guide to Gambas needtodothisforeachoftheseveniconsandaddcodeasfollows:


'Gambasclassfile PUBLICSUBToolButton1_Click() TextLabel1.Text="VertUndoclicked." END PUBLICSUBToolButton2_Click() TextLabel1.Text="VertRedoclicked." END PUBLICSUBToolButton3_Click() TextLabel1.Text="VertHelpclicked." END PUBLICSUBToolButton4_Click() TextLabel1.Text="HorizConfigureBtnclicked." END PUBLICSUBToolButton5_Click() TextLabel1.Text="HorizColorButtonclicked." END PUBLICSUBToolButton6_Click() TextLabel1.Text="HorizPrinterBtnclicked." END PUBLICSUBToolButton7_Click() TextLabel1.Text="HorizExitButtonclicked." WAIT0.5 ME.Close END

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

A Beginner's Guide to Gambas


END PUBLICSUBRadioButton3_Click() TextLabel1.Text="RadioButton3clicked." END PUBLICSUBRadioButton4_Click() TextLabel1.Text="RadioButton4clicked." END PUBLICSUBButton1_Click() TextLabel1.Text="Button1clicked." END PUBLICSUBButton2_Click() TextLabel1.Text="Button2clicked." END PUBLICSUBButton3_Click() TextLabel1.Text="Button3clicked." END

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

A Beginner's Guide to Gambas


TextLabel1.Text="Checkbox3checked." ELSE TextLabel1.Text="Checkbox3unchecked." ENDIF END

Nowsaveyourworkand executethissimpleprogram. Youshouldsee somethingsimilartothis:

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

A Beginner's Guide to Gambas


hTabStrip=NEWTabStrip(ParentASContainer) DIMhTabAS.Tab hTab=hTabStrip[IndexASInteger]

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas HereiswhatwewilldoforTab1:

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

A Beginner's Guide to Gambas

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

Now,wearegoingtoaddaComboBoxtoTab3. Nothingfancy,justa simpleComboBoxwiththreeitems.SelecttheComboBoxcontrolandplaceiton thetabasshownbelow:

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

Forourlasttab,Tab4,wearegoingtosimplydisplaythecurrenttime. ThiswillrequireuseoftheTimercontrol.WearegoingtoneedtoaddaLabel andaTimercontroltoTab4,asshownbelow:

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

Toactuallyusethetimer,weneedtosetanEvent.Wedothisbysingle clickingontheTimercontrolthenrightclickingthemouse. Choose Events and selecttheTimerevent.YouwillbeplacedintheCodeEditorandyouneedtoadd asinglelineofcode:


PUBLICSUBTimer1_Timer() Label1.Text=Str$(Now)

186

A Beginner's Guide to Gambas


END

ThislineofcodewillupdatetheLabel1.Textfieldeverysecondthatthe Tab4isdisplayed.Ineffect,youhavecreatedaclockontheTabbydoingthis. Thatisallthereistoit.RuntheprogramandseehowTabStripswork.Next,we movetoFileoperations.

187

A Beginner's Guide to Gambas

Chapter 9 Working with Files


We are going to introduce you to Gambas file management and input/output(filei/o)operationsinthischapter.Gambashasafullfeaturedset offunctionsandsubroutinestosupportnearlyanykindoffilei/ooperationyou mayneedtoimplementinyourprograms.

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

A Beginner's Guide to Gambas


True

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.

The special genericcharacter \ prevents the character following itfrom beinginterpretedasageneric.StandardGambaslanguagesyntaxis:


Filenamearray=Dir(Directory[,Filepattern])

Hereisanexamplecodesegmenttohelpyou
'Printadirectory SUBPrintDirectory(DirectoryASString) DIMsFileASString FOREACHsFileINDir(Directory,"*.*") PRINTsFile NEXT END
189

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


True 4K

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

Ifthe APPENDkeyword isspecified,thenthefilepointerismovedtothe endoffilejustafterthefileisopened.IftheDIRECTkeywordisspecified,the inputoutputarenotbuffered. Ifthe WATCHkeyword isspecified,thefileis watchedbytheinterpreterusingthefollowingconditionalguidelines:


Ifatleastonebytecanbereadfromthefile,theeventhandlerFile_Read()iscalled. Ifatleastonebytecanbewrittentothefile,theeventhandlerFile_Write()iscalled.

IftheBIGorLITTLEkeywordisspecified,allsubsequentREADandWRITE operationsonthisfilewill use bigEndian or littleEndian data representation. Variable receives the object that represents the opened stream. CLOSE is the reciprocalfunctionandsimplyclosesanopenedfile.SyntaxforusingCLOSEis:
192

A Beginner's Guide to Gambas


CLOSE#File

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

A Beginner's Guide to Gambas


DIMlineCtrASInteger OPEN"TheRaven.txt"FORREADAS#hFile WHILENOTEof(hFile) LINEINPUT#hFile,sInputLine PRINTStr(lineCtr)&Chr(9)&sInputLine INClineCtr WEND CLOSE#hFile END

NOTE:Youshould not usetheLINEINPUTcalltoreaddatafromabinaryfile becauseitwilllosethelinefeedcharacters. Forreadingdatafrombinaryfiles, youmustusetheREADcommandinstead:


READ#hFile,OneLine,256

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

A Beginner's Guide to Gambas languagesyntaxforstandardinputstreams:


WRITEExpression[,Length]

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

A Beginner's Guide to Gambas


COPYSource_pathTODestination_path

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

InordertodemonstratemostofthefileandI/Ofunctionsdescribedinthis chapter,wearegoingtocreateanapplicationthatwillactasasimpletexteditor. Theintenthereisnottocreateafullblowntexteditor,buttoshowyouhowto usethesefunctionsinthecontextofanapplication.Theapplicationwewillbuild inthischapterisalittlemorecomplexthanwhatwehaveseensofarinthatwe willbecreatingtwoforms,aninputfile,ahelpfile,andusingquiteafewsystem iconswhichwillbecopiedfromtheLinuxOSdistribution'ssystemIconfolder(s). Hereiswhatourapplicationwilllooklikeatruntime:

Figure72TheFileOpsprogramatruntime.
196

A Beginner's Guide to Gambas Inthisprogram,wewillcreateamainmenu,atextareatodisplayandedit textwith,andwewillcreatestatuselementsatthebottomofthedisplay.Wewill alsointroductuseoftheTimercontrol(shownastheclockinthepicturebelow). Thisform,namedForm1.form,willlooklikethisindesignmode:

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:

FileNew Edit SelectAll Edit Configure

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

Caption "New" "Open..." "Save..." "Saveas..." "Print" "Exit"

IconProperty(filename) Picture["filenew.png"] Picture["fileopen.png"] Picture["filesave.png"] Picture["filesaveas.png"] Picture["fileprint.png"] Picture["exit.png"]

Caption "SelectAll" "Undo" "Redo" "Cut" "Copy" "Paste" "Preferences"

IconProperty(filename) Picture["selectall.png"] Picture["undo.png"] Picture["redo.png"] Picture["editcut.png"] Picture["editcopy.png"] Picture["editpaste.png"] Picture["configure.png"]

Caption "Colors" "Font"

IconProperty(filename) Picture["colorize.png"] Picture["charset.png"]

"Contents" "About"

Picture["contents.png"] Picture["buildingblocks.png"]

198

A Beginner's Guide to Gambas HereisthecodeforwewilluseforForm1.Wewillgothruthislinebyline soeverythingisfullyexplained. Westartourprogrambydeclaringtwoclass globalvariables,sCurrentFileNameandsCurrentFileLength.


'Gambasclassfile sCurrentFileNameASString sCurrentFileLengthASInteger

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

WewillassignourfilenametothesCurrentFileNamestringvariableand checktoseeifthefileexistsintheprojectfolder.Ifitexists,thentheprogram willopenthefileandgettheinitialfilelength.Wewilldisplaythefilenameand sizeintheForm1.Captionproperty.Whileitisnotcustomarytodisplaythefile sizelikethis,itisdoneheresimplytodemonstratetheuseoftheLoffunction.


sCurrentFileName="TheRaven.txt" IFExist(sCurrentFileName)THEN OPENsCurrentFileNameFORREADAShFileIn sCurrentFileLength=Lof(hFileIn)'toshowhowtogetfilesize Form1.Caption=""&sCurrentFileName&",size:"&Str (sCurrentFileLength)&"bytes."

Now,wewillenteraloopstructuretoreadallthelinesofthetextfileinto ourTextArea1.Textproperty.Wewillcontinuetoloopuntilwehavereachedthe endofthefile. Aswereadeachlineintomemoryandassignittothevariable sInputLine,wemustremembertoaddtheCRLF(aCarriageReturn(Chr(13)and aLineFeed(Chr(10)) totheendofthelinesoitwilldisplayproperlyinthe control.


WHILENOTEof(hFileIn) LINEINPUT#hFileIn,sInputLine TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine WEND
199

A Beginner's Guide to Gambas Assoonasweexittheloop,meaningwehavereachedtheendofthefile, wewillclosethefile.


CLOSEhFileIn

Ifourchecktoseeifthefileexistsfailed,wewouldenterthisELSEblock ofcodeanddisplayamessageindicatingthatthefiledidnotexist.Next,wecall ourFileOpenItem_Click()subroutinetohavetheuserpickafiletoopen.


ELSE Message.Info("File"&sCurrentFileName&"doesnotexist.") FileOpenItem_Click()'forceafiletobepickedifnodefault. ENDIF END

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

A Beginner's Guide to Gambas


PUBLICSUBFileOpenItem_Click()

Thisroutinerequirestwolocalvariables.hFileInisthehandletotheFILEobject wewillopenandsInputLineisastringvariablethatwewillusetoreadthetext fileintoourTextArea1.Textproperty.


DIMhFileInASFile DIMsInputLineASString

Justbeforethecalltothestandarddialog,wecansetthewindowcaption (ortitle)usingtheDialog.Titleproperty.Wewillalsosetafilterforthedialogto onlylookforfileswitha.txtextension. Asalastresort,wewilllettheuser choosetoviewalltypesoffilesbyselectingthefilter*.*fromwithinthedialog.


Dialog.Title="Chooseatextfile" Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]

WhenthecalltoDialog.OpenFileismade,rememberthatitwillreturna TRUEvalueiftheuserclicksontheCancelbutton,otherwise,FALSEisreturned. WewillcheckforaTRUEvalueandreturnifthatiswhatweget.Otherwise,it meanstheuserselectedafileandwewillprocessit.


IFDialog.OpenFile()THEN RETURN ELSE

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

A Beginner's Guide to Gambas


WHILENOTEof(hFileIn) LINEINPUT#hFileIn,sInputLine TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine WEND CLOSEhFileIn ENDIF END

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

A Beginner's Guide to Gambas


sTmpName=Application.Path&/sCurrentFileName

Justaswedidpreviously,wewillsetthetitleandfilterproperties,then callthestandardfiledialog.
Dialog.Title="Savetextfileas..." Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]

IfthestandarddialogcallreturnsTRUE,theuserhascancelledoutofthe routineandwewillsimplyreturntothecallingprocess(i.e.,ourstandardevent loop).


IFDialog.SaveFile()THEN RETURN

Ifthefilenamesarethesame,wewillpopuptheMessageBoxandreturn:
ELSEIFsTmpName=Dialog.PathTHEN Message.Info("Filenotsaved:namesameascurrentfile.","OK") RETURN

Otherwise,wesettheglobalvariabletothefilenamereturnedfromthe standardfiledialogandcalltheSavemethod,passingthefilenameandourtext asparameters. Weupdatethecaptionofthewindowasthelastthingwedo beforereturningtothecallingprocess.


ELSE sCurrentFileName=Dialog.Path File.Save(sCurrentFileName,TextArea1.Text) Form1.Caption=sCurrentFileName ENDIF END

PrintinganytypeofitemisprettyeasyinGambas.OurFile|Printmenu itemwillinvokethissubroutinewhenclicked.Wewilldeclareourlocalvariables first:


PUBLICSUBFilePrintItem_Click() 'integervariablestoholdourmarginvalues DIMiLeftMarginASInteger DIMiTopMarginASInteger DIMiRightMarginASInteger DIMiBottomMarginASInteger

203

A Beginner's Guide to Gambas


'stringvariableswewilluse DIMarsTxtToPrintASString[] DIMiTxtPosYASInteger DIMsTxtLineASString DIMstrMsgASString 'integervariablesourprogramusestocalculatepagedimensions DIMiPrinterAreaWidthASInteger DIMiPrinterAreaHeightASInteger

We MUST call the Printer.Setup() subroutine before we actually try to print something.ItismandatorytocallthisfunctioninGambas.
IFPrinter.Setup()THENRETURN

Thenextcallensuresthedefaultpapersizeissetto8.5by11(Letter).If youarenotintheUnitedStates,itshouldprobablybesettoA4asthatisthe standardusedinmostplacesoutsidetheU.S.TheGambasPrinter.Setupdialog defaultstoA4settingseverytimeyoucallit,soifyouareusingaprinterthat onlyusesLettersizepaper,overridingthispropertyistheeasiestwaytohandle thatsituation.


'overridetheprinter.setupdialogsoyoudon'thave 'tosetthiseverysingletimeyouprintsomething Printer.Size="Letter"'orA4,orwhateveryouuse 'olderprintersdonotseemtobesettoDPIslowerthan600inGB 'sowewillsetitmanuallyforanolderHPLaserjetIIIprinter 'ifyourprinterisnewer,youcancommentthislineout Printer.Resolution=300'myHPLJIIIsettings

Fora300dpiprinter,avalueof300wouldequalaoneinchmargin.Now, wesetthemarginvaluesbyusingthePrinterproperties(ortheonesweoverrode above)returnedfromthePrinter.Setupcall.


'setleftmargintooneinch,equaltotheDPIoftheprinter iLeftMargin=Printer.Resolution 'settopmargintooneinch,equaltotheDPIoftheprinter iTopMargin=Printer.Resolution 'setrightmargintooneinch,equaltotheDPIoftheprinter iRightMargin=Printer.Resolution 'settopmargintooneinch,equaltotheDPIoftheprinter iBottomMargin=Printer.Resolution

204

A Beginner's Guide to Gambas


'DefinethePrintableareawidth iPrinterAreaWidth=Printer.WidthiLeftMarginiRightMargin 'DefinethePrintableareaheight iPrinterAreaHeight=Printer.HeightiTopMarginiBottomMargin

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")

Weare ready to print. To do so,you MUST firstcalltheBeginmethod and specifythatyouwantthePrinterobjecttobetheoutputdeviceusedbytheDraw method:


Draw.Begin(Printer)'InitializesthedrawroutineforPrinter

Inourcodebelow,wehavecalledtheDraw.Rectfunctiontodrawaborderatone inchmarginsaroundourpage.
'makeaborderaroundthepage Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin) 'nowwewillloopthrougheachlineinthearrayandprintit FOREACHsTxtLineINarsTxtToPrint
205

A Beginner's Guide to Gambas


'incrementthevertical(Y)linepositionforeachlineprinted iTxtPosY=iTxtPosY+Draw.TextHeight(sTxtLine) 'testthelineposition...ifis>thebottomoftheprinter 'areathenweneedtoresetittozeroandperformanewpage IFiTxtPosY>=(iPrinterAreaHeight)THEN iTxtPosY=0'reinittheCurrentTextPositionY Printer.NewPage 'makeaborderaroundthenewpage Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin) ENDIF'ourtesttoseeiflinefallspastbottommargin

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

A Beginner's Guide to Gambas


aString="prh\""&sCurrentFileName&"\""&"o10<\""& sCurrentFileName&"\"|lpr" message.Info(aString,"Ok") SHELLaString END

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

A Beginner's Guide to Gambas Thecodeabovecouldalsohavebeenwritteninamoresimplifiedmanner withoutusingtheIntegervariableiLength.Itcouldhavebeenreducedtoasingle line,asshownbelow:


PUBLICSUBEditSelectAllItem_Click() TextArea1.Selection(0,TextArea1.Length) END

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

A Beginner's Guide to Gambas


Form2.Show END

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

TheconstructorwillcalloursubroutineReadPrefs,passingthenameofthe configurationfileasaparameter.FileOps.confisthenamewewilluseforholding ourapplication'sconfigdata. Next,wepopulate theTextLabel1.Textproperty withthecurrentdefaultdirectory,whichdefaultstowheretheapplicationresides ondisk.


PUBLICSUB_new() ReadPrefs("FileOps.conf") TextLabel1.Text=Application.Path&"isthedefaultdirectory." 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

Asyoucanseefromabove,alocalstringvariableMyPathisdeclaredand populatedbyconcatenatingthecurrentapplicationpathwiththeconfiguration filenameFileOps.conf.Next,wecallourWritePrefssubroutineandpassthevalue ofMyPathasaparameter.Thatpathwillbestoredinthefileandcanbereadby anyotherclassthatneedstofindoutthisinformation. HereistheReadPrefs() subroutineforaccomplishingthistask:


PUBLICSUBReadPrefs(filenameASString) 'declareourlocalvariables DIMsInputLineASString DIMhFileInASFile 'seeifthefilealreadyexists,ifsoopenit. IFExist(filename)THEN OPENfilenameFORREADAS#hFileIn 'readoursinglelineofdata 'ifthereweremorelines,wecouldsetupaWHILENOTEofLOOP LINEINPUT#hFileIn,sInputLine 'updatethedisplaydata TextLabel1.Text=sInputLine 'closethefile CLOSE#hFileIn ELSE 'therewasno.conffiletoopen Message.Info("Nopreferences.conffilepresent.","OK") ENDIF END

211

A Beginner's Guide to Gambas Thereciprocalroutine,WritePrefs()isshownbelow:


PUBLICSUBWritePrefs(filenameASString) 'declareourlocalvariables DIMMyPathASString DIMhFileOutASFile 'noteweareusingtheDialog.Pathvalue,notApplication.Path MyPath=Dialog.Path&/filename 'ifthereisalreadyaconfigfile,openitforwrite 'ifnot,openforcreateandwrite IFExist(MyPath)THEN OPENMyPathFORWRITEAS#hFileOut ELSE OPENMyPathFORWRITECREATEAS#hFileOut ENDIF 'printourdatatothefile PRINT#hFileOut,MyPath 'closethefile CLOSE#hFileOut END

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

A Beginner's Guide to Gambas


'setdialogcaptiontoremindtheuserweareselectingFOREGROUND Dialog.Title="SelectTextColor" 'callthestandarddialogroutinetoselectcolor Dialog.SelectColor 'updateourTextArea1.ForeColorwiththevalueselected. TextArea1.ForeColor=Dialog.Color END

Selectingthefontanditsattributesforourprogramisjustassimpleasit wastochoosecolors.Basically,wewillsetthedialogcaption,callthestandard Dialog.SelectFontroutine,andupdateourTextArea1.Fontproperty,likethis:


PUBLICSUBFormatFontItem_Click() Dialog.Title="Selectfont" Dialog.SelectFont TextArea1.Font=Dialog.Font END

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

Theshellcallabovepointstoafilenamed Help.html. Forpurposesof


213

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

A Beginner's Guide to Gambas

Chapter 10 Math Operations


Gambasperformsmathematicaloperationswithalibraryof intrinsicand derivedfunctions.AccordingtotheonlineencyclopediaWikipedia15,anintrinsic function is a function available in a given language whose implementation is handled specially by the compiler. Typically, it substitutes a sequence of automaticallygenerated instructions for the original function call, similar to an inlinefunction.Compilersthatimplementintrinsicfunctionsgenerallyenablethem only when the user has requested optimization, falling back to a default implementationprovidedbythelanguageruntimeenvironmentotherwise. Intrinsicfunctionsarebuiltintothecompilerofaprogramminglanguage, usuallytotakeadvantageofspecificCPUfeaturesthatareinefficienttohandle via external functions. The compiler's optimizer and code generator fully integrate intrinsic functions, which can result in some surprising performance speedups in calculation. Derived functions, on the other hand, are built in Gambasbyusingknownmathematicalformulastoapplyspecificalgorithmsthat implement intrinsic functions. A table of derived functions and their correspondingalgorithmscanbefoundattheendofthischapter.

PrecedenceofOperations
WhenyouusevariousoperatorsinanexpressioninGambas,thereisa specificprecedenceofoperationsthatGambasusestoperformtheoperation.A welldefinedprotocolisfollowed:

Allexpressionsaresimplifiedwithinparenthesesfromtheinsideoutside Allexponentialoperationsareperformed,proceedingfromlefttoright Allproductsandquotientsareperformed,proceedingfromlefttoright Allsumsanddifferencesareperformed,proceedingfromlefttoright

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


END

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

A Beginner's Guide to Gambas


STATICPUBLICSUBMain() DIMyASVariant Y=0.5 PRINTATan(Y) END

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

A Beginner's Guide to Gambas multiplydegreesby /180.Toconvertradianstodegrees,multiplyradiansby 180/ .StandardGambaslanguagesyntaxis:


Result=Cos(number)

Thenumberargumentcanbeanyvalidnumericexpressionthatexpresses anangleinradians. ThefollowingexampleusestheCosfunctiontoreturnthe cosineofanangle:


STATICPUBLICSUBMain() DIMMyAngleASFloat DIMMySecantASFloat MyAngle=1.3'Defineangleinradians. MySecant=1/Cos(MyAngle)'Calculatesecant. PRINT"Secantofangle"&MyAngle&"(inradians)is:"&MySecant END

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

A Beginner's Guide to Gambas


Cosh()ofangle1(inradians)is:1.543080634815

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

A Beginner's Guide to Gambas Theconsolerespondswith:


2.718281828459

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas follows: Logn(x)=Log(x)/Log(n) Hereisanexampletotry:


STATICPUBLICSUBMain() DIMnASFloat DIMxASFloat DIMlognASFloat n=2 x=10 logn=Log(x)/Log(n) PRINTlogn&"istheresultofLogn("&x&")" END

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

A Beginner's Guide to Gambas Examples:


STATICPUBLICSUBMain() PRINTMax(6,4,7,1,3) PRINTMax(Now,CDate("01/01/1900"),Cdate("01/01/2100")) PRINT PRINTMin(6,4,7,1,3) PRINTMin(Now,CDate("01/01/1900"),CDate("01/01/2100")) END

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

A Beginner's Guide to Gambas


PRINTRnd(Pi,Pi(2)) PRINT Randomize DOWHILEDice<>1 Dice=Int(Rnd(1,7)) 'producearandomnumberbetween1and6tosimulatethedicethrow PRINT"Youthrewa"&dice LOOP END

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

A Beginner's Guide to Gambas number+1.Ifthenumberisstrictlynegative,itreturnstheintegernumber1. Gambaslanguagesyntaxis:


Sign=Sgn(Number)

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

A Beginner's Guide to Gambas

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

Thefollowingexampleuses theSqrfunctiontocalculate thesquarerootofa number:


STATICPUBLICSUBMain() DIMMySqrASFloat
229

A Beginner's Guide to Gambas


MySqr=Sqr(4)'Returns2 PRINTMySqr&"istheresultofSqr(4)" MySqr=Sqr(23)'Returns4.795831523313 PRINTMySqr&"istheresultofSqr(23)" MySqr=Sqr(0)'Returns0 PRINTMySqr&"istheresultofSqr(0)" 'MySqr=Sqr(4)'Generatesaruntimeerror 'PRINTMySqr&"istheresultofSqr(4)" END

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

A Beginner's Guide to Gambas

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.

Gambas Derived Math Functions


Function
InverseSine InverseCosine HyperbolicSine HyperbolicCosine HyperbolicTangent InverseHyperbolicSine InverseHyperbolicCosine InverseHyperbolicTangent Logarithmtobase10

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

A Beginner's Guide to Gambas

Other Derived Math Functions


Secant Cosecant Cotangent InverseSecant InverseCosecant InverseCotangent HyperbolicSecant HyperbolicCosecant HyperbolicCotangent InverseHyperbolicSecant InverseHyperbolicCosecant InverseHyperbolicCotangent LogarithmtobaseN Sec(X)=1/Cos(X) Cosec(X)=1/Sin(X) Cotan(X)=1/Tan(X) Arcsec(X)=Atn(X/Sqr(X*X1))+Sgn((X)1)*(2*Atn(1)) Arccosec(X)=Atn(X/Sqr(X*X1))+(Sgn(X)1)*(2*Atn(1)) Arccotan(X)=Atn(X)+2*Atn(1) HSec(X)=2/(Exp(X)+Exp(X)) HCosec(X)=2/(Exp(X)Exp(X)) HCotan(X)=(Exp(X)+Exp(X))/(Exp(X)Exp(X)) HArcsec(X)=Log((Sqr(X*X+1)+1)/X) HArccosec(X)=Log((Sgn(X)*Sqr(X*X+1)+1)/X) HArccotan(X)=Log((X+1)/(X1))/2 LogN(X)=Log(X)/Log(N)

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

A Beginner's Guide to Gambas


PRINTDerived.Sec(myVal)&"issecant" PRINTDerived.CoSec(myVal)&"iscosecant" PRINTDerived.CoTan(myVal)&"iscotangent" PRINT PRINTDerived.ArcSec(myVal)&"isarcsecant" PRINTDerived.Arccosec(myVal)&"isarccosecant" PRINTDerived.Arccotan(myVal)&"isarccotangent" PRINT PRINTDerived.HSec(myVal)&"ishyperbolicsecant" PRINTDerived.HCoSec(myVal)&"ishyperboliccosecant" PRINTDerived.HCoTan(myVal)&"ishyperboliccotangent" PRINT PRINTDerived.HArcSec(myVal)&"ishyperbolicarcsecant" PRINTDerived.HArcCoSec(myVal)&"ishyperbolicarccosecant" PRINTDerived.HArcCoTan(myVal)&"ishyperbolicarccotangent" PRINT PRINTDerived.LogN(myVal,2)&"isLogNof:"&myVal&"tobase2" PRINT"ofmyVal:"&myVal WEND END

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

A Beginner's Guide to Gambas


PUBLICFUNCTIONArccosec(xASFloat)ASFloat DIMresultASFloat result=Atn(x/Sqr(x*x1))+(Sgn(x)1)*(2*Atn(1)) RETURNresult END PUBLICFUNCTIONArccotan(xASFloat)ASFloat DIMresultASFloat result=Atn(x)+(2*Atn(1)) RETURNresult END PUBLICFUNCTIONHSec(xASFloat)ASFloat DIMresultASFloat result=2.0/(Exp(x)+Exp(x)) RETURNresult END PUBLICFUNCTIONHCoSec(xASFloat)ASFloat DIMresultASFloat result=2.0/(Exp(x)Exp(x)) RETURNresult END PUBLICFUNCTIONHCoTan(xASFloat)ASFloat DIMresultASFloat result=(Exp(x)+Exp(x))/(Exp(x)Exp(x)) RETURNresult END 'thisroutinecurrentlyproducesanerrorinGambas 'ifyoutrytousetheformularesult=Log((Sqr(x*(x+1))+1)/x) 'becausetheLogfunctiononlyworkswithnonnegativenumbers 'bydesign.Thisisaworkaroundtogetyouthesameresults PUBLICFUNCTIONHArcsec(xASFloat)ASFloat DIMresultASFloat DIMTemp1ASFloat DIMTemp2ASFloat DIMTemp3ASFloat Temp1=((x*1)*(x+1))+1 Temp2=Sqr(Abs(Temp1)) Temp3=Log(Temp2) result=Temp3*1 'thiscallwillgenerateanerrorbecausethe 'Sqrfunctionwillnotworkwithnegativevalues 'result=Log((Sqr(x*(x+1))+1)/x)
234

A Beginner's Guide to Gambas


RETURNresult END PUBLICFUNCTIONHArccosec(xASFloat)ASFloat DIMresultASFloat result=Log((Sgn(x)*Sqr(x*x+1)+1)/x) RETURNresult END PUBLICFUNCTIONHArccotan(xASFloat)ASFloat DIMresultASFloat result=Log((x+1)/(x1))/2 RETURNresult END PUBLICFUNCTIONLogN(xASFloat,nASFloat)ASFloat DIMresultASFloat result=Log(x)/Log(n) RETURNresult END

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

A Beginner's Guide to Gambas thischapteranditistimetotakeabreaknow.Inthenextchapter,wearegoing tocoverthebasicconceptsofobjectoriented(OO)programmingandshowyou howpowerfulGambascanbewhenyoutakeadvantageoftheseOOfeatures.

236

A Beginner's Guide to Gambas

Chapter 11 Object-Oriented Concepts


In the field of computer science, objectoriented programming (OOP) is considered a computer programming paradigm. The general idea is that a computerprogramiscomposedofacollectionofindividualunits(calledobjects), each of which is capable of receiving messages, processing data, and sending messages to other units or objects. This differs from the traditional view of programmingwhereaprogramisseenasalistofinstructionsthatareexecutedin asequentialorderbythecomputer. Proponents of objectoriented programming have claimed the approach gives programmersmoreflexibilityandfacilitatesmakingchangestoprograms when needed. The paradigm is very popular in companies and government entitiesthatconductsoftwareengineeringanddevelopmentasamatterofcourse. Furthermore, many people believe OOP to be easier to learn for novice programmers when compared with other languages such as Java, C++, etc. OOP,theyclaim,issimplertodevelopandmaintainandthatitlendsitselftoa better understanding of complex situations and procedures than other programmingmethods. There are an almost as many critics of the OO paradigm as there are proponents.SomeofthemostcommonargumentscriticsraisearethatOObased languageslikeSmalltalk,Lisp,andothershavehadtheirprogressstalledwiththe adventofnewerlanguageslikeC++,C#,andJava.Small,interpretedlanguages likeTcl,Perl,andPythonhavedevelopedafairlylargefollowingbuttheyarenot makinganyprogressinthedevelopmentofatrueOOparadigm.Criticsalsohave saidtheobjectorientedapproachdoesnotadequatelyaddressfuturecomputing requirements.Theyfeelobjectorientedlanguageshavesacrificedsimplicitythe verythingthatmakesprogrammingapproachabletoawideraudience.Java,for example, is an extremely complex implementation of OO concepts. Others contend concepts like encapsulation and inheritance, which were originally intendedtosaveprogrammersfromthemselveswhiledevelopingsoftware,have failedbecausetheyimplementglobalproperties. Modularityisanotherwayof keepingthingslocalinscopesopeoplecanunderstandcodebetter. Thatwas whatencapsulationwassupposedtoaccomplish. Today,opensourcesoftware seemstohaveevolvedaworkableapproachtotheproblemofcodemaintenance, althoughitisnotwithoutitsownissues. Objects promised reuse, and the programming community has not seen
237

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas merelytemplatethatisusedbytheprogramatruntime. Theclassitselfisnot useddirectly.Touseaclass,youmustmakeavariabledeclarationoftheclass datatype,createacopyoftheclassfortheprogramtouse,theninstantiatethe copy.Theinstantiatedcopyiscalledanobject.Sinceaclassisarealdatatype, thedeclarationoftheobjectlookslikeanyothernormalvariabledeclaration:


object_nameASClass_name

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

A Beginner's Guide to Gambas


PUBLICStreet2ASString PUBLICCityASString PUBLICStateASString PUBLICZip5ASString PUBLICZip4ASString PUBLICAreacodeASString PUBLICPrefixASString PUBLICLast4ASString PUBLICRecordIDASInteger

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

A Beginner's Guide to Gambas


'willinstantiateitbelow DIMMyContactRecordASContact 'alocalintegervartokeeptrackofhowmanyrecordsweadded DIMRecordNumASInteger 'thisvariablewilltakethestringreadinandconvertallthefields 'thatarecommadelimitedintoanarrayusingthesplitstatement DIMarsInputFieldsASString[] 'thiscounterisusedtoloopthroughthearrayandassignvalues 'tothecontactrecords DIMcounterASInteger filename="contacts.data"'hardcodedbecauseitwillnotchange 'wewillusethecurrentdirwheretheappistobuildfullpathname fullpath=Application.Path&/filename 'now,seeifthefilealreadyexists,ifsoopenitforREAD. IFExist(fullpath)THEN OPENfullpathFORREADAS#hFileIn 'startwithrecord1 RecordNum=1 'wewillloopthrougheverylineofdatauntilwereachEndoffile WHILENOTEof(hFileIn) 'everycontactaddedtothecollectionmustbeinstantiated 'eachtimearecordisaddedtothecollection.YouCAN 'reusethesameclassvarforeachreinstantiationthough. MyContactRecord=NEWContact'hereiswhereitrenewsitself 'readthelineinfromfileandstoreinstringvarsInputLine LINEINPUT#hFileIn,sInputLine 'usedforconsoledebugging PRINT"Reading:"&sInputLine 'now,fillourarrayofstringsusingSplittoconverttheline 'ofstringdatareadintofieldsinanarray arsInputFields=Split(sInputLine,",") 'fordebugonlytoshowthatallfieldsconvertcorrectly FORcounter=0TO14 PRINT"Loading:"&arsInputFields[counter] NEXT 'now,weputthefielddataintoourlocalcontactclassvar
244

A Beginner's Guide to Gambas


'andwilladdthatcontactrecordtothecollectionofcontacts MyContactRecord.FirstName=arsInputFields[0] MyContactRecord.Initial=arsInputFields[1] MyContactRecord.LastName=arsInputFields[2] MyContactRecord.Suffix=arsInputFields[3] MyContactRecord.Street1=arsInputFields[4] MyContactRecord.Street2=arsInputFields[5] MyContactRecord.City=arsInputFields[6] MyContactRecord.State=arsInputFields[7] MyContactRecord.Zip5=arsInputFields[8] MyContactRecord.Zip4=arsInputFields[9] MyContactRecord.Areacode=arsInputFields[10] MyContactRecord.Prefix=arsInputFields[11] MyContactRecord.Last4=arsInputFields[12] MyContactRecord.RecordID=CInt(arsInputFields[13]) MyContactRecord.Deleted=CBool(arsInputFields[14]) 'fordebugoutputtotheconsole PRINT"Addingdataforrecord:"&RecordNum&""; PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName 'allrecordfieldsareassigneddata,soweaddtocollection cTheData.Add(MyContactRecord,CStr(RecordNum)) 'fordebugoutputtotheconsole PRINTcTheData[CStr(RecordNum)].LastName&"stored." 'incrementourrecordcounterandclearthesInputLinevariable INCRecordNum sInputLine="" WEND'loopformorerecords 'closethefilewhennomorerecordsexistinthefile CLOSE#hFileIn ELSE'nofilefound,putupamessagetotheuser Message.Info("Nocontacts.datafilepresent.","OK") ENDIF 'fordebugonly,wewilllistalltherecordsinthecollection PRINT"HereiswhatisstoredincTheData:" FOREACHMyContactRecordINcTheData PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName NEXT RETURNcTheData'returnthecollection(nowfilled)withdata END'ofGetData

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

A Beginner's Guide to Gambas


'usetheFOREACHconstructtodothis. FOREACHMyContactRecordINcTheData 'weconcatenateeachfieldtothelast,insertingcommas 'tobeusedasfielddelimitersforthereadoperation sInputLine=sInputLine&MyContactRecord.FirstName&"," sInputLine=sInputLine&MyContactRecord.Initial&"," sInputLine=sInputLine&MyContactRecord.LastName&"," sInputLine=sInputLine&MyContactRecord.Suffix&"," sInputLine=sInputLine&MyContactRecord.Street1&"," sInputLine=sInputLine&MyContactRecord.Street2&"," sInputLine=sInputLine&MyContactRecord.City&"," sInputLine=sInputLine&MyContactRecord.State&"," sInputLine=sInputLine&MyContactRecord.Zip5&"," sInputLine=sInputLine&MyContactRecord.Zip4&"," sInputLine=sInputLine&MyContactRecord.Areacode&"," sInputLine=sInputLine&MyContactRecord.Prefix&"," sInputLine=sInputLine&MyContactRecord.Last4&"," sInputLine=sInputLine&MyContactRecord.RecordID&"," sInputLine=sInputLine&CStr(MyContactRecord.Deleted)&"," 'fordebugonly,toshowwhatisbeingstored PRINT"Storing:"&sInputLine 'thiscallisactuallywhatputsthedataintothefile PRINT#hFileOut,sInputLine 'clearoutourstringvartobereusedinthenextiteration sInputLine="" NEXT'iterationofthelooptoenumerateobjects 'gotthemallwrittennow,soclosethefile CLOSE#hFileOut RETURN'withoutpassingavariableback,hencesubroutine END

Form1.classfile Save the Contact.class file and close it. Our contact class definition is completesonowwewillneedtocreateaformnamedForm1.Form1willserve asthemaininterfacebetweentheuserandtheprogramandit'sdata. Hereis whatourfinishedformwilllooklike:

247

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas Form1Constructor


'theconstructorroutinecalledwhenform1_open()iscalled PUBLICSUB_new() 'instantiatethecollectionthatwillholdouraddressrecords Contacts=NEWCollection 'instantiateanewcontact(record)thatisblank ContactRecord=NEWContact 'fordebugonly PRINT"CallingGetData..." 'calltheGetDatamethoddefinedinthecontactclassdefinition ContactRecord.GetData(Contacts) 'settherecordpointertothelastrecordfoundinthedataset RecordPointer=Contacts.Count 'fordebugonly PRINT"In_new(),rtnfmGetDatawith:"&RecordPointer&"records." 'thedefaultconstructorwillensureatleastonerecordexists 'iftheContactscollection'scountpropertyshows<1record. IFRecordPointer<1THEN 'addourdummydata ContactRecord.FirstName="John" ContactRecord.Initial="Q" ContactRecord.LastName="Public" ContactRecord.Suffix="II" ContactRecord.Street1="12345GambasDrive" ContactRecord.Street2="Apt101" ContactRecord.City="Dancer" ContactRecord.State="TX" ContactRecord.Zip5="77929" ContactRecord.Zip4="0101" ContactRecord.Areacode="888" ContactRecord.Prefix="666" ContactRecord.Last4="4444" ContactRecord.RecordID=1 ContactRecord.Deleted=FALSE RecordPointer=ContactRecord.RecordID Contacts.Add(ContactRecord,CStr(ContactRecord.RecordID)) ENDIF 'checkourcollectiontomakesurerecordsexist IFContacts.Exist(CStr(RecordPointer))THEN

249

A Beginner's Guide to Gambas


'fordebugonly PRINT"Recorddataexistsfor"&CStr(RecordPointer)&"records." 'thisforloopisfordebugonly FOREACHContactRecordINContacts PRINTContactRecord.FirstName&""&ContactRecord.LastName NEXT ELSE 'ifnorecords,putupaMessageBoxtoinformuser Message.Info("Recordsdonotexist!","Ok") ENDIF END

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

A Beginner's Guide to Gambas

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

OnceyouhavecompletedtheToolButtons,wewilladdtheregularbutton asourQuitbutton.SelectaButtonfromtheToolBoxandplaceitontheform inthelowerrightcorner,ascloseasyoucantoFigure74.SettheTextproperty forthisbuttontoQuit.Aslongaswearehere,wecancodetheprogram'sexit routine,whichwillbecalledwhenthisbuttonisclicked.DoubleclickontheQuit buttonandyouwillbeplacedinthecodeeditor.Addthiscode:


PUBLICSUBQuitBtn_Click() 'prompttosavedatabeforewequit SELECTMessage.Question("Savebeforeexit?","Yes","No","Cancel") CASE1 'iftheusersaysyes,wesave SaveAllBtn_Click CASE2'wedon'tsave,justclose

251

A Beginner's Guide to Gambas


CASE3'theycanceled,sowereturntotheprogram RETURN CASEELSE'wedonothingbutclose ENDSELECT ME.Close'hereweclosethewindow END'programstops Adding the Labels and TextBoxes

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


State.Text=ContactRecord.State Zip5.Text=ContactRecord.Zip5 Zip4.Text=ContactRecord.Zip4 AreaCode.Text=ContactRecord.Areacode DialPrefix.Text=ContactRecord.Prefix DialLast4.Text=ContactRecord.Last4 'updatethecurrentrecordstatusfieldwithcurrentdata StatusLabel.Text="Record:"&CStr(RecordPointer) StatusLabel.Text=StatusLabel.Text&"of"&CStr(Contacts.Count) 'calltheRefreshmethodtorepainttheformcontents Form1.Refresh 'selectthecontentsoftheFirstNamefield FirstName.Select 'setthecursorfocustotheFirstNamefield FirstName.SetFocus ELSE'norecordsexist! 'fordebugonly PRINT"InUpdateForm,Record:"&RecordPointer&"notfound." ENDIF 'fordebugonly PRINT"LeavingUpdateForm..." END Coding Toolbuttons: First, Prev, Next, and Last

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

A Beginner's Guide to Gambas youwillbetakentothePrevRecordBtn_Click()subroutine.Addthiscode:


PUBLICSUBPrevRecordBtn_Click() 'fordebugonly PRINT"inPrev:currentpointeris:"&RecordPointer 'wearemovingtoalowerrecordsowedecrementtherecordpointer DECRecordPointer 'ifwemovedpastrecord1thenresettorecord1 IFRecordPointer=0THEN RecordPointer=1 ENDIF 'updateourcontactvaraiblewiththenew(prev)recorddata ContactRecord=Contacts[CStr(RecordPointer)] 'ifwearealreadyatthebeginningofthedatanotifytheuser IFRecordPointer=1THEN 'fordebugonly PRINT"Atfirstcontactalready!" ELSE 'fordebugonly PRINT"inPrevnowcurrentpointeris:"&RecordPointer ENDIF 'updateourformwiththenewdata UpdateForm END

Now,wewillcodetheNextbutton.DoubleclickonthethirdToolButton ()andyouwillbetakentotheNextRecordBtn_Click()subroutine. Addthis code:


PUBLICSUBNextRecordBtn_Click() 'fordebugonly PRINT"inNext:currentpointeris:"&RecordPointer 'wemoveforwardthroughthecollectionsoweincrementthepointer INCRecordPointer 'ifwemovedpastthelastrecord,resettothelastrecord IFRecordPointer>Contacts.CountTHEN RecordPointer=Contacts.Count ENDIF 'updatethecontactrecordwiththenewdata
255

A Beginner's Guide to Gambas


ContactRecord=Contacts[CStr(RecordPointer)] 'ifwearealreadyatthelastrecord,telltheuser IFRecordPointer=Contacts.CountTHEN 'fordebugonly PRINT"AtLastcontactalready!" ELSE 'fordebugonly PRINT"inNext,thecurrentpointeris:"&RecordPointer ENDIF 'updateourformagainwiththenewdata UpdateForm END'nextrecordmove

ThelastToolButtonweneedtocodeformovingaroundinthedataisfor theLastRecordBtn_Click()subroutine.Thissubroutinewillplaceusattheendof thedatacollection,atthelastrecord.DoubleclickonthefourthToolButtonand addthiscode:


PUBLICSUBLastRecordBtn_Click() 'setrecordpointertolastrecordusingcollection.countproperty. RecordPointer=Contacts.Count 'updateourrecordvarwiththenewdataforthelastrecord ContactRecord=Contacts[CStr(RecordPointer)] 'updatetheformwiththenewdata UpdateForm END Coding ToolButtons: Adding a record

Now,let'sgothroughhowtoaddanewcontacttothecollection.Double clickonthefifthToolButton,thelittlepersonicon,andyouwillbeputinthecode windowattheAddBtn_Click()subroutine.Let'sgothroughthecode:


PUBLICSUBAddBtn_Click() 'declarealocalcontactvaraiblejustforuseinthissubroutine DIMMyContactRecordASContact 'instantiatethecontactrecordsowecanuseit MyContactRecord=NEWContact 'ifthereisnofirstname,wewillnotaddarecord IFFirstName.Text<>""THEN 'fordebugonly PRINT"Adding"&FirstName.Text&"tocollection."
256

A Beginner's Guide to Gambas


'weareheresowefoundafirstname.AssigntheTextboxdata 'tothefieldsstoredintherecord: 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 MyContactRecord.State=State.Text MyContactRecord.Zip5=Zip5.Text MyContactRecord.Zip4=Zip4.Text MyContactRecord.Areacode=AreaCode.Text MyContactRecord.Prefix=DialPrefix.Text MyContactRecord.Last4=DialLast4.Text 'incrementtherecordkeysoeachkeyisuniquewhenaddedto 'thecollection.Gambasrequiresthatthisbeconvertedtoa 'stringvariablewhenweactuallyadditbelow. MyContactRecord.RecordID=Contacts.Count+1 'ifweaddingarecorditisnottaggedasdeleted MyContactRecord.Deleted=FALSE 'setglobalrecordpointertothevalueoftheincrementedkey RecordPointer=MyContactRecord.RecordID 'now,calltheCollection.Addmethodtoaddtherecord Contacts.Add(MyContactRecord,CStr(RecordPointer)) 'thisisfordebugonlytoshowwhathasbeenadded IFContacts.Exist(CStr(RecordPointer))THEN 'fordebugonly PRINT"Record"&CStr(RecordPointer)&"added!" ELSE 'fordebugonly PRINT"Recorddoesnotexist!" ENDIF ELSE'cannotaddacontactwithoutafirstname,telluser Message.Info("Cannotaddwithoutafirstname","Ok") ENDIF 'updatetheformwiththenewdata UpdateForm 'thisisfordebugpurposes,showallrecordsinthecollection FOREACHMyContactRecordINContacts PRINT"Record"&CStr(RecordPointer)&":";
257

A Beginner's Guide to Gambas


PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName NEXT END'addroutine Coding ToolButtons: Clearing data

ThesixthToolButtonisusedtoclearthedataontheformtoallowusersto startwithafresh,blankformtoenterdata. ItsimplyblanksouteachTextbox field.DoubleclickontheClearBtnandenterthiscode:


PUBLICSUBClearBtn_Click() FirstName.Text="" MI.Text="" LastName.Text="" Suffix.Text="" Street1.Text="" Street2.Text="" City.Text="" State.Text="" Zip5.Text="" Zip4.Text="" AreaCode.Text="" DialPrefix.Text="" DialLast4.Text="" END

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

A Beginner's Guide to Gambas


IFLen(MI.Text)>1THEN sTemp=Mid$(MI.Text,1,1) MI.Text=sTemp ENDIF END PUBLICSUBSuffix_Change() DIMsTempASString IFLen(Suffix.Text)>3THEN sTemp=Mid$(Suffix.Text,1,3) Suffix.Text=sTemp ENDIF END PUBLICSUBState_Change() DIMsTempASString IFLen(State.Text)>2THEN sTemp=Mid$(MI.Text,1,2) State.Text=sTemp ENDIF END PUBLICSUBZip5_Change() DIMsTempASString IFLen(Zip5.Text)>5THEN sTemp=Mid$(MI.Text,1,5) Zip5.Text=sTemp ENDIF END PUBLICSUBZip4_Change() DIMsTempASString IFLen(Zip4.Text)>4THEN sTemp=Mid$(MI.Text,1,4) Zip4.Text=sTemp ENDIF END PUBLICSUBAreaCode_Change() DIMsTempASString IFLen(AreaCode.Text)>3THEN sTemp=Mid$(AreaCode.Text,1,3) AreaCode.Text=sTemp
259

A Beginner's Guide to Gambas


ENDIF END PUBLICSUBDialPrefix_Change() DIMsTempASString IFLen(DialPrefix.Text)>3THEN sTemp=Mid$(DialPrefix.Text,1,3) DialPrefix.Text=sTemp ENDIF END PUBLICSUBDialLast4_Change() DIMsTempASString IFLen(DialLast4.Text)>4THEN sTemp=Mid$(DialLast4.Text,1,4) DialLast4.Text=sTemp ENDIF END

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

A Beginner's Guide to Gambas callingShow.Thisisbecausewewanttheusertoentersomethingandclickthe Searchbutton.Hereiswhattheformitselflookslikeindesignmode:

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

Atthispoint,wehavepoppeduptheform,obtainedtheuserinputofalast nametosearchfor,andhavepassedthatvariablebacktoourprogramusingthe moduleconduitmethoddescribedabove.Now,wearereadytoactuallysearch thecollectionandfindtheentry.Hereisthecodetodothat:


PUBLICSUBDoFind() 'declareacontactobjectforlocaluse DIMMyContactRecordASContact 'instantiateit MyContactRecord=NEWContact 'settherecordpointertothefirstrecordinthecollection RecordPointer=1 'fordebugonly PRINT"InDoFindwith:"&SearchKey
262

A Beginner's Guide to Gambas


'useFOREACHtoiteratethrougheachobjectinthecollection FOREACHMyContactRecordINContacts 'assigneachtemprecordtoourglobalcontactobject ContactRecord=Contacts[CStr(RecordPointer)] 'ifthelastnamematchessearchkey,updatetheformandleave IFContactRecord.LastName=SearchKeyTHEN 'fordebugonly PRINT"Found:"&MyContactRecord.LastName 'nowupdatetheform UpdateForm BREAK'forcereturnwiththisstatement ENDIF 'nomatchsoweincrementtherecordpointerandmovetothenext INCRecordPointer NEXT END

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

A Beginner's Guide to Gambas


MyContactRecord.State=State.Text MyContactRecord.Zip5=Zip5.Text MyContactRecord.Zip4=Zip4.Text MyContactRecord.Areacode=AreaCode.Text MyContactRecord.Prefix=DialPrefix.Text MyContactRecord.Last4=DialLast4.Text 'addtheworkcopytothecollectionwiththesame 'keythatbelongedtotherecordwedeletedabove Contacts.Add(MyContactRecord,CStr(RecordPointer)) IFContacts.Exist(CStr(RecordPointer))THEN 'fordebugonly PRINT"Record"&CStr(RecordPointer)&"updated!" ELSE PRINT"Recordnotupdated!"'wewantthisoutputififfailed ENDIF 'updatetheformwiththenewdata UpdateForm END

Toolbuttonsagain:DeletingaRecord Iftheuserwantstodeletearecordinacollectionwealsohavetothink abouthowtohandlethat.Managingwhichkeysareavailableandwhicharenot couldbeaprogrammer'snightmaresoaneasierapproachistosimplymarkthe recordasdeletedandblankit.Thatway,itisavailableforreusewiththesame key.Itblanksoutthedataand,whenthesaveoccurs,doesnotstoretheolddata, effectivelydeletingit.Onlydifferenceis,wecanreusethekeybyhavingtheuser simplyenterdatainanemptyrecordandclicktheupdatebutton.Hereishow thisisaccomplished:


PUBLICSUBDeleteRecordBtn_Click() 'declareourlocalcontactobject DIMMyContactRecordASContact 'instantiateit MyContactRecord=NEWContact 'removethecurrentrecordusingthebuiltinRemovemethod Contacts.Remove(CStr(RecordPointer)) 'clearallthefieldsontheform ClearBtn_Click 'setthefirstfieldwithanindicatorthattherecordisdeleted
264

A Beginner's Guide to Gambas


MyContactRecord.FirstName="<DeletedRecord>" 'leavetherestblankbysimplyassigningthemafterclearing MyContactRecord.LastName=LastName.Text MyContactRecord.Initial=MI.Text MyContactRecord.Suffix=Suffix.Text MyContactRecord.Street1=Street1.Text MyContactRecord.Street2=Street2.Text MyContactRecord.City=City.Text MyContactRecord.State=State.Text MyContactRecord.Zip5=Zip5.Text MyContactRecord.Zip4=Zip4.Text MyContactRecord.Areacode=AreaCode.Text MyContactRecord.Prefix=DialPrefix.Text MyContactRecord.Last4=DialLast4.Text 'markrecordasdeleted MycontactRecord.Deleted=TRUE 'addtheblanked,deletedrecordasitexiststothecollection Contacts.Add(MyContactRecord,CStr(RecordPointer)) IFContacts.Exist(CStr(RecordPointer))THEN 'fordebuggingonly PRINT"Record"&CStr(RecordPointer)&"markeddeleted!" ELSE 'ifitfails,wewantamessage Message.Info("Recordnotmarkeddeleted!","Ok") ENDIF 'updatetheform UpdateForm END

ToolButtonsagain:SavingData Thelastthingweneedtocodeisthesavebutton. Thisisreallysimple becausewehavealreadybuiltamethodinourContactclassfiletodothat.Here, allwedoiscallthePutDatamethod:


PUBLICSUBSaveAllBtn_Click() 'invokethePutDatamethod ContactRecord.PutData(Contacts) 'fordebugonly PRINT"Contactssavedtocontact.datafile." END

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

A Beginner's Guide to Gambas

Chapter 12 Learning to Draw


TheDrawclassistheclassusedinGambasfordrawingonanobject.The objectmaybeoftypePicture,Window,Printer,Drawing,orDrawingAreaobject. This class isstatic. Itisimportanttorememberthatbeforestarting todraw anything,youmustcallthe Begin methodbypassingitahandletotheobject typeyouwanttodraw. Onceyoudo that,you cancallanyofthedrawing methodsGBprovidestodrawpoints,lines,texts,pictures,etc.However,itisnot clearlydocumentedthatyoumustalsosettheDrawingArea'sCachedpropertyto Trueifyouwanttoseeyourdrawingappearontheform.Whenyourdrawingis finished,youmustcalltheEndmethod.

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

A Beginner's Guide to Gambas TosettheBackColorpropertytored,youwouldusethiscode:


Draw.BackColor=Color.Red

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

A Beginner's Guide to Gambas capableoffillingapolygonwithacolororpatternorboth. Thisclassisstatic. TheFillStylepropertyreturnsorsetsthestyleusedbydrawingmethodscapable offillingapolygonwithacolororpatternorboth.TheFillclasssupportsseveral predefinedFillStyleconstantsusedtorepresentfillpatternsfordrawing:


BackDiagonal Dense37 Dense88 None Cross Dense50 Dense94 Solid CrossDiagonal Dense6 Diagonal Vertical Dense12 Dense63 Horizontal

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

A Beginner's Guide to Gambas


STATICPROPERTYInvertASBoolean

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


'setadefaultlinewidthof2pixels Draw.LineWidth=2 END

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

A Beginner's Guide to Gambas


Draw.ForeColor=color.Black 'setcurrentfonttoArial draw.Font.Name="Arial" 'turnonboldface draw.Font.Bold=TRUE 'turnoffitalic draw.Font.Italic=FALSE 'turnoffunderline draw.Font.Underline=FALSE 'settextsizeto16points draw.Font.Size="16" 'startaloopandcontinueuntilweiterate10times FORcounter=0TO9 'outputtextandincrementtheypositionby40*counter 'theoptionalwidth,heightparametersaregivenas100,60 draw.Text("SampleText",10,10+40*counter,100,60) NEXT'iterationoftheloop 'nowsetfontto24points draw.Font.Size="24" Draw.ForeColor=color.Blue'andchangecolortoblue FORcounter=0TO9'loopanother10times 'allwechangeisxpositiontomovethetextright200pixels draw.Text("MoreSampleText",200,10+40*counter,100,60) NEXT'iteration 'refreshthedrawingareatoseewhatwasdone da.Refresh END'wearedonewithtextstuff!

Onceyouhaveaddedthecodeabove,saveyourworkandclicktheRUNbutton. Hereiswhatyoushouldsee:

273

A Beginner's Guide to Gambas

Figure79ResultsofclickingtheTextButton.

DrawPrimitives:Point/Rect/Ellipse/Line TheDraw.PointmethoddrawsasinglepixelwhiletheDraw.Rectmethod drawsarectangle.Gambaslanguagesyntaxforthesetwomethodsis:


STATICSUBPoint(XASInteger,YASInteger) STATICSUBRect(XASInteger,YASInteger,WidthASInteger,HeightASInteger)

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

A Beginner's Guide to Gambas


Draw.Rect(5+5*counter,5+5*counter,da.W/2+5*counter,da.H/2+5*counter) 'ifwehitanevennumber,invoketoggleInvertpropertyon/off IFcounterMOD2=0THEN draw.Invert=FALSE ELSE draw.Invert=TRUE ENDIF NEXT'iterationoftheloop 'ensureinvertissettooff draw.Invert=FALSE 'setcurrentfgdcolortoblack draw.Forecolor=color.Black 'setapointmidscreen draw.Point(da.W/2,da.H/2) 'nowwewillmakeatinycrosshairfromthefirstpoint 'bymovingonepixelup,down,leftandrightofthecenter 'dotwesetwiththefirstdraw.pointcall draw.Point(da.W/21,da.H/2) draw.Point(da.W/2+1,da.H/2) draw.Point(da.W/2,da.H/21) draw.Point(da.W/2,da.H/2+1) 'updatethedisplaytoseewhatwedid da.Refresh END'oftherect/pointdemocode

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)

TheDraw.Ellipsemethodwilldrawanellipseorcircle.Remember,acircle isanellipsewithequalwidthandheightparameters,whichiswhyyoudonotsee aDraw.CirclefunctioninGambas.TheGambaslanguagesyntaxforDraw.Ellipse is:


STATICSUBEllipse(XASInteger,YASInteger,WidthASInteger,HeightAS Integer[,StartASFloat,LengthASFloat])

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

A Beginner's Guide to Gambas


'changethecolortodarkblue Draw.ForeColor=color.DarkBlue 'setupforasolidfill.Anyfillablecontainerthatiscalledafter 'thiscallwillbefilledwiththepatternspecifiedbelow draw.FillStyle=fill.Solid 'setupaloopthatwillcreate12increments FORi=0TO360STEP30 'ifwefallona90degreeincrement,switchcolors IFiMOD45=0THEN draw.FillColor=color.Yellow ELSE draw.FillColor=color.Red ENDIF 'drawafilledellipseof12segments,startingateachvalueofi 'andsweepingfor30degrees,asspecifiedintheoptionalparms Draw.Ellipse(x1,y1,x2,y2,i,30) NEXT 'now,turnoffthefillstyle draw.FillStyle=fill.None 'setourfgdcolortoblack draw.ForeColor=color.Black 'letsdrawsomelines,startxatmidscreenhorizaxis25pixels x1=da.W/225 'startouryatmidscreenontheverticalaxis y1=da.H/2 'startwithalinewidthofasinglepixel lwidth=1 'loop8times,movingdownalongtheyaxisin25pixincrements FORi=10TO200STEP25 'drawaline draw.Line(da.W/2,i,da.W/2+150,i) 'increaselinethicknessvariable INClwidth 'setthenewwidth draw.LineWidth=lwidth NEXT'iterationoftheloop

277

A Beginner's Guide to Gambas


'outoftheloop,resettoadefaultof2pixwide draw.LineWidth=2 'now,letsstartanotherloopanddrawsomeellipses FORi=1TO40STEP3'letsmake13ofthem 'movingthisoneleftalongthehorizaxis Draw.Ellipse(x1i*5,y1,75,200) 'andmovingthisonerightalongthehorizaxis Draw.Ellipse(x1+i*5,y1,75,200) 'ifwehitanevennumberinourloopchangecolors IFiMOD2=0THEN draw.ForeColor=color.Red ELSE draw.ForeColor=color.Black ENDIF NEXT'iterationoftheloop 'refreshthedrawingareatoseeourwork da.Refresh END'endoftheellipsesandlinesdemocode

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

A Beginner's Guide to Gambas


'turnoffthefill draw.FillStyle=fill.None 'refreshtoseeourwork da.Refresh END

Saveyourworkandruntheprogram.WhenyouclicktheFillRectbutton, youshouldseesomethingsimilartothis:

Figure82OutputafterclickingtheFillRectbutton.

DrawPrimitives:PolygonandPolyline The Draw.Polygonmethod drawsapolygonwith n vertices. Thevertices arespecifiedinanIntegerarrayusingthisGambaslanguagesyntax:


STATICSUBPolygon(PointsASInteger[])

ThePointsparameterisanarrayofIntegercontainingthecoordinatesof thepolygonvertexes.Thecoordinatesareassumedtobeinx,yformatsothere mustbetwointegersinthearrayforeachvertexofthepolygon. The Draw.Polylinemethod worksnearlythesameasthePolygonroutine exceptthatwithapolylinethefigurebeingdrawndoesnotneedtobeclosed. Thisissometimesreferredtoasavoidpolygon.Apolylineisaseriesofvertices


280

A Beginner's Guide to Gambas joinedfromonetothenextbyaline.Thelinewilldrawfromthelastvertexto thenextvertexspecifiedinthearray.TheGambaslanguagesyntaxforPolyline is:


STATICSUBPolyline(PointsASInteger[])

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

A Beginner's Guide to Gambas


triangle=Array(x1,y1,x2,y2,x3,y3) 'setafillstyle draw.FillStyle=fill.Dense63 'andafillcolor draw.FillColor=color.DarkMagenta 'anddrawthepolygonusingthetrianglearraydata draw.Polygon(triangle) 'remembertosetfillstyletoNone draw.FillStyle=fill.None 'callrefreshtoseeourwork da.Refresh END'andwearedonewiththepolygonroutine

Saveyourworkandruntheprogram.WhenyouclicktheFillPolybutton, youshouldseesomethingsimilartothis:

Figure83UsingDraw.Polygontodrawa triangle.

Now,let'sseehowthe Draw.Polylinemethod works.Doubleclickonthe Polylinebuttonandcreateaclickevent.Whenthecodewindowappears,enter thiscode:


PUBLICSUBPolyLineBtn_Click() 'declaresomevariablestocreateourvertices DIMx1ASInteger DIMy1ASInteger DIMx2ASInteger
282

A Beginner's Guide to Gambas


DIMy2ASInteger DIMx3ASInteger DIMy3ASInteger DIMx4ASInteger DIMy4ASInteger 'declareanintegerarraytoholdthepolylinedata DIMlinesASInteger[] 'clearthedrawingarea da.Clear 'startourfirstpointmidscreenabout10pixelsfromthetop x1=da.w/2 y1=10 'thenextpointwillbe10pixelsinfromfarleft,down200pixels x2=da.Left+10 y2=da.H200 'our3rdvertexwillbedeadcenterofthedrawingareaonhorizaxis 'andverybottomofthedrawingareaforvertaxis x3=da.W20 y3=da.H20 'andthe4thvertexwillbedeadcenterxandyofthedrawingarea x4=da.W/2 y4=da.H/2 'loadtheverticesintothearray 'ifwewantedtoclosethepolygon,allweneedtodoisaddthe 'x1,y1verticestotheendofthearray 'uncommentthenextlinetotryitandsee 'lines=Array(x1,y1,x2,y2,x3,y3,x4,y4,x1,y1) lines=Array(x1,y1,x2,y2,x3,y3,x4,y4) 'ensureanyfillstylesareturnedoff draw.FillStyle=fill.None 'setthecolortodarkgreen draw.ForeColor=color.DarkGreen 'drawthelines draw.Polyline(lines) 'refreshtoseeourwork da.Refresh END'ofthepolylinedemoroutine

283

A Beginner's Guide to Gambas Saveyourworkandruntheprogram.WhenyouclickthePolylinebutton, youshouldseesomethingsimilartothis:

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])

Thisclassactslikeanarrayofpixels. ThinkofXasrowsandYascolumnsof imagepixels.Hereishowthecodetogetorsetapixelofanimagewouldwork:


DIMhImageASImage DIManIntegerASInteger anInteger=hImage[XASInteger,YASInteger]

ThecodeabovewillreturnthecolorofanimagepixelatX,Ywhilethefollowing
284

A Beginner's Guide to Gambas codewillsetthecolorofanimagepixeltothevalueofanInteger:


hImage[XASInteger,YASInteger]=anInteger

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

TheImageclasssupportsseveralmethods.Theseinclude:Clear,Copy,Fill,Flip, Load,Mirror,Replace,Resize,Rotate,Save,andStretch. Clearwillcleartheimage,settingallpixelvaluestozero. Copyreturnsacopyoftheimage,oracopyofapartofit.Thecopymethodis declaredasafunction,asshownbelow:


FUNCTIONCopy([XASInteger,YASInteger,WidthASInteger,Height ASInteger])ASImage

Fillfillstheimagewithaspecifiedcolor.Gambaslanguagesyntaxis:
SUBFill(ColorASInteger)

285

A Beginner's Guide to Gambas Flipreturnsamirroredcopyoftheimage.Themirroredcopyiscreatedusingthe horizontalaxisoftheimage.


FUNCTIONFlip()ASImage

LoadandSaveloadorsavesanimagefromafileortoafilerespectively.The fileextensionof Path willspecifythegraphicsfileformatusedwiththesaved image. CurrentlysupportedfileformatsareJPEG,PNG,BMP,GIFandXPM. Gambaslanguagesyntaxis:


SUBLoad(PathASString) SUBSave(PathASString)

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

Thefunctionwillrotatetheimage n degrees. Theangleisspecifiedindegrees, notradians. Stretchreturnsastretchedcopyoftheimage.IftheoptionalparameterSmooth isspecifiedasTrue,asmoothingalgorithmisappliedtothereturnedresult.The Gambaslanguagesyntaxis:


FUNCTIONStretch(WidthASInteger,HeightASInteger[,SmoothAS Boolean])ASImage
286

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])

IftheoptionalWidthandHeightparametersarenotspecified,thenewpictureis void.YoucanspecifyifthepicturehasamaskwiththeTransparentparameter. Thisclassactslikeanarray.


DIMhPictureASPicture hPicture=Picture[PathASString]

Thecodeabovewillreturnapictureobjectfromtheinternalpicturecache. If the picture is not present in the cache, it is automatically loaded from the specifiedfile. Inordertoinsertapictureintheinternalpicturecache,usethis code:
DIMhPictureASPicture Picture[PathASString]=hPicture

Depth returnsorsetsthedepthofthepicture. Whensettingdepthvalues,you mustonlyusethefollowingvalues:2,8,16,and24.Itisdeclaredas:


PROPERTYDepthASInteger

Heightisareadonlyattributethatreturnstheheightofthepictureasaninteger. Itisdeclaredas:
287

A Beginner's Guide to Gambas


PROPERTYREADHeightASInteger

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

A Beginner's Guide to Gambas


'specifythatthecontentsofthedrawingareaarecachedinmemory Drawingarea1.Cached=TRUE 'resizedrawingareatosizeoftheimageconvertedfmpicture DrawingArea1.Resize(i.Width,i.Height) 'clearthedrawingarea DrawingArea1.Clear() 'calltheDraw.Begin(mandatory)methodtostarttodraw Draw.Begin(DrawingArea1) 'puttheimageinthedrawingareastartingatorigin0,0 Draw.Image(i,0,0) 'callthe(mandatory)Draw.Endmethodtoquitdrawing Draw.End 'maketheimagevisible DrawingArea1.Visible=TRUE 'refreshthedrawingareatoseewhatwasdone DrawingArea1.Refresh END

Saveyourworkandruntheprogram.Clickthebuttonandascreenshotof yourdesktopwillbeplacedonthedrawingareaoftheform. Prettyeasyusing theGambasmethods,isn'tit? TransparentisaBooleanflagthatcanbereadorset.Itindicateswhetherornot thepicturehasamask.Gambaslanguagesyntaxis:


PROPERTYTransparentASBoolean

MethodssupportedbyPictureincludeClear,Copy,Fill,Flush,Load,Resize,and Save. Clearwillclearthepicture,settingallpixelvaluestozero. Copyreturnsacopyofthepicture,oracopyofapartofit.Thecopymethodis declaredasafunction,asshownbelow:


FUNCTIONCopy([XASInteger,YASInteger,WidthASInteger,Height ASInteger])ASImage

289

A Beginner's Guide to Gambas Fillfillsthepicturewithaspecifiedcolor.Gambaslanguagesyntaxis:


SUBFill(ColorASInteger)

FlushFlushestheinternalpicturecache.Themethodtakesnoparametersandis calledusingthisconvention:
STATICSUBFlush()

LoadandSaveloadsorsavesapicturefromafileortoafilerespectively.The fileextensionof Path willspecifythegraphicsfileformatusedwiththesaved picture. CurrentlysupportedfileformatsareJPEG,PNG,BMP,GIFandXPM. Gambaslanguagesyntaxis:


SUBLoad(PathASString) SUBSave(PathASString)

Resizeresizestheimagetothesizespecifiedbythewidthandheightparameter given:
SUBResize(WidthASInteger,HeightASInteger)

The Tile method draws a tiled picture in the DrawingArea. Gambas languagesyntaxisasfollows:
STATICSUBTile(PictureASPicture,XASInteger,YASInteger,Width ASInteger,HeightASInteger)

Let'snowgobacktoouroriginalgfxDemoprogramandfinishcodingthelast button. StartGambasandloadthegfxDemoproject.OpenForm1anddouble clickontheTileImgbutton.Whenthecodewindowappears,addthiscode:


PUBLICSUBTileBtn_Click() 'declareourlocalvarshere 'wewillneedapicturevartoholdthepictureweload DIMmypicASPicture 'weneedacountervarforourloopwork DIMcounterASInteger 'wearealsogoingtoneedsomeintegervars DIMiASInteger DIMjASInteger

290

A Beginner's Guide to Gambas


'setiandjtozerotostart i=0 j=0 'instantiatepicturevariable,setwidth,heightsoitisnotvoid mypic=NEWPicture(170,105,FALSE) 'clearthedrawingarea da.Clear 'nowloadthepictureusingtheloadmethod mypic.Load("GambasShrimp.png") 'wewilltilethepictureicolumnsacrossperjrowsdown 'inourcasewewillhave4rowsof3imagesperrow 'sowewillneedtoloop12times FORcounter=0TO11 'drawthetile draw.Tile(mypic,i*175,j,170,105) 'incrementourcolumncounter INCi 'checktoseeifwehavethreeacross IFiMOD3=0THEN 'ifso,movevalueofj(ouryaxis)image.height+5pixelsdown j=j+110 'resetcolumncountertozero i=0 ENDIF'ourchecktoseeif3across NEXT'iterationoftheloop 'refreshthedisplaytoseethework da.Refresh END'oftheTileImgbuttoncode

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

A Beginner's Guide to Gambas system,simplygototheGambaswebsiteandusetherightmousebuttonoverthe mascotimagetosaveacopytoourgfxDemoprojectfolder.Now,saveyourwork andruntheprogram. ClicktheTileImgbuttonandyoushouldseesomething similartothis:

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:

Doubleclick on the formwhenitopens and thecode window appears.


293

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

A Beginner's Guide to Gambas projectdirectory.ThatisallthecodeweneedtoaddtoviewanSVGfile.Save yourworkandruntheprogram.Whentheprogramstarts,clicktheLoadbutton andyoushouldseeapicturesimilartothis:

Figure86LoadinganSVGfileinGambas.

IhopeyouhaveenjoyedourshortlittletourdeforceofGambasdrawing capabilities. ThischapterhaspresentedallofthebasicsneededtouseGambas foralmostanygraphicsrelatedneeds.Attheendofthisbook,inAppendixA,we presentaspecialgraphicsprogramthatyoucanusetodrawevenmoreadvanced 2D/3DrenderedobjectsusingaGKStypegraphicsclasscreatedinGambas.

295

A Beginner's Guide to Gambas ContentsofSVGfilefloppy.svgdownloadedfromhttp://openclipart.org:


<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <!-- Created with Sodipodi ("http://www.sodipodi.com/") --><svg height="400pt" id="svg548" sodipodi:docbase="/home/nicu/svg_gal/computers/" sodipodi:docname="/home/nicu/svg_gal/computers/floppy.svg" sodipodi:version="0.32" width="400pt" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink"> <metadata> <rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <cc:Work rdf:about=""> <dc:title>Clipart by Nicu Buculei - antenna</dc:title> <dc:description></dc:description> <dc:subject> <rdf:Bag> <rdf:li>hash</rdf:li> <rdf:li></rdf:li> <rdf:li>computer</rdf:li> </rdf:Bag> </dc:subject> <dc:publisher> <cc:Agent rdf:about="http://www.openclipart.org"> <dc:title>Nicu Buculei</dc:title> </cc:Agent> </dc:publisher> <dc:creator> <cc:Agent> <dc:title>Nicu Buculei</dc:title> </cc:Agent> </dc:creator> <dc:rights> <cc:Agent> <dc:title>Nicu Buculei</dc:title> </cc:Agent> </dc:rights> <dc:date></dc:date> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/> <dc:language>en</dc:language> </cc:Work> <cc:License rdf:about="http://web.resource.org/cc/PublicDomain"> <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/> <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/> <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/> </cc:License> </rdf:RDF> </metadata> <defs id="defs550"/> <sodipodi:namedview id="base" showgrid="true"/> <path d="M 52.5712 53.9929 L 407.003 53.9929 L 443.463 89.6056 L 441.768 447.429 L 53.4191 445.733 L 52.5712 53.9929 z " id="path551" style="fill:#00007b;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:3.75;strokelinejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;"/> <path d="M 371.39 53.9929 L 371.39 145.569 C 371.39 145.569 368.846 159.135 355.279 163.375 C 341.713 164.222 156.866 164.223 156.866 164.223 C 156.018 165.071 144.995 157.439 144.147 152.352 C 143.299 147.264 142.451 145.569 142.451 145.569 C 142.451 145.569 144.147 53.145 143.299 53.145 C 142.451 53.145 372.238 53.9929 371.39 53.9929 z " id="path552" sodipodi:nodetypes="cccccccc" style="fill:#a3a6a6;fill-rule:evenodd;stroke:black;strokeopacity:1;stroke-width:2.32865;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;" 296

A Beginner's Guide to Gambas


transform="matrix(1.000000,0.000000,0.000000,1.152582,0.000000,-6.413116)"/> <rect height="185.694977" id="rect553" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="321.362518" x="89.879768" y="249.862976"/> <rect height="9.32714844" id="rect554" style="font-size:12;fill:#808080;fill-rule:evenodd;stroke-width:1pt;" width="0.00000000" x="410.394348" y="240.535797"/> <path d="M 334.929 76.0389 C 334.081 76.0389 282.358 76.0389 282.358 76.0389 L 282.358 165.071 L 334.929 165.071 L 334.929 76.0389 z " id="path555" style="fill:#00007b;fill-rule:evenodd;stroke:black;stroke-opacity:1;strokewidth:2.5;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;"/> <rect height="55.1149292" id="rect556" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="321.362549" x="89.8797607" y="249.862946"/> <rect height="6.783386" id="rect557" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="287.445648" x="105.142365" y="335.503052"/> <rect height="5.935455" id="rect558" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="287.445648" x="104.294426" y="371.115822"/> <rect height="5.935455" id="rect559" style="font-size:12;fill:#df8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="286.597717" x="105.142365" y="406.728516"/> <rect height="5.08750916" id="rect567" style="font-size:12;fill:#000000;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="78.8567657" x="159.409393" y="75.1909637"/> <rect height="5.08754730" id="rect568" style="font-size:12;fill:#000000;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="58.5066528" x="161.105225" y="87.9097748"/> <rect height="5.08750916" id="rect569" style="font-size:12;fill:#180003;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="76.3130035" x="161.105225" y="100.628624"/> <rect height="5.93548584" id="rect570" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="114.469490" x="105.990288" y="261.733826"/> <rect height="5.08752441" id="rect571" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="44.0919495" x="106.838211" y="277.844360"/> <rect height="5.087512" id="rect572" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;" width="33.916901" x="178.063675" y="277.844386"/> <path d="M 150.317 158.228 C 151.899 153.481 148.734 63.2911 155.063 63.2911 C 161.392 63.2911 292.722 61.7089 292.722 61.7089 C 232.595 68.038 164.557 66.4557 150.317 158.228 z " id="path566" sodipodi:nodetypes="cccc" style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:1pt;strokelinejoin:miter;stroke-linecap:butt;fill-opacity:0.5;"/> </svg>

297

A Beginner's Guide to Gambas

Chapter 13 Error Management


Error management is a key area for developers doing any kind of applicationdevelopment.Errormanagementisaverypowerfulconceptandcan make development work much easier if it is used efficiently. As a Gambas developer,itishighlyrecommendedthatyouadoptanappropriatestrategyfor error management that will enable you to build high quality and robust applications.Improperhandlingoferrorscanandwilldegradetheperformance ofyourapplication,it'sperceptionbyyourusercommunity,andultimately,its overallacceptance.Inordertounderstanderrormanagement,itisimportantto knowthetypesoferrorsthatcanoccurinaprogram.Wewillbrieflyexplainthe mostcommonerrorcategoriesinthefollowingsectionsandtrytopointoutsome thingsyoushouldwatchforasyouwriteyourcode. GeneralConceptsofErrorManagement Errorscanhavemanycauses.Dependingonthecause,theerrormightbe recoverable.Arecoverableerrorisoneforwhichyourapplicationcanidentifythe errorcauseandtakesomeactiontoresolveormitigatetheproblem.Someerrors mightberecoverablecanbehandledwithouttheneedtoindicatetotheuserthat an error was even encountered. For example, an error generated when a requestedfiledoesnotexistisrecoverable.Theapplicationcanbeprogrammedto displayanerrormessageinsuchanevent. Errorssuchasvalidationerrors,for whichtheapplicationcannotcontinueprocessingbutcanprovideerrorspecific feedbackcanalsobeconsideredrecoverableifhandledproperly.Forexample,an error that occurs when a user enterstextwhere a number is required can be considered recoverable because the application can recognize the error and redisplaythedatafieldalongwithamessagethatprovidesinformationaboutthe causeoftheerror,allowingtheusertoreenterdatausingcorrectinput. ErrorHandling Therearethreekeyfactorstoconsiderwhenprogrammingtoavoiderrors: prevention,detection,andrecovery.Takingadequatestepstopreventerrorswill certainlyhelptoensureyouhaveahappyusercommunity. However,howdo youpreventerrorsiftheycannotbedetectedbytheprogrambeforetheuserwill suffertheconsequences?Haveyouandyourteamtakenthetimetoinvestigate andaccountforeverypossiblekeystroke,input,anddatatypethatausercould enter?Reallythinkaboutthiswhileyouarestillinthedesignphaseandagain
298

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:

Error.Class Error.Code Error.Text Error.Where

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

Let'screateaquickexampletodemonstratehowtousetry. OpentheGambas IDEandcreateanewgraphicaluserinterfaceproject.Createastartupclassform andputanExitbuttonontheform,namedExitBtn.Doubleclickonthebutton andaddthiscode:


PUBLICSUBExitBtn_Click() DIMaASInteger DIMbASInteger a=2 b=0 TRYPRINTa/b IFERRORTHEN Message.Error("CLASS:"&Str(Error.class)&",CODE:"&error.code& ",="&error.text&"AT:"&error.where,"OK") ENDIF END

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

A Beginner's Guide to Gambas


FINALLY TextLabel1.Text="CLASS:"&Str(Error.class)&",CODE:"& error.code&",="&error.text&"AT:"&error.where TextLabel1.Refresh CATCH IFERRORTHEN Message.Error("CLASS:"&Str(Error.class)&",CODE:"& error.code&",="&error.text&"AT:"&error.where,"OK") ENDIF Message.Info("ClearedtheError","OK") TextLabel1.Text="<center><strong>Errorhasbeencleared." END

Whenyouruntheprogram,youshouldseethisastheopeningscreen:

Figure88CATCHtestprogramopeningscreen.

Now,clicktheerrorbuttontogenerateourerrorandyoushouldseethis:

Figure89DivbyZeroerrorcaughtbyCATCH.

YoushouldalsonoticethatthemainscreenTextLabelhaschangedtothis:

307

A Beginner's Guide to Gambas

Figure90TheTextLabelupdatedwitherrorinfo.

OnceyouclicktheOkbuttonfortheErrorMessagedialog,youwillseethis:

Figure91Infomessagethattheerroris cleared.

Now,clicktheOKbuttonontheInfomessageandtheTextAreaisupdatedlike this:

Figure92Mainscreenaftererrorhasbeencleared.

ThisshouldgiveyouaprettygoodideaofhowtousetheGambaserror managementfeaturestohelpmanageerrorswhentheyoccurinyourcode(and theyinevitablywilloccur). Nothandlingerrorslikethedivbyzeroweusedin


308

A Beginner's Guide to Gambas ourexamplewillbeashowstopperinmostcircumstances.Asaquickexample, gobacktoourcode,intheErrBtn_Clicksubroutineandcommentouttheselines:


'FINALLY 'TextLabel1.Text="CLASS:"&Str(Error.class)&",CODE:"& error.code&",="&error.text&"AT:"&error.where 'TextLabel1.Refresh 'CATCH 'IFERRORTHEN 'Message.Error("CLASS:"&Str(Error.class)&",CODE:"& error.code&",="&error.text&"AT:"&error.where,"OK") 'ENDIF 'Message.Info("ClearedtheError","OK")

Now,runtheprogramagainandclicktheErrorbutton.Hereiswhatyouget:

Figure93DefaultGambaserrordialog.

Youcantrytocontinue,butthereisnoguaranteethatyourprogramwill workcorrectlyorthatitwillevencontinue.Thisisdefinitelynotwhatyouwould wantyouruserstosee. Itjustmakesgoodsensetousethetoolsavailablein Gambastopreventthiswhenyoucan.Now,letsmoveontoseehowwecanuse eventstohelpwritebettercode.

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

A Beginner's Guide to Gambas InstanceName_EventNametoinvokethemethodtobecalledbytheeventlistener whensuchaneventisraised.Let'saddtoourpreviousexampletodemonstrate theuseofevents. Addanotherbuttontotheformforourpreviousexample, namedEventBtn.Doubleclickandaddthiscodetotheprogram:


EVENTMyEvent(MsgASString)ASBoolean PUBLICSUBEvent1Btn_Click() DIMbResultASBoolean RAISEMyEvent("Raiseanevent")ASbResult IFbResultTHEN TextLabel1.Text="Cancelledtheevent" ELSE TextLabel1.Text="Raisedtheevent" bResult=NOTbResult STOPEVENT ENDIF END

Saveyourworkandruntheprogram. ClicktheEventbuttonandyourdisplay shouldlooklikethis:

Figure94Oureventwasraised.

311

A Beginner's Guide to Gambas

Chapter 14 Mouse, Keyboard and Bit Operations


Themousewasdesignedtobeareplacementforgatheringkeyboardinput fromauser.WhileGUIdesignhasadvancedsignificantlysincetheearlydaysof windowedinterfaces,theevolutionofthemousehasnot. Probablythebiggest change for the mouse was going optical and cordless. However, the basic functionality remainsvirtually thesame. Provide anX,Y position, clicka left, right, or middle button and detect it's state as up or down, and check the movementofthemousewheelorchangethedeltavaluewhenthewheelmoves. Gambas, of course, supports all of these basic features with an easy to code, logicalapproach.Inthenextfewpages,wewillshowyouhowtomastermouse andkeyboardinput.Finally,asalastexercise,wewillcreateaprogramtoshow youhowtousebitoperators.Let'sstartwiththemouse.

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

Ifthemousemoves,wewanttochangethecursorshape,dependingon whichquadrantofthedrawingareathemouseisin.WewillusetheMousemove eventandcodethis:


313

A Beginner's Guide to Gambas


'ifthemousemoves,wewillupdatethecursorshapedependingonthe 'quadrantthemouseislocatedat PUBLICSUBda_MouseMove() 'checkthetopleftquadrant IFmouse.X<=da.W/2ANDmouse.Y<=da.H/2THEN da.Mouse=mouse.Pointing 'elsewecheckthebottomleftquadrant ELSEIF mouse.X<=da.W/2ANDmouse.Y>=da.H/2THEN da.Mouse=mouse.Cross 'elsewecheckthetoprightquadrant ELSEIF mouse.X>=da.W/2ANDmouse.Y<=da.H/2THEN da.Mouse=mouse.SizeNWSE 'otherwise,itmustbeinthebottomrightquadrant ELSEIF mouse.X>=da.W/2ANDmouse.Y>=da.H/2THEN da.Mouse=mouse.SizeNESW 'ifitisanywhereelse,makeitthedefault ELSE da.Mouse=mouse.Default ENDIF

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

A Beginner's Guide to Gambas Iftheuserhaspressedand releasedamousebutton,we willresetthemouse cursortothenormalstate.


'wheneveramousebuttonisreleased,resetmousecursortonormal PUBLICSUBda_MouseUp() da.Mouse=mouse.Default END

Finally,iftheuserpressesanykey,wewillresetthedrawingareabyclearingit andredrawthequadrantbycallingthesameroutineusedtoopentheform:
'checkkbdeventstoclearthedrawingareaandredrawthequadrants PUBLICSUBForm_KeyPress() da.Clear Form_Open() END That'sit.Whenyouruntheprogram,youshouldseesomethinglike this:

Figure95MouseOpsprogramrunning.

Asyoumovethemousefromquadranttoquadrant,noticehowthecursor changes. Tryboththeleftandrightmousebuttonsandpressthespacebarto clearthedrawingandrestart.Whenyouaresatisfiedeverythingworks,movethe mousewheelandtheprogramwillterminate. Now,let'slearnaboutkeyboard operations.

315

A Beginner's Guide to Gambas

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

Forfunctionkeys: F1F2F3F4F5F6F7F8F9F10F11F12 ForshiftedFkeys: F13F14F15F16F17F18F19F20F21F22F23F24 Forallotherkeys: BackSpace BackTab


Enter Insert Pause SysReq Esc Menu Print Tab CapsLock Escape NumLock Return Delete Help PageDown ScrollLock End Home PageUp Space

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

A Beginner's Guide to Gambas incheswideand1/2tall. SettheLabel.TextpropertytoPressanykey...and setthecontrolfontsizeto14pointandmakeitbold.Doubleclickontheform andthecodewindowappears.Hereisthecodewewilladdtoourprogram:


'Gambasclassfile 'wewillcheckthekeyreleaseeventtoseewhattodo PUBLICSUBForm_KeyRelease() 'wheneverakeyisreleased,checkthecode SELECTkey.code CASEkey.Tab'ifitisatabkey textlabel1.Text="Keycodeis:"&key.Code&",TAB." CASEkey.BackSpace'orbackspace textlabel1.Text="Keycodeis:"&key.Code&",Backspace." CASEkey.CapsLock'orcapslock textlabel1.Text="Keycodeis:"&key.Code&",CapsLock." CASEkey.F1'oraFkey textlabel1.Text="Keycodeis:"&key.Code&",F1key." CASEkey.F2 textlabel1.Text="Keycodeis:"&key.Code&",F2key." CASEkey.F3 textlabel1.Text="Keycodeis:"&key.Code&",F3key." CASEkey.F4 textlabel1.Text="Keycodeis:"&key.Code&",F4key." CASEkey.F5 textlabel1.Text="Keycodeis:"&key.Code&",F5key." CASEkey.F6 textlabel1.Text="Keycodeis:"&key.Code&",F6key." CASEkey.F7 textlabel1.Text="Keycodeis:"&key.Code&",F7key." CASEkey.F8 textlabel1.Text="Keycodeis:"&key.Code&",F8key." 'ifnoneoftheabove,isitprintable?Ifso,showcodeandvalue CASEELSE IFkey.Code>32ANDkey.Code<128THEN textlabel1.Text="keycodeis:"&key.Code&","&Chr(key.Code) ELSE'otherwisejustthecode textlabel1.Text="keycodeis:"&key.Code ENDIF ENDSELECT END 'checkkeydowneventtofilteroutshift,control,alt,etc. PUBLICSUBForm_KeyPress() IFkey.ShiftTHEN textlabel1.Text="Keycodeis:"&key.Code&",SHIFT" ELSEIFkey.AltTHEN
317

A Beginner's Guide to Gambas


textlabel1.Text="Keycodeis:"&key.Code&",ALT" ELSEIFkey.ControlTHEN textlabel1.Text="Keycodeis:"&key.Code&",CTRL" ELSEIFkey.Code>32ANDkey.Code<128THEN textlabel1.Text="keycodeis:"&key.Code&","&Chr(key.Code) ELSEIFkey.EscTHEN'ifanESCkeyispressed textlabel1.Text="keycodeis:"&key.Code&",ESC" ELSE textlabel1.Text="keycodeis:"&key.Code ENDIF END PUBLICSUBForm_Open() ME.Caption="KeyboardOperations" END

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:

Gambas Bit Operations


Operator
BTst BClr BSet BChg Shl Shr Rol Ror

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

A Beginner's Guide to Gambas aboveontheform,asshowninthefigurebelow:

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

IftheuserentersanyvalueintheTextBox2fieldtochangeabit,weneed toupdatetheformandreflectthechangedvalues.Wewillworryaboutwhatto dowiththenewvaluealittlelateroninthecode.Fornow,itisasimplecallto theRefreshmethodweneed:


PUBLICSUBTextBox2_Change() form1.Refresh'refreshourdisplayanytimethebitvaluechanges END

WhentheuserspecifiesanintegervalueintheTextBox1field,wewillonly reacttotheentrywhentheTABkeyispressed. ThatcausesaLostFocusevent, whichiswhatwewillcodefor.Hereiswhatweneedtodonext:

320

A Beginner's Guide to Gambas


PUBLICSUBTextBox1_LostFocus() 'weneedalocalintvartoworkwith DIMmyIntASInteger 'convertourstringtextvaluetoanint myInt=CInt(textbox1.text) 'checktoseeifitisin8bitrange IFInt(myInt>=0)AND(myInt<256)THEN Label2.Text="Hex:"&Hex(myInt)'converthexvalue label3.Text="Bin:"&Bin(myInt)'convertbinvalue label7.Text=Str$(myInt)'updateourtextfields form1.Refresh'refreshtheform ENDIF END

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

WhentheuserpressestheSetbutton,wewanttosetthebitspecifiedforthe integerrepresentedbythefirstparameter.Thisisessentiallytheoppositeofclear discussedabove.


PUBLICSUBSetBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger 'convertourstringtextvaluetoanint myInt=CInt(textbox1.text) 'iftheintegerisbetween0and255process,otherwiseignore IFInt(myInt>=0)AND(myInt<256)THEN 'convertstringvaluetoanint
321

A Beginner's Guide to Gambas


result=CInt(TextBox2.Text) 'setthebit i=BSet(myInt,result) 'updatethelabels label5.Text="Bset:"&Bin(i) label7.Text=Str$(i) ENDIF END

TheBchgfunctionisreallyjustaninvertoperation. Whenouruserclicksthe Changebutton,wewillexecutethiscode:


PUBLICSUBChangeBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=BChg(myInt,result) label5.Text="Bchg:"&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

TheShrfunctioniswillshiftthevalueof MyInt n bitsrightwhere n is specified bythesecond parameter. Whenouruserclicks theShrbutton,this subroutinewillbeexecuted:


322

A Beginner's Guide to Gambas


PUBLICSUBSHRBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=Shr(myInt,result) label5.Text="SHR:"&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

A Beginner's Guide to Gambas


'rotateleft PUBLICSUBROLBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=Rol(myInt,result) label5.Text="ROL:"&Bin(i) label7.Text=Str$(i) ENDIF END 'rotateright PUBLICSUBRORBtn_Click() DIMiASInteger DIMresultASInteger DIMmyIntASInteger myInt=CInt(textbox1.text) IFInt(myInt>=0)AND(myInt<256)THEN result=CInt(TextBox2.Text) i=Ror(myInt,result) label5.Text="ROR:"&Bin(i) label7.Text=Str$(i) ENDIF END

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

A Beginner's Guide to Gambas executetheprogram.Yourresultsshouldbesimilartothis:

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

Chapter 15 Gambas and Databases


This chapter describes in detail the process of using a MySQL or PostgreSQL databasefromwithintheGambasprogrammingenvironment. For ourpurposes,wewillassumethatMySQLisalreadyinstalledonyourmachine (oramachineaccessibletoyoufromyourmachine)andthataMySQLserveris availableforyoutoconnecttofromwithinyourGambasprogram.Ifthisisnot thecase,thenyouwillhavetorefertotheMySQLmanualandfigureouthowto installtheMySQLdatabasedistributiononyourparticularsystem. Youshould alsobeawareofthefactthatGambaswillalsoworkwithPostgreSQLandSQLite. SQLiteisnotatrueclient/serverarchitecturelikeMySQLandPostgreSQL.Itisa flatfiledatabasesystemanddoesnotusetheclient/serverdatabasemodel.For ourpurposesinthischapter,wewillsticktoMySQLsinceitisprobablythemost widelyusedofthethreedatabaseproducts. The MySQL database package consists of the MySQL server and many clientprograms.TheMySQLserverisaprogramthatstoresandmanagesallof your databases within the MySQL environment. The client programsthat are includedwithMySQLaretoonumeroustolistherebutitisimportantforyouto understandthateachclientapplicationservesaspecificpurposerelatedtothe managementand/or administration of data or metadata stored on theMySQL server.Theclientprogramwewillbedealingwithinthischapteriscalledmysql (noteitisspelledinlowercaseletters). Thisclientprogramprovidesa command line interface (CLI) you can use to issue SQL statements interactively to the MySQLserverandseetheresultsdisplayedimmediately. Themaindifference between MySQL and mysql isthat MySQL isusedtorefertotheentire MySQL distributionpackageortorefertothe MySQL serverwhile mysql referstothe clientCLIprogram. Whatpurposedoesitservetohavebothaclientandaserverinsteadofa singleprogram?Theserverandclientprogramsaredividedintodifferententities soyoucanusetheclientprogram(s)onyoursystemtoaccessdataonaMySQL serverthatcouldberunningonanothercomputer. Byseparatingthepackage into a server and n clients, it serves to separate data from the data retrieval interface. Beforeyoubeginworkingonthischapter,itishighlyrecommended thatyoufamiliarizeyourselfwithMySQLbydownloadingthelatestmanualfrom theofficialMySQLwebsite18.Ataminimum,completethetutorialinChapter3 oftheMySQLUserManualbeforeproceedingwiththischapter. Onceyouare
18 See URL http://www.mysql.com/ . 326

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

A Beginner's Guide to Gambas statement)wouldbethesameasifyoutypedSHOWDATABASESfromthemysql clientCLI.


Host

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

TheLoginpropertyisusedtosetorgettheuserlogindatathatisusedfor establishingtheconnectiontothedatabase. Onceagain,thisappliestoMySQL andPostgreSQL,notSQLite. SinceSQLitehasnoconceptofusers,accesstoa SQLitedatabaseiscontrolledbythefilepermissionsettingsofthedatabasefile itself.ThismeansthattheLoginpropertyisalwaysgoingtobesettotheuserid oftheuserthatisexecutingtheGambasprogramthatusestheSQLitedatabase. Syntaxis:


PROPERTYLoginASString Name

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

A Beginner's Guide to Gambas


PROPERTYNameASString Password

ThePasswordpropertywillreturnorsetthepasswordusedforestablishing aconnectiontothedatabase.Callingconventionis:
PROPERTYPasswordASString Port

ThePortpropertyisusedtogetorsettheTCP/IPportusedforestablishing theconnectiontoadatabase.ThedefaultportdependsontheconnectionType. Syntaxis:


PROPERTYPortASString Tables

TheTablespropertyisusedtoobtainavirtualcollectionthatcanbeused formanagingallofthetablesofadatabase.Syntaxis:
PROPERTYTablesAS.ConnectionTables Type

TheTypepropertyrepresentsthetypeofthedatabaseserveryouwantto connectto. InGambas,thecurrentlysupporteddatabasetypeare:"postgresql", "mysql",and"sqlite".Thetypepropertyusesthissyntax:


PROPERTYTypeASString Users

The Users property returns a collection of all users registered in the databaseserver.Likeanyothercollectionobject,itcanbeenumeratedwithFOR EACH.Syntaxis:
PROPERTYUsersAS.ConnectionUsers Version

The Versionproperty isareadonlyvaluethatreturnstheversionofthe


330

A Beginner's Guide to Gambas databasethatthedriverhasconnectedwith.Syntaxis:


PROPERTYREADVersionASInteger

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

TheOpenmethodisusedtoopenaconnectiontothedatabase.Priorto makingthecalltoOpen,youshouldsettheconnectionpropertieswiththedata necessarytousethedatabase.Generally,ataminimumyouwillneedtospecify thetypeofdatabase,thehost,aloginIDandpassword,and thenameofthe databaseyouwishtouse.Thesyntaxforopenis:


FUNCTIONOpen()ASBoolean

ThecodeexamplebelowshowshowtousetheOpenmethodtoconnect user jrittinghouse toaMySQLdatabasenamedGambasBugsthatisstoredon Hostlocalhost:


DIM$hConnAsNEWConnection
332

A Beginner's Guide to Gambas


WITH$hConn .Type="mysql" .Host="localhost" .Login="jrittinghouse" .Password="ab32e44" .Name="GambasBugs" ENDWITH TRY$hConn.Open IFErrorTHENPRINT"Databasecannotbeopened.Error=";Error.Text

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

A Beginner's Guide to Gambas case.UsingtheFindmethodallowsyoutowriterequeststhatareindependentof theunderlyingdatabase,meaningitwillworkwithPostgreSQLorMySQLwithout anycodechangerequired.


Create

TheCreatemethodisusedtobuildaread/writeResultobjectwhichcan usedtocreaterecordsinatable.Standardcallingconventionis:
FUNCTIONCreate(TableASString)ASResult Edit

TheEditmethodreturnsaread/writeResultobjectusedforeditingrecords inthespecifiedtable. Query isequivalenttoanembeddedSQLWHEREclause usedforfilteringthetable,andtheArgumentsarequotedasneededbytheSQL syntaxandsubstitutedintheRequeststring(likeinsscanfinC)asweexplained previously.Standardcallingconventionis:


FUNCTIONEdit(TableASString[,QueryASString,ArgumentsAS,...])ASResult

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

The Quotemethod returnsaquotedidentifieryoucanusetoinsertina SQLquery.Thisidentifiercanbeatableorfieldname.Syntaxis:


FUNCTIONQuote(NameASString)ASString

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

ResultObjects TheresultobjectisaclassthatisusedtoreturntheresultofaSQLrequest. Thisclassisnotcreatableanditactsjustlikeareadonlyarray.Itisenumerable usingtheFOREACHstatement.Declareanditeratearesultobjectasfollows:


DIMhResultASResult FOREACHhResult 'dosomethingwiththedata NEXT

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

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas

Figure99TheFMainformindesignmode.

TheFRequestformismuchsimplertobuild.Itisshowninthefigurebelow:

Figure100FRequestFormindesignmode.

TheFRequestformcontainsasinglecontrol,whichwehavenotpreviously introduced,theTableViewcontrol. ThiscontrolisfoundintheQTtoolsetwe discussedpreviously.Wewillshowyouhowtousethiscontrolwhenwediscuss theFRequestformcodebelow.Fornow,let'sjumpintothecodefortheFMain formandseehowthingswork.


'Gambasclassfile

$hConn isdeclaredasaprivatevariableandwillbeusedbyallsubroutinesin
339

A Beginner's Guide to Gambas thisclassfile.Notethatthevariableisprefixedwitha$symboltoindicateitisa privateclassvariable.Whilenotrequired,itisagoodprogrammingconvention tofollow.


PRIVATE$hConnASConnection

Whenevertheuserhasfilledoutthedataatthetopoftheformwiththeir username,host,password,etc.,andclickstheconnectbutton,theprogramwill cometothissubroutineandtrytousethatdatatoestablishaconnectiontothe database.


PUBLICSUBbtnConnect_Click() 'weneedtohaveastringtoworkwithsodeclaresNameaslocal DIMsNameASString 'nowwegetalittletricky.ifadatabasewaspreviouslyopened 'andisstillopen,thisnextlinewouldcloseit.UsingTRY 'wouldallowanyerrortobecaught(seeCATCHbelow). 'Ifthereisnotanopendatabasetoclose,noharmwasdone 'andthecodeexecutionproceeds. TRY$hConn.Close 'weassignthedataintheTextboxtxtNametoourstringvarsName 'andsetthedatabaseconnectionpropertiestothevaluesprovided 'bytheuserbyusingtheWITH/ENDWITHconstruct. sName=txtName.Text WITH$hConn .Type=cmbType.Text'thetypeofdatabaseplatformtouse .Host=txtHost.Text'hostnameofthedatabase .Login=txtUser.Text'USERID .Password=txtPassword.Text'USERpassword ENDWITH

Atthispoint,alltheconnectionpropertiesaresetbutwehavenotopened theconnectionyet. Thefollowingcodesegmentwillseeifadatabasewiththe namespecifiedbysNameexistsand,ifnot,itwillcreateitifthecheckboxto createdatabaseischecked.


IFchkCreate.ValueTHEN $hConn.Open'opentheconnection 'seeifadatabasesNameexistsandifnot,addittotheserver IFNOT$hConn.Databases.Exist(sName)THEN $hConn.Databases.Add(sName) ENDIF

340

A Beginner's Guide to Gambas


'nowclosetheconnection $hConn.Close ENDIF

Now,wearereadytoopenthedatabase.Eitheritalreadyexistedandwe openthatdatabaseorwewillopenthenewonewecreatedifthecheckboxwas checked.First,settheNamepropertyfortheconnectiontosNameandthencall theOpenmethod:


$hConn.Name=sName $hConn.Open 'wesettheenabledpropertiesforbothprogramformstoTRUE 'andplacesomedefaulttextintheSQLrequestboxatthe 'bottomoftheFMainform: frmDatabase.Enabled=TRUE frmRequest.Enabled=TRUE txtRequest.Text="SHOWTABLES" 'ifourTRYfailedorifanyerroroccurredduringthissubroutine, 'theCATCHstatementwoulddisplayanERRORdialogwiththetextof 'theerrormessage. CATCH Message.Error(Error.Text) END'ofconnectBtn_Clicksubroutine

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

A Beginner's Guide to Gambas


hTable.Fields.Add("id",gb.Integer) hTable.Fields.Add("firstname",gb.String,16) hTable.Fields.Add("name",gb.String,32) hTable.Fields.Add("birth",gb.Date) hTable.Fields.Add("active",gb.Boolean) hTable.Fields.Add("salary",gb.Float) 'wecanspecifyaprimarykeyforthedatabasetable.Inthis 'case,theidfieldisusedaswecancreateuniqueintegerindex 'data hTable.PrimaryKey=["id"] 'thecalltotheUpdatemethodcommitsthechangestothedatabase 'andmakesthempermanent. hTable.Update 'nowweputupasimpledialogtoinformtheuserwehave 'successfullycompletedthecreationtask. Message.Info("Table"&txtName.Text&"hasbeencreated.")

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

A Beginner's Guide to Gambas


'needaResultobjecttostoreourresults DIMiIndASInteger DIMrTestASResult 'settheBusyflagtopreventinterruptionstoourprocess INCApplication.Busy 'wearegoingtostartthedatabasetransactionprocesswithBEGIN $hConn.Begin 'createthedatabasetablefirst 'rTest=$hConn.Create("test") rTest=$hConn.Create(txtName.Text) 'now,setupalooptocreate100records FORiInd=1TO100 'maketherecordidbethecountervariablevalue rTest!id=iInd 'randomlysetthefirstnametobeoneofthefiveinthearray rTest!firstname=["Paul","Pierre","Jacques","Antoine","Mathieu"][Int(Rnd(5))] 'makethelastnameacatenatedvaluewiththeintegerindexvalue rTest!name="Name#"&iInd 'randomlychooseadatebyaddingavaluefrom110,000tothe 'basedateofJan1,1970 rTest!birth=CDate("01/01/1970")+Int(Rnd(10000)) 'settheactiveflagtoeither0or1(TRUEorFALSE) rTest!active=Int(Rnd(2)) 'randomlychooseasalaryfigurefrom1,000to10,000 rTest!salary=Int(Rnd(1000,10000)) 'updatethisrecordwiththedatasemiarbitrarydatavalues rTest.Update NEXT'iterationoftheloop 'commitalladdedrecordstothedatabase $hConn.Commit 'lastthingtoexecutebeforeleavingthesubroutine FINALLY 'decrementthebusyflag DECApplication.Busy 'popupamessagetoinformtheuserwhatwedid Message.Info(txtName.Text&"hasbeenfilled.")

344

A Beginner's Guide to Gambas


'putadefaultSQLqueryintheSQLQuerytextbox txtRequest.Text="select*from"&txtName.Text 'fixourbuttonstomakesense btnFill.Enabled=FALSE btnDelete.Enabled=TRUE btnCreate.Enabled=FALSE 'ifsomethinggoeswrong,abortallchangeswiththeRollbackand 'showtheerrormessagetotheuser CATCH $hConn.Rollback Message.Error(Error.Text) END'ofthefilldatasubroutine

IftheuserentersanarbitrarySQLrequestintheSQLqueryboxatthe bottomoftheform,wewillusetheExecmethodtoperformthequeryanddisplay theresultsoftherequestusingtheFRequestform.Hereishowthatisdone:


PUBLICSUBbtnRun_Click() 'declarearesultobjecttoholdtheresultsofthequery DIMrDataASResult 'declareaformvariablesowecanshowtheFRequestform DIMhFormASFRequest 'executethequeryusingtheExecmethodandassigntheresultsto 'theresultobjectrData rData=$hConn.Exec(txtRequest.Text) 'passthedatabaseconnectionhandleandtheresultdatatothe 'FRequestformwhenitisinstantiated hForm=NEWFRequest($hConn,rData) 'nowdisplaytheformtotheuserwiththeresultdata hForm.Show 'comehereifthereisaprobleminthesubroutineanddisplayamsg CATCH Message.Error(Error.Text) END'ofsqlquerysubroutine

Whenever our program runs and the FMain form opens, we need to instantiateourconnectionvariable$hConn.Whenevertheformisclosed,wewill closetheconnection.
PUBLICSUBForm_Open()
345

A Beginner's Guide to Gambas


$hConn=NEWConnection END PUBLICSUBForm_Close() $hConn.Close END

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

A Beginner's Guide to Gambas


'andsetthetitlepropertytobethestringvariablevalue ME.Title=sTitle END

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

A Beginner's Guide to Gambas


FOREACHhFieldIN$rData.Fields WITHhField 'thisisadebuglinethatwascommentedout 'PRINT.Name;":";.Type;"";.Length 'thisnextlinesetsthecolumnnametobethefieldname tbvData.Columns[iInd].Text=.Name 'here,thecalltoWidthFromTypeisusedtodeterminewhatdata 'typethefieldisandwhattheappropriatewidthshouldbe tbvData.Columns[iInd].Width=WidthFromType(tbvData,.Type,.Length,.Name) ENDWITH 'incrementourindexcounter INCiInd NEXT'iterationofresultdata 'setthenumberofTableViewrowstobethesameasthenumber 'ofrowsofdataintheresultobject tbvData.Rows.Count=$rData.Count 'lastthingwedointhissubroutineisdecrementthebusyflag FINALLY DECApplication.Busy 'iftherewereanyerrorsinthissubroutinewewouldshowamessage CATCH Message.Error("Cannotexecrequest."&"\n\n"&Error.Text) END'ofReadDatasubroutine

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

A Beginner's Guide to Gambas refreshedisonlywhatisvisibleinthecontrol. Thecontrolcandisplayahuge amountofdatawithoutholdinganyofthedatavaluesdirectlyinstorageitself. Thatiswhatyourprogramarrayisusedfor.Whileitsoundsabitawkward,itis apragmaticsolutionthatallowsGambastodisplaydatafromadatabaseina prettyefficientmanner.


PUBLICSUBtbvData_Data(RowASInteger,ColumnASInteger) 'thisgetstothecorrectrow $rData.MoveTo(Row) 'thisactuallyassignsdatafromtheresultsobjecttothetableview tbvData.Data.Text=Str($rData[tbvData.Columns[Column].Text]) END

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

A Beginner's Guide to Gambas


IFiLength=0THENiLength=255 iLength=Min(32,iLength) iWidth=hCtrl.Font.Width("X")*iLength+16 ENDSELECT iWidth=Max(iWidth,hCtrl.Font.Width(sTitle)+8) RETURNiWidth END

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

A Beginner's Guide to Gambas

Chapter 16 Global Gambas


Gambas has been designed from the very beginning to support an internationalcommunity.Beinganopensourceproduct,peoplefromeverywhere ontheplanetparticipateintheongoingcareanddevelopmentoftheGambas product.TheabilityGambasprovidestodeveloperstocreateasinglecodebase thatwillsatisfyusersfromeverycountryisasignificantstepintherecognitionof aglobalcommunity.Gambasallowsdeveloperstowriteprogramsthatareeasily translatedtonearlyanylanguage,withouthavingtorewritecodeandwithout having to hire an expensive outsource firm to do the job. The processes of Internationalization and Localization are significantly enhanced by the Gambas approach. ThefollowingsectionswillprovideanoverviewthateveryGambas developershouldbeawareofinordertoproducegloballyacceptablecode.We are,ofcourse,allfromoneplanetandshouldalwaysconsidertheramifications andimplicationsofwhatweplaceinanopensourcecommunity.

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

A Beginner's Guide to Gambas

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

Thexxxbitpositionsarefilledwiththebitsofthecharactercodenumber inbinaryrepresentation.Therightmostxbitistheleastsignificantbit.Onlythe shortestpossiblemultibytesequencewhichcanrepresentthecodenumberofthe charactercanbeused.Notethatinmultibytesequences,thenumberofleading 1bitsinthefirstbyteisidenticaltothenumberofbytesintheentiresequence.

HowtotranslateinGambas
TotranslateGambasintoyourownlanguage,opentheGambasprojectin theIDE,and click onTranslate...in theProjectmenu,asshowninthefigure below:

355

A Beginner's Guide to Gambas

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

A Beginner's Guide to Gambas


Savethecurrenttranslation. Reloadthecurrenttranslation(Note:changesarelostwhenyoureload). Deletethecurrenttranslation. Duplicateanexistingtranslation. Exportthecurrenttranslationtoa.pofile. Mergeatranslationfile. Verifyatranslationbycheckingifeverysymbolcharacterispreserved.

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

A Beginner's Guide to Gambas thelanguageoftheuser.

Targetlanguagecharacterscanbecorrectlyenteredanddisplayedby theuserandtheycanbereadfromandwrittentothenativefilesystem ofthetargetplatform.

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

A Beginner's Guide to Gambas

This page intentionally blank.

360

A Beginner's Guide to Gambas

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)

A Beginner's Guide to Gambas


Eventdrivenlanguage.......................................................(46) Eventhandler.....................................................................(77) Eventdrivenprogramming..............................................(309) Eventdrivensystem........................................................(309) Execmethod....................................................................(327) Existfunction...................................................................(190) Existmethod....................................................................(167) Expandproperty.................................................................(67) FileSystemSafeUCSTransformationFormat(FSS/UTF).... (353) Fillclass...........................................................................(269) FillColorproperty............................................................(268) FillStyleconstants............................................................(269) FillStyleproperty.............................................................(269) FillXproperty..................................................................(269) FillYproperty..................................................................(269) Finally..............................................................................(306) Floatdatatype...................................................................(32) FLUSHfunction..............................................................(195) Focuscontrol......................................................................(72) Fontclass............................................................(108pp.,269) Fontproperty......................................................................(67) FOREACH........................................................................(50) FOREACHconstruct.......................................................(55) FORstatement..........................................................(49p.,55) ForeColorproperty............................................................(67) Foregroundproperty..........................................................(67) Frameclass.........................................................................(92) GambasCodeEditor..........................................................(28) Gambascodingenvironment.............................................(29) Gambascomponentlibrary................................................(91) Gambasconstants..............................................................(34) GambasConstants..............................................................(34) Gambasdatatypes.......................................................(30,33) GambasDevelopmentEnvironment..................................(66) GambasIconEditor.................................................(162,198) GambasIDE.................................................................(27,58) GambasInterpreter..............................................(19,21,266) GAMBASinterpreter.......................................................(141) Gambaskeywords..............................................................(46) Gambasmascot..................................................................(38) GambasToolBox...............................................................(57) GambasWiki.............................................................(20,165) Gb.dbcomponent.............................................................(327) GNUPublicLicense..........................................................(19) GOTOinstruction..............................................................(49) Grabmethod.......................................................................(71) GraphicalUserInterfaceclasses........................................(58) GridCell............................................................................(171) GridViewarray................................................................(171) GridViewcontrol..........................................................(171p.) GTK+.................................................................................(21) Hproperty..........................................................................(68) Handleproperty.................................................................(68) Handles...............................................................................(61) Heightproperty.........................................................(68,272) Hidemethod.......................................................................(71) Hostproperty...................................................................(329) HSVfunction.....................................................................(63) Html...................................................................................(70) HTML..............................................................(26,81p.,84p.) HungarianNotation...........................................................(31) IconEditor.........................................................................(28) IconViewcontrol........................................(149,154pp.,158) IFstatement...............................................(47,101,161,168) IFStatement.......................................................................(47) IFTHENELSE................................................................(110) Imageclass....................................................................(284p.) INCoperator......................................................................(43) Infiniteloop........................................................................(51) Inheritance........................................................................(240) Inkscape...........................................................................(292) Integerdatatype................................................................(32) Internationalization....................................................(22,351) Intrinsicandderivedfunctions........................................(215) Invertproperty.........................................................(269,275) IsDirfunction...................................................................(191) ISO/IEC10646.................................................................(352) Isolation............................................................................(332) Java......................................................................(19,53,237) Javalikearrays..................................................................(53) Keyclass..........................................................................(316) KILLfunction..................................................................(196) LABEL............................................................................ ...(49) Layoutcontrols.............................................................(176p.) Leaveevent........................................................................(74) Leftproperty......................................................................(68) LIKE....................................................................(43,45,189) LineStyleproperty...................................................(270,276) Linspire...........................................................................(22) Linux......................................(19,142,177,196p.,238,266) ListEditor........................................................................(185) ListBoxcontrol...............................................................(89p.) ListViewcontrol.........................................................(158pp.) LittleEndian....................................................................(192) Loadconditions...............................................................(302) Localization.....................................(138pp.,142p.,145,351) Lof()function...................................................................(195) Loginproperty................................................................(329) Loopingstructures.............................................................(49) Lowermethod....................................................................(71) MenuEditor............................................................(98p.,197) MenuItems.........................................................................(99) Messageclass...................................................................(112) MessageBoxcontrol........................................................(112) MicrosoftVisualBasic...................................................(19) MIMETYPE......................................................................(70) MKDIRfunction..............................................................(196) MODfunction....................................................................(40) MODoperator....................................................................(40) Mouseclass...................................................................... (312) Mouseproperty..................................................................(68) Movemethod.....................................................................(71) MoveCurrentmethod...................................(161,165p.,168) MySQL.............................................................................(326) MySQLmanual................................................................(326) MySQLserver..................................................................(326) Nameproperty................................................................(329) Nativearray........................................................................(53) NEWkeyword....................................................................(30)

362

A Beginner's Guide to Gambas


NewProjectWizard.....................................................(37,72) Nextproperty.....................................................................(69) NEXTstatement.................................................................(50) NEXTStatement................................................................(49) NOToperator.....................................................................(44) Objectdatatype.................................................................(33) Objectorientedprogramming.........................................(237) Objecttypedata...............................................................(238) OOconcepts.....................................................................(238) OOparadigm....................................................................(237) OOP..................................................................................(237) OOPL...............................................................................(238) OpenContentLicense.......................................................(2p.) OpenFileDialog...................................................(104,117p.) ORoperator................................................................(41,188) Panelclass.......................................................................... (95) Panelcontrol......................................................(95,177,184) Parameterpassingerrors..................................................(301) Parentproperty...................................................................(69) Passwordproperty............................................................(330) Pictureclass...............................................................(69,287) Picturecontrol....................................................................(78) Pictureobject...............................................................(65,79) Pictureproperty..................................................................(69) PNGfile.............................................................................(79) Polymorphism..................................................................(240) Portproperty....................................................................(330) PostgreSQL......................................................................(326) Poweroperator...................................................................(41) Predefinedconstants....................................(62,67,103,148) Previousproperty...............................................................(69) PRINTstatement...................................................(38,46,51) PRINTStatement...............................................................(46) PRIVATEkeyword............................................................(30) ProgressBarcontrol............................................................(73) ProjectExplorer...................................................(25pp.,37p.) ProjectMenu......................................................................(27) PUBLICkeyword........................................................(30,34) Qt.........................................................................(21,58,142) QT................................................................................(58,60) QTlibrary.........................................................................(347) QUITcommand.................................................................(37) Quotemethod...................................................................(335) Racecondition.................................................................(301) RadioButtonclass..............................................................(95) RadioButtoncontrol..........................................................(95) Raisemethod......................................................................(71) Recoverableerror.............................................................(298) Refreshmethod..................................................................(72) Removemethod...............................................................(168) REPEATandUNTIL.........................................................(53) Resizemethod....................................................................(72) Resultobject............................................................(333,335) RETURNcommand...........................................................(37) RGBfunction.....................................................................(63) ROLLBACKstatement....................................................(331) SaveFileDialog.......................................................(104,118) ScalableVectorGraphics................................................(292) ScreenXproperty...............................................................(69) ScreenYproperty..............................................................(69) ScrollViewcontrol...........................................................(294) SELECTstatement............................................(48,105,114) SelectColorDialog..................................................(103,105) SelectDirectoryDialog............................................(104,119) SelectFontDialog.......................................................(108pp.) SelectionTool....................................................................(28) SetFocusmethod................................................................(72) SetFocus()method.............................................................(69) Shortdatatype...................................................................(32) Showmethod.....................................................................(71) SQLWHEREstatement.................................................(333) SQLite..............................................................................(326) Standaloneexecutable.......................................................(20) Statfunction.....................................................(150,153,191) STATICkeyword...............................................................(30) StatusBar...........................................................................(26) STEPkeyword...................................................................(50) Stringconstants...............................................................(34p.) Stringdatatype.............................................(32,34,55,126) Stringfunctions................................................................(125) Stringoperators..................................................................(36) SubMenus..........................................................................(99) SVG..................................................................................(292) SVGspecification............................................................(292) Systemclass...............................................................(91,150) Tablesproperty................................................................(330) TableViewcontrol...........................................................(348) TabStripcontrol............................................................(181p.) Tagproperty.......................................................................(69) Temp$function................................................................(192) Terminalapplication..........................................(37,125,232) Textproperty...............................................................(64,69) Textboxcontrol..........................................................(83,166) TextBoxcontrol......................................................(82p.,252) TextHeightproperty.........................................................(272) TextWidthproperty.........................................................(272) Timerevent......................................................................(186) ToggleButtoncontrol......................................................(92p.) ToolBar..............................................................................(28) ToolBox.............................................................................(27) ToolBoxwindow......................................................(27p.,60) ToolTip..............................................................................(28) ToolTipproperty................................................................(69) Topproperty.......................................................................(70) Transaction.......................................................................(331) Transparentproperty........................................................(270) Treeview...........................................................................(105) TreeView......................................(25,28,37,57pp.,64,163) TreeViewcontrol...........................................(163pp.,167pp.) Trolltech......................................................................... ..(347) TRY..................................................................................(304) TRYstatement.................................................................(305) Typeproperty...................................................................(330) UCS2...............................................................................(353) UCS4...............................................................................(353) Unicodestandard.............................................................(352) Usersproperty..................................................................(330) UTF8............................................................................ ...(353) UTF8charset..........................................................(135,141) Validationerror................................................................(298)

363

A Beginner's Guide to Gambas


Valueproperty...................................................................(70) Variantdatatype.........................................................(33,55) VB....................................................................(19,32,37,59) Versionproperty..............................................................(330) Virtualclass.DrawClip...................................................(268) Virtualdispatch................................................................(242) Visibleproperty.................................................................(70) Wproperty.........................................................................(68) WAIT.................................................................................(71) Warningmessages...........................................................(115) WATCHkeyword............................................................(192) WHILE...WEND..............................................................(52) Widthproperty...................................................(68,272,276) Wikipedia.........................................................................(215) Windowproperty...............................................................(70) WITH.................................................................................(35) WITHkeyword..................................................................(35) Xproperty..........................................................................(68) XWindows........................................................................(78) X/OpenJointInternationalizationGroup........................(353) XORoperator.....................................................................(42) Yproperty..........................................................................(68)

364

You might also like