Dvapb
Dvapb
Dvapb
TM
Progress software products are copyrighted and all rights are reserved by Progress Software Corporation. This manual is also copyrighted and all rights are reserved. This manual may not, in whole or in part, be copied, photocopied, translated, or reduced to any electronic medium or machine-readable form without prior consent, in writing, from Progress Software Corporation. The information in this manual is subject to change without notice, and Progress Software Corporation assumes no responsibility for any errors that may appear in this document. The references in this manual to specific platforms supported are subject to change. Allegrix, A [Stylized], ObjectStore, Progress, Powered by Progress, Progress Fast Track, Progress Profiles, Partners in Progress, Partners en Progress, Progress en Partners, Progress in Progress, P.I.P., Progress Results, ProVision, ProCare, ProtoSpeed, SmartBeans, SpeedScript, and WebSpeed are registered trademarks of Progress Software Corporation or one of its subsidiaries or affiliates in the U.S. and/or other countries. A Data Center of Your Very Own, Allegrix & Design, AppsAlive, AppServer, ASPen, ASP-in-a-Box, BusinessEdge, Business Empowerment, Empowerment Center, eXcelon, Fathom, Future Proof, IntelliStream, ObjectCache, OpenEdge, PeerDirect, POSSE, POSSENET, ProDataSet, Progress Business Empowerment, Progress Dynamics, Progress Empowerment Center, Progress Empowerment Program, Progress for Partners, Progress OpenEdge, Progress Software Developers Network, PSE Pro, PS Select, SectorAlliance, SmartBrowser, SmartComponent, SmartDataBrowser, SmartDataObjects, SmartDataView, SmartDialog, SmartFolder, SmartFrame, SmartObjects, SmartPanel, SmartQuery, SmartViewer, SmartWindow, Technical Empowerment, Trading Accelerator, WebClient, and Who Makes Progress are trademarks or service marks of Progress Software Corporation or one of its subsidiaries or affiliates in the U.S. and other countries. SonicMQ is a registered trademark of Sonic Software Corporation in the U.S. and other countries. Vermont Views is a registered trademark of Vermont Creative Software in the U.S. and other countries. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. Any other trademarks and/or service marks contained herein are the property of their respective owners. This product includes Raster Imaging Technology copyrighted by Snowbound Software 1993-2000. Raster imaging technology by SnowboundSoftware.com This product includes software developed by the Apache Software Foundation (http://www.apache.org/). Copyright 1999 The Apache Software Foundation. All rights reserved (Xalan XSLT Processor) and Copyright 2000-2002 The Apache Software Foundation. All rights reserved (Jakarta-Oro). The names Apache, Xerces, Jakarta-Oro, ANT, and Apache Software Foundation must not be used to endorse or promote products derived from this software without prior written permission. Products derived from this software may not be called Apache or Jakarta-Oro, nor may Apache or Jakarta-Oro appear in their name, without prior written permission of the Apache Software Foundation. For written permission, please contact apache@apache.org. Software distributed on an AS IS basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License agreement that accompanies the product. Portions of this software are copyrighted by DataDirect Technologies, 1991-2002. This product includes software developed by Vermont Creative Software. Copyright 1988-1991 by Vermont Creative Software. This product includes software developed by IBM and others. Copyright 1999, International Business Machines Corporation and others. All rights reserved. This product includes code licensed from RSA Security, Inc. Some portions licensed from IBM are available at http://oss.software.ibm.com/icu4j/. This product includes the RSA Data Security, Inc. MD5 Message-Digest Algorithm. Copyright 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. This product includes software developed by the World Wide Web Consortium. Copyright 1994-2002 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University), http://www.w3.org/Consortium/Legal/. All rights reserved. This work is distributed under the W3C Software License [http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231] in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
December 2003
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preface1 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . OpenEdge Application Development Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Concepts and terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . External versus internal procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What is smart about SmartObjects? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Visible versus nonvisible objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reading and writing 4GL widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inter-object communication: signatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Anatomy of a database application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Working with AppBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Single-window or multi-window design? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Designing for character-based environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building an application in AppBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Starting and stopping AppBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Starting from the ADE Desktop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Starting from the Tools menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Starting from the operating system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stopping AppBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder for Web-based applications . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder main window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Current-object fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Status bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Menu bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 13 14 14 14 111 112 113 113 115 115 116 116 117 118 21 23 23 23 23 24 24 24 25 26 26
2.
Contents File menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Edit menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compile menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tools menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Layout menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Window menu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Help menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tool bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object Palette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Placing objects from the Object Palette . . . . . . . . . . . . . . . . . . . . . . . . . . Object Palette options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customizing the Object Palette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting your preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Section Editor preference options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Workspaces: design windows and source-code editors . . . . . . . . . . . . . . . . . . . . . Editing source code safely: the Section Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . Opening the Section Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choosing a section to edit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the Section Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inserting text-string tokens from lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring look-and-feel: object properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inspecting a procedure file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Test-driving your design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saving your work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3. Organizer Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction to organizer objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Organizer object roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a new procedure-based organizer instance . . . . . . . . . . . . . . . . . . . . . . . SmartWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartWindow visual properties . . . . . . . . . . . . . . . . . . . . . . SmartDialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartDialog visual properties . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartDialog procedure settings . . . . . . . . . . . . . . . . . . . . . . SmartFrames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartFrame visual properties. . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartFrame procedure settings . . . . . . . . . . . . . . . . . . . . . . Basic windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring frame properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 29 211 212 214 215 216 217 218 219 224 225 225 226 226 230 237 239 239 240 241 245 254 254 256 257 31 33 34 35 36 37 316 316 319 319 320 322 322 323 323 323 324
iv
Contents Rectangles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring rectangle properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple SmartContainers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and populating a Simple SmartContainer. . . . . . . . . . . . . . . . . Placing and configuring a SmartContainer module. . . . . . . . . . . . . . . . . Creating paged layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Page identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Special pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why only SmartObjects?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging with SmartFolders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging without SmartFolders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging whole windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. Data-Access Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction to data-access objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartDataObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Static SmartDataObjects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic SmartDataObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a SmartDataObject master . . . . . . . . . . . . . . . . . . . . . . . . . . . . Editing a SmartDataObject master . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a SmartDataObject instance. . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a SmartDataObject instance . . . . . . . . . . . . . . . . . . . . . . . . Data validation limitation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using the dynamic SmartDataObject . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartBusinessObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a SmartBusinessObject. . . . . . . . . . . . . . . . . . . . . Populating and configuring a SmartBusinessObject . . . . . . . . . . . . . . . . Synchronizing SmartDataObjects using DATA links. . . . . . . . . . . . . . . . Configuring a SmartBusinessObject instance. . . . . . . . . . . . . . . . . . . . . How the CascadeOnBrowse property works . . . . . . . . . . . . . . . . . . . . . SmartFilters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartFilter properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Making changes to the data stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a freestanding query object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining and editing queries using Query Builder . . . . . . . . . . . . . . . . . . . . . . . . . Table mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Join mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Where mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sort mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting database fields for browsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating calculated fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 324 325 328 328 330 332 333 333 335 335 339 341 41 42 42 42 44 44 410 411 413 415 418 419 421 422 423 428 430 431 432 437 438 438 439 441 442 443 444 445 448
Contents 5. Data-Display/Capture Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction to data-display objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartDataBrowsers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dynamic SmartDataBrowser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a dynamic SmartDataBrowser instance. . . . . . . . . . . . . . . . . . . Static SmartDataBrowser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a SmartDataBrowser master . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring SmartDataBrowser properties. . . . . . . . . . . . . . . . . . . . . . . . Editing a SmartDataBrowser master . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a SmartDataBrowser instance . . . . . . . . . . . . . . . . Configuring a SmartDataBrowser instance . . . . . . . . . . . . . . . . . . . . . . . Scrolling to the last record in the data stream . . . . . . . . . . . . . . . . . . . . . SmartDataViewers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a SmartDataViewer master . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding and removing SmartDataViewer fields. . . . . . . . . . . . . . . . . . . . . Configuring SmartDataViewer properties. . . . . . . . . . . . . . . . . . . . . . . . . SmartDataFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Placing and configuring a SmartDataField instance. . . . . . . . . . . . . . . . . SmartSelects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Placing a SmartSelect instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a SmartSelect instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example: assigning a new sales rep . . . . . . . . . . . . . . . . . . . . . . . . . . . . Basic data browsers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a basic data browser instance . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a basic data browser instance . . . . . . . . . . . . . . . . . . . . . . . Combo boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a basic combo box instance . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a basic combo box instance . . . . . . . . . . . . . . . . . . . . . . . . . Operating a basic combo box. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an ActiveX combo box instance. . . . . . . . . . . . . . . . . . . . . . . . . Configuring an ActiveX combo box instance . . . . . . . . . . . . . . . . . . . . . . Basic data viewers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a basic data viewer instance . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a basic viewer instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multi-line editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an editor instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring an editor instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fill-ins (single-line editors) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a fill-in instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a fill-in instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Radio button sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a radio-set instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a radio-set instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selection lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a selection list instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 53 54 54 54 57 57 512 517 519 519 520 522 523 528 529 535 536 537 538 539 543 545 546 546 551 552 553 557 561 562 565 566 566 567 567 567 571 571 571 575 576 577 579 580
vi
Contents Configuring a selection list instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . Slider controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a slider-control instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a slider control instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spin controls (ActiveX) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a spin control instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a spin-control instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toggle boxes (check boxes) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a toggle box instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a toggle box instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. Data-Communication Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartB2BObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML schema and mapping files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mapping options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XML schema Mapping Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Starting the XML Mapping Tool. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an XML map file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a master SmartB2BObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a SmartB2BObject instance . . . . . . . . . . . . . . . . . Configuring a SmartB2BObject instance. . . . . . . . . . . . . . . . . . . . . . . . . SmartSender and SmartReceiver objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and completing a SmartSender master . . . . . . . . . . . . . . . . . . Placing and configuring a SmartSender instance . . . . . . . . . . . . . . . . . . SmartRouters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Handling multiple document types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Callable document-handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a document-handling package . . . . . . . . . . . . . . . . . . . . . . . . . Creating a document-routing package . . . . . . . . . . . . . . . . . . . . . . . . . . SmartProducers and SmartConsumers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a SmartProducer instance. . . . . . . . . . . . . . . . . . . Configuring a SmartProducer instance . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and placing a SmartConsumer instance. . . . . . . . . . . . . . . . . . Configuring a SmartConsumer instance . . . . . . . . . . . . . . . . . . . . . . . . . Batch mode: starting and stopping a SmartConsumer . . . . . . . . . . . . . . The message-handling relationship: internal details . . . . . . . . . . . . . . . . . . . . . . . Example of sendHandler code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example of sendHandler override code . . . . . . . . . . . . . . . . . . . . . . . . . Example of receiveReplyHandler code . . . . . . . . . . . . . . . . . . . . . . . . . . Example of receiveHandler code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example of receiveHandler override code . . . . . . . . . . . . . . . . . . . . . . . Example of sendReplyHandler code. . . . . . . . . . . . . . . . . . . . . . . . . . . . Example ofsendReplyHandler override code . . . . . . . . . . . . . . . . . . . . . 580 583 583 584 586 586 587 589 589 590 61 62 63 66 610 611 612 617 617 618 622 624 625 627 628 630 630 631 633 634 635 637 638 640 642 644 645 645 648 650 650 651
vii
Contents 7. Control Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction to control objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartToolbars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Placing a SmartToolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a SmartToolbar instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a new SmartToolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding a filter-control window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartPanels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating and configuring a SmartPanel instance . . . . . . . . . . . . . . . . . . . Basic pushbuttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a pushbutton instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring a pushbutton instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other Objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple (undefined) SmartObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ActiveX (OCX) objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating an ActiveX object instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Configuring an ActiveX object instance . . . . . . . . . . . . . . . . . . . . . . . . . . Generic ActiveX event handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ActiveX (OCX) properties data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Static images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Static text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Timer objects (ActiveX) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Frequently Used Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ActiveX control frame properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADM pages manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced procedure settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Colors selector and editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choosing colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining new colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom lists naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Database field selector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method library includes list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Procedure settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Properties window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartLinks editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartObject properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a SmartObject placeholder . . . . . . . . . . . . . . . . . . . . . . . . . . . . String attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Traversal-path editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Temp-tables maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 72 72 73 74 76 76 79 711 713 714 715 81 82 82 83 84 89 810 810 815 816 A1 A3 A4 A7 A9 A10 A11 A12 A16 A17 A19 A20 A22 A23 A26 A28 A29 A30 A31 A33
8.
A.
viii
Contents Text style selector and editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choosing a type style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Defining a type style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B. Multiple Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why use multiple layouts? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What is a layout? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Two types of layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Master layout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alternate layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating alternate layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Selecting a predefined alternate layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifying layouts with layout inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Layout inheritance behavior at run time . . . . . . . . . . . . . . . . . . . . . . . . . Layout inheritance behavior at design time. . . . . . . . . . . . . . . . . . . . . . . Re-establishing layout inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How multiple layouts work: a look at the code . . . . . . . . . . . . . . . . . . . . . . . . . . . Run-time properties and AppBuilder settings . . . . . . . . . . . . . . . . . . . . . Layout cases internal procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enable_UI internal procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alternate layout limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Modifiable properties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Text widgets in alternate layouts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combo boxes in alternate layouts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SIZE-TO-FIT setting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Switching between layouts at run time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simulating character applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Running character applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Character client connection issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Double-byte characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiple layouts for SmartObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating SmartObject alternate layouts . . . . . . . . . . . . . . . . . . . . . . . . . Modifying SmartObject layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applying SmartObject layouts at run time . . . . . . . . . . . . . . . . . . . . . . . . Customizing AppBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom object files and extended features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating custom object files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . General coding rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Entry types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding a button to the Object Palette . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding a SmartObject to a palette button pop-up menu . . . . . . . . . . . . . Adding a new template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding a widget to a palette button pop-up menu. . . . . . . . . . . . . . . . . . A36 A36 A37 B1 B2 B2 B3 B3 B4 B7 B8 B9 B9 B10 B10 B12 B12 B14 B16 B17 B18 B18 B18 B19 B19 B20 B21 B22 B22 B23 B24 B24 B30 C1 C2 C2 C3 C4 C4 C6 C8 C9 ix
C.
Contents Creating extended features (XFTRs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The &ANALYZE-SUSPEND directive for XFTRs . . . . . . . . . . . . . . . . . . . The event-mapping comment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The compilable code comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The ending comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The &ANALYZE-RESUME directive for XFTRs . . . . . . . . . . . . . . . . . . . . How AppBuilder runs XFTR event handlers. . . . . . . . . . . . . . . . . . . . . . . AppBuilders API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Context IDs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Naming convention. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilders API summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Add/remove SmartLinks (adeuib/_ablink.p) . . . . . . . . . . . . . . . . . . . . . . . Access section (adeuib/_accsect.p) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder database table names (adeuib/_dbtbnam.p) . . . . . . . . . . . . . AppBuilder information (adeuib/_uibinfo.p) . . . . . . . . . . . . . . . . . . . . . . . AppBuilder create (adeuib/_uib_crt.p) . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder delete (adeuib/_uib_del.p) . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder dialog (adeuib/_uib_dlg.p) . . . . . . . . . . . . . . . . . . . . . . . . . . . Window save (adeuib/_winsave.p). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reserved names (adeuib/_namespc.p) . . . . . . . . . . . . . . . . . . . . . . . . . . Example using AppBuilders API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C18 C20 C20 C21 C22 C22 C22 C22 C23 C23 C24 C24 C27 C31 C33 C39 C42 C43 C44 C45 C47 Index1
Contents Figures Figure 11: Figure 12: Figure 13: Figure 14: Figure 15: Figure 21: Figure 22: Figure 23: Figure 24: Figure 25: Figure 26: Figure 27: Figure 28: Figure 29: Figure 210: Figure 211: Figure 212: Figure 213: Figure 214: Figure 215: Figure 216: Figure 217: Figure 218: Figure 219: Figure 220: Figure 221: Figure 31: Figure 32: Figure 33: Figure 34: Figure 35: Figure 36: Figure 37: Figure 38: Figure 39: Figure 310: Figure 311: Figure 312: Figure 41: Figure 42: Figure 43: Figure 44: Figure 45: Design-time representation of a nonvisible SmartObject . . . . . . . . . . . SmartObject Menu Button menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toy phone book application at run time . . . . . . . . . . . . . . . . . . . . . . . . SmartLinks between SmartObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . Toy phone book links in SmartLinks Editor . . . . . . . . . . . . . . . . . . . . . AppBuilder main window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Current-object fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Status bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder tool bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object Palette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Workspace for a visible object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Workspace element for nonvisible object . . . . . . . . . . . . . . . . . . . . . . Section Editor physical interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sections listing dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Find dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Replace dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Field Selector dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choose Event dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Insert Procedure Call dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listing insertable procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preprocessor Names dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query Builder dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object Names dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Choose Insert File Name dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . Code Preview dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stop button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Window property sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Window Advanced Properties dialog box . . . . . . . . . . . . . . . . . . . . . . SmartDialog Property Sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartDialog Advanced Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartFrame Property Sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartFrame Advanced Properties dialog box . . . . . . . . . . . . . . . . . . . Rectangle property sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rectangle Advanced Properties dialog box . . . . . . . . . . . . . . . . . . . . . Paging using a SmartFolder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging using pushbutton controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging using radio-set controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Paging a whole window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilation of a SmartDataObject . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartBusinessObject in a Web environment . . . . . . . . . . . . . . . . . . . Data relationship among five tables . . . . . . . . . . . . . . . . . . . . . . . . . . . Resynchronization hierarchy defined by DATA SmartLinks . . . . . . . . Query Builder in Table mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 112 118 120 121 24 25 26 218 220 238 238 239 240 241 242 245 246 247 249 250 251 252 253 255 256 39 314 317 318 320 321 325 327 336 339 340 341 43 419 420 424 439
xi
Contents Figure 46: Figure 47: Figure 48: Figure 49: Figure 410: Figure 411: Figure 412: Figure 413: Figure 61: Figure 62: Figure 63: Figure 64: Figure 65: Figure 66: Figure 67: Figure 68: Figure 69: Figure 610: Figure 611: Figure 71: Figure 72: Figure 73: Figure A1: Figure A2: Figure A3: Figure A4: Figure A5: Figure A6: Figure A7: Figure A8: Figure A9: Figure B1: Figure B2: Figure B3: Figure B4: Figure B5: Figure B6: Figure B7: Figure B8: Figure B9: Figure B10: Figure C1: Figure C2: Figure C3: Figure C4: xii Sample query for OF-joinable tables . . . . . . . . . . . . . . . . . . . . . . . . . . . Query sample with incomplete join criteria . . . . . . . . . . . . . . . . . . . . . . Query Builder in Join mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query Builder in Where mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query Builder in Sort mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Query Builder in Options mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Column Editor button in Query Builder . . . . . . . . . . . . . . . . . . . . . . . . . Column Editor dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartB2BObject in inter-business communications . . . . . . . . . . . . . . . Simple one-to-one XML mapping in data communication . . . . . . . . . . . Mapping an XML node to a function . . . . . . . . . . . . . . . . . . . . . . . . . . . XML Mapping Tool window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The SmartSender and SmartReceiver in B2B communication . . . . . . . SmartRouter distributing incoming documents . . . . . . . . . . . . . . . . . . . Basic message-handling blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message routing using SmartRouter . . . . . . . . . . . . . . . . . . . . . . . . . . . The Smart Message-interface objects . . . . . . . . . . . . . . . . . . . . . . . . . Outbound message-handling process . . . . . . . . . . . . . . . . . . . . . . . . . Inbound message-handling process . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartToolbar fully enabled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartToolbar in record-changed state . . . . . . . . . . . . . . . . . . . . . . . . . SmartToolbar in transaction-pending state . . . . . . . . . . . . . . . . . . . . . . Pages dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Advanced Procedure Settings dialog box . . . . . . . . . . . . . . . . . . . . . . . Custom lists naming dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartWindow main procedure settings dialog box . . . . . . . . . . . . . . . . Properties Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartLinks editor dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . String Attributes dialog box for static text . . . . . . . . . . . . . . . . . . . . . . . String Attributes dialog box for a combo box . . . . . . . . . . . . . . . . . . . . Tab Editor dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Master layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Character alternate layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alternate Layout dialog box for SmartObjects . . . . . . . . . . . . . . . . . . . . SmartDataViewer master layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartDataViewer Address alternate layout . . . . . . . . . . . . . . . . . . . . . SmartDataViewer Balance alternate layout . . . . . . . . . . . . . . . . . . . . . SmartDataViewer menu buttons pop-up menu . . . . . . . . . . . . . . . . . . Menu buttons pop-up menu in alternate layout . . . . . . . . . . . . . . . . . . Instance property sheet in alternate layout . . . . . . . . . . . . . . . . . . . . . . SmartDataViewer properties with layout options . . . . . . . . . . . . . . . . . Sample entry for SmartObject type . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sample entries for adding a SmartObject master . . . . . . . . . . . . . . . . . Sample entries for new templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XFTR in browser.w template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 440 441 442 443 444 445 446 62 64 65 610 623 627 628 629 633 642 643 74 74 74 A5 A7 A16 A21 A22 A24 A30 A30 A32 B5 B6 B24 B25 B25 B26 B27 B27 B28 B29 C6 C7 C9 C19
xiii
Contents Tables Table 11: Table 12: Table 13: Table 14: Table 21: Table 22: Table 23: Table 24: Table 25: Table 26: Table 27: Table 28: Table 29: Table 210: Table 211: Table 41: Table 51: Table 71: Table 72: Table 73: Table A1: Table B1: Table B2: Table C1: Table C2: Table C3: Table C4: Table C5: Basic 4GL object types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartObject types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ActiveX (OCX) object types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Benefits of using SmartObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . File menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Edit menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compile menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tools Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Layout menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Window menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Help menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Default object tool description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Preference options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Options on the Insert Procedure Call dialog box . . . . . . . . . . . . . . . . . . How to make changes to the data stream . . . . . . . . . . . . . . . . . . . . . . . Dynamic SmartDataBrowser display/update rules . . . . . . . . . . . . . . . . SmartToolbar properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SmartPanels options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Button properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Progress color table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standard layouts and run-time expressions . . . . . . . . . . . . . . . . . . . . . Modifiable properties in alternate layouts . . . . . . . . . . . . . . . . . . . . . . . Custom object files and their contents . . . . . . . . . . . . . . . . . . . . . . . . . Settable attributes for custom widgets . . . . . . . . . . . . . . . . . . . . . . . . . AppBuilder events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Naming conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . API procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 18 110 111 27 29 211 212 214 215 216 217 221 227 248 437 56 75 710 716 A12 B5 B18 C3 C11 C21 C23 C24
xiv
Preface
This Preface contains the following sections: Purpose Audience Organization Using this manual Typographical conventions Examples of syntax descriptions OpenEdge messages
Purpose
This guide provides a basic introduction to using AppBuilder for Rapid Application Prototyping/Development (RAP/RAD).
Audience
Database programmers who appreciate the time and energy advantages of using WYSIWYG layout editors for RAP/RAD. This guide presumes that you understand programming in general, though it does not require that you know the Progress 4GL specifically. You can create simple applications using AppBuilder alone, but you will find it hard to do sophisticated work without at least some programming ability with the Progress 4GL.
Organization
Chapter 1, Introduction Introduces basic terminology and concepts that are important to understand when working with AppBuilder. Chapter 2, AppBuilder Interface Walks through the user-interface elements apart from the common dialog boxes, which are collected together in Appendix A. Chapter 3, Organizer Objects Describes objects that integrate smaller objects functionally or visually. Organizer objects include Windows, Dialog Boxes, Frames, and even the Rectangle. Chapter 4, Data-Access Objects Describes objects that help read and write the logical database. These range from the basic Query object through the powerful SmartBusinessObject. Chapter 5, Data-Display/Capture Objects Describes the many objects that you can use to present the user with information from the data stream, and capture both changes and new data. They range from powerful SmartObjects to the simplest boolean Toggle Box. Preface2
Preface Chapter 6, Data-Communication Objects Describes the transformation and communication objects you can use to create, send, receive, and process data messages. Chapter 7, Control Objects Describes the few objects that provide a nearly-pure control function: SmartToolbar, SmartPanels, and the lowly Pushbutton. Chapter 8, Other Objects Describes those few objects that seem not to fit well elsewhere: Static Text and Image objects, for example. Appendix A, Frequently Used Dialogs Describes the standard dialogs that you will encounter over and over again, nearly unchanged regardless of context. Appendix B, Multiple Layouts Describes how to create, from a single code base, layouts that vary in appearance across platforms and contexts. Appendix C, Customizing AppBuilder Describes ways you can change AppBuilder itself so that it will more closely meet your needs.
Preface3
Typographical conventions
This manual uses the following typographical conventions:
Description Bold typeface indicates commands or characters the user types, or the names of user interface elements. Italic typeface indicates the title of a document, provides emphasis, or signifies new terms. Small, bold capital letters indicate OpenEdge key functions and generic keyboard keys; for example, GET and CTRL. A hyphen between key names indicates a simultaneous key sequence: you press and hold down the first key while pressing the second key. For example, CTRL-X. A space between key names indicates a sequential key sequence: you press and release the first key, then press another key. For example, ESCAPE H.
KEY1 KEY2
Syntax:
Fixed width
A fixed-width font is used in syntax statements, code examples, and for system output and filenames. Fixed-width italics indicate variables in syntax statements. Fixed-width bold indicates variables with special emphasis. Uppercase words are Progress 4GL language keywords. Although these always are shown in uppercase, you can type them in either uppercase or lowercase in a procedure. All statements except DO, FOR, FUNCTION, PROCEDURE, and REPEAT end with a period. DO, FOR, FUNCTION, PROCEDURE, and REPEAT statements can end with either a period or a colon. Large brackets indicate the items within them are optional. Small brackets are part of the Progress 4GL language. Large braces indicate the items within them are required. They are used to simplify complex syntax diagrams.
[]
[]
{}
Preface4
Preface
Convention {}
Description Small braces are part of the Progress 4GL language. For example, a called external procedure must use braces when referencing arguments passed by a calling procedure. A vertical bar indicates a choice. Ellipses indicate repetition: you can choose one or more of the preceding items.
| ...
FOR
is one of the statements that can end with either a period or a colon, as in this example:
DISPLAY
STREAM stream
] [
UNLESS-HIDDEN
] [
NO-ERROR
In this example, the outer (small) brackets are part of the language, and the inner (large) brackets denote an optional item:
INITIAL [ constant
, constant
Preface5
OpenEdge Development: AppBuilder A called external procedure must use braces when referencing compile-time arguments passed by a calling procedure, as shown in this example:
{ &argument-name }
In this example, EACH, FIRST, and LAST are optional, but you can choose only one of them:
PRESELECT
EACH
FIRST
LAST
record-phrase
In this example, you must include two expressions, and optionally you can include more. Multiple expressions are separated by commas:
, expression
] ...
In this example, you must specify MESSAGE and at least one expression or SKIP [ (n) any number of additional expression or SKIP [ ( n )
], and
] is allowed:
MESSAGE
expression
SKIP
( n )
] } ...
&argument-name = "argument-value",
In this example, you must specify {include-file, then optionally any number of argument or and then terminate with }:
{ include-file
argument
&argument-name = "argument-value"
] ...
Preface6
Preface
ACCUM max-length
[ [
] [ STREAM-IO ]
CENTERED
n COLUMNS
FRAME frame ] { field [ = expression ] } [ WHEN expression ] } ... | { record [ EXCEPT field ... ] }
{ [
Preface7
OpenEdge messages
OpenEdge displays several types of messages to inform you of routine and unusual occurrences: Execution messages inform you of errors encountered while OpenEdge is running a procedure; for example, if OpenEdge cannot find a record with a specified index field value. Compile messages inform you of errors found while OpenEdge is reading and analyzing a procedure before running it; for example, if a procedure references a table name that is not defined in the database. Startup messages inform you of unusual conditions detected while OpenEdge is getting ready to execute; for example, if you entered an invalid startup parameter.
After displaying a message, OpenEdge proceeds in one of several ways: Continues execution, subject to the error-processing actions that you specify or that are assumed as part of the procedure. This is the most common action taken after execution messages. Returns to the Progress Procedure Editor, so you can correct an error in a procedure. This is the usual action taken after compiler messages. Halts processing of a procedure and returns immediately to the Progress Procedure Editor. This does not happen often. Terminates the current session.
OpenEdge messages end with a message number in parentheses. In this example, the message number is 200:
If you encounter an error that terminates OpenEdge, note the message number before restarting.
Preface8
Preface
Preface9
Preface10
1
Introduction
According to many industry estimates, in applications with a graphic user interface, the GUI itself might account for as much as 75% of the total application code. The OpenEdge AppBuilder tool is a Rapid Application Prototyping/Development (RAP/RAD) tool similar in concept to, for example, Microsofts Visual development tools. The main component of AppBuilder is a What-You-See-Is-What-You-Get (WYSIWYG) interface layout editor. AppBuilder appreciably simplifies your application programming effort by: Supporting drag-and-drop layout of interface elements. Creating the object description and initialization code on your behalf. Helping you create and manage the integrating code.
OpenEdge Development: AppBuilder This chapter briefly introduces some important concepts, and describes AppBuilder and its place in the Progress 4GL application programmers toolkit: OpenEdge Application Development Model Concepts and terminology What is smart about SmartObjects? Visible versus nonvisible objects Widgets Reading and writing 4GL widgets Inter-object communication: signatures Anatomy of a database application Working with AppBuilder Single-window or multi-window design? Designing for character-based environments Building an application in AppBuilder
12
Introduction
For detailed information about the Application Development Model, see OpenEdge Development: ADM and SmartObjects. The related API reference is OpenEdge Development: ADM Reference.
13
RUN example.w.
External procedures typically have some number of internal procedures and functions defined locally to them. Because these internal procedures and functions implement the external procedures repertoire of behaviors, they are often known as methods. They are defined as normal Progress 4GL subprograms and begin with one of the reserved words PROCEDURE or FUNCTION.
AppBuilder objects
AppBuilder provides for your use a full array of basic 4GL objects, several powerful ADM SmartObjects, and even three ActiveX (OCX) objects. Basic objects are objects that are available directly as part of the Progress 4GL, for example in a VIEW-AS clause. Some are very basic indeedstatic rectangles, for examplewhile others, such as Editors, can be quite complex underneath.
14
Introduction Table 11 lists the basic Progress 4GL objects available in AppBuilder. The descriptions represent how the objects appear under MS-Windows. Table 11: Role Organizer Basic 4GL object types Object Window Description The outermost organizer object. It is not modal, can have a menu bar and pulldowns, and can parent all other objects. Technically a type of frame with its own dedicated window. Dialog boxes are modal, cannot have a menu bar, cannot be resized, and must be parented by a window. You typically use them for capturing user input on a specific issue. An object that delimits a rectangular area and defines a TAB-traversal group. Frames can have their own border and title bar. You can use frames to organize and display other objects. A static object that visually delimits a rectangular area. You can use a rectangle to group other objects for emphasis. A rectangle does not define a traversal group or have any active characteristics; it is purely a visual object. A group of related instructions that tell OpenEdge to find a subset of records from one or more database tables. This is a standalone object, but several objects have a query function embedded in them. An object that displays the results of a database query in row/column tabular format. Each row represents a record, and each column a field. Usually called a browse widget. (1 of 3)
Dialog box
Frame
Rectangle
Data access
Query
Data browser
15
OpenEdge Development: AppBuilder Table 11: Role (Data display and capture) Basic 4GL object types Object Combo box Description An object that combines a fill-in with a selection list. The fill-in shows the current value. The user can set the value by typing into the fill-in, or by picking an item from those in the list. An object that displays the results of a database query one record at a time, using one fill-in per field. Also called a DB-Fields widget A field-level object that allows editing of large (typically multi-line) character fields. By default, editors support features such as cut, copy, paste, and word-wrap. A field-level object that accepts user input, typically a single line of text. The system evaluates that text, possibly performing additional processing such as type conversion and validation, and assigns the result to a database field or a variable. A group of buttons representing a set of values for a variable, only one of which can be valid at a given time. Selecting a button automatically deselects the previous choice. A scrollable list of character strings. The strings are the possible values for an underlying field or variable. You can use a selection list to allow an end user to select one or several items from a predetermined list of character values. (2 of 3)
Data viewer
Editor
Radio-button set
16
Introduction Table 11: Role (Data display and capture) Basic 4GL object types Object Slider control Description A virtual knob that the user moves along a track. The track represents some subrange of INTEGER; a built-in readout displays the current value. The limiting values are -32,768 and 32,767. Only a value of type INTEGER, without extent, can be displayed by a Slider. A small, square box that represents a logical value. You can use groups of check boxes to represent sets of properties. A field-level object that a user typically selects to invoke some action. AppBuilder offers one generic pushbutton plus others predefined for special purposes. Standalone text that is not bound to any other object, though it might appear to be. A static field-level object used to display a bitmap from a graphics file. The Progress 4GL supports many different graphic formats under MS-Windows. (3 of 3)
Other
SmartObjects are much more complex than the objects listed in Table 11. True subprogram modules, SmartObjects are external procedures that may contain hundreds of lines of 4GL code in themselves and their superprocedures. All SmartObjects are implemented as external procedures, but only those external procedures based on the file smart.i qualify as SmartObjects.
17
OpenEdge Development: AppBuilder Table 12 lists the SmartObjects available in the current release, and the abbreviations used elsewhere in this document. Table 12: Role Organizer SmartObject types SmartObject SmartWindow (SWin) Description Outermost Smart organizer object. Acts as a container and integrator for other objects, including other SmartContainers such as SmartFrames, etc. A Smart, special-purpose frame object supported by a dedicated window. Allows you to create reusable Smart layouts not suited to implementation as SmartDialogs. Implements the tabbed-file-folder metaphor for managing paged interface displays. Provides all functionality from the class without the overhead of a visible window. Useful for modules that can operate unattended in the background.
SmartContainer
(1 of 3)
SmartDialog (SDialog) SmartFrame (SFrame) SmartFolder (SFolder) Simple SmartContainer (SSC) Data access SmartDataObject (SDO)
A query interface to a database. This object, available in both static and dynamic forms, supplies the data stream used by other objects such as the SmartDataViewer or the SmartDataBrowser. An SDO has no visible representation at run time. A dedicated organizer object that integrates up to 20 SDOs, providing a single point of contact for other objects. In addition, the SBO allows you to update from multiple SDOs in a single server-side transaction. A dynamic record-filtering object, visible at run time. Offers the user the ability to focus the associated SmartDataObjects query as tightly as desired.
SmartBusinessObject (SBO)
SmartFilter (SFilter)
18
Introduction Table 12: Role Data display and capture SmartObject types SmartObject SmartDataBrowser (SDB) Description Encapsulates a browse widget to view and possibly update data. Displays in a row/column format, and can present the fields for multiple records simultaneously. Presents a set of fields representing a single record. You can order and arrange the fields visually in any way that meets your needs. Adds special-purpose functionality to a SDV on a per-field basis. The special functionality can be of any desired sophistication. A specialized SmartDataField representing a data-driven pick list. You would use it for updating a field in one table based on the values drawn from a related table. Transforms message-body blocks of data between 4GL and XML representations based on a protocol (mapping) file that you create. Transforms message-body blocks of data in ways that you define. The code you write can be anything from no-ops to the most sophisticated transformations; these are very general tools. Determines which SBB should handle some message received by a SmartConsumer, and starts that object. These objects are the SmartObject interface to the SonicMQ messaging system. The SProdr creates message bodies for use by other objects, and inserts them into the message system when complete. The SConsr watches the inbound piplelines and passes incoming messages upstream for processing. (2 of 3)
Data communication
SmartB2BObject (SBB)
SmartSender (SSndr) and SmartReceiver (SRcvr) SmartRouter (SRtr) SmartProducer (SProdr) and SmartConsumer (SConsr)
19
OpenEdge Development: AppBuilder Table 12: Role Action Control SmartObject types SmartObject SmartToolbar (STB) SmartPanel (SP) Other Simple SmartObject (SSO) Description A general-purpose control object, optionally combining a menu-bar system with a toolbar object. A cluster of dedicated pushbuttons. AppBuilder offers versions for Navigation, Update, and Commit. An unfinished object that serves as a basis for new SmartObject types that you might wish to define. (3 of 3)
In addition to basic 4GL objects and ADM-compliant SmartObjects, AppBuilder also supports the popular ActiveX object type. ActiveX (OCX) objects resemble SmartObjects in implementing complex functionality, but are defined on Microsofts ActiveX standard rather than the ADM. ActiveX components are available from many third-party sources. Table 13 lists the ActiveX (OCX) objects AppBuilder provides for your use. Table 13: Role Data display and capture ActiveX (OCX) object types ActiveX object Combo box Description An object that combines a fill-in with a hidden selection list. Once the user makes the selection list visible by pressing the associated button, choosing from the listed items sets the current value of the fill-in. Two opposed pushbuttons and an optional readout field. Operating one of the pushbuttons changes the value of the object either up or down. Generates an event at some regular interval that you specify.
Spin control
Other
Timer
110
Introduction
Easier integration
Greater consistency
Establishes a consistent look and feel across multiple applications because different applications can instantiate the same SmartObject master. This consistency makes it easier for you to create a special corporate image for your customers, if you choose.
111
All SmartObjects display a Menu button (sometimes called a Ventilator button) as part of their design-time representation. The menu under the Menu button, shown in Figure 12, provides access to the objects property sheets, SmartLinks, and master definition.
Figure 12:
Other nonvisible objects are generally represented by simple, abstract icons. They exhibit little commonality in the details of their appearance.
112
Introduction
Widgets
The word widget is a synonym for thing or item; it is a generic reference. In recent years, widget has become a widely used term among programmers for a user-interface element. The 4GL follows this convention. In its role as a WYSIWYG layout editor, AppBuilder provides a design-time user-interface element even for objects that are neither part of the run-time user interface nor even visible at run time. In this guide, therefore, the term widget will be used freely as a synonym for object or building-block, regardless of whether it is a widget in the 4GL sense of the term.
The syntax of this statement can give the impression to a programmer familiar with other languages that, in the 4GL environment, basic widgets are mere visual expressions of data (VIEW-AS) handled entirely at the level of the r-code interpreter. If that were so, then an assignment statement such as:
iExampleSlider = 8192.
would immediately cause (in this example) the knob of the slider widget to move halfway up the track. The actual situation is slightly more complicated.
113
OpenEdge Development: AppBuilder Each widget represents two storage locations, not one. There is the storage location that you identify with the widget when you create the instanceiExampleSlider in the exampleplus an anonymous storage location conceptually allocated in the system display buffer. These locationsmain memory and screen displayare independent of one another, from the standpoint of your code. User keyboard and mouse actions modify the anonymous location in the display buffer; assignment statements modify the identified location in main memory. A change made to one of the locations is not automatically reflected in the other location. You must explicitly close that gap by copying changes from one storage location to the other whenever required by the logic of your program. If you want changes made to a variable to appear on the display, use DISPLAY:
iExampleSlider = 8192. DISPLAY iExampleSlider WITH FRAME fMain. /* replace fMain with the actual identifier of the frame that encloses the iExampleSlider widget */
If you want changes made to the display to reflect in the variable, use ASSIGN:
/* copy the current value from the anonymous location */ ASSIGN iExampleSlider. /* insert code here that uses the widget value */
The benefit of such a disconnected model is speed. Since device I/O is very slow compared to operations on memory, it is better not to do device i/o except when necessary. The Progress I/O model helps you manage that problem. Note: The 4GL is much more complex, sophisticated, and adaptable than this brief introduction might imply. DISPLAY and ASSIGN are not the only routines that can move data between the two storage locations. Use this information as a way to make things happen while you are learning more subtle methods.
114
Introduction
Finding records involves opening a database file and searching through it for records that have certain characteristics. The desired characteristics are defined in a query. A query might be as simple as get all records or highly complex, involving comparisons on many different fields in a multitude of records. Records returned by a query can be displayed in tabular format for easy browsing, formatted in a more complex way suitable for editing, or used to generate, for example, mailing labels. Modifying a record is a simple clerical process on one level. But because humans are involved, mistakes are virtually guaranteed to occur. A careful developer will account for this fact and take steps to check the changes being made, insofar as checking is practical. Once changes have been made, the modified records must be written back to the database. This can be done immediately, for simple updates, or buffered to a staging area as part of a more complex transaction process. AppBuilder supports objects that address all four steps in this framework.
115
AppBuilder can help with steps 2 through 4. Application design is beyond the current scope of this guide. The design process has both a technical and a usability aspect, and those developers who pay attention to both are generally the most successful. There are a number of formal tools and methodologies that can help with technical design. Use whichever seems best. At present, however, there are no similar tools to help you make your application easy and pleasant to use. The best advice is to test your design assumptions early and often with real users. There are books on usable software design that can help acquaint you with those techniques.
Multi-window designs might work well for applications that present separable but related clusters of functionality.
116
Introduction Multiplexed (paged, paneled) designs may seem the most natural choice for applications that require a mixed interface, where there is a certain core functionality that remains in view while another part of the window changes in a task-oriented way. No matter what you choose, you will probably find that you can make legitimate arguments for a different choice. The advantages of one design over another are typically relative, not absolute. For example, AppBuilder itself uses a multi-window design (main, palette, workspace), yet it is not hard to imagine it as a single-window design instead. Multi-window applications are generally somewhat more difficult to design and develop. You might decide during the design phase of the project that there are advantages to a multi-window design, but that they are outweighed by the practical difficulties. Or you might decide that the advantages you could offer your customer make a multi-window design well worth the extra effort required to create it. For more information on single-window versus multi-window design issues, see OpenEdge Development: Progress 4GL Handbook.
117
SmartPanels
Simple pushbutton
Figure 13:
118
Introduction This application illustrates some important features of AppBuilder: The SmartWindow is an organizer object and a member of the class SmartContainer. SmartContainers supply an integrating context for other SmartObjects. Higher-level organizer objects such as windows, dialogs, and frames provide an integrating context for all objects placed in them, but the level of integration depends on the objects involved. The SmartDataViewer, like most SmartObjects, is incorporated into the application as an instance of a master object. You create a SmartObject master in a separate operation before assembling the final application window. SmartObject masters are based on one of several SmartObject templates that are provided by AppBuilder. The two SmartPanels are supplied by AppBuilder predefined and precompiled. You simply select and place them. SmartObjects communicate smoothly with each other behind the scenes. For example, clicking on the navigation buttons in the SmartPanel causes the SmartDataViewer to display a new record. This command and data communication between SmartObjects takes place along SmartLink pathways. AppBuilder helps create appropriate SmartLinks during the application assembly process. Each SmartLink represents a type of message to be sent when an event occurs. The messages are sent by the SmartObject experiencing the event to all other SmartObjects that are registered as being interested in events of that kind. Although it is not visible at run time, the SmartDataObject is a critical component of this application. It is the object that receives the navigation requests from the SmartPanel and supplies the data to the SmartDataViewer for display and, perhaps, modification. Note that in Figure the SmartDataObject widget is obscuring part of the large static text object, yet the text is completely visible in Figure 13. You can place nonvisible objects such as the SmartDataObject anywhere you like in your workspace. They are totally invisible at run time. The two static rectangle widgets serve to visually pull together and regularize the edges of the controls and the viewer object. Enclosing related widgets is one way to make them seem more related and reduce the sense of clutter. Even purely visual elements, used wisely, can greatly enhance the usability of your applications. Here, widening the border and filling the upper rectangle with color (modifying the colors in the Viewer to agree) creates a bit of additional visual interest, though the deep blue color might be less appropriate in a real application than in this toy one.
119
OpenEdge Development: AppBuilder The basic, static text object is an example of a special font definition. Used carefully, special fonts can add to the usability and the visual appeal of your applications. The Done pushbutton is another basic object. At run time, choosing the Done button ends execution and releases resources in an orderly way. AppBuilder supplies a number of predefined pushbuttons as well as a generic one. When you add such a dedicated button to the layout, AppBuilder automatically generates appropriate trigger code. When you create your own applications, you have the option of choosing from the set of predefined buttons, or using the generic pushbutton and writing your own trigger code. The Done button is an example of a custom object definition. It is defined in the progress.cst file. For information about creating and making available your own custom objects, see Appendix C, Customizing AppBuilder. Figure 14 shows the SmartLinks connecting the SmartObjects in the toy application. Conceptually, SmartLinks are dedicated, directional message pathways between two SmartObjects. The event-Source object experiences an event, and reports that event to the event-Target object using the 4GL Publish/Subscribe mechanism.
SmartDataViewer
Data
Update
TableIO
Figure 14 shows four SmartLinks. The first is a Navigation SmartLink between the Navigation SmartPanel and the SmartDataObject. When the user chooses one of the pushbuttons in the SmartPanel array, SmartPanel sends a Navigation message to the SmartDataObject, asking it to change the position of its current-record pointer.
120
Introduction Whether this will mean a new read from the storage device is a matter for the SmartDataObject to decide, based on factors including the size of the RowObject temp-table you declared when creating it. The SmartPanel knows nothing about such matters; SmartObjects are only loosely coupled to one another. When the SmartDataObject has changed its pointer in response to the request from the SmartPanel, it sends a Data message to the consumer of the data stream it supplies: the SmartDataViewer. When the user changes the data, and confirms the change using the Update Panel, the Update Panel reports that confirmation to the viewer, and the viewer sends an Update message back to the SmartDataObject. Not shown in Figure 14 are links between the SmartContainer (the SmartWindow) and the SmartObjects that it contains, because those links are automatically created and removed by AppBuilder as you add and remove SmartObjects from the SmartContainers workspace. You never have to deal with them explicitly. Figure 15 shows how these four links appear in the SmartLinks Editor. For further information about the editor, see the SmartLinks editor section on page A23.
Figure 15:
121
122
2
AppBuilder Interface
The AppBuilder interface has a number of components: Main window Object Palette Workspace windows Source-code Section Editor Various dialog boxes for object properties, etc.
This chapter describes the AppBuilder user interface in detail, and explains how to use it. It includes these sections: Starting and stopping AppBuilder AppBuilder main window Object Palette Setting your preferences Workspaces: design windows and source-code editors
OpenEdge Development: AppBuilder Editing source code safely: the Section Editor Configuring look-and-feel: object properties Inspecting a procedure file Test-driving your design Saving your work
22
AppBuilder Interface
PROWIN32.EXE -p _ab.p
You can also choose AppBuilder from the MS-Windows Start menu.
23
Stopping AppBuilder
You can end your development session and exit AppBuilder by any of these actions: Choose FileExit from the AppBuilder main menu. Click on the close icon in AppBuilders main window. Select Close from the pop-up menu of the small AppBuilder icon on the main window.
24
AppBuilder Interface The AppBuilder main window is divided into four areas: Menu bar Tool bar Current object fields Status bar fields
See the Menu bar section on page 26 for a description of the menu bar and the related toolbar.
Current-object fields
The current-object fields display the Object identifier and, often, additional information such as a text or label string. Both fields are generally editable. Figure 22 shows current object fields for a SmartWindow.
Figure 22:
Current-object fields
The current object is a single object that is part of the design window. Only one object can be current at a time. Thus, if you select more than one object in a design window, nothing will be listed in these fields. The current object fields display the following information: Object Specifies the name (identifier) of the current basic 4GL widget, SmartObject instance, structured procedure file, method library, or structured include file. For character windows, this field displays the words TERMINAL-SIMULATION when the window is selected. No window name displays because in character mode there is never more than one window open. If some object in the window is selected instead, that objects identifier displays here. Title/Label/Text/Master/File For basic widgets other than text, specifies the title or label, if one is available. For text objects, which have no label or title, this field displays the text widgets string value. For structured procedure files, method libraries, and structured include files, it specifies the pathname of the procedure file.
25
Status bar
Figure 23 shows the status bar.
Figure 23:
Status bar
From left to right, these fields display: Status information about current AppBuilder activity. The Design Page in the current smart organizer object. If the current organizer/container is not smart, this field is blank. The name of the currently selected object type in the Palette. For example: SmartDataBrowser. The text LOCK if the current object icon is latched (locked) down for multiple placements. It is blank otherwise.
Menu bar
The menu bar provides access to nearly all the AppBuilder functionality, apart from the component objects. Note that some menu options are not available when you are working in WebSpeed development mode.
26
AppBuilder Interface
File menu
The File menu allows you to create, open, save, and print procedure files, as shown in Table 21. Table 21: File New... Open... Close Close Windows... Save Save As... Save All... Print Creates a new external procedure or component file. Opens an existing external procedure or component file. Closes the current file. Closes some or all of the active windows. Saves the current objects files. Saves the current objects files, possibly under a different name. Saves all open files. Prints the source for the current procedure-based object. File menu
(List of the most-recently-used structured-procedure objects.) Exit FileNew Opens the New dialog box. After you choose the object or component you want to create, AppBuilder reads in the appropriate template. A template is an incomplete procedure file for an object. After loading the template, AppBuilder will take some further, template-specific action: Windows, dialog boxes, and outer-level frames: AppBuilder opens a design window or workspace where you assemble and arrange the widgets that will make up your applications user interface. AppBuilder also opens a workspace if you choose Simple SmartObject, since the majority of SmartObjects will have a visible representation. When designing WebSpeed applications, you do not work with a design window. See OpenEdge Getting Started: WebSpeed tutorial for an overview. Exits the current AppBuilder session.
27
OpenEdge Development: AppBuilder SmartObjects based on a master: AppBuilder starts the design wizard for that class of object. After the design wizard runs to completion, you will have a fully defined SmartObject master that you will normally save to disk. Procedure, include file, or methods library: AppBuilder opens two windows. One shows a tree view of the editable sections of that file type, and the other displays the built-in source-code section editor with a code stub for the current section type.
FileOpen Opens an existing object file and displays its associated design window or tree view. If AppBuilder cannot determine how to present the file in a better way, it will use a procedure window. You can also drag and drop a file from the MS-Windows Explorer or desktop to the AppBuilder main window. AppBuilder opens the file according to type, and prompts you to connect to any necessary databases. FileSave Saves the current procedure file locally or remotely, according to your current development mode. AppBuilder prompts you for a filename only if you have not saved this file before. FileSave As Opens the Save As dialog box for the current procedure file. Normally you would Save As in order to change the filename, but you can Save As to the original filename if you wish. FileSave All Immediately performs a save on all open files being maintained by AppBuilder. Newly-created files are saved locally or remotely according to the Development Mode setting. Previously-existing files are saved to the locations from which they were opened, regardless of the Development Mode setting. Caution: You must perform individual saves on any files that AppBuilder opens in a Procedure Editor window rather than a Section Editor. Use of the Procedure Editor means that AppBuilder does not maintain the file.
28
AppBuilder Interface FilePrint Prints the source code of the current structured-procedure file, not the currently selected object specifically. If you clear the Use Print Dialog Box option in the Preferences dialog box, the file is printed to the default printer immediately, without further prompting.
Edit menu
The Edit menu allows you to perform a number of coarse-grain, generic editing operations such as cutting and pasting, as shown in Table 22. Table 22: Edit Undo Cut Copy Paste Duplicate Delete Copy to File... Insert from File... Tab Order... Goto Page... EditUndo Shortcut: CTRL-Z Undoes the most recent operation, including a Delete, if possible. The menu item text shows what that operation was. Item temporarily changes to Redo after an Undo. If undoing the most recent operation is not possible, this item is greyed out. Undoes the most recent operation, if possible. Item temporarily changes to Redo after an Undo. Moves the current selection to the system Clipboard. Copies the current selection to the system Clipboard. Copies the contents of the system Clipboard to the current cursor location. Duplicates the selection. Removes the selection permanently, unless Undone. Exports the selection to a file on disk. Imports the objects defined in a file on disk. Sets the traversal order for the current frame. Changes the current ADM page. Edit menu
29
OpenEdge Development: AppBuilder EditCut Shortcut: CTRL-X Cuts the currently selected object, if any, to the clipboard. EditCopy Shortcut: CTRL-C Copies the currently selected object, if any, to the clipboard. EditPaste Shortcut: CTRL-V Pastes a copy of the current clipboard contents to the current workspace, at the current cursor position. EditDuplicate Creates a copy of the currently selected object without using the Clipboard. The new copy is pasted directly on top of the original. To see the original, the duplicate must first be moved out of the way. EditDelete Removes the currently selected object, if any. You can recover a deleted object if you can Undo the operation, but you cannot recover by pasting because the Clipboard is not involved. EditCopy to FIle Opens a dialog box to copy the source code for the currently selected object to an export (.wx) file. EditInsert from File Opens a dialog box to insert the contents of some file into the procedure editor at the current insertion point. EditTab Order Only enabled when a frame is selected, this item opens the editor that allows you to define the traversal order for objects in the frame. The editor offers five predefined orderings plus a custom ordering that you can define on a per-frame basis. EditGoto Page Only enabled when editing a SmartContainer. Opens the dialog box that lets you set the ADM Design Page. See the Simple SmartContainers section on page 328 for information about the meaning of the Design Page. 210
TAB
AppBuilder Interface
Compile menu
The Compile menu allows you to invoke the Progress interpreter to inspect, test, and debug your work, as shown in Table 23. Table 23: Compile Run Check Syntax Debug Code Preview Close Character Run Window CompileRun Shortcut: F2 Compiles and runs the current workspace. While the workspace is running, no AppBuilder control is available other than the Stop button, which appears in place of the Run button in the toolbar. CompileCheck Syntax Shortcut: SHIFT-F2 Does a syntax check on the current workspace without running it. CompileDebug Shortcut: SHIFT-F4 Compiles the current workspace and starts the Application Debugger. CompileCode Preview Shortcut: F5 Opens a source-code viewer on the currently selected SmartObject master. If the currently selected SmartObject is an instance rather than a master, the viewer window will instead display the source of the current container object (workspace). CompileClose Character Run Window Closes the currently open character-mode test window, if any. Compiles and runs the current workspace. Compiles but does not run the current workspace. Starts the debugger on the current workspace. Opens a read-only window on the current source file. Closes the current character-mode window. Compile menu
211
Tools menu
The Tools menu, as shown in Table 24, gives you access to several of the important AppBuilder dialog boxes as well as the other OpenEdge tools installed on your system. Table 24: Tools New Procedure Window New ADM Class... Property Sheet... Procedure Settings... Color... Database Connections... Opens a version of the Procedure Editor in a new window. Tools Menu
Creates all files for a new class under the ADM standard. Opens the base property sheet for the current object. Opens the base procedure-settings dialog box for the current procedural object. Sets colors for the current selection. Connects and disconnects databases.
(List of all OpenEdge tools installed on your system.) ToolsNew Procedure Window Shortcut: CTRL-F3 Opens a version of the Procedure Editor, with a reduced number of menu items. The Procedure Editor is not AppBuilders built-in Section Editor, and should not be used to edit files that were created by AppBuilder. (Note that the behavior of this Procedure Editor may be slightly different to that of the standard Progress editor of the same namethe two do not use the same underlying code.) ToolsNew ADM Class Opens a dialog box to allow basic definition of a new class, generating all the relevant files. Entering the classname automatically fills in the blanks for the other fields. ToolsProperty Sheet Opens the appropriate base-properties dialog box for the current object.
212
AppBuilder Interface ToolsProcedure Settings Opens the file-level properties dialog box for the current procedure file. Procedure settings include the: Type of procedure file. Filename. Description. Location of the properties for ActiveX objects, if any, in this context. Directory in which AppBuilder compiles the procedure file. External tables (if any) required for the procedure file. Settings for running from AppBuilder. Custom lists available for the procedure file. Relevant information about partition and pages, if the file represents a SmartObject.
Additionally, if you open a template, you can access the templates advanced procedure settings. These settings determine, among other things, what types of objects you can place in a design window. For more information, see the Procedure settings section on page A20. ToolsColor Opens the color selector for the current object. Not available in Remote (WebSpeed) mode. ToolsDatabase Connections Opens a window to display, add to, or remove current database connections.
213
Options menu
The Options menu, as shown in Table 25, allows you to set both general and editor-specific preference items, and change the visibility and magnetism of the layout grid. Table 25: Options Preferences... Editing Options... Snap to Grid Display Grid OptionsPreferences Opens the dialog box that allows you to set various preferences. See the Setting your preferences section on page 226 for detailed information. OptionsEditing Options Opens the dialog box that allows you to set editing-environment preferences such as color-coding, tab size, etc. See the Setting your preferences section on page 226 for detailed information. OptionsSnap to Grid Determines whether objects will snap to the nearest gridline(s) in frames. The gridlines need not be visible. This switch affects all layout workspaces, not just the current one. OptionsDisplay Grid Determines whether layout gridlines will be visible. This switch affects all layout workspaces, not just the current one. Opens the Preferences dialog box. Opens the dialog box for editor-specific preferences. Turns the layout-grid magnetism on and off. Turns the visibility of the layout grid on and off. Options menu
214
AppBuilder Interface
Layout menu
The Layout menu allows you to define additional layouts and to arrange selected objects in regular ways, as shown in Table 26. Table 26: Layout Alternate Layout... Center Left-to-Right in Frame Center Top-to-Bottom in Frame Even Spacing Left-to-Right Even Spacing Top-to-Bottom Move-to-Top Move-to-Bottom Align Opens the Alternative Layout dialog box. Centers selected objects horizontally. Layout menu
Moves the selected object all the way forward. Moves the selected object all the way back. Allows you to align multiple objects along a selected feature.
LayoutAlternate Layout Opens the Alternate Layout dialog box. You can define the conditions for additional layouts using this dialog box. For more information, see Appendix B, Multiple Layouts. LayoutCenter Left-to-Right in Frame LayoutCenter Top-to-Bottom in Frame Centers all selected objects along one axis (X or Y) within the frame, without changing their positions on the other axis. LayoutEven Spacing Left-to-right LayoutEven Spacing Top-to-Bottom Evenly spaces the objects from one another along one axis (X or Y) without changing the overall space they take up, and without changing their positions on the other axis.
215
OpenEdge Development: AppBuilder LayoutMove-to-Top LayoutMove-to-Bottom Changes the Z-axis layering order of the selected object. Moving it to the top makes it seem to overlay all other objects (that is, it makes the object seem closest to the viewer); moving it to the bottom makes it seem to be overlaid by all other objects (makes it seem furthest away). Some objects do not respond to relayering requests. LayoutAlign Opens a submenu where you can choose the feature on which to align multiple objects. Objects can be aligned on their: Label colons. Left or right edges, or horizontal center (vertical centerline). Top or bottom edges, or vertical center (horizontal centerline).
Window menu
The Window menu provides access to the built-in Section Editor, the common-properties editor window, the OCX properties editor, and a list of current objects, as shown in Table 27. Table 27: Window Code Section Editor Hide Object Palette Properties Window OCX Property Editor Window menu Action Invokes built-in source-code editor Determines whether the objects palette is visible. Opens common-properties window. Opens OCX properties window.
(List of procedure objects currently open) WindowCode Section Editor Shortcut: CTRL-S Invokes the built-in source-code editor on the current object. Unlike other editors, including the standard Procedure Editor, the built-in Section Editor will not make object source code unmanageable by AppBuilder.
216
AppBuilder Interface WindowHide Object Palette Determines whether the Object Palette is visible. The menu item changes to Show Object Palette when the Object Palette is hidden. WindowProperties Window Opens the window that lists certain of the common properties of all selected objects. For example, all objects have an origin and a size. Where property values differ between objects, as is typically the case, the differences are represented by a range in the Properties window. You can set substitute a single value for the range, and this will affect all selected objects. WindowOCX Property Editor If the current object is an ActiveX object, opens an editor window for the objects properties. If the current object is not an ActiveX object, selecting this item opens a window with no content.
Help menu
The Help menu provides access to useful information of various kinds, as shown in Table 28. Table 28: Help Help Topics Messages... Recent Messages... Cue Cards... About AppBuilder HelpHelp Topics Opens the online help window. HelpMessages Opens a window that displays the text associated with the message number you enter. Help menu Action Opens the Online Help window. Displays text associated with a message number. Allows you to review recent messages. Allows you to review recently dismissed cue cards. Provides information about the current AppBuilder version.
217
OpenEdge Development: AppBuilder HelpRecent Messages Opens a window that allows you to review recent messages that AppBuilder generated, if any. HelpCue Cards Opens a window that displays recently dismissed cue cards, if any. HelpAbout AppBuilder Opens a window that displays the version of AppBuilder you are running, the current version of the operating system, and the total and free hardware memory.
Tool bar
Most buttons on the tool bar correspond to menu options. The exceptions are the List Objects button, and the Development Mode switch. The Development Mode switch is a special option not present in all versions of AppBuilder. See Figure 24. Procedure settings Edit code Object properties Development mode switch
New
Save
Open
Run
List objects
Colors
Figure 24:
You can use the MS-Windows Tooltip feature to view the action labels for each button. For a more complete description of the buttons function, see the description for the corresponding menu item, as noted. Click on the tool bar buttons to invoke the following AppBuilder actions: New Corresponds to FileNew. Open Corresponds to FileOpen. Save Corresponds to FileSave.
218
AppBuilder Interface Print Corresponds to FilePrint. Procedure Settings Corresponds to ToolsProcedure Settings. Run Corresponds to CompileRun. Edit Code Corresponds to WindowCode Section Editor. List Objects Invokes the List Objects dialog box, which lists all the objects in use in the AppBuilder session, allowing you to access their Property Sheets. There is no other way to open this dialog box. Object Properties Corresponds to ToolsProperty Sheet. Colors Corresponds to ToolsColor. Development Mode Switch If present, alternates the development mode between local and remote. These modes affect where AppBuilder compiles, runs, and saves objects. For more information on using remote (WebSpeed) development mode, see OpenEdge Getting Started: WebSpeed.
Object Palette
For your convenience, the Object Palette makes available all the component objects supplied with AppBuilder. Only the major organizers (windows, dialogs, SmartFrame) are not on the Palette. Create them from the list in the FileNew dialog box.
219
Figure 25:
Object Palette
Each icon has a MS-Windows Tooltip that identifies it. Or, if you would prefer to work with a pulldown menu of object names instead of the icons, select the OptionsShow Menu Only item on the Palettes menu. By dragging the edge of the Palette appropriately, you can change the shape of the Palette through a broad range, from one (long) row to two columns. You can also choose where to position the Palette within the MS-Windows display area.
220
AppBuilder Interface Table 29 shows the default set of object tools: Table 29: Icon Default object tool description Description Pointer This tool does not create any object; it is part of AppBuilder itself. Use this tool when selecting, rearranging, or resizing objects in the visual-layout workspace. Also choose this tool if you wish to change your mind after selecting another tool but before placing that object. Basic data viewer (DB-Fields) Prompts you to connect a database, if necessary, and then to identify first a table and then fields in the table. Creates a query based on your selection, and adds to the workspace one labelled fill-in per field, arranged in a single column. Query Prompts you to connect a database, if necessary, and then starts the Query Builder dialog box. This widget is visible only at design time. Basic data browser Prompts you to connect a database, if necessary, and then starts the Query Builder dialog box. The results of the query are automatically displayed by the widget. Frame Adds a frame to the workspace. Use a frame to visually group other objects or, generally only in character mode, to serve as a window (viewport) into a data display. Rectangle Adds a static rectangle to the workspace. Rectangles have no associated functionality. Use rectangles to visually group other objects. Image Adds a static, bitmapped Image to the workspace. AppBuilder supports many different image formats under MS-Windows. This object is, of course, meaningless in a character environment. Radio button set Adds a set of three radio buttons to the workspace, with generic labels. You can change the number of buttons in the set after placement. Radio-button sets represent any small set of discrete values where only one can be valid at a given time. Toggle box Adds a single toggle box (check box) to the workspace, with a generic label. Toggle boxes represent a single LOGICAL (Boolean) value. Generally, you should set up the box so that the unchecked condition represents No, False, Empty, Not set, etc. (1 of 4)
221
OpenEdge Development: AppBuilder Table 29: Icon Default object tool description Description Slider control Adds a slider control widget to the workspace, with optional readout. You can choose to orient this widget vertically or horizontally. A slider control can represent INTEGER values from 32768 to 32767. Pushbutton Adds a pushbutton to the workspace, with a generic label. You would typically use a pushbutton for activating some process rather than selecting a static condition. Pushbuttons are represented as momentary-on (nonlatching) devices: when released, they return to the up or inactive state. Selection list Adds a selection list to the workspace. A selection list presents a scrollable set of items displayed as character strings. Multi-line editor Adds a multi-line text editor widget to the workspace. You can set the size of the edit buffer, as well as the availability of features such as wordwrap. Combo box Adds to the workspace a drop-down list, or a combo box with your choice of drop-down or visible list element. A true combo box allows the user to type a value into the fill-in component or select from the items displayed by the list component. Fill-in Adds a single-line editor to the workspace. Although a fill-in presents its data at run-time as a character string, you can specify automatic type conversion such that, for example, the value is actually LOGICAL with the users only choice being between some two string literals you define such as True and False. Static text Adds a string of static text to the workspace. You control font, color, and size. ActiveX (OCX) control Opens a list of ActiveX controls for your selection. ActiveX controls can be broadly similar in capability to SmartObjects, but they follow Microsofts Component Object Model (COM) standard, not the ADM. Spin Buttons (ActiveX) Adds an ActiveX spin button control to the workspace. Spin buttons allow setting an INTEGER value. They are functionally similar to a hardware thumbwheel device. You can choose the upper and lower bounds of the range and the increment/decrement value. (2 of 4)
222
AppBuilder Interface Table 29: Icon Default object tool description Description Combo box (ActiveX) Adds an ActiveX combo box to the workspace. See the description of the 4GL combo box for general details about this type of object. Timer (ActiveX) Adds an ActiveX timer object to the workspace. Timers are used as countdown devices that endlessly generate an event at an interval you determine. A timer has no run-time representation or associated data value. SmartDataObject Adds an ADM database interface to the workspace. A SmartDataObject manages a data stream to and from disk, filtering records and responding to requests from other ADM controls residing upstream. SmartObject Adds some SmartObject of your choosing to the workspace. SmartFolder Adds an ADM tabs widget to the workspace. A SmartFolder provides a well-defined context within which you can divide your total interface into functional units. SmartPanel Adds one of the predefined ADM button arrays to the workspace. SmartPanels are dedicated toolbars, providing upstream control of other SmartObjects. SmartDataBrowser Adds an ADM tabular data display to the workspace. SmartDataBrowsers provide a multi-record, row/column interface to the data stream. SmartDataViewer Adds an ADM data display to the workspace. SmartDataViewers provide a single-record interface to the data stream. You can arrange their layout to suit your design. SmartDataField Adds special capabilities of your choosing to a SmartDataViewer on a per-field basis. SmartFilter Adds an ADM Smart Query-By-Form capability to the workspace. (3 of 4)
223
OpenEdge Development: AppBuilder Table 29: Icon Default object tool description Description SmartToolbar Adds an ADM menu and toolbar to the workspace. The default SmartToolbar offers the same navigation and update functions that are provided by the corresponding SmartPanels. SmartContainer Allows you to add an outer-level container object, such as a SmartWindow, to another container. This creates a child-parent relationship. (4 of 4)
Multiple placements To place more than one object of the same kind without having to reselect the tool, left-click the icon a second time. For all SmartObjects based on a master, this second click must occur after you have selected the exact master you intend to use. The image of a padlock will appear on the icon. This indicates that the object tool is latched (locked) down and will allow you to make as many placements as you like.
224
AppBuilder Interface When you wish to release the lock on that tool, select the Pointer icon. The image of the lock goes away, and the button returns to the up position. Locking a tool is easy to do inadvertently. If you find your cursor seems to be stuck, check for the lock icon. Clear it by selecting the pointer tool, and simply delete from the workspace any extra objects that the accidental lock caused you to add. Changing your mind If you change your mind in the middle of the placement process, you can cancel by selecting the pointer tool. If you change your mind after placing the object, simply delete it from the workspace. There will be no residue left behind.
225
AppBuilder preferences
To begin setting AppBuilder-specific preferences, choose OptionsPreferences. The dialog box opens at the General options tab:
226
AppBuilder Interface Table 210 describes the Preference options available: Table 210: Preference options Description Normally cleared. Setting this box causes AppBuilder to offer a brand new SmartWindow workspace for your use whenever it starts up. This might be especially convenient if you typically complete work on a particular window during an edit session and are ready for a fresh workspace next time. It is less useful if you normally resume work on an existing, partly completed window. Normally cleared. AppBuilders output is application source code, including references to database fields. By default, such references are not fully qualifiedany database that can supply the fields will be presumed to be the correct one. This can cause subtle difficulties in some circumstances. Setting this box causes AppBuilder to write out more complete references that are less prone to such errors. Normally cleared. Setting this box causes AppBuilders main window to go to an iconic state rather than stay open, when you start a test run or a debug session. Normally cleared. Setting this box causes AppBuilder to generate code without including widget specifications from the Data Dictionary. If you then need to make changes in representation, you need make them in only one place (the Dictionary) rather than two (Dictionary and source). Normally set with a default value of 4. As a convenience, the File pull-down menu includes menu items that point to the 4 most recently opened structured-procedure files. You can open one of the files again by selecting its menu item. If you would like more or fewer than 4 files to be listed here, change the number. If you prefer that no files be listed, clear the box. Normally cleared. By default, double-clicking an object opens its Property Sheet. You can choose to open the Section Editor instead, by setting this box. Normally cleared. Setting this box allows you to have a separate Section Editor open for each open workspace. By default, a single Section Editor switches context according to which workspace has focus. (1 of 2)
227
OpenEdge Development: AppBuilder Table 210: Preference options Description Normally CHARACTER. Unlike procedures, functions return a value upon termination and a call to them can, for example, appear on the right-hand side of an assignment operator. You can choose here the default data type of the value they return. It will apply to all functions defined thereafter for which you do not specify some other data type. The other choices are COM-HANDLE, DATE, DECIMAL, HANDLE, INTEGER, LOGICAL, MEMPTR, RAW, RECID, ROW-ID, and WIDGET-HANDLE. Choose this button to open the Color Selector dialog box. Use it to set the foreground and background colors for your character-window workspaces. See the Colors selector and editor section on page A10. Advisors are dialog boxes that appear from time to time to offer advice about how to complete certain processes. Working with AppBuilder, you will most often see Advisors appear to suggestand offer to help withcreation of SmartLinks between SmartObjects. Cue cards appear when you create SmartObjects. They offer a brief definition of the object, and hints on how to use it. (2 of 2)
Character-terminal colors
Advisors
Cue cards
WebSpeed Options tab If you have WebSpeed installed, you can use AppBuilder as your layout editor for both standard and Web applications. If you do not have WebSpeed installed, you will not see this tab. Your Preferences dialog box will only have the General, Grid Units, and Print tabs:
228
AppBuilder Interface You can change any or all of the settings here, if the default values do not meet your needs: Web Browser Enter the path to the browser you wish to use for WebSpeed development. By default, AppBuilder uses the path to the browser identified in the Registry. Choose the Browse button to open the standard MS-Windows file system navigation tool, if you want to locate your preferred browser interactively. Broker URL Enter the URL of the WebSpeed broker you will use to run your Web objects. Choosing the Test button will display a test page of broker information if the URL you enter is a valid one. Open new Browser Window Normally set. Clear this box to re-use a single browser window rather than generate new windows for each Web object. PSC recommends that you do not clear this box if using Netscape Navigator.
Grid Options tab One of the hallmarks of good design is that things line up neatly. Graphic designers solved this problem by lining things up against a grid, originally printed on their workspace in a pale, cool-blue ink that was visible to the human designer but not to the platemaking camera. AppBuilder provides a similar grid to help you lay out your widgets neatly in the application workspace. You can make it visible to you, but it is never visible to the users of your application:
You can choose a grid spacing in this tab. It will apply only to graphical frames; the character window has a fixed size. If you plan to run your application in both GUI and character-cell contexts, you might wish to define your grid to be 1.0 x 1.0 characters in size, and take care not to consume more than 80 x 21 cells for any single layout.
229
OpenEdge Development: AppBuilder Once you have a grid defined, choose OptionsSnap to Grid to cause your widgets to automatically jump to the closest grid intersection, if you release the widget nearby. Choose OptionsDisplay Grid to make the grid lines visible to you as a series of dots. The two options are independent of one another. Note that any changes you make to the grid spacing here will apply only to frame objects you create afterward, not to objects that you have already created. The Snap and Display menu item settings apply immediately to all existing and future workspaces, however. Print tab The Print tab gives you some control over the way AppBuilder will print the source code it generates for you:
The Font and Page Length items are self-explanatory. If you clear the Use Print Dialog Box setting, AppBuilder will queue all subsequent print requests to the default printer immediately, without opening the Print dialog box.
In certain cases, Section Editor applies your settings to individual blocks of language statements within a file, not merely to the whole file indiscriminately. Thus, you can (for example) embed a block of JavaScript code in a file that is otherwise HTML code, and Section Editor correctly color-codes and formats the embedded block and the surrounding blocks differently, each in the way you have specified for the particular language.
230
AppBuilder Interface To begin configuring your Section Editor preferences, choose OptionsEditing Options. The Editing Options dialog box opens:
The Section Editor determines what settings to use by looking at the filename extension. The example shows default settings for Progress 4GL source file (.w extension). The notation Refers to to the right of the drop-down list indicates that changes will be written to a file common to several extensions, in this example to all extensions associated with the 4GL. Syntax expansion Normally set. Clearing this box prevents the Section Editor from completing partial tokens or expanding syntax macros. Example: when this box is set, if you type in IF and press CTRL-SPACE, the Section Editor inserts the rest of an IF template conforming to 4GL syntax. Indent style Determines the column where the new line starts after you press RETURN: None Line starts in left-most column. Auto Line starts in same column as preceding line. Syntax indent The Section Editor tries to determine where to start the line by taking current language syntax into account. The absolute integer field (default: 4) determines the amount of change for new levels of indenting.
Tabs You can specify either: A tab interval by typing in an integer preceded by a + sign. For example, +3. Actual tab stops by typing them in as space-separated, ascending integers. For example, 3 5 8 11 16 20 30.
231
OpenEdge Development: AppBuilder Alias filename Enter the fully qualified filename where AppBuilder is to store alias (macro) definitions for the particular extension type. You can have as many alias files as you have languages defined. For OpenEdge file extensions, the default aliases file is
p4gl.als
Color Coding button Choosing this button opens the Color Coding Setup dialog box, described in the Color Coding Setup dialog box section on page 232. Alias button Choosing this button opens the Alias Setup dialog box, described in the Alias setup section on page 234. Options button Choosing this button opens a syntax-specific-formatting dialog box, described in the Options section on page 236.
Choose the Update button to make your changes to these settings permanent. Color Coding Setup dialog box The Color Coding setup dialog box allows you to set the color for a particular class of token within a particular language. You can add new tokens to the most appropriate of several lists that AppBuilder maintains for the use of the recognizer:
232
AppBuilder Interface
To set color and style for some class of token: 1. Choose the Colors button. The Color Settings dialog box opens:
2. 3.
Check the Set Embedded language Color box, if appropriate. Select the class of token in the Screen Element list for which you wish to make changes. The meaning of two of the listed elements might not be immediately clear to you: Window text is any text not otherwise defined. Attributes (HTML only) are recognized modifiers within an HTML tag. For example, in the tag <img src="somelocation">, src is an attribute.
Note that there are a few categories that, while still listed, are not settable in this version of the editor: Current Line, Cursor, No Save Line, Inserted Line, Line Number, and Message. 4. Click on color swatches to set foreground and background colors, and select the radio button for style. The sample text immediately reflects your choices. Choose Apply to save your choices for the selected token class without also dismissing the dialog box. When you have finished making changes, choose OK.
5.
6.
233
OpenEdge Development: AppBuilder Alias setup The Section Editor has a powerful macro-expansion capability. AppBuilder supplies predefined tokens that expand to common 4GL syntactic constructs, and using these tokens can reduce your typing effort considerably. The Alias Setup dialog box provides you the means to define additional tokens that the Section Editor will later expand in the same way:
The expansion process is straightforward. For example, when you type IF and press CTRL-SPACE, the editor adds two spaces and the keyword THEN, and places the cursor between the two embedded spaces in exactly the right position for you to enter the IF test expression. Similarly, you can type in the predefined macro &FR, press CTRL-SPACE, and the editor will expand that to be {&FRAME-NAME}. You can add additional items for automatic expansion, or even correction. If there is some typing mistake that seems to be a favorite of yours, you can enter it together with the relevant correction, and not have to worry about it any more. The transposition DIPSLAY for DISPLAY is an example of thisthat error is such a popular one that PSC has already included it in the list.
234
AppBuilder Interface
To add a new expansion: 1. Choose New. The Enter New Alias Name dialog box opens:
2.
Type in the token to be expanded and choose OK. The dialog box closes and the token appears in the list of tokens. Type the expansion value into the editor. The expansion value may have multiple lines. Use %\c (percent sign, backslash, c) to represent the final position of the edit cursor, after expansion. Choose OK.
3.
In addition to being able to define an alias that will place the cursor properly, you can define aliases that prompt for completion. For example, if you still do old-style debugging, using disclosure code, you might wish to define a disclosure message that would reveal the value of some variable at a certain point in your program. To define a disclosure message that would reveal the value of some variable at a certain point in your program: 1. 2. 3. Follow Step 1and Step 2, above, calling the new alias PEEK. Type in this expansion string: MESSAGE At %(loc) %(var) is %(val). Choose the Add button in the bottom row. The Enter Alias Parameter dialog box opens:
4.
Type in loc as the parameter name, and Location as the actual prompt string. You can leave Initial Value blank for this example, unless you do want some text as the initial value.
235
OpenEdge Development: AppBuilder 5. Repeat Step 3 and Step 4 for var and val, using Variable and Value, respectively, as the prompts. Choose OK. Open the Section Editor in a context suitable for testing your new alias. Type in PEEK and press CTRL-SPACE The editor immediately opens a dialog box to prompt you for the three parameters, afterward inserting the fully expanded call to MESSAGE in place of PEEK:
6.
Options The Options dialog box allows you to customize the appearance of your source code in various ways:
236
AppBuilder Interface You can change as many of these values as you like: DO/END style Choose between having the DO block begin on the same line as the THEN token, or on the next line at the same indent level as the IF (default). Insert DO/END immediately Normally cleared. Setting this box makes the editor create every IF template with an attached DO/END block. Insert blank line between DO/END Normally cleared. Setting this box the editor include a blank line when creating a DO/END block. Minimum keyword length Choose the number of characters you must type (default: 1 character) before the editor will consider it a possible alias token. The editor will ignore CTRL-SPACE for any string with fewer characters than this. Smart Paste Normally set. Clearing this box makes the editor ignore indentation when pasting. When Smart Paste is turned on, the editor attempts to correctly indent any text that you paste. Indent WHEN from CASE Normally set. Clearing this box makes the editor put the
WHEN clause at the same indent level as the enclosing CASE. The editor will normally indent WHENs
Keyword Case Normally all-caps. Choose the style the editor uses when expanding aliases. Auto-case Keywords Normally set. Clearing this box makes the editor ignore differences between the Keyword Case setting and how you type keywords manually. When set, the editor changes your manual style to conform to your Keyword Case choice; for example, changing a lowercase keyword to all caps.
237
OpenEdge Development: AppBuilder The workspace for laying out visible objects is a design window. Figure 26 shows a design window for a SmartWindowit is the SmartWindow itself. SmartWindows are outer-level organizers and members of the class SmartContainer.
Figure 26:
The workspace for non-visible objects is the built-in source-code Section Editor, together with a window that shows a tree view of the editable components. Figure 27 shows a tree-view window.
Figure 27:
238
AppBuilder Interface It is important that you use only the built-in Section Editor to maintain your AppBuilder objects. All AppBuilder-generated procedure files conform to a specific format, which allows AppBuilder to read and update them. AppBuilder cannot reliably read and understand a file that does not conform to this format. Even apparently trivial changesin some cases, adding a blank charactercan render a file unopenable. For more information about editing AppBuilder-generated procedure files, see the Editing source code safely: the Section Editor section on page 239. If you open in AppBuilder a procedure file that it did not generate, AppBuilder does not display a design window or tree view for it. You must maintain such files manually, so AppBuilder displays the file in a standard procedure window.
You can also double-click on the object if you have that preference item checked in the OptionsPreferences dialog box. Figure 28 shows the user interface elements visible when editing the Triggers section. The visible elements vary from section to section.
Figure 28:
If you select Triggers, Procedures, or Functions as the main category, you must also select an individual Trigger, etc., or choose the New button. Existing Triggers, etc. are listed in the combo box below the Sections list. Choose the List button to the right of the Sections combo box. The dialog box shown in Figure 29 will appear.
Figure 29:
This dialog box lists all the sections and subsections that you can edit, to the level of internal procedures and individual triggers. To make a selection, highlight the name and choose OK.
240
AppBuilder Interface
Cutting, copying, and pasting text To cut a block of text, highlight the block of text, then choose EditCut (shortcut: CTRL-X). The Section Editor removes the block of text from the current editing area and places it in the system clipboard. To copy a block of text, highlight the block of text, then choose EditCopy (shortcut: The Section Editor copies the block of text and places it in the system clipboard. Once a block of text has been cut or copied into the system clipboard, you can paste it at any current cursor location by choosing EditPaste (shortcut: CTRL-V). Finding and replacing text Within the current editing area, you can search for and replace text strings. To search for a text string, choose SearchFind (shortcut: CTRL-F). The Find dialog box appears, as shown in Figure 210.
CTRL-C).
Figure 210:
241
OpenEdge Development: AppBuilder In the Find What field, type the text string that you want to find. Set search options as needed: Activate the Match Case toggle box to make the search case-sensitive. Activate the Down radio button to search forward; activate the Up radio button to search backward. Activate the Wrap at Beginning/End toggle box to specify that upon reaching the beginning or end of the current editing area, you return to the top or bottom and begin to search again.
When you choose OK, the Section Editor searches for the first instance of the text string. To find the next instance of the text string, choose SearchFind Next (shortcut: F9). To find the previous instance of the text string, choose SearchFind Previous (shortcut: SHIFT-F9). To replace instances of the text string with a different string, choose SearchReplace (shortcut: CTRL-R). The Replace dialog box appears, as shown in Figure 211.
Figure 211:
The following search and replace features are available: Find What Enter the substring to be searched for. Replace With Enter the replacement substring. Match Case Activate this toggle box to match the search targets case.
242
AppBuilder Interface Search All Sections The default search-and-replace is local to the section being edited. To search globally within the current file, check this box. Replace All Click on this button to replace all occurrences of the target substring without further confirmation. When you use the Replace All option, a message box displays indicating the Replace All is complete and the number of occurrences that were replaced. Transforming text A block of selected text can be indented, unindented, commented out, or uncommented by choosing EditFormat Selection, and then choosing the operation desired. Inserting text from lists The process of creating code involves entering many reserved words, identifiers, filenames, and similar tokens. The possibilities for error are numerous. To reduce error and, in most cases, save keystrokes, AppBuilder helps you insert text strings for these token types: Database fields Event names Internal procedure calls Preprocessor names Queries Object names Filenames
For each of these items, AppBuilder provides a way for you to choose or specify a text string that AppBuilder inserts into the edit buffer at your cursor location. You can access this capability by right-clicking in the editing area, or by choosing from the Insert menu. For detailed instructions, see the Inserting text-string tokens from lists section on page 245. Inserting whole files You can insert (merge) the contents of a whole text file into the edit buffer at the current cursor location. This is convenient if you have used another editor to write some code that you now wish to integrate into your AppBuilder file. 243
OpenEdge Development: AppBuilder To insert the contents of a text file, choose InsertFile Contents. The following dialog box opens:
Note: Apart from the dialog box title shown by the title bar, and the end result, this is the same dialog box that appears when you choose InsertFilename. Make sure of what you are inserting. By default, this dialog box points to the src/template directory and lists the header and superprocedure files found there. You can list different files, or files in a different directory, by selecting from the choices in the respective drop-down lists. You can edit the list of directories by choosing Edit Path, and you can add a directory without editing by selecting a file using the Browse button, which invokes the standard Open File dialog box. Saving your changes Since the Section Editor is a feature of AppBuilder rather than a separate utility, it has no Save option of its own. To save your changes, use the FileSave or FileSave As menu items in the AppBuilder main window. This will save all changes made to the current object, not just those you made using the Section Editor. Undoing your changes To undo all unsaved changes made to the current editing area, choose EditUndo All. This restores the file to the state it was in when you entered this editing area.
244
AppBuilder Interface To undo only your most recent unsaved change, choose EditUndo. This option undoes your last edit. If you use Section Editor features such as Insert or Paste, Undo undoes the most recent action. Successive Undos switch between redoing and undoing the previous edit. Deleting whole sections To delete all the non-AppBuilder code in a particular subsection (an individual trigger, procedure, etc.), choose EditDelete Trigger (procedure, etc.) The menu item text varies according to the element you are currently editing. Caution: You cannot Undo the deletion of a whole subsection, such as a trigger. If you use the EditDelete subsection type function, and then change your mind, you will have to re-enter all the deleted code. It cannot be recovered by using Undo or Undo All.
Figure 212:
This dialog box lets you choose any field for any currently connected database.
245
To specify a database field: 1. 2. 3. Select a database. The Tables and Fields lists change. Select a table. The Fields list changes again. Select the field names that you want to insert in the current editing area: 4. The Select All button selects all of the fields for the current table. The Deselect All button deselects all of the currently selected fields. To select multiple fields but not all of them, hold down the CTRL key while selecting.
Specify a prefix (qualifier) for the field name: The None radio button prefixes nothing to the field name. The Table radio button prefixes the table name to the field name. The Database.Table button prefixes the database and table names to the field name.
5.
Choose OK to insert the fields. AppBuilder inserts the field names at the cursor location in the current editing area or replaces selected text.
Event names To insert event names in an editing area, choose InsertEvent Name. The Choose Event dialog box appears, as shown in Figure 213.
AppBuilder Interface This dialog box displays a list of all events recognized by the Progress 4GL. To choose a listed event, select it and click on OK: Use the Event Filters radio buttons to view different types of events. To specify a keyboard event, choose the Keyboard Event button.
Procedure/function calls To insert a call to an internal procedure or function or to a SUPER procedures internal procedure or function in an editing area, choose InsertProcedure Call. The Insert Procedure Call dialog box appears, as shown in Figure 214.
Figure 214:
247
OpenEdge Development: AppBuilder Table 211 identifies and describes the options available on the Insert Procedure Call dialog box. Table 211: Option Procedure Object Options on the Insert Procedure Call dialog box Description Displays the name of the procedure object that is active in the code Section Editor as indicated by the entry THIS-PROCEDURE, any SmartObjects, or super procedures defined for the object. A drop-down list is available from which you can choose a different procedure object. To edit a Web object, choose web-utilities-hdl from the drop-down list to access the internal entries of the Web utility. The web-utilities-hdl is a procedure handle defined for all Web objects that reference event procedures, method procedures, and API functions of the Web utility object, web-util.p. Entries in Object When either the Procedures option or the Functions option is selected, this option displays a list of names of the current procedure objects procedures or functions, respectively. The procedure call code that you can insert into the code Section Editor from this list displays in the Code to Insert field. If procedures or functions are for actively running SmartObjects and super procedures, the insert code includes any run-time parameters for that procedure or function. You might have to replace each parameter name with the appropriate expression (that is, a constant, field name, variable name, or expression) for the specific call in your code. The data type of each parameter displays in comments. For procedures and functions in the THIS-PROCEDURE object, the dialog box does not provide the run-time parameters. You can determine the appropriate run-time parameters by switching to that procedure or function in the Section Editor and reviewing any parameter definitions. About Entry button If clicked, displays additional information about the procedure or function currently highlighted. If the current procedure object is a SmartObject and it has an internal procedure named object-help, choose About to run that procedure in the object, passing the current procedure name as an INPUT parameter. The object can provide procedure-specific help. If the object has no object-help procedure, the Insert Procedure Call dialog box runs AppBuilder online help for the selected procedure. (1 of 2)
248
AppBuilder Interface Table 211: Option Code to Insert V8 Call button Options on the Insert Procedure Call dialog box Description Displays the code that you can insert into the code Section Editors edit area. You can edit this code before inserting it into the Section Editor. Allows you to access the Insert Procedure Call - Version 8 dialog box to insert Version 8 style ADM RUN, DISPATCH, and NOTIFY procedure calls into code. You might need to use this dialog box if you maintain Version 8 style SmartObjects in the Version 9 AppBuilder. For more information about the Version 8 functionality associated with the Insert Procedure Call - Version 8 dialog box, see the Progress Version 8 documentation. Use the Procedure Object drop-down list to select the appropriate ADM object. This allows you to call the procedures and functions for that super procedure. Figure 215 shows the procedures for containr.p. (2 of 2)
Figure 215:
249
OpenEdge Development: AppBuilder The Procedure Object field lists all of the procedure handles (THIS-PROCEDURE or SmartObject instances) referred to in the current procedure file. For a standard window procedure file, THIS-PROCEDURE is the only procedure handle. For a SmartContainer, each SmartObject instance has a handle that is listed, in addition to THIS-PROCEDURE, which is listed for the SmartContainer itself. When you choose a procedure handle in the Procedure Object field, all of the internal procedures or functions listed pertain to the procedure associated with the object. Note: AppBuilder does not keep track of parameters needed for internal procedures in THIS-PROCEDURE. It does this only for procedures and functions in SmartObject instances used by THIS-PROCEDURE. If you insert a RUN statement for a procedure defined in THIS-PROCEDURE, you must either check to see if the correct parameters are passed or wait for the Progress Compiler to do so.
Preprocessor names To insert preprocessor names in an editing area, choose InsertPreprocessor Name. The Preprocessor names are listed under its tab in the Code References window, as shown in Figure 216.
Figure 216:
250
AppBuilder Interface To select a preprocessor name, click on the name and choose OK. For more information about preprocessor names, see the online help. Queries You can use AppBuilders query-building dialog boxes to generate a query definition rather than typing in the query. To do this, choose InsertQuery. The Query Builder dialog box appears, as shown in Figure 217.
Figure 217:
This dialog box is the first in a series of dialog boxes that help you generate a query. For more information about building queries in AppBuilder, see the Defining and editing queries using Query Builder section on page 438. When you finish generating the query, choose OK. The Section Editor inserts the entire text of the query at the cursor location in the current editing area.
251
OpenEdge Development: AppBuilder Object names To insert object names in the current editing area, choose InsertObject Name. The Code References window appears, open to the Object Names tab, as shown in Figure 218.
Figure 218:
This dialog box displays the 4GL object names of all widgets and SmartObject instances available in the procedure file: The left column contains the name of each widget and SmartObject instance. The right column contains the label or title of each widget.
To insert an object, click on it and choose OK. To insert more than one, hold down the CTRL key while selecting. The Section Editor will insert your choice at the cursor.
252
AppBuilder Interface Filenames To insert a files pathname in the current editing area, choose InsertFile Name. The Choose Insert File Name dialog box appears, as shown in Figure 219.
Figure 219:
Note: This is the same dialog box that appears when you wish to insert the contents of a file rather than only a filename. Make sure of what you are doing To insert the files pathname, select the filename and choose OK. The Section Editor inserts the files pathname at the current cursor location in the editing area. By default, this dialog box displays all of the .i and .p files in the src/template directory.
253
For the properties that apply to a given type of object, see the discussion of that object type.
254
AppBuilder Interface At any time in an AppBuilder session, you can examine the current state of a procedure file as it exists in AppBuilders memory. To do this, choose CompileCode Preview from the AppBuilder main menu. AppBuilder builds a readable version of the procedure file and places it into a content browser, the Code Preview dialog box, as shown in Figure 220.
Figure 220:
The Code Preview dialog box shows the current state of the design window as 4GL code. You can copy code from the Code Preview dialog box and paste it into the Section Editor. To copy and paste text: 1. 2. 3. 4. In the Code Preview dialog box, highlight the text you want to copy. Press CTRL-C to copy the highlighted text. In the Section Editor, move the text cursor to where you want to insert the text. Press CTRL-V to paste the text.
255
OpenEdge Development: AppBuilder You can also search for text strings in the file. To do this, press CTRL-F. AppBuilder displays the Find dialog box, where you can specify the string you want to search for. To search forward, press F9; to search backward, press SHIFT-F9.
Run-mode STOP button replaces edit-mode RUN (running figure) button. Figure 221: Stop button
Choosing the Stop button stops the design window even if the window is, for example, caught in an endless loop. Choosing the Stop button always closes the run window and re-enables AppBuilders editing functionality.
256
AppBuilder Interface
257
258
3
Organizer Objects
Organizer objects provide the visual and sometimes the execution context for other objects. Organizer objects include windows, dialog boxes, frames, and even rectangles. This chapter discusses the following topics: Introduction to organizer objects Organizer object roles Creating a new procedure-based organizer instance SmartWindows SmartDialogs SmartFrames Basic windows Basic dialogs Basic frames
OpenEdge Development: AppBuilder Rectangles Simple SmartContainers Creating paged layouts Paging with SmartFolders Paging without SmartFolders Paging whole windows
32
Organizer Objects
In addition, AppBuilder offers three types of component-level organizer in the Object Palette: SmartFolder Basic frame Basic rectangle 33
The basic window and dialog objects do not have ADM smart logic. Because they lack this supporting logic, you cannot place SmartObjects in them. You can place other objects in them, such as basic frames and field-level objects, and ActiveX objects. Apart from the differences in how smart they are, windows and SmartWindows serve comparable functional purposes, as do dialogs and SmartDialogs. Basic frame objects are essentially static organizers. Their role is to provide a visual context for the field-level objects they contain. Additionally, frame objects allow you to define the order in which pressing the TAB key will traverse their contents.
34
Organizer Objects Rectangles are also static organizers, used to provide a visual context for other objects. Unlike frames, Rectangles do not create a traversal group; their role is entirely visual. The SmartContainer toolnot to be confused with the Simple SmartContainercreates no object. AppBuilder provides the SmartContainer tool as a convenient way for you to associate independent organizer objects of the class SmartContainer, such as SmartWindows, with one another in parent/child relationships. The balance of this chapter discusses the available organizer objects in more detail.
35
OpenEdge Development: AppBuilder This dialog box contains the following user-interface elements: Objects Lists the available types of files. The objects in this list all exist as external procedures on disk. Note that there also might be file types listed, such as Structured Include, that do not represent objects. Template Invokes the Template dialog box, which allows you to preview a procedure template file. When you choose a template, AppBuilder adds it to the Objects selection list. Adding a procedure to this selection list allows you to open it as an untitled procedure. Show Specifies which procedure types you want to see in the Object selection list. Depending on your license, the options in this area might be different than those shown here. Description A description of the currently highlighted object type.
2.
Select SmartWindow from the Object selection list, then choose OK. AppBuilder loads a template as an untitled procedure and opens a workspace on your screen. For visible objects such as a SmartWindow, the workspace is the actual window you will populate. In other cases, such as when you select a Structured Procedure file, Structured Include file, or Method Library, AppBuilder opens the Section Editor as the workspace.
3.
Adjust the size and position of the new SmartWindow as needed. Click on the title bar to select the SmartWindow, and move it to a convenient place on your display. Resize the SmartWindow by dragging its edges.
SmartWindows
SmartWindows are general-purpose, outer-level organizer objects. They have ADM Smart technology embedded in them, and can fully integrate other SmartObjects such as SmartDataObjects, SmartToolbars, and so forth. SmartWindows are members of the SmartContainer class. Unlike the other SmartContainer objects, a SmartWindow can serve as your applications main window or as one of the windows in a multi-window design.
36
Organizer Objects Note that a SmartWindow comes fitted with a frame that covers the client area of the window. The frame should automatically resize as you resize the SmartWindow. You can also resize it separately, if you choose. You might wish to do that in order to have room for additional frames. Besides providing the required context for widget placement, frames also group widgets for traversal using the TAB key, and you might wish to define more than one such group. Note that, rather than resizing the default frame, you could instead add a new frame for each separate traversal group, overlaying the default frame. SmartWindows are file-level (external procedure) objects. Unlike the objects embedded in the Progress 4GL itself, objects defined by external procedures typically are complex. Such objects have a set of properties associated with their nature as a subprogram module, and additional setsif they have a visible run-time representationassociated with whatever widgets they put up as their user interface. The sections below discuss these different properties and their meanings.
37
OpenEdge Development: AppBuilder To open the Properties dialog box for the window part of the SmartWindow object, use one of these methods: While holding down the CTRL key, click in the client area of the SmartWindow until you see that you have the window selected (its identifier will display in the Object field of AppBuilders main window). Then choose ToolsProperty Sheet. Although this method is to be preferred, you may find it requires several clicks if the window is not empty. Expose some of the underlying window. Then double-click on the area you exposed.
Caution: You should not leave bare window surface exposed unnecessarily, since there is a slight possibility that you might then unintentionally place an object partly outside the frame, causing it to disappear.
To expose some of the underlying window: 1. Select the frame part of the SmartWindow by clicking in the client area (the area below the title bar). A border with handles will appear, as shown in this figure:
2.
Drag the bottom-center handle upward a bit. This exposes the surface of the underlying window widget, though there might be little or no visible difference.
38
Organizer Objects Once you have the window selected, opening the property sheet will cause the dialog box shown in Figure 31 to appear. Instance identifier Title-bar text Application icons Context help setup Origin and Sszes Colors selector Font selector Popup menu editor String attributes Menu bar editor
Attributes
Figure 31:
Minimal configuration changes Although you can choose to accept many default settings, you should at least ensure that each SmartWindow you create is uniquely identifiable. To individualize a SmartWindow, make these changes: Change the generic instance identifier to one that more closely describes the window instance you are creating. The instance identifier is the token that will appear in the source code, and is the default value for the filename. Note that OpenEdge identifiers for window objects are conventionally prefixed with a w. Change the generic title bar text to a string that identifies the particular window, or the application if the window you are creating is its main window. Click each of the icon image buttons and identify the icon bitmap (.ico) files for the large (32x32) and small (16x16) icons that will be used to represent the window.
39
OpenEdge Development: AppBuilder Miscellaneous properties (other settings) There are a number of changes to a windows appearance or behavior that you can make, if the default settings do not suit your purposes. They are listed here: 3D Normally set. Clearing this box changes the color of the windows client area, but has no other obvious effect. Control-Box Normally set. Clearing this box clears and disables the Max-Button and Min-Button check boxes. The run-time effect is to remove all three buttons from the right end of the windows title bar and the small icon from the left end. Only the title string remains. Drop-Target Normally cleared. Setting this box causes the window to generate an event when some object is dragged and dropped onto it. You can write code to intercept and respond to such events under program control. Explicit Position Normally cleared. Setting this box enables the Column and Row settings in the Geometry section, and initializes them to the current location of the upper-left corner of this window. You can then freely reposition the window during design time, and the window will start up in the location you choose rather than in some location determined by the operating system. Hidden Normally cleared. Setting this box prevents this window from displaying itself in response to implicit requests. Explicit code must be used to display a HIDDEN window. If initializing this SmartWindow will take a noticeable amount of time, keeping the window hidden meanwhile might be less worrisome to your customer, as long as you display a progress indicator. Keep Frame Z-Order Normally set by AppBuilder when generating code. Prevents nested frames from inappropriately changing their layering in response to getting the input focus. Max Button, Min Button Normally set. Clearing these boxes eliminates the buttons that appear at the right end of the title bar. Those buttons allow the user to make the window go to a full-screen or iconic state, respectively. Message Area Normally cleared. Setting this box adds an area for messages at the bottom of the window, but above any Status Area. Character windows always have a Message Area. Resize Normally cleared. Setting this box allows the user to resize the window by dragging its edges. Widgets in the client area do not respond automatically to this resizing in any way.
310
Organizer Objects Scroll Bars Normally cleared. Setting this box allows scroll bars to be automatically activated as needed. Setting the Scroll Bars option gives meaning to the Virtual Width/Height values shown in the Geometry section. Scroll bars exist to move different portions of some notional space into and out of view as desired. The size of the area currently in view is reflected in the Width and Height numbers, shown in character units in the main property sheet and pixel units in the Advanced Properties dialog box. The total size of the logical area, both visible and scrolled-off, is shown by the Virtual numbers. Those dimensions are referred to as Virtual rather than Total because they could conceivably represent a much larger area than could be displayed whole by any physical device. Unless the window can be scrolled, however, the total and visible areas are effectively identical, making the Virtual numbers meaningless for practical purposes. Sensitive Normally set. Clearing this box causes the window to decline the input focus when offered. Show in Taskbar Normally set. Clearing this box causes the window to iconize to a position above the taskbar rather than within the taskbar itself. Small Title Normally cleared. Setting this box has the same effect as clearing Control Box, plus it reduces the height of the title bar to the minimum needed for the title. Status Area Normally cleared. Setting this box adds a status area at the bottom of the window. Suppress Window Normally cleared. Setting this box effectively removes the window widget, leaving only the frame. Frames are displayed by default in the current window, which might be a scratch window created for the purpose. View Normally set. Useful only when the frame is HIDDEN.
Menus Unlike SmartDialogs and SmartFrames, a SmartWindow can have a menu bar and pull-down menus. It can also have a pop-up menu. You create both types of menu using the same editor and the same procedure. Note: You cannot use this menu if you plan to place a SmartToolbar, even if you only intend to use the toolbar element of that object. The built-in menu and the SmartToolbar are incompatible. See the description of the SmartToolbar object in OpenEdge Development: ADM and SmartObjects.
311
OpenEdge Development: AppBuilder The procedure for creating a pop-up menu is identical to creating a menu bar and pull-down menus, apart from the button you choose at the start. To create a menu bar and pull-down menus: 1. Choose the Menu Bar button. The editor shown here opens:
2.
Change the default identifier for the menu object to reflect your naming conventions, if desired. Enter the label for the first menu item. A corresponding identifier will immediately be generated in the Object field. Modify that identifier, if desired: You must precede one of the letters in each label with an ampersand (&) so the user can choose the menu item from the keyboard. The choice of letter must uniquely identify the menu item within its group (bar or pull-down). If you have not determined where this item will reside, you can defer selecting a character until later. By convention, a menu item on a pull-down ends in an ellipsis (...) if choosing it will open another level of pull-down or invoke a dialog box. Example: Save As...
3.
312
Organizer Objects If you wish to define string attributes for the label, enter them in the area to the right of the label. For further information, see the String attributes section on page A30.
4.
Repeat Step 3 until you have entered all the items that will appear anywhere in the menu system you are creating. Select each menu item that is to appear in a pull-down rather than on the bar. Mark it by choosing the >> button. You will see a dash appear in front of the item. The >> button can be used more than once, and each use will prepend another dash. The number of dashes indicates the nesting level of the pull-down on which the item will appear: No dashes means the item will be on the menu bar itself. One dash means the item will be on the main pull-down menu. Two dashes means the item will be on a cascade/fly-out menu off the pull-down. Three dashes means the item will be on a second level of cascade menu.
5.
If you change your mind, remove unwanted dashes by choosing the << button. 6. Select each menu item and use the Up and Down buttons to move it into the correct position relative to the other items. The first item on a pull-down menu should appear immediately below the item that causes the pull-down to open. Example: in the figure shown in Step 1, the Cut item would be the first item in the Edit pull-down. If the item is a pull-down item, and is to appear with a check mark in front of it whenever selected, check the Toggle-box option. 7. Arrange pull-down items into logical groups by inserting rule lines (Rule button) and nonselectable blank items (Skip button) as appropriate. Select each item that will be frequently used and define an accelerator (shortcut) key for it. Choose the Key button and, when the capture dialog appears, press the actual key or combination (such as CTRL-X for Cut) that is to become the shortcut. Note: To create a shortcut for an item on the menu bar, you must first change it to a pull-down item using the >> button. After you have defined the shortcut, move it back to the menu bar using the << button. The shortcut will remain defined. 9. Select each item that will not be active on startup and check the Disabled box. Save your work. 313
8.
OpenEdge Development: AppBuilder Context-sensitive help If you plan to provide context-sensitive help, check the Context Help box and specify the full pathname of the relevant help file. String attributes, window color, status area font You can set several other characteristics of the window, if you choose: String attributes. Font used for text written to the Status Area, if any. Colors used for the windows foreground and background. By default, MS-Windows applications leave their window colors undefined so that the end user can set them as a preference item.
See the online help system for further information. Advanced properties Choose the Advanced button to set additional properties. The Advanced Properties dialog box shown in Figure 32 will appear.
Figure 32:
314
Organizer Objects The advanced properties shown here are common to most objects. You can modify any that do not meet your needs: Private Data Not used by AppBuilder. AppBuilder assigns the contents of this field to the windows PRIVATE-DATA attribute. You can write code to read and operate on that value in any way that meets your needs. Generated Code Layout Unit Determines whether AppBuilder uses character or pixel units when generating source code for this object. Custom Lists Custom lists would be called macros in other languages such as C. They provide a convenient way to avoid typing a large number of identifiers when many objects are to be treated identically. For example, if you check the box for List 1, the identifier for this window is associated with List 1. Later, any time a reference to this procedures List 1 is encountered by the preprocessor, the identifier for this windowtogether with the identifiers for all other objects you associated with List 1 in this procedurewill be substituted in the source code in place of the reference. You can choose to include this window in up to six such macros. You can also give the macros themselves more meaningful identifiers; see the Custom lists naming section on page A16. Geometry You can set the exact startup size and position for this window, in pixel units. Startup position is only meaningful when you set the Explicit Position box. Always on Top, Top Only You can set either of these options, but not both. Neither is set by default: Top Only prevents this window from being occluded by other windows belonging to this session. Always on Top prevents this window from being occluded by any other window, even those belonging to other applications.
Sync With Master Forces this layout to take on the attributes of the master layout. This pushbutton is disabled unless this layout is an alternate layout. For more information on alternate layouts, see Appendix B, Multiple Layouts.
315
SmartDialogs
SmartDialogs are special-purpose, outer-level organizer objects, technically a type of frame with a dedicated, inseparable window. They are members of the SmartContainer class, and can integrate other SmartObjects. They differ from SmartWindows in that they: Cannot serve as the main window of your application. Cannot have a menu bar. Cannot be resized at run time or scrolled. Cannot generate or accept SmartLinks of type Filter. Can accept other widgets placed directly on them (that is, without your having to interpose a separate frame).
Because they are always modal, they must be dismissed before any other window can gain focus, so the number of roles they can play is not large. You will typically want to use them to capture user input without which your program cannot continue.
316
Organizer Objects To open the property sheet, shown in Figure 33, double-click on the client area of the SmartDialog, or choose ToolsProperty Sheet.
Tab editor
Figure 33:
Minimal configuration changes Although you can choose to accept many default settings, you should at least ensure that each SmartDialog you create is uniquely identifiable. To individualize this SmartDialog, make these changes: Replace the generic instance identifier with one that more closely describes the dialog instance you are creating here. The instance identifier is the token that will appear in the source code, and is the default value for the filename. Note that Progress identifiers for dialog objects are conventionally prefixed with a g. Change the generic title bar text to a string that identifies this particular dialog.
317
OpenEdge Development: AppBuilder Miscellaneous properties (other settings) Dialogs have fewer miscellaneous properties than windows do, but those they have in common have the same meaning in both contexts. Dialogs also have a few properties in common with frames: No Auto Validate Normally cleared. Setting this box turns off, for all field-level objects in the dialog box, the automatic validation defined in the Data Dictionary. Open the Query Normally cleared. Setting this box automatically populates the fields in this dialog box, if there is a query defined. Use Dict Exps Normally cleared. Setting this box makes all the validation expressions and help strings defined in the Data Dictionary available to all the widgets assigned to this SmartDialog.
Advanced properties To open the Advanced Properties dialog box shown in Figure 34, choose the Advanced button.
Figure 34:
318
Organizer Objects The only differences in advanced properties between a window and a dialog are: Dialog boxes are always modal, so there is no option to make them always appear in front of other objects. Modal objects always appear in front of other objects. Dialog boxes have an option to allow box-selection, normally cleared. Box-selection is sometimes called marquee-selection or lasso-selection. It refers to selecting more than one object by dragging a dynamically generated box (the marquee) around them.
SmartFrames
SmartFrames are special-purpose organizer objects. They are members of the SmartContainer class and can integrate other SmartObjects. Every SmartFrame must be supported by a SmartWindow or SmartDialog; they are not independent or outer-level objects. The principal benefit SmartFrames offer is reusability. If you have a self-contained layout that includes SmartObjects, and will be reused repeatedly but would not be appropriate to implement as a SmartDialog, consider implementing it on a SmartFrame.
319
Figure 35:
Minimal configuration changes Although you can choose to accept many default settings, you should at least ensure that each SmartFrame instance you create is uniquely identifiable. To individualize a SmartFrame, make these changes: Replace the generic instance identifier with one that more closely describes the frame instance you are creating. The instance identifier is the token that will appear in the source code, and is the default value for the filename. Note that Progress identifiers for frame objects are conventionally prefixed with an f. If your new frame will have a visible title bar, change the generic text to a string that identifies the purpose of the frame.
320
Organizer Objects Miscellaneous properties (other settings) You can make a number of changes to a frames appearance and behavior, if the default settings do not suit your purposes. Some properties are discussed in the sections on SmartWindows and SmartDialogs. Listed here are the properties unique to frames: Down Normally cleared. Setting this box allows as many frame iterations (logical lines of output) as will fit to be written to the frame before pausing. This option has no meaning if the frame is not being used for direct output. No Box Normally set. Clearing this option causes the frame to display with a visible border. Title Bar Normally cleared. Setting this box clears the No Box option and causes the frame to display with a border and a prominent, visible title bar. You can set the background and foreground colors of the title bar (choose the Title Bar Color button), though the settings have no effect when the application is running under MS-Windows.
Advanced properties You can make several changes to a frames behavior or appearance in the Advanced Properties dialog box. To open the dialog box, shown in Figure 36, choose the Advanced button.
Figure 36:
321
OpenEdge Development: AppBuilder Some properties are discussed in the sections on SmartWindows and SmartDialogs. Listed here are the properties unique to frames: {&FRAME-NAME} Normally cleared. Manual Highlight Normally cleared. Setting this box allows you to use special highlighting for certain objects. Movable Normally cleared. Setting this box allows the user to move the frame within the enclosing space (window, dialog, or other frame). Page Top, Page Bottom Normally cleared. Resizable Normally cleared. Setting both this box and the Selectable box allows the user to resize the frame, within the boundaries of the enclosing object. Selectable Normally cleared. Setting this box allows the user to select and, if Resizable is also set, resize the frame.
Basic windows
Basic windows are general-purpose, outer-level organizer objects. Basic windows are SmartWindows without the ADM smart technology. They are external-procedure objects, and can be used as the main window in your non-ADM applications, but they cannot support SmartObjects. For information about configuring your basic window objects, see the SmartWindows section on page 36. There are only two differences in default properties: Basic windows have the Keep Frame Z-Order property set; SmartWindows do not. Basic windows do not initialize in a Hidden state; SmartWindows do.
322
Organizer Objects
Basic dialogs
Basic dialogs are special-purpose, modal organizer objects. Basic dialogs are SmartDialogs without the ADM technology; they cannot support SmartObjects. For information about configuring your basic dialog objects, see the SmartDialogs section on page 316. There is only a single difference in default properties: Basic dialogs have the Open Query property set; SmartDialogs do not.
Basic frames
Basic frames are non-window, component organizer objects. You can place SmartObjects on a basic 4GL frame, even if it is nested in other basic frames, as long as the outer-level object that supports them all is a SmartWindow or SmartDialog.
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object:
3.
323
Rectangles
Rectangles are the simplest organizer objects. Their role is entirely visual. Rectangles can be nested within frames and can be placed within or partly within (overlapping) other rectangles. You can place SmartObjects on a rectangle as long as there is an appropriate Smart organizer (SmartWindow, SmartDialog, or SmartFrame) to support them. By default, a rectangle appears as a figure with a closed, sunken border 2 pixels thick:
By combining a text widget with a rectangle, you can create an object similar in appearance to an MS-Windows frame widget:
There is no line object in the 4GL, but by carefully sizing, positioning, and coloring one or two rectangles, you can create the illusion of a line object. This can be convenient as a visual spacer.
324
Organizer Objects
To create and place a rectangle: 1. Click on the Rectangle tool icon in the Object Palette:
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object:
3.
Figure 37:
325
OpenEdge Development: AppBuilder Minimal configuration changes You should change the default identifier, shown in the Object field, to a token that more accurately identifies the role of this rectangle in your design. Border width (edge pixels) Rectangles can be very useful as a way to visually define a special area, for example one whose appearance will change because of paging. You might wish to make such an area even more visually special by changing the thickness of the border. This rectangle shows a distinctive, eight-pixel border:
To change the thickness of the border, enter the new value in the Edge Pixels field. The results of specifying too thick a border are undefined. A value of zero (0) will cause the rectangle border to disappear, effectively making the rectangle itself disappear unless it has a fill of a contrasting color. Geometry Normally, the location of a widget is calculated at its upper-left corner. You can set the location of a rectangle to be its upper-right corner instead, if you wish, by setting the appropriate radio button. Additionally, by setting the width or height of a rectangle to zero (0) pixels in the Advanced Properties dialog box, you can create the illusion of a line. Miscellaneous properties (other settings) Rectangles are such simple objects that they have very few properties. You can make changes to those few, if the default settings do not meet your needs: Enable Normally set. Clearing this box causes the rectangle to decline input focus when offered. For this option to be meaningful, you must also set either the Movable or Resizable property. For more information, see the Advanced Properties section. Filled Normally cleared. Setting this box fills the rectangle with the background color.
326
Organizer Objects Graphic Edge Normally set. This box interacts with the Edge Pixels (border thickness) setting: Specifying an Edge Pixels value of three or less causes a line-drawing character to be used for the border in character environments. Values over three clears this box and a block character is used for the border in character environments. Clearing this box sets the Edge Pixels value to eight and a block character is used for the border in character environments.
Hidden Normally cleared. Setting this box prevents the rectangle from displaying itself in response to implicit requests. See the online help for further information.
Advanced properties You can make several changes to a rectangles behavior or appearance in the Advanced Properties dialog. To open the dialog box, shown in Figure 38, choose the Advanced button.
Figure 38:
Four properties you may wish to modify are: Manual Highlight Normally cleared. Setting this box allows you to define and use a special highlighting scheme when the object is selected. Movable Normally cleared. Setting this box plus the Selectable and Enabled boxes allows the user to move the rectangle within the bounds of the enclosing frame object.
327
OpenEdge Development: AppBuilder Resizable Normally cleared. Setting this box plus the Selectable and Enabled boxes allows the user to resize the rectangle within the bounds of the enclosing frame object. Selectable Normally cleared. Setting this box plus the Enabled box allows the user to select the rectangle.
Simple SmartContainers
The Simple SmartContainer provides you with a way to create smart modules that can run in batch mode without a user interface. You can see this usage illustrated in Figure 66, where loadable modules are created by packaging SmartDataObjects and SmartB2BObjects in simple SmartContainers. Since neither the SmartDataObject nor the SmartB2BObject has a run-time representation, there is no need to use a visible container. The simple SmartContainer provides the critical services encapsulated in the SmartContainer super procedure without the overhead of a visible window. This can be very convenient in selected cases. Of course, if you prefer to use a visible SmartContainer such as a SmartWindow, you are perfectly free to do so.
328
Organizer Objects
To create a complete object in AppBuilder: 1. Choose FileNew. Choose Simple Smart Container from the dialog box that appears:
2.
The container appears. Note that objects of this type do not have a frame element, so you will not see a grid even if you have grid visibility turned on in your Preferences:
3.
Reduce the size of the container workspace, if desired. Begin completing your new module by adding a non-visible SmartObject to the container. Shown here is a SmartDataObject:
Caution: If you place an object that has a visible representation at run time, the behavior of your simple SmartContainer module will be undefined.
329
OpenEdge Development: AppBuilder 4. Add additional objects as desired to complete the module. Shown here is a SmartB2BObject:
As you add such additional objects, Advisors might appear and offer to create SmartLinks for you. Examine each offer and accept those that seem appropriate. 5. 6. 7. Configure each object you employ in the module. Open a Section Editor, if necessary, and add code to complete the module. When you have completed the module, save your work using a distinctive filename. Note that simple SmartContainer filenames conventionally begin with c.
330
Organizer Objects
To place and configure a Simple SmartContainer module that you created: 1. Click the SmartContainer tool icon in AppBuilders Object Palette:
2.
When the Choose dialog box opens, select a SmartContainer module and click OK:
3.
Move your cursor to an empty place in your workspace and click to release the object. You will see a representation similar to this:
331
OpenEdge Development: AppBuilder 4. Click the instances Menu button and choose Properties. The SmartObject Properties dialog box opens:
5.
Change the Object identifier to one that more clearly reflects the role of this container in your application. If you wish to use this instance as a placeholder, check the Parameterize as Variable box. For information about placeholders, see the Creating a SmartObject placeholder section on page A29 and OpenEdge Development: ADM and SmartObjects. Save your work.
6.
7.
Note that the simple SmartContainer does not have a separate Instance Properties dialog box
332
Organizer Objects
Page identifiers
Each ADM page is identified by a unique, non-negative integer. Page 0 (zero) exists by default; you must create and assign numbers to all other pages that you need. You need not assign page numbers sequentially, and it is fine to leave gaps. You can define up to 32767 pages for a given contexta much larger number than you would probably want to try to manage. To create a new page, you need merely make it the current design page (see the Special pages section on page 333). A page remains in existence as long as it is the current design page, or has objects assigned to it. AppBuilder automatically destroys empty pages that are not current.
Special pages
Three page designations have special meaning within the paging system: Design page Page 0 (zero) Startup page
These page designations are discussed individually in the following subsections. Design page When you place SmartObjects into a design window workspace, you are placing them on the current design page, whatever that might be at the time. The current design page setting appears in the status bar of the AppBuilder main window, and is meaningful only for placing SmartObjects. The default design page is always page 0. An ADM page may have any unique, non-negative integer as its identifier. AppBuilder places basic 4GL and ActiveX objects on Page 0, regardless of the Design Page setting. Only SmartObjects may reside on pages other than Page 0. You may be able to work around this limitation by placing such non-Smart objects in a SmartFrame, and then placing the SmartFrame on the page of your choice. As the name suggests, the Design Page setting is relevant only in design mode. It is not meaningful at run time, and is ignored.
333
To make a diferent page with the Design Page: 1. Open the dialog box using one of these methods: Double-click on the Page Number field in the AppBuilder main window. Choose EditGoto Page. Open the Procedure Settings dialog box (ToolsProcedure Settings), choose the Pages button, and finally choose the Design button in the Pages dialog box.
2.
Enter the number of the new Design Page. If that page does not exist, AppBuilder creates it immediately.
Note: Remember that although you can change the Design Page, the change only affects SmartObjects. When you place other objects, including ActiveX objects, you are placing them on Page 0 regardless of the Design Page setting. To see the contents of all pages at once, change the Design Page value to a question mark (?). You can then align objects that reside on different pages so that page-changes appear neater and more orderly. All else being equal, users perceive neatness to indicate higher quality. Page 0 (zero) Page 0 is the default page in every SmartContainer. If you create a SmartContainer and add objects to it without changing any of the paging settings, then all of the objects will be on Page 0. Page 0 objects are always displayed. If you have some objects assigned to Page 0, some assigned to Page 1, and some assigned to Page 2, the possibilities for display will be: Page 0 objects only; Page 0 objects + Page 1 objects; Page 0 objects + Page 2 objects. Unless you write special code to handle the situation, you cannot exclude Page 0 objects when displaying objects on other pages. Startup page You can choose to designate one page, in addition to Page 0, to be displayed when the SmartContainer starts up. This is called the Startup Page.
334
Organizer Objects Page 0 is the default Startup Page. Unless you explicitly specify a nonzero page number as the Startup Page, only the objects placed on Page 0 will display when you run the SmartContainer. For example, if you use a SmartFolder to organize the viewing and hiding of pages, you typically designate Page 1 (which always corresponds to the leftmost folder tab) as the Startup Page. If you leave the Startup page set to Page 0 when you use a SmartFolder, then the SmartObjects in the folder will not appear when the application starts up. You set the Startup Page in the Pages dialog box, which you invoke from the Procedure Settings dialog box.
335
Figure 39:
While convenient to use and appropriate for many applications, SmartFolder may not be suitable for all cases. Although you can define up to 32 tabs, they will all be shown in a single line. This spares your users the disorientation of having tab rows re-order themselves, but might require that they use a horizontal scrollbar. To manage paging in your application using SmartFolder: 1. Sketch out the purpose and organization of each tabbed page. Keep in mind these points: There is no tab for Page 0. The leftmost tab always selects Page 1. Non-Smart objects will always be visible by default, regardless of the tab selected. They always reside on Page 0, and objects on Page 0 are always visible unless you add special code to manage the situation. If your design requires that you place non-Smart objects within the perimeter of the SmartFolder, you might need to treat them in a special way. For example, a rectangle cannot be placed directly on the surface of a SmartFolderit sinks below the surface and cannot be seen. Nor can it be brought to the surface using LayoutMove-to-Top. To use a rectangle for visual organization, you must first place a borderless (thus invisible) frame object, with its Scroll Bars option turned off, on the SmartFolder. Then place the desired rectangle on the frame. The frame will keep the rectangle from sinking through the SmartFolder. (You should probably avoid placing non-Smart objects within the SmartFolder if you can.) 336
Organizer Objects 2. Be sure that your workspace is a SmartWindow, SmartDialog, or SmartFrame. No other organizer object will support ADM paging. Set your Design Page to 0. Caution: Since nested paging is not possibleADM supports only a single set of pages for any single SmartContainerthe SmartFolder must always reside on Page 0. If you place the SmartFolder on, for example, Page 1, it will abruptly disappear from view the moment you select the tab for any other page. 4. Click the SmartFolder tool icon in the Object Palette:
3.
5.
Move your cursor over an empty spot on your workspace, and click again to place the new SmartFolder:
6.
An Advisor dialog box will appear, offering to create a Page SmartLink between the Smart workspace and the new SmartFolder object. Examine the offer, and accept it if it seems appropriate. The Page link allows the SmartFolder to tell the Smart organizer which page to display when the user selects a tab. For more detailed information about SmartLinks and their meanings, see OpenEdge Development: ADM and SmartObjects.
7.
If necessary, click on the SmartFolder to reveal its handles (you can see them illustrated in Step 5). Use the handles to adjust the size and position of the SmartFolder appropriately.
337
OpenEdge Development: AppBuilder 8. Click on the SmartFolders Menu button and choose Instance Properties. This dialog box will open:
Enter the labels for the tabs you will use. To move to a new field, choose the Insert button. If you wish to insert a field before the current field, use the UP-ARROW key. To remove an entry, choose the Remove button. If you wish to use a special font for the tab labels, choose the Font button and select a font in the dialog box that opens in response (see the Text style selector and editor section on page A36 for more information.) By default, the width of the each tab agrees with the label; tabs are not of fixed size. If you prefer fixed-size tabs (shown in Figure 39), check the appropriate box and enter a size for the tab. You may need to experiment to achieve a pleasing effect.
When you have finished configuring the tabs and their labels, choose OK to dismiss the dialog. 9. Set the Design Page to 1 (remember: the leftmost tab selects Page 1, not Page 0). Place and arrange the SmartObjects belonging to Page 1. To control how the objects layer on top of one another, use LayoutMove-to-Top and LayoutMove-to-Bottom. Check to be sure this is effective: not all objects respond to relayering requests. Note: Remember that only SmartObjects can participate in ADM paging. If your layout includes non-Smart objects, they will remain visible regardless of the tab selected.
338
Organizer Objects 10. Repeat Step 9 for each succeeding page you defined, being sure to set the Design Page correctly each time before beginning to place objects. If you make a mistake, open the Pages dialog and move the misplaced objects to the correct page. See the ADM pages manager section on page A4 for more information. 11. Set your Startup Page to the appropriate nonzero number, generally 1. Save your work.
Figure 310:
339
Figure 311:
The two layouts illustrated here resemble a SmartFolder in appearance, but that was a deliberate design choice, not a requirement of the technology. You could create designs that look very different to these. You could use images rather than text on pushbutton controls. You could arrange the control buttons along the side or bottom rather than the top, color-code them, use very long strings as labels, and so forth. The possibilities are numerous. The key to paging is the selectPage() procedure:
RUN selectPage ( 63 ) .
Inserted as the trigger code for a pushbutton CHOOSE event, the example call would reveal all SmartObjects assigned to page 63 and hide all others. The value of the argument can be any non-negative INTEGER. An alternative to the selectPage() call is the viewPage() call. Calling viewPage(63) would reveal all SmartObjects assigned to page 63, but it will not hide any others. Anything in view before the call will still be in view after. This creates quite a different effect. AppBuilder supplies a pushbutton that contains the following code for the Choose event:
340
Organizer Objects Right-click the pushbutton object icon in the Palette and choose the View Page item from the list. You can convert this button very easily by substituting a call to selectPage() for the existing call to viewPage(). Make this substitution using AppBuilders built-in Section Editor. Pushbuttons are not your only choice for paging controls. AppBuilder also supplies a set of radio buttons predefined with selectPage( ) calls. Right-click the radio-set object icon in the Palette and choose the Page Select item from the list. Note: You should keep in mind that Progress Software Corporation supplies this radio set as a convenience, but does not necessarily endorse its use. Most experienced GUI users expect radio-button sets to represent data, so using them as action controls might cause confusion and reduce your applications usability.
Figure 312:
341
To reproduce the example shown in Figure 3-12: 1. Create a new SmartWindow. This will be the Work window. Populate it with a SmartDataObject, SmartDataViewer, and the two SmartPanels (navigate and update). Save this assembly under a distinctive name. Create a second new SmartWindow. This will be the control window. Populate it with two pushbuttons, using the View Page versions of the buttons for convenience. Change their labels appropriately. Select the button that will open the Work window. Open the Section Editor and replace the call to viewPage(1) in the trigger code with a call to selectPage(1). Close the Section Editor window. Set the Design Page to 1. Select the SmartContainer object tool from the Palette. When the Selection dialog box opens, choose the file that represents the Work window you created and saved in Step 1. Place this object in the control window. A SmartWindow placed in this way will not display its run-time representation, but instead will present as a non-visible SmartObject. This is as it should bethe Work window is an independent SmartWindow and thus has no code that would allow it to open within the control window as a component object. Within the control window, the Work window is indeed a non-visible object. 6. Select the button that will close the Work window. Open the Section Editor and replace the call to viewPage(1) in the trigger code with a call to selectPage(32768). Note that the number need not be 32768simply choose some distinctive, non-negative integer that you are not using for an actual page number. A call to selectPage( ) always turns off the old page before turning on the new one. However, since you have not defined a page 32768, there is no new page to turn on. So pressing this button will only have the effect of closing (turning off) the Work window. 7. Save the control window object. Run it, and choose the buttons to open and close the work window.
2.
3.
4.
5.
342
4
Data-Access Objects
Locating, reading, and writing database records is the one fundamental activity in any database application. This chapter describes the data-access objects AppBuilder supplies for your use, and discusses how to create, modify, and use them. Topics discussed in this chapter include Introduction to data-access objects SmartDataObjects SmartBusinessObject SmartFilters Making changes to the data stream Creating a freestanding query object Defining and editing queries using Query Builder Selecting database fields for browsing
These are in addition to the standard Progress objects including standalone queries and objects that combine data access with visualization and update capability. The rest of this chapter discusses how to use these building blocks in your applications.
SmartDataObjects
SmartDataObjects are modular data pumps that incorporates ADM Smart technology. They communicate in a loosely coupled way with other ADM SmartObjects using SmartLinks, and with objects on the Web using WebSpeed. They can also function in an Open4GL environment with non-Progress objects. SmartDataObjects are supplied for your use in both dynamic and static forms.
Static SmartDataObjects
Static SmartDataObjects act as custom data pumps, each producing and managing a specific data stream based on the terms of a specific query. You define a base version of that query within a master version of the object at design time.
42
Data-Access Objects Depending on your business needs, you can also define and add custom validation routines to the master object. These validation routines can operate at various levels of granularity, from a single field to a whole transaction. Once you have the master defined, you can then use instances made from it as often as you like. When you compile such a static SmartDataObject, the Compiler creates two different versions of the executable r-code. One represents the complete object, usable in any context. The other is a stripped-down, client-only version. Figure 41 illustrates this process.
Source SmartDataObject
4GL Compiler
D:\...\dSDO_cl.w
D:\...\dSDO.w
Figure 41:
Compilation of a SmartDataObject
The stripped-down version (identified by _cl in the filename, for example: dTest_cl.w) will load whenever there is no local database connection. A _cl object expects to cooperate with the complete version of the same object loaded as part of an AppServer partition. You can associate business rules or any other required logic with the object by writing the necessary code.
43
Dynamic SmartDataObjects
The dynamic version of the SmartDataObject is designed particularly for distributed use. A static client-side SmartDataObject can only deal with one particular data streamthe specific data stream being supplied by its counterpart on the server. This is a limitation that can be significant where many such streams are involved, if the client-side objects are not stored locally. The OpenEdge WebClient is one such caseit is designed to be downloaded for use over a wide-area network such as the Internet. (See OpenEdge Deployment: WebClient Applications, for detailed information about downloading and using the new WebClient.) The dynamic SmartDataObject solves a large part of this problem. The dynamic object acts as a generic, general-purpose data pump. It is not limited to handling a specific data stream, as a static SmartDataObject is. The dynamic object automatically cooperates with any static, server-side SmartDataObject and can be attached to any client-side display object such as a SmartDataBrowser or SmartDataViewer. These broad capabilities come at the cost of client-side customization. Because it is designed to handle a data stream of any composition, you cannot enhance the dynamic SmartDataObject with custom routines. This is true even of custom validation procedures. You can add custom client-side validation routines to the static object, if you choose, but you should remain aware that all such custom routines will actually run in the static object on the AppServer, not on the client. Since any SmartDataObject is only a data pump, you must connect its data stream to other modules for display or manipulation. Those other objects can take a number of forms, both OpenEdge and non-OpenEdge. You define and create them separately from the SmartDataObject.
44
Data-Access Objects Design considerations Before you start the SmartDataObject Wizard, you should consider these questions: Will you need to define a temp-table first to reduce the amount of processing? Large quantities of data can affect performance. If your application must repeatedly traverse a very large database, you might get a significant performance increase by first subsetting to a temp-table, and then operating on that subset instead. Note that although the wizard will allow you to define such a temp-table, and will allow you to assign it as the SmartDataObjects data source, you must write the code by hand that actually locks and copies records from the permanent table. This population step must take place before you give the SmartDataObject access to the temp-table at run time, if the rest of your application expects to find records in the table. What databases and tables do you want this SmartDataObject to use? This base query can be refined or sorted at run time. What fields do you want to expose to client objects, and what properties (such as read-only) do you want to set for each data element? What are your plans for validating data on the client side (the user interface side) and the SmartDataObject side? See the Data validation limitation section on page 415 for a discussion of an unusual and potentially important issue.
Creating the master AppBuilders SmartDataObject Wizard has four pages. Only pages 2 and 3 involve significant work: 1. 2. 3. 4. Introduction. Creating the temp-tables, if any, and the query. Selecting the fields the SmartDataObject will offer to visualization objects. Congratulations.
45
To create a SmartDataObject master: 1. Open the Choose dialog box by clicking on the SmartDataObject tool icon in the Object Palette. When the dialog box opens, start the SmartDataObject Wizard by choosing New:
Note: You could also start the wizard by choosing FileNew and selecting the SmartDataObject item from the list, or by right-clicking the icon in the Object Palette and selecting New SmartDataObject from the pop-up menu. 2. Page 1 of the SmartDataObject Wizard appears:
46
4.
The SmartDataObject supports an external super procedure that allows you to encapsulate business logic called the data logic procedure. You can reuse this data logic procedure or specify a unique data logic procedure for each SDO. Activate the Use SDO logic procedure to indicate you want to use a data logic procedure. Specify the appropriate template in the Use template field and the procedure name in the Logic procedure file name field. When you have completed the logic procedure portion, choose Next to move to Page 3:
5.
6.
If this SmartDataObject will operate on one or more temp-tables, choose the Define Temp-Tables button to open the Temp-Tables Maintenance Editor. Using the editor, define the temp-tables this SmartDataObject will use. See the Temp-tables maintenance section on page A33 for information about how to use the editor.
47
OpenEdge Development: AppBuilder 7. Choose the Define Query button to start Query Builder. Define the base query this SmartDataObject will use. See the Defining and editing queries using Query Builder section on page 438 for information about how to use Query Builder. Note: The option to create a free-form query is not available to you at this stage. If you need or want to create a free-form query, you must create a placeholder using Query Builder and then edit the query after the wizard completes. See the Editing a SmartDataObject master section on page 410 for further information. 8. When you finish with Query Builder, you will see displayed on Page 3 the text of the query you just created. When you are satisfied with your choices for temp-tables and query, choose Next to go to Page 4 of the wizard:
9.
Note that at this point, the list of fields is empty. Choose Add Fields to start the Column Editor, and use the editor to select the fields that you want to make available through this SmartDataObject. For information about how to use the Column Editor, see the Selecting database fields for browsing section on page 445.
48
Data-Access Objects 10. When you return from the Column Editor, the list will be populated with the fields you have chosen:
11. Choose Next on Page 4 of the wizard to advance to the wizards final page. If you successfully defined a database query and the related SmartDataObject RowObject temp-table fields, the Congratulatory screen displays. (If not, press the Back button and make any necessary changes.) 12. Choose Finish to dismiss the wizard and reveal the new SmartDataObject master, if it was not already visible:
13. Choose FileSave and give the new master a descriptive filename. Note that, by convention, SmartDataObject filenames begin with d. The new SmartDataObject master is now available for your use.
49
OpenEdge Development: AppBuilder Note, too, that AppBuilder actually creates two different forms of the master. If you were to give it the name dExampleSDO and then check the file system, you would see: A standalone version, named dExampleSDO.w. This version is loaded whenever there is a local database connection. AppBuilder creates it with the DB-REQUIRED preprocessor value set to YES, since it should not load if there is no database connection. A client-side version, named dExampleSDO_cl.w. AppBuilder creates it with set to NO. This version is loaded when there is no local database connection, on the presumption that the application is running in client/server mode and the database is resident on the server side. This version is compiled with all DB-REQUIRED internal procedures stripped out, which can create a problem. See the Data validation limitation section on page 415 for further information.
DB-REQUIRED
dExampleSDO_cl.w
410
Data-Access Objects 2. Double-click on the object. The SmartDataObject property sheet dialog box appears:
3.
Choose the Query button to edit the existing query, if necessary. See the Defining and editing queries using Query Builder section on page 438 for information about how to use Query Builder. Click on the Fields button to modify the original fields and their attributes. See the Selecting database fields for browsing section on page 445 for information about how to use the Column Editor. Save your changes.
4.
5.
411
To use a SmartDataObject in your application: 1. Open the Choose dialog box by clicking on the SmartDataObject tool icon in the Object Palette. When the dialog box opens, select the appropriate SmartDataObject master from the list:
If you have difficulty remembering which SmartDataObject master is which, choose Preview to open a dialog box that displays the fields listing for the selected master:
2.
Position the new instance (created automatically when you chose the master) anywhere you like in your smart organizer workspace, and click to release. This is the design-time representation you will see:
412
Data-Access Objects 3. AppBuilder will now automatically look for opportunities to create SmartLinks between it and other SmartObjects in the same organizer context. If it thinks it has found such an opportunity, an Advisor window opens. The example shown here presumes that you had previously placed a Navigation SmartPanel:
If the suggested link seems appropriate for the needs of your application, choose OK. If you decide later to make changes, you can easily revise the linkage using the SmartLinks Editor. For more information the SmartLinks Editor, see the SmartLinks editor section on page A23. 4. Set the properties of this SmartDataObject instance. See the Configuring a SmartDataObject instance section on page 413 for further information. Save your work.
5.
413
To configure the SmartDataObject instance: 1. Click the Menu button to open the SmartDataObject menu. Choose the Properties item. The properties dialog box opens:
2.
Change the Object identifier to one that more accurately reflects the role of this SmartDataObject in your application. If you wish to use the object as a placeholder, see the Creating a SmartObject placeholder section on page A29. Choose OK to dismiss the dialog box. Click the Menu button again, and choose the Instance Properties item. That dialog box opens:
3.
4.
5.
414
Data-Access Objects The Instance Properties you can change in Step 5 are: Partition Normally cleared (set to None). If this SmartDataObject is to run on an AppServer, you must assign it to a partition from this list. If there are no partitions listed, you can define as many as you need using the AppServer Partition Deployment Tool, available from the PRO*Tools toolbar. Partition tags that you define in this way are immediately made available to AppBuilder, and appear in this list. Rows to Batch Normally 200. This number represents the number of records fetched from the data source into the RowObject temp-table per read operation. Any choice you make here has performance implications that cannot be easily characterized. Experiment to see what number gives the best performance for your particular application. Force to Stateful Operating Mode Cleared and cannot be set unless you assign this object to a partition. Setting this box will cause this object to bind its AppServer connection for the duration of the session. When the box is cleared, connection binding is determined by the AppServer itself.
The final two options are specific to use of the SmartDataObject in a WebSpeed context. They have no meaning in a standard client-server context. For further information, see the online help and the WebSpeed documentation: Destroy on each stateless Web Request Normally cleared. Disconnect AppServer on each Web Request Normally cleared.
415
OpenEdge Development: AppBuilder Those conditions are: The application will run on an AppServer. Applications that do not run on an AppServer are not affected. Note that good practice suggests that you always design for the greatest flexibility of use. The client program does not require a local database connection via a SmartDataObject. Client programs that must have such a local connection in order to run are not affected. Note that good practice suggests that you always account for the case of no local connection. Your routines validate rows or columns (fieldnameValidate(), RowObjectValidate()). Routines that validate whole transactions (TransactionValidate()) are not affected.
The problem comes about because all DB-REQUIRED routines are removed from the client-only version of the SmartDataObject during compilation. This allows the program to load and run in the absence of a database connection. If your validation routines are marked DB-REQUIRED, then they, too, will be removed. Normally, calling a non-existent routine would cause a run-time error. But calls to optional routines never complain if they fail, and validation routines are always optional. The net result is that, when the client-only object is loaded, database updates are carried out without client-side validation checks even though you wrote the routines to perform them. Neither the compiler nor the interpreter can detect this logical error. Solving the problem These guidelines will let you avoid errors. Divide your validation tasks according to whether they require a database lookup operation. References to RowObject or other temp-tables do not count as lookup operations. Write your fieldnameValidate() and RowObjectValidate() procedures to include only the validation operations that do not require lookup. Do not include direct references to a database in these procedures, and turn off the DB-REQUIRED flag in them. AppBuilder offers a convenient option in the Section Editor for this purpose. Put any validation operations requiring lookup into one of the TransactionValidate() procedures. Keep the DB-REQUIRED flag turned on in these procedures.
By writing your fieldnameValidate() and RowObjectValidate( ) procedures such that you can legitimately turn off the DB-REQUIRED flag in them, you ensure that these routines will survive compilation and that all validation will occur as you intend. 416
Data-Access Objects Forcing server-side validation It is generally more efficient to do row and column validation on the client side, as part of SubmitRow(). There are some cases where this is not possiblesuch as calling a SmartDataObject from a Java program where no client-side version of the object exists. You would then want to force all validation, including row/column validation, to take place on the server. You can do this with a single line of code. This code also works in the case where there is a client. In that case, the client-side validation operations take place first on the client side, and then a second time on the server side. This introduces some inefficiency, but is not otherwise harmful. To force all validation to take place on the server, regardless of whether it also takes place in the client: 1. Open your SmartDataObject master for editing. It will appear on your display:
2.
Choose WindowCode Section Editor, and then select Procedures from the sections list. Create a new procedure called initializeObject( ) or edit the existing procedure by that name, if you already created itand include in it this line:
3.
4.
All instances made from the SmartDataObject master you just changed will now perform all row/column validation on the client sideif there is a clientand on the server side too.
417
418
Data-Access Objects
SmartBusinessObject
The SmartBusinessObject allows you to neatly package and fully synchronizeincluding the ability to update in a single, server-side transactionup to twenty SmartDataObjects. Figure 42 illustrates the place of a SmartBusinessObject in a Web-enabled application.
Internet
AppServer Internet Adapter Web server AppServer SDO2 SDO1 SDO3 Database SmartBusinessObject SmartB2B SmartProducer
HTTP or HTTPS
SDO1
SDO2
Database
4GL-JMS API
Figure 42:
Each static SmartDataObject produces and manages a single data stream. The nature and composition of that data stream is dependent on the query that you define within the object. Although you can cause a single SmartDataObject to produce a data stream of great complexity by the skillful use of JOINs, the result is often messy and difficult to use for business purposes. One way to reduce complexity is to create a number of SmartDataObjects, each with a more simple query, and then synchronize them at the application level. For example, you might create five SmartDataObjects that respectively supply: 1. 2. 3.
Customer Order
records.
OrderLine
419
Inventory
Order
OrderLine OrderLine
Item Inventory Item Inventory Item Inventory Item Inventory Item Inventory Item Inventory
Order Customer
Order OrderLine
Figure 43:
Synchronizing their read operations is not difficult. You can use DATA SmartLinks for that purpose regardless of whether you use a SmartBusinessObject. The difficult task is synchronizing updates. In general, there is no simple way to update multiple, standalone SmartDataObjects in a single transaction, if the objects run in a distributed environment. Such objects operate independently of one another on an AppServer. The new SmartBusinessObject solves this problem by providing a single context for all the SmartDataObjects you embed in it. Because the code you write in the SmartBusinessObject can operate on all the RowObject temp-tables belonging to its subordinate SmartDataObjects, the SmartBusinessObject allows you to perform updates in a single server-side transaction. With the SmartBusinessObject, you can create and manage integrated data streams that are as complex and powerful as your customers business needs demand.
420
Data-Access Objects The SmartBusinessObject presents a single point of contact for external modules such as Smart data-display objects. Internally, it uses its CONTAINER links to connect those external objects with the SmartDataObjects it containscommunicating navigation instructions from a SmartPanel, for example, or sending data out to a SmartDataViewer for visualization. This all happens automatically; you need do nothing to make it work. The SmartDataObjects synchronize themselves using DATA links that you create.
To create a SmartBusinessObject master: 1. Click the SmartBusinessObject tool icon in the Object Palette:
When the Choose dialog box opens, click the New button. Note: You can also choose FileNew or the New button on AppBuilders main-window toolbar. When the New dialog box appears, select SmartBusinessObject from the Object list and click OK.
421
OpenEdge Development: AppBuilder 2. AppBuilder creates the appropriate workspace, which looks like a frameless SmartWindow. Because a SmartBusinessObject has no frame element, you will see no layout grid even if you have grid visibility turned on:
3.
Populate the object and configure it. See the Populating and configuring a SmartBusinessObject section on page 422 for more detailed information. Save the object using a distinctive filename. Note that SmartBusinessObject names conventionally begin with sbo. Click the SmartContainer tool icon in the Object Palette. When the Selection dialog box opens, select the SmartBusinessObject master you just defined. Move your mouse cursor over your application workspace and click to place the new object instance. If you have already placed other SmartObjects such as a SmartDataBrowser, an Advisor might now appear and offer to create SmartLinks between those objects and the new SmartBusinessObject. Examine the offers and accept those that meet your needs. If the Advisor does not offer to create all the links you desire, choose ToolsProcedure Settings and open the SmartLinks Editor to add links by hand. For information about the SmartLinks Editor, see the SmartLinks editor section on page A23. Save your work.
4.
5.
6.
7.
8.
422
Data-Access Objects 2. Create and place the SmartDataObjects, add DATA links to represent the logical dependencies among them, and identify the foreign-field (relational) mappings. For detailed information about creating and placing SmartDataObjects, see the Synchronizing SmartDataObjects using DATA links section on page 423. 3. Determine whether the users of your application are more likely to prefer efficiency or completeness when browsing the data stream and set the property CascadeOnBrowse accordingly. This is a somewhat subtle issue. See the How the CascadeOnBrowse property works section on page 430 for further information. Determine your validation needs and create the appropriate routines to perform those tests. The SmartBusinessObject makes it easier to perform comprehensive validation tests. Besides the tests local to each SmartDataObject, you can write validation routines that run in the SmartBusinessObject itself. The SmartBusinessObject can see the Update tables belonging to each of its contained SmartDataObjects and you can take advantage of that fact to create whole-stream validation. Within the SmartDataObjects themselves, their update tables all have the same RowObjUpd identifier. Since they have separate namespaces internally, this is not a problem. But at the level of the SmartBusinessObject, each such update table needs a unique name. The ObjectName property serves that purpose. So if your SmartBusinessObject contains two SmartDataObjects to which you have given the ObjectNames CustSDO and OrderSDO, you can write code referring to fields in their respective RowObjUpd tables as CustSDO.SomeFieldName and OrderSDO.SomeFieldName and everything will work as you intend. For additional information about creating validation routines, see OpenEdge Development: ADM and SmartObjects.
4.
423
OpenEdge Development: AppBuilder Figure 44 shows the hierarchy imposed by the DATA links.
Figure 44:
Before deciding how to organize your DATA links, determine your business focus. If you are interested in both Customer and Order records, which are more central? Are you interested in orders only in connection with a particular customer? Or is your focus the order itself, with customer information being secondary? In the first case, you would create your DATA link from the Customer object to the Order object. In the second case, the link would go in the opposite direction. How you organize the dependencies is a function of your business goals. Note: The SmartBusinessObject itself can be the target of a DATA link from some SmartDataObject outside itself. The effect when resynchronization takes place is exactly as though both objects were combinedthe resynchronization process propagates through both objects.
To create a synchronizing relationship between two SmartDataObjects within the SmartBusinessObject: 1. 2. Create and place the first (controlling) object. Create the second (controlled) object, being sure to include at least one field shared with the first object. For example, the CustNum field is common to both the Customer table and the Order table. That field (the foreign field) relates those two tables. Note that the field need not have the same name in both tables, although it often does.
424
Data-Access Objects 3. Place the second object. An Advisor dialog box appears and offers to create a DATA link from the first object. Accept the offer:
4.
Another Advisor dialog box appears asking you if you wish to identify the foreign-field (relational) mapping. Unless you have a reason to defer this operation, accept the offer:
425
OpenEdge Development: AppBuilder 5. The Multi-Field Mapping dialog box now opens, presenting you with lists of available fields. Select the field common to both tables, for example CustNum:
6.
Choose the Map button. Your selections disappear from the Source and Target lists and reappear as an associated pair in the Mapped Fields field:
7.
Create additional associations, if you so desire and there are suitable field pairs. When you have finished, choose OK to close the dialog box. Synchronization between these two SmartDataObjects is now established.
426
Data-Access Objects 8. Repeat from Step 2 for each additional SmartDataObject you place, creating a synchronizing DATA link only from the immediately preceding object. Note: The Advisor is not aware of your goal, so it will offer to create a link from any existing object. It is easy to become confused and select the wrong object. If you make such a mistake, use the SmartLinks Editor to correct it. 9. When you have linked all the SmartDataObjects appropriately, save your work.
If you were to create the relationships shown in Figure 44, they would appear similar to this in the SmartLinks Editor:
427
2.
Change the object identifier to more accurately reflect the role of this SmartBusinessObject in your application. If you wish to use the object as a placeholder, check the Parameterize as Variable box. See the Creating a SmartObject placeholder section on page A29 for further information about placeholders and resolving them at run time.
3.
428
Data-Access Objects 4. Choose OK to close the dialog box. Click the Menu button again and choose the Instance Properties item. That dialog box opens:
5.
Select the Partition to which this object will be assigned when running on an AppServer. If there are no partitions listed, you can define as many as you need. Close the dialog box and use the AppServer Service Parameter Maintenance Tool, available from the PRO*Tools toolbar. The Partition tags that you define in this way are immediately made available to AppBuilder and will appear in this list when you reopen this dialog box. Note: Unlike the SmartDataObject, a SmartBusinessObject always binds a dedicated AppServer connection for the entire application session. SmartBusinessObjects never run in connectionless mode. Because of how complex they are internally, having to repeatedly make and break momentary connections would be impractical.
6.
If desired, clear the CascadeOnBrowse check box to improve performance when browsing. See the How the CascadeOnBrowse property works section on page 430 for more detailed information about how this property affects the objects behavior. Use the MoveUp/MoveDown buttons to arrange the list of SmartDataObject names to agree with the synchronization hierarchy you have defined. The first object (Customer, in the example shown in Figure 44) must be at the top of the list. The order of objects at the same level (in Figure 44, Item and Inventory are at the same level) is not significant. Choose OK to close the Instance Properties dialog box. Save your work.
7.
8. 9.
429
430
Data-Access Objects
SmartFilters
The query you build into your SmartDataObject might return thousandsor even millionsof records. A return of such size can totally overwhelm users, causing them to fervently wish for a way to further subset the data stream. AppBuilder offers an ADM SmartObject to deal with that problem: SmartFilter. SmartFilter provides a query-by-form (QBF) interface to the data stream supplied by your SmartDataObject. Using SmartFilter, the user of your application can narrow the query as much as desired, possibly causing the query to return only a few records or even no records at all. Being able to focus the query more tightly can be very convenient for the user. As seen by the user, SmartFilter is rather simple. Each filterable field is represented by one or two editable fields representing a value and a comparison operator. The user controls the objects behavior using three buttons: Apply filter Immediately activates the filter, reducing the size of the data stream. To clear the effect of a filter, the user must choose Blank and then Apply. Blank Clears all editable fields and resets the operators (if visible) to their default states, ready for the next setup. Reset Restores the most recent filter expressions. Does not clear the fields.
SmartFilter is supplied as a pre-compiled master rather than as a template. To include an instance of SmartFilter in your application: 1. Click on the SmartFilter tool icon in the Object Palette:
2.
There might be a short pause while AppBuilder creates the instance. Position the cursor over the workspace and click to place the instance.
431
OpenEdge Development: AppBuilder 3. If you previously placed a SmartDataObject, AppBuilder now opens an Advisor window offering to create a Filter link to it. Unless you have reason not to do so, accept the offer:
4.
Inspect the properties for this SmartFilter and change any that do not meet your needs. See the Configuring SmartFilter properties section on page 432 for information about how to do that. When you have finished making changes, choose OK to dismiss the properties dialog box. Click the object to select it. Drag the handles to position and size the object to suit your layout. Your SmartFilter is now ready for use.
5. 6.
432
Data-Access Objects To open the dialog box, choose Instance Properties from the Menu button menu. The dialog box appears as shown here:
Data This area identifies the data source, and the fields to be filtered: For your convenience, if you place the SmartFilter object into your workspace after you place the SmartDataObject, AppBuilder automatically fills in the Target field for you. This is generally the best way to do it. But if you place the SmartFilter instance first, you can still fully configure it. Click the Browse button and, when the Choose dialog box opens, select the appropriate SmartDataObject and choose OK. The object filename immediately appears in the Target field, and a list of database fields supplied by that master populates the Fields field. Note that you are not in any way attaching that data source at this point; you have merely identified it so that you can configure your SmartFilter. By default, none of the fields supplied by the SmartDataObject are filterable. Choose Edit Field List and select the fields to make available for filtering. They will appear in the Fields list. If you change your mind about one of the fields, simply select it and choose Remove. Removing the field from the filterable list has no effect on the data stream or the SmartObject assigned to display the data. To restore a field to the filterable list, choose Edit Field List and add it back. Note that performance might be unacceptably low if the number of records is large and you allow the user to filter on fields that are not indexed.
433
OpenEdge Development: AppBuilder Style You can define the amount of control the user has over the filter operation by setting the Style value. The Style you choose applies to all fields unless you modify the setting for a particular field. The possible values for Style are: Implicit Choosing this option removes the relationship operator from the users control. The user still selects the value against which the filter tests, but cannot change the nature of the test (equality, inequality, etc.). You set the type of test at design time using the related combo box. By default, the operation you choose in the combo box is ignored for character string fields. Character strings undergo a BEGINS test regardless of the setting in the combo box. If you want character strings to be tested using the operator you set in the combo box, uncheck the BEGINS box in the String Operator frame (below the Style radio buttons). When Style is set to Implicit, you can set individual fields to be Ranges, instead. See the View as Range Fields option in the Field properties section on page 436. Explicit The default Style. Choosing this style allows the user to select the type of test on a per-field basis. The user selects the operator from a combo box (default) or by setting a radio button; see the Operator View As section on page 435. Because BEGINS can be applied on a per-field basis for character fields (it appears in their list of operator choices), the global BEGINS option is disabled when Style is set to Explicit. You can set individual fields to be ranges. See the View as Range Fields option in the Field properties section on page 436. Range Choosing this style causes the SmartFilter to display two fill-ins for each field, representing the upper and lower bounds of a range. The user types in the limiting values, which are considered inclusive. For example, entering c as the lower bound and e as the upper, for a CHARACTER field, will return all records where the value for that field is in the range c* through e, inclusive. Note that while e itself would be included, e* is not. Similarly, entering bounds of 10 and 100 for an INTEGER field would return all records where the value of that field is in the range 10 - 100, inclusive. When Style is set to Range, you can set individual fields to be Explicit, instead. See the Explicit Operator option in the Field properties section on page 436.
434
Data-Access Objects Inline Choosing this style requires that the user enter the comparison operator along with the value. For example, to test for INTEGER values over 10, the user must type in > 10. If the user enters a value without an operator, for example 10 rather than >10, SmartFilter will presume the intended operator is EQUALS. The only exception is if the field is of type CHARACTER and the BEGINS check box is set. In that case SmartFilter will perform the BEGINS test instead. String operators When these check boxes are enabled, setting them overrides any conflicting setting in Style. BEGINS When checked, SmartFilter will perform a BEGINS test against CHARACTER fields CONTAINS If the field being filtered is word-indexed, SmartFilter will represent the field as an editor widget sized according to the Number of Lines in Editors setting in the Size & Position section.
Operator View As By default, the SmartFilter lists the operators for Explicit fields in a combo box. You can force the options to be listed as radio buttons instead. To choose a representation, set the appropriate radio button. Size and position Allows you to set three visual characteristics of the SmartFilter instance: Default Field Widths Set the displayed width of the editable portion of the filter fields. You can set the width separately for non-CHARACTER fields, and can override these settings on a per-field basis in the Field Properties section. The width you set here only affects the visible portion of the field, and it has no effect outside the SmartFilter itself. Field Position You can control where the editable portion of the field starts. To minimize the amount of space the filter takes up in the X dimension, set this value to the character count of the longest field label, plus two. For example, if your longest label is Postal-Code:, set the value to 14. If you use a smaller number, the field will hide the right end of one or more labels. If you use a larger number, both the fields and their labels will move to the right within the SmartFilters frame.
435
OpenEdge Development: AppBuilder Number of Lines in Editors If SmartFilter represents any field as an editor widget, this value is the number of lines that will be displayed. If you set this value to 1, the widget will display with the same height as a fill-in, and it will have no word-wrapping. If you set the value to 2 or more, the field will have word-wrapping and a vertical scroll bar.
Field properties Each filterable field has several default properties that you can change. Note that such changes have no effect on the database, the data stream, or how the data-display object treats the field. All changes are local to the SmartFilter. To begin, select the field whose properties you wish to change: To change the label that identifies the field, uncheck the Filter Target box and type in the new text for the label. By default, the label is inherited from the fieldname in the schema. To change the field width, uncheck the Use Default box and type in the new value in character units. The default value is taken from the field definition in the schema. You can add text for a Tooltip identification by typing it into that fill-in. If you plan to provide context-sensitive help, enter a unique INTEGER value for this field in the Help ID fill-in. The filter operators (equals, greater than, etc.) all refer to a single value. To select instead for values that fall within a certain range, check the box View as Range Fields. This option is available only when Style is Implicit or Explicit. When View as Range Fields is checked, a second editable field appears in place of the operators list. You can override the Range style on a per-field basis by setting the Explicit Operator box. The user will then see a single fill-in field instead of two, and be able to choose the comparison operator from a combo box.
436
Data-Access Objects
If the field is being displayed, remove the field reference from the SmartDataBrowser and SmartDataViewer first, then remove it from the SmartDataObject. If it is not being displayed, simply recompile.
Add the field reference to the SmartDataObject first. Then add it to the SmartDataBrowser and SmartDataViewer, if you want them to display it. If you do not want them to display it, simply recompile. Make the field updatable in the SmartDataObject first. Then make it updatable in the SmartDataBrowser and SmartDataViewer. Make it read-only in the SmartDataBrowser and SmartDataViewer first. Then make it read-only in the SmartDataObject.
437
2.
Place the object anywhere in the workspaceit is not visible at run time. In general, it is a good idea to place it in an unoccupied corner, if you can, in case you need to gain access to it later. The query object is represented by this icon in your workspace, at design time:
3.
When you click to place the new query object, the Query Builder dialog will open. Use that dialog box to compose the terms of the query. See the Defining and editing queries using Query Builder section on page 438 for further information.
438
Data-Access Objects Place a basic Data Browser (Browse) object in the workspace AppBuilder starts Query Builder. The browse object has all the internal logic necessary to use the query, though only in a self-contained way. You manually add any additional logic you require. Place a Query object in the workspace AppBuilder then starts Query Builder. Such a query object is not connected to anything after you define it. You must manually add the code to make use of it. Choose the Query button from the property sheet of a frame object AppBuilder then starts Query Builder. As is true of the query object, you must manually write the code that makes use of this embedded query, after you have finished defining it. Note: You can construct or modify queries by hand, using AppBuilders Section Editor, but such queries cannot later be edited using Query Builder. If you wish to have all queries be maintainable in Query Builder, you would have to replace any such free-form queries with their Query Builder-generated logical equivalents. Query Builder always starts in Table-selection mode.
Table mode
In this mode, the Query Builder allows you to specify the tables you want in the query. When you modify a query from the property sheet of a frame or browse, the Query Builder also initializes to this mode. Figure 45 shows how the Query Builder appears in Table mode.
Figure 45:
OpenEdge Development: AppBuilder To select a database table, select the table name in the Available Tables list and choose the Add button; you can also double-click on the name. To remove a table from the Selected Tables & Joins list, select the table name and choose the Remove button; you can also double-click on the name. After you select the tables you want, the AppBuilder displays the query in the Query panel. For example, if you choose the Customer, Order, and Order-Line tables, the Query field appears, as shown in Figure 46.
Figure 46:
As you select tables, the AppBuilder establishes the relationship among them and the other tables that you have selected. If two tables share a common key with the same name and data type, they are OF joinable. If they are not OF joinable, you must establish how they will be joined. For example, if you choose the Customer and Local-Default tables, the AppBuilder displays the query in the Query panel, as shown in Figure 47.
FOR EACH sports.Customer NO-LOCK, EACH sports.Local-Default WHERE TRUE /* Join to Customer incomplete */ NO-LOCK:
Figure 47:
The comment indicates that you must complete the relationship of the Local-Default table to the Customer table. Complete the join criteria by choosing the Join button to enter Join mode. 440
Data-Access Objects If you select three or more tables and AppBuilder can establish the relationship among them, the AppBuilder still allows you to choose a table and change its join criteria. You do this by selecting the table in the Selected Tables & Joins list and choosing the Switch Join Partners button.
Join mode
When you activate the Join radio-set button in the Query Builder dialog box, you enter Join mode, and the Query Builder appears as in Figure 48.
Figure 48:
To enter this mode, you must already have selected at least two database tables. If you select more than two tables, you can use the down arrow button in the Join combo box to choose the combination of tables you want to join. If two tables are OF joinable, you can change their join criteria by activating the Customize Join toggle box to establish a WHERE clause between the two tables. Your comparison options are equal, not equal, less than, greater than, less than or equal, and greater than or equal. To use one of these options, double-click in a field from one of the tables, double-click on one of the comparison buttons, then click in another field from the other table. As you establish comparisons between fields, the AppBuilder displays the 4GL code in the Join Criteria panel. When you choose OK, the AppBuilder displays the code in the Query Builders Query field (and in the widgets property sheet, if the query is an embedded one). You can link the comparisons with AND or OR. 441
OpenEdge Development: AppBuilder If you are familiar with the Progress 4GL, you can edit the Join Criteria field by clicking in it and typing in the code directly.
Where mode
To specify search criteria for a table, activate the Where radio set button in the Query Builder dialog box. The Query Builder enters Where mode and appears as in Figure 49.
Figure 49:
First, select a field from the list of fields. The AppBuilder displays the possible comparison operators for that field. These operators are sensitized based on the type of field. For example, if you select the Cust-num field, the Contains button is not sensitized because Cust-num is not a word-indexed field. Also, Begins and Matches are not sensitized either, because Cust-num is an integer field. After you select a field, choose one of the enabled comparison buttons. A dialog box appears that lets you supply a constant for comparison (you cannot specify variables). If you choose either the List or Range button, the dialog boxes that appear allow you to specify whether the list or range is inclusive or exclusive. The AND and OR buttons extend the relationships between logical fields and also let you combine logical phrases with a complex expression. The AppBuilder displays the 4GL text of the clause in the Where Criteria editor. When you choose OK, the AppBuilder displays the code in the Query Builder when it is in Table mode, and in the widgets property sheet if the query is an embedded one. 442
Data-Access Objects If you are familiar with the Progress 4GL, you can type the search criteria directly into the Where Criteria panel.
Sort mode
To specify the sort order you want for your query, activate the Sort radio set button. The Query Builder enters Sort mode and appears as in Figure 410.
Figure 410:
Note: If your query uses the {&SORTBY-PHRASE} preprocessor value to specify a sort order for the final result, the AppBuilder prevents you from entering this Sort mode by making the Sort button insensitive. You can set the query to use the {&SORTBY-PHRASE} from the Options mode of the Query Builder. For more information, see the Options mode section on page 444. To specify the sort criteria, select fields from the Available Fields list. The Table combo box allows you to move between tables if you chose more than one table while in Table mode. In the Sort Criteria editor, AppBuilder displays the fields you choose and the sort criteria you specify. When you choose OK, the sort criteria is also displayed in Table mode. The Ascending and Descending radio buttons allow you to specify the display order of the sorted records.
443
Options mode
To specify query-tuning options and other query parameters, choose the Options button. Query Builder enters the Options mode and appears as in Figure 411.
Figure 411:
Editable find, join, and field list criteria To support the QUERY FIELD-LIST feature, Query Builder displays an editable browse with the following fields: Table Specifies the tables in the query. This field is not editable. Find Specifies the find criteria (EACH, FIRST, or LAST). This field is editable. Join Specifies the type of join (INNER or OUTER). This field is editable. Returned Specifies which fields are returned (included in the field list) when records are fetched to satisfy the query (All Fields or Fields Used). This field is editable. To change the Find field, double-click in it until the desired value appears or type E, F, or L. To change the Join field, double-click in it until the desired value appears or type I for INNER or O for OUTER.
444
Data-Access Objects The Returned field is a logical field that can be set in one of two modes: All Fields (the default) and Fields Used. When you select All Fields, the query fetches all fields of the table. When Fields Used is selected, the query returns only those fields in the FIELDS-IN-QUERY preprocessor list. For browses, this is controlled in the Column Editor; for frame queries, this is controlled by what fields you place in the frame. To select All Fields, either double-click in the field until All Fields appears or type A. To select Fields Used, double-click in the field or type F. Editable query tuning options You specify query-tuning parameters by entering your choice of parameters in the Query Tuning Options panel. Depending on your choices, the AppBuilder inserts code like the following into the OPEN-QUERY statement:
Query-tuning parameters correspond to the QUERY-TUNING keyword. This keyword is available with the FIND, FOR EACH/LAST/FIRST, and OPEN-QUERY statements. For more information, see OpenEdge Development: Progress 4GL Reference.
Figure 412:
445
OpenEdge Development: AppBuilder Because columns are defined only in relationship to a table, this option is disabled until you have selected at least one table in Query Builder. When you choose this button, the Column Editor dialog box opens, as shown in Figure 413.
Figure 413:
Initially, the Fields list is empty apart from the notice reassuring you that the empty state is normal. To select fields (columns) and define the conditions for their display: 1. Choose the Add button. The Multi-Field Selector dialog box opens:
446
Data-Access Objects Choose the fields you wish to display and move them to the selected list. You can move them by double-clicking, or by selecting them and choosing Add. Hold down the CTRL key to select more than one field at a time. Use the Move Up/Move Down buttons to reorder the list. When finished, choose OK. 2. If you wish to create and display calculated fields, choose the Calculated Field button. The Calculated Field Editor dialog box opens:
Calculated fields are fields whose content does not come directly from the database. The content of a calculated field represents the result of some transforming expression applied to the content of one or more other fields, which can themselves be calculated fields. For information about how to use this dialog box to create calculated fields, see the Creating calculated fields section on page 448. 3. Set the Enable check box for each updatable field. If you wish to enable or disable all fields at once, choose the appropriate button. When you select a field that is enabled for update, you can set additional characteristics: Disable Autozap By default, a field is cleared when the user begins typing into it. This characteristic is called autozapping. Set this check box to disable such automatic clearing of the current field. Column Read-only Set this check box to temporarily disable update on the field (column). Fields must be enabled at design time if they are to be enabled at all; you cannot first enable them under program control. Auto-Return Automatically moves the input focus to the next field when this field is full. If this field is the last field, having Auto-Return set causes a GO event to be generated. 447
OpenEdge Development: AppBuilder 4. Clear the Visible check box for any field that is not to be seen at initialization. Fields are Visible by default. Set the Auto-Resize check box if you want the field to be able to change its size to agree with changes in certain run-time conditions, such as font size or text format. Set the font, colors, and string attributes for the data to be displayed in the column. Set the string value, font, and colors for the label that will appear at the top of the column. Set the format for the data to be displayed in the column. Choose the Format Help button to see the Format dialog box:
5.
6. 7. 8.
9.
Set the Column Help string. If the parent window of the browse has a status area defined, this string will appear there whenever a field in this column has the input focus. If the parent window has no status area defined, this string does not appear. If this field is left blank, the Browse displays a generic prompt.
448
Data-Access Objects
To create a calculated field from the Column Editors dialog box: 1. Click the Calculated Fields button. The dialog box opens:
2.
Compose the expression whose result will appear in the field. You can compose by typing directly into the field, by double-clicking on tokens (Fields, Functions, Operators), or by some combination of these two methods. The expression can be of any complexity. Choose OK when the expression is complete. The dialog box closes. The newly defined field appears in the list of fields with the default identifier CALC, a default type of CHARACTER x(8), and no label. Change the identifier to one more meaningful in the context of your application. Add a label, if appropriate. Change the data type and format, if necessary, to reflect the nature of the data. For example, if the expression yields a floating-point result, change the data type to DECIMAL and the format string to one that portrays DECIMAL values. If appropriate, choose Advanced and enter a Help string for this field. Use the Move Up/Down buttons to put the new field into the correct relationship to the other fields that will display. Note: Calculated fields are created in a not-updatable state. Although you can set them to be updatable, in general you should not: a calculated field is a scratch field, and is undefined in the context of the database. It can be easy to forget this. If you do choose to make a calculated field updatable, you must write the code yourself that will interpret any changes that a user makes.
3.
4.
5. 6.
449
450
5
Data-Display/Capture Objects
Presenting data to the user in a way appropriate for inspection or update is a major activity in a database application. Typically, the same objects that present data also capture new and changed data. This chapter describes the data-display/data-capture objects AppBuilder supplies for your use: Introduction to data-display objects SmartDataBrowsers Dynamic SmartDataBrowser Static SmartDataBrowser SmartDataViewers SmartDataFields SmartSelects Basic data browsers
OpenEdge Development: AppBuilder Combo boxes Basic data viewers Multi-line editors Fill-ins (single-line editors) Radio button sets Selection lists Slider controls Spin controls (ActiveX) Toggle boxes (check boxes)
52
Data-Display/Capture Objects
Additionally, the Progress 4GL provides a number of basic objects that display and capture data. These include: Data browser with built-in query, for representing data in tabular row/column format. Combo box, for presenting a list of choices. Data viewer (DB-Fields) with built-in query, for representing data on a per-record basis. Editor (multi-line editor), with most of the capabilities of a standard text editor. Fill-in (single-line editor), for capturing a small amount of data. Radio-button set, for representing an exclusive set of (usually non-string) choices. Selection list, for presenting a list of choices. Slider control, for representing a point within a subrange of INTEGER. Toggle box (check box), for representing a Boolean (LOGICAL) choice.
This chapter discusses these building blocks and their role in your applications.
53
SmartDataBrowsers
SmartDataBrowsers are browse widgets enhanced with ADM smart technology. A SmartDataBrowser presents the results of a query in simple row/column tabular format. Each row displayed in a SmartDataBrowser always represents one record from the data stream (the record itself might be a dynamic composite created by a JOIN operation). Each column represents one of the fields in the records. The SmartDataBrowser can display any of the standard data types that can be represented by ASCII text. A SmartDataBrowser displays and possibly updates data supplied by a SmartDataObject to which the SmartDataBrowser is connected by SmartLinks. AppBuilder supplies two types of SmartDataBrowser for your use: Dynamic You place an instance of the predefined dynamic SmartDataBrowser in your application. This object is able to connect to and interact with any SmartDataObject. Static Using the wizard provided by AppBuilder, you define a static SmartDataBrowser master object to connect to and cooperate with a particular SmartDataObject. You later select and place an instance of the master object in your application.
Dynamic SmartDataBrowser
The dynamic SmartDataBrowser is capable of displaying and updating records supplied by any SmartDataObject. You make the connection and set up the conditions at design time.
54
Data-Display/Capture Objects 2. Right-click the SmartDataBrowser tool icon in the Object Palette:
Choose dynamic SmartDataBrowser from the menu that opens. 3. Position your mouse cursor over the workspace and click to place the object. It appears as a Browse widget, initially with only a single column:
4.
AppBuilder immediately opens an Advisor window if it finds opportunities to create SmartLinks to other objects. Examine the recommendations and accept all that seem appropriate. Click on the Menu button and select Instance Properties from the menu. That dialog box opens:
5.
55
OpenEdge Development: AppBuilder 6. If you wish to display or allow updates to fewer fields than the SmartDataObject would permit, make those changes now. Choose the appropriate button to open a selector dialog. See Table 51 for a description of how AppBuilder makes use of your choices. Table 51: Dynamic SmartDataBrowser display/update rules AppBuilder response Your choice Make no changes Display Display all fields provided by the SmartDataObject (the value of the DataColumns property). Update Allow updates on all fields enabled in the SmartDataObject (the value of the UpdatableColumns property). If there is a TableIO source, then allow updates on all fields that are enabled in the SmartDataObject, if they are also being displayed. If no TableIO source, then allow no updates at all. Specify only the enabled list. Specify both the display list and the enabled list. 7. Display all fields provided by the SmartDataObject (the value of the Data Columns property). Display the fields you chose. Allow updates on the fields you chose. Allow updates on the fields you chose.
If you wish to allow the user to search on one of the displayed fields, select it from the Search Field combo box. Clear the Enable and View check boxes to initialize the object in a hidden, insensitive state.
8.
56
Data-Display/Capture Objects 9. Set the Down value to the number of rows you wish the browser to display. If you wish the object to determine its own best width, check the Calculate Width box and, if desired, enter a Max Width limiting value. Note: The design-time representation does not account for the Down and Width choices you make, so you cannot predict the run-time appearance from it. You will need to experiment to determine how to get the run-time appearance you desire. A good first approximation for number of lines might be to show 1 or 2 more lines than your Down setting (1 to account for the column-labels line, and a second if there will be a horizontal scroll bar) 10. Unless the total number of records in the data stream is same or less than the Rows To Batch value, the user will not be able to use the scroll bar to reach the last record. The last record reachable by using the scroll bar is the last record in the buffer, not the last record in the data stream. This can be confusing to the user. To solve this problem, check the Scroll Remote Results List box. You might also have to write some code. For more information see the Scrolling to the last record in the data stream section on page 520. Unless you need to add special logic, the dynamic browser will typically be a lower-cost choice than a static browser.
Static SmartDataBrowser
The static SmartDataBrowser you use in your application is an instance of a master object that you create. Each master SmartDataBrowser is designed to cooperate with a particular SmartDataObject master, exchanging a well-defined set of data fields in a particular order.
57
OpenEdge Development: AppBuilder AppBuilder supplies a wizard to help with creating SmartDataBrowser masters. The wizard has four pages, only two of which involve significant work: 1. 2. 3. 4. Introduction. Identifying the data source. Selecting the fields to display from the data stream. Congratulations.
To create a SmartDataBrowser master: 1. Start the SmartDataBrowser Wizard by clicking on the SmartDataBrowser tool icon in the Object Palette:
When the Choose dialog box opens, choose New. Note: You could also start the wizard by choosing FileNew and selecting the SmartDataBrowser item from the list, or by right-clicking the icon in the Palette and selecting New SmartDataBrowser from the menu that appears. 2. The SmartDataBrowser Wizard starts up, and displays its first page:
58
Data-Display/Capture Objects 3. When you have finished reading the introductory text, choose Next to move to Page 2:
4.
Choose the Browse button and select the appropriate SmartDataObject master. Its filename will appear in the fill-in. Choose Next to move to Page 3:
5.
59
OpenEdge Development: AppBuilder 6. Choose the Add Fields button to open a Multi-Field Selector dialog box:
7.
The fields Available for display appear in the left-hand list. Select those you wish the SmartDataBrowser to display and click the Add button to move them to the Selected list in the right-hand window. If you make a mistake, click the Remove button. When you have finished selecting fields, you can reorder them using the Move Up and Move Down buttons. When they are in the order you want them displayed, choose OK. The Selector dialog box closes and the list of selected fields appears in the wizard:
510
Data-Display/Capture Objects 8. Choose Next to advance to the wizards final page. If you have successfully defined a data source and selected the fields to display, you will see Congratulations!. If you do not, choose the Back button and make any necessary changes:
9.
Choose Finish to dismiss the wizard and reveal the new SmartDataBrowser master, if it was not already visible.
10. Choose FileSave and give the new master a descriptive filename. Note that SmartDataBrowser filenames conventionally begin with b:
511
2.
Click on the object to select it, if necessary, and choose ToolsProperty Sheet. The Property Sheet dialog box opens:
512
Data-Display/Capture Objects Minimal configuration Although you can accept many of the default settings, you might wish to make two changes to individualize the object. Note that these changes will apply to all created instances: Change the identifier to more closely reflect the objects nature. Add a title string, if you plan to allow the Browse component to display a title bar.
Query and fields Since the SmartDataBrowser uses the data stream from a SmartDataObject, you can change only the fields and their ordering. The Query button is disabled because the query belongs to the SmartDataObject, not the browse widget: Choosing the Fields button starts Column Editor and allows you to modify the columns this SmartDataBrowser will display. For information about how to use Column Editor, see the Selecting database fields for browsing section on page 445. By default, all columns can be scrolled horizontally, if there are too many columns to display at once. You can choose to lock the leftmost columns in place, so that scrolling does not affect them. Enter in the Locked Columns box the number of columns you want to freeze in place. Caution: If you lock more columns than will fit in the browses viewable width, you effectively disable the horizontal scroll bar, because all scrolling will take place out of sight to the right. When displaying a vertical scroll bar, the system tries to size the scroll bars thumb slider to reflect the total number of lines in the data stream. The larger the number of lines, the smaller the thumb. However, that thumb size is based on the number of records being batched by the SmartDataObject, not on the total number in the stream. In general, the total number of records in the stream will be larger. When that is the case, the system cannot correctly size the thumb. If you can predict, even approximately, the total number of records in the data stream, you can improve the accuracy of the scroll bars appearance. Enter your estimate in the Max Data Guess field. Type into the Tooltip field the identifying text that you want the system to display whenever the mouse cursor hovers over this SmartDataBrowser.
513
OpenEdge Development: AppBuilder Geometry You can set the exact origin and size of any SmartDataBrowser instance created from this master. Set the values, in character units, in the appropriate fields. You can choose whether the origin is measured at the upper-left corner (the default) or the upper-right corner. If you prefer to use pixels rather than character units, choose the Advanced button and set the values in that dialog box instead. Miscellaneous properties (other settings) You can make a number of changes to the appearance and behavior of the browse component of the SmartDataObject master, if the default settings do not meet your needs: Column Scrolling Normally set. Clearing this check box causes the horizontal scrolling granularity to be one character. The default is one field (column). This option applies only when running under MS-Windows. Drop Target Normally cleared. Setting this check box causes the system to generate an event when the user drags and drops another object onto this one. You must write code to deal with that event. Enable Normally set. Clearing this check box causes the entire widget to be insensitive. Expandable Normally set. Clearing this check box prevents the last column from stretching to cover any background exposed by scrolling. When Column Scrolling is set, and the browse window is scrolled all the way to the right, some background will generally be exposed because it is unlikely that the last n columns will exactly fit the browse width. When this option is set, the last column is expanded cosmetically to the right to mask any exposed background from view. This option applies only when running under MS-Windows. Hidden Normally cleared. Setting this check box prevents implicit display of the object. Multiple Selection Normally cleared. Setting this check box allows the user to select multiple rows. If any of the fields are updatable, you must also clear the No Row Markers check box. Note: Multiple selection is not supported by the ADM. If you wish to use this option, you will have to write code to manage and communicate the multiple values as a special case.
514
Data-Display/Capture Objects No Assign Normally set. When cleared, any changes to updatable fields are automatically written back to the database when the user moves to a different row (record). No Auto-Validate Normally set. Clearing this box causes the interpreter to automatically run validation checks. No Box Normally cleared. Setting this check box causes the Browse window to display without a border. Under MS-Windows, this border is a single-pixel line. No Labels Normally cleared. Setting this check box prevents display of the column labels. No Tab Stop Normally cleared. Setting this check box removes the SmartDataBrowser from the applicable TAB-traversal list. Under MS-Windows, removing the object from the traversal list has some effects that might confuse the user. No Validate Normally cleared. Setting this check box disables all validation conditions specified in the Data Dictionary for fields in this SmartDataBrowser. Open the Query Normally cleared. Setting this check box activates the query and populates the fields during initialization. In a SmartDataBrowser, this option has no effect. Scroll bar Vertical Normally set. Clearing this option hides the vertical scroll bar. The user can still scroll using the arrow keys. If you use a SmartPanel for navigation with this SmartDataBrowser, you should probably clear this box to avoid confusion. Separators Normally set. Clearing this check box causes the widget to paint itself without lines separating the rows and columns. When this box is set, the Colors selector (see the Colors selector and editor section on page A10) offers you the option of selecting a special color for the separator lines. Title Bar Normally cleared. Setting this check box causes the browse widget to display a full-width frame-like title bar. Specify the title string if you set this option.
515
OpenEdge Development: AppBuilder Advanced properties Choose the Advanced button. The Advanced Properties dialog box will open:
You can make a number of changes to the SmartDataBrowsers appearance and behavior by changing the default settings in this dialog box: Help Text in this field displays in the status bar of the parent window when the SmartDataBrowser has the focus. If the parent window has no status area, this text will not display. Private Data AppBuilder writes out the contents of this field as the value of the objects PRIVATE-DATA attribute. You can write code to read and operate on that value in any way that meets your needs. Generated Code Layout Unit Controls whether AppBuilder describes the position and size of this SmartDataBrowser in character or pixel units when it generates source code. Geometry Expresses the origin and size of this widget in pixels. You can set a particular origin and size for the object here rather than interactively, if you wish. You can also choose to have the origin measured at the upper-right rather than the upper-left corner. Column Movable Normally cleared. Setting this check box allows the user to reorder the columns by dragging.
516
Data-Display/Capture Objects Column Resizable Normally cleared. Setting this check box allows the user to resize the columns interactively. Resizing the column has no effect on the actual field widths. Column Searching Normally cleared. Setting this box in read-only browsers allows the user to search in an individual field across all records. Updatable browsers allow such searching by default. The search is started by clicking the desired column title and typing the letter for which to search. No prompt appears for the letter. The browser scrolls its window to bring into view and make current the next record, if any, in which the search field data begins with the typed-in letter. Movable Normally cleared. Setting this check box and the Selectable check box allows the user to move the entire SmartDataBrowser object around within the bounds of the enclosing frame. Resizable Normally cleared. Setting this check box and the Selectable check box allows the user to change the size of the SmartDataBrowser object, within the limits of the enclosing frame. Row Resizable Normally cleared. Setting this check box allows the user to change the vertical size (height) of the rows by dragging a horizontal separator line. Selectable Normally cleared. Setting this check box allows the user to select the SmartDataBrowser object.
517
To edit your SmartDataBrowser master: 1. Choose FileOpen and select the source file (for example: bSampleSDB.w). The SmartDataBrowser object appears, displaying its Browse widget in a layout workspace:
2.
Click on the Browse widget to select it, and choose ToolsProperty Sheet. The Property Sheet dialog box opens:
3.
Choose the Fields button to open the Column Editor dialog box (note that the Query button is not available). See the Selecting database fields for browsing section on page 445 for instructions on how to use the Column Editor.
518
Data-Display/Capture Objects 4. Make your changes to the fields list. If you wish to change other master properties, see the Configuring SmartDataBrowser properties section on page 512. Save your changes.
5.
2.
3.
4. 5. 6.
519
To configure the properties in a SmartDataBrowser instance when the values do not meet your needs: 1. Click the Menu button and choose Instance Properties from the menu that appears. That dialog box opens:
2. 3. 4. 5.
To disable the object at startup, clear the Enable box. If multiple layouts are defined, choose one from the list. To hide the object at startup, clear the View box. To enable scrolling to the last record in the data stream, set the Scroll Remote Results List checkbox. You might also need to write some code. For details, see the Scrolling to the last record in the data stream section on page 520. Choose OK and save your work.
6.
Data-Display/Capture Objects
To fix the problem in your SmartDataBrowser: 1. Click the SmartDataBrowsers Menu button and select Instance Properties. That dialog box opens:
2. 3.
Set the Scroll Remote Results List check box. Save your work.
If you have a trigger defined for the ROW-DISPLAY event, you must modify it. Follow these steps: 1. Click the Menu button and choose Edit Master. The master workspace opens (its appearance may be different):
2.
Select the workspace if necessary and open a Section Editor window. Create a new procedure, for example OldRowDisplayHandler, and move the code from your ROW-DISPLAY handler into the new procedure.
521
OpenEdge Development: AppBuilder 3. Create a new function as an override for rowDisplay. Put in it a call to the procedure you just created, followed by a RUN SUPER statement. If you name your procedure OldRowDisplayHandler, your function body would look like this:
RUN OldRowDisplayHandler . /* run original local code */ RUN SUPER . /* run the handler in the super procedure*/
4.
Open your local ROW-DISPLAY trigger in the Section Editor. It should now have no code in it, because you moved that code to the new procedure you created. Add this line as the new body of your local trigger:
5.
6.
Now, when the user drags the thumb to the bottom of the scroll bar, bringing the last record in the buffer into view, the browser requests a new batch of records from the Data-Source. When the new batch is received, the browser repositions its thumb to account for the new total record count. Thus, the first time a new batch is requested, the thumb will in general reposition to the middle of the scrollbar because the former last record is now in the middle of the buffer. The second read will create a total of three batches, with the thumb positioned at the two-thirds point, and so forth.
SmartDataViewers
While the SmartDataBrowser is useful for rapidly scanning many records, it is less easy to focus on the fields of a single record. This is particularly true when there are a large number of fields involved. The SmartDataBrowser can only display data in tabular format; no more subtle arrangement is possible. The SmartDataViewer displays fields from a single record at a time. By default, each field is represented by a fill-in widget, and the fields are stacked in a single left-aligned column. In contrast to the SmartDataBrowser, you can completely rearrange the fields of a SmartDataViewer master to suit your layout, and can even replace individual fill-ins with special-purpose SmartDataFields that you create.
522
Data-Display/Capture Objects The SmartDataViewer instances you use in your applications are each based on a master object that you design. SmartDataViewer masters are static objects; you design each one to display records supplied by a particular SmartDataObject. Once you design a SmartDataViewer master, you can reuse it repeatedly in your applications.
To create a SmartDataViewer master: 1. Start the SmartDataViewer Wizard by clicking on the SmartDataViewer tool icon in the Object Palette:
When the Choose dialog box opens, choose New. Note: You could also start the wizard by choosing FileNew and selecting the SmartDataViewer item from the list, or by right-clicking the icon in the Palette and selecting New SmartDataViewer from the menu that appears.
523
OpenEdge Development: AppBuilder 2. The SmartDataViewer Wizard starts up and displays its first page. When you have finished reading the introductory text, choose Next to move to Page 2:
3.
Choose the Browse button and select the appropriate SmartDataObject master. Its filename appears in the fill-in. Choose Next to move to Page 3:
4.
524
Data-Display/Capture Objects 5. Choose the Add Fields button to open a Multi-Field Selector dialog box:
6.
The fields available for display appear in the left-hand list. Select those you wish the SmartDataViewer to display and click the Add button to move them to the Selected list in the right-hand window. If you make a mistake, click the Remove button. When you have finished selecting fields, you can reorder them using the Move Up and Move Down buttons. When they are in the order you want them displayed, choose OK. The Selector dialog box closes and the list of selected fields appears in the wizard:
7.
Choose Next to advance to the wizards final page. If you have successfully defined a data source and selected the fields to display, you will see Congratulations!. If you do not see that page, choose the Back button and make necessary changes.
525
OpenEdge Development: AppBuilder 8. Choose Finish to dismiss the wizard and reveal the new SmartDataViewer master, if it was not already visible:
9.
Fields in a SmartDataViewer are read-only unless you connect them to the appropriate TableIO source, such as an Update SmartPanel. If you do connect them to Update controls, then all fields become updatable unless you explicitly make them read-only. To make any of the individual fields read-only, double-click on it to open its property sheet. When the Property Sheet dialog box opens, set the Read-only check box and choose OK. Note the difference in how fields display at run time, depending on their state. In the first case, there is no Update SmartPanel, and so all fields are read-only. The fill-ins display their content without displaying themselvesthe fields are not outlined or modelled in any way; they are invisible. All text looks static. This is the same effect you will get if you set the fields to be not-updatable in the SmartDataObject:
526
Data-Display/Capture Objects In the second case, there is an Update SmartPanel, and so all fields are updatable if they are updatable in the SmartDataObject. The fill-ins display their content in the ordinary way:
In the third case, there is an Update SmartPanel, but the Name field has its Read-only property set. Here, the Name field is clearly in a different state to the others, and the experienced user will recognize that it is not editable. However, this style of presentation only applies where the field is updatable in the SmartDataObject, but set read-only in the fill-in. If it is not updatable in the SmartDataObject, it appears as in the first example:
10. Choose FileSave and give the new master a descriptive filename. Note that SmartDataViewer filenames conventionally begin with v. The new master object is now available for your use. If you plan to replace one or more of the simple fields with SmartDataFields, do it now. See the Placing and configuring a SmartDataField instance section on page 536 for information about that process. Note: Although SmartDataViewers can be members of the class SmartContainer, they are not organizer objects, so placing SmartObjects in them other than SmartDataFields is not supported. The only exception is that, if you replace one or more of the fields with SmartSelect objects, you can also include an equal number of SmartDataObjects to feed them.
527
2.
3.
Click on an empty spot in the master objects workspace, not the main workspace. The Multi-Field Selector dialog box opens:
528
Data-Display/Capture Objects 4. 5. Move the desired fields from the Available list to the Selected list. Choose OK. Position, size, and configure the newly added fields in the master workspace. Save your work.
2.
Click on the fill-in to select it, and choose ToolsProperty Sheet. The Property Sheet dialog box opens:
529
OpenEdge Development: AppBuilder Minimal configuration Although you can accept many of the default settings, you might wish to make three changes: Add a Tooltip string. Under MS-Windows, Tooltips display whenever the user allows the mouse cursor to hover for a few seconds over an object for which a Tooltip is defined. Add a unique integer as the identifier for context-sensitive help, if you plan to provide such help as part of your application. Set the Read-Only check box (in the Other Settings area) to prevent the user from modifying the data in the field.
Rearranging the layout The way a viewers fields are laid out is also a property that can be changed, though only at the level of the master. All instances created from a given master share the same physical layout. To have different layouts for different applications, you must either create extra copies of the master and lay out each one differentlyeffectively creating separate mastersor use the alternate-layouts feature. See Appendix B, Multiple Layouts for information about that feature. To create a custom layout: 1. Open the master object by choosing FileOpen. The object opens in a design window workspace:
2.
Save the master under the name you will use for the new arrangement. Do this before you actually make any changes, so that you will not risk getting confused later and overwriting the original arrangement.
530
Data-Display/Capture Objects 3. Resize the workspace appropriately, drag the individual fill-ins into the new arrangement, and save again:
Note that you should make the workspace no larger than needed, since the amount of space taken up by an instance is always the same as the masters workspace. Other property changes By default, AppBuilder predefines certain properties of each fill-in that is used by a SmartDataViewer, and makes some of the properties read-only: Object identifier. Label. Allowed field format and size. Help string.
AppBuilder creates and assigns a unique identifier, and sets the other properties to conform to the field definition from the data stream. You cannot assign a different identifier or change the basic data type, but you can make changes to the label, field specifications, or help string.
531
To make changes to the label, field specifications, or help string: 1. Click the Database Field button, and when the dialog box opens, clear the check boxes for the properties you wish to set by hand. Choose OK to dismiss the dialog box. If you clear all three, the properties dialog box appears as shown here:
2.
You can now enter new values for the label and the format specification. If you wish to pick the format specifier from a list, choose the Format button to open that dialog box:
532
Data-Display/Capture Objects You can more directly change other properties: No Label Normally cleared. Setting this check box turns off display of any label. Setting this check box does not clear the actual label text; the label string remains visible in the property sheet. The only other effect of setting or clearing this box is to alter the values in the Geometry section so that the fill-in stays at the same XY location within the enclosing frame. Geometry Reflects the XY origin and size, in character units, of the fill-in. By default, the fill-in is colon-aligned. You can change that to left- or right-alignment, though the only noticeable effect that will have is to change the X origin value. Auto-Resize Normally cleared. Setting this box causes the object to automatically change its displayed size to agree with the current type size. Auto-Return Normally cleared. Setting this box causes focus to move to the next object in the traversal list once this fill-in has accepted as many characters as it can. Blank Normally cleared. Setting this box prevents the fill-in from echoing input back to the display. Useful for password fields and similar applications. Deblank Normally cleared. Setting this box causes the fill-in to automatically discard any leading blanks from input. Disable Auto-Zap Normally cleared. Setting this box prevents the fill-in from automatically clearing its input field whenever it gets the focus. Display Normally set. Clearing this box prevents the SmartDataViewer from automatically populating this fill-in during initialization. Drop Target Normally cleared. Setting this box causes this object to experience an event whenever the user drags another object onto this one. You must write the appropriate event-handling code. Enable Normally set. Clearing this box makes the fill-in decline input focus when offered. Hidden Normally cleared. Setting this box prevents the fill-in from responding to implicit requests to display itself. It will only honor explicit requests. Native Normally cleared. Setting this box causes the fill-in to vary its behavior according to the underlying platform (MS-Windows, for example) rather than behaving in the same way regardless of platform.
533
OpenEdge Development: AppBuilder No Tab Stop Normally cleared. Setting this box removes this fill-in from the enclosing frames traversal list. Normally, pressing the key causes focus to move to the next object in the list. When this box is set, the fill-in can neither lose nor gain focus when the user presses the TAB key. If the widget has the focus, it will ignore the key, and if it does not, focus will cycle through the other members of the traversal list while ignoring this widget. Caution: Making this fill-in Movable or Resizable (Advanced Properties) prevents this fill-in from gaining input focus using the mouse. So if you also set this property, you effectively prevent the widget from ever gaining input focus. No Undo Cleared. Cannot be set. The 4GL Engine will always journal changes to the data in this fill-in. Read-Only Normally cleared. Setting this box prevents the user from changing the content of the fill-in. Remove from Layout Cleared. Cannot be set unless defining an alternate layout. Shared Cleared. Cannot be set. This fill-in will always be local to the SmartDataViewer within which it is defined. View as Text Normally cleared. Setting this box causes this fill-in to display the contents of its field as though it were static text: read-only, and without any border or 3D effect.
Advanced properties A fill-in has only the minimum advanced properties, but you can change those that do not meet your needs. Initial value You cannot set this for a fill-in that is part of a SmartDataViewer. Help Unless this fill-in inherits the help string defined in the data dictionary, the text you enter here will display in the parent windows status bar whenever this fill-in has input focus. No text will display if the window has no status bar. Private data AppBuilder assigns the contents of this field as the value of the PRIVATE-DATA property. You can write code to manipulate this data in any way you desire. Layout units You can choose character or pixels. This setting affects source code generation only.
534
Data-Display/Capture Objects Custom lists You can add this fill-in to any or all of the six lists (macros) maintained by the enclosing frame. Geometry Shows the same information as in the base property sheet, but in pixel units. Manual highlight Normally cleared. Setting this box allows you to write code to define a custom highlight effect. Your custom effect will be applied whenever this fill-in has input focus. Movable Normally cleared. Setting this box makes it impossible for the user to give this fill-in input focus by clicking with the mouse. Instead, the user can use the mouse to drag the fill-in fieldbut not the label, which remains where it wasto a different position within the bounds of the enclosing frame. Resizable Normally cleared. Setting this box makes it impossible for the user to give this fill-in input focus by clicking with the mouse. Instead, if the Selectable box is also set, clicking with the mouse causes handles to appear so that the user can resize the object. Selectable Normally cleared. Setting this box allows the user to select this object. Caution: If you make this fill-in Movable or Resizable, and you also set the No Tab Stop option in the base property sheet, you effectively prevent this object from ever gaining input focus.
SmartDataFields
A simple fill-in is not necessarily the best representation for all data fields. Sometimes it would be very convenient to bring the power of ADM Smart technology down to the level of the individual data field in a SmartDataViewer. AppBuilder offers the SmartDataField object as a way for you to do that. The SmartDataField instances you use in your applications are each based on a master object that you design for a particular purpose. Once you design a SmartDataField master, you can reuse it repeatedly whenever you need a SmartDataViewer field with that particular capability.
535
OpenEdge Development: AppBuilder AppBuilder supports SmartDataFields only as replacement for simple SmartDataViewer fields, not for standalone placement. You can extend their applicability, if you wish, by writing the necessary supporting code. For information about creating SmartDataField masters, see OpenEdge Development: ADM and SmartObjects.
2.
When the Choose dialog box opens, select the appropriate master and click OK. Alternatively, right-click on the SmartDataField tool icon in the Object Palette, then select an object from the menu that opens.
536
Data-Display/Capture Objects 3. Position your mouse cursor over the field you are replacing, and click to make the replacement. The SmartDataField representation appears in place of the original fill-in:
4.
Add a static text label, if appropriate. A SmartDataField does not inherit the label of the field it replaces. AppBuilder supplies stubs for the enableField() and disableField() procedures. Open the Section Editor and add additional code to make those procedures work for the particular SmartDataField you added.
5.
SmartSelects
The SmartSelect is a predefined SmartDataField object that represents a self-populating set of choices. You would typically use a SmartSelect to choose a new value for a field from among a relatively small group of possibilities drawn from a related table. The SmartSelect object is data-driven. Most widgets used in an application have their values embedded as data within the program itself, so that changing the values in any way typically requires recompilation. Since the SmartSelect obtains its values from the database being modified, instead, recompilation is rarely required. Some examples of the kind of situation for which a SmartSelect would be appropriate: Assigning a different sales rep to an account. Typically a company has a small number of sales reps, each of whom calls on many accounts. Changing a customers credit limit, if the possible choices are few. For example: discredited; credit hold; credit not requested; $10,000; $50,000; $100,000; unlimited. Changing some demographic value in a personnel record. For example: single, partnered, married, separated, divorced, widowed, deceased, dependent.
537
OpenEdge Development: AppBuilder Setting the circulation status of a book in a library-management system. For example: on-order, reference, reserved, available, checked-out, bindery, lost. Picking a customer number for use in order-entry. Since customer numbers are important to the seller rather than the customer, customers rarely remember them.
You can configure each SmartSelect instance to represent its set of values using your choice of four different widgets: combo box (the default), radio set, selection list, or a browse that opens in its own popup window. Of those four, only the browse is capable of handling a large or unpredictable number of values. You might find it helpful to experiment before deciding on a representation.
2.
Create, if necessary, and place the SmartDataObject that will supply values to the SmartSelect. Right-click on the SmartDataField tool icon in the Object Palette:
3.
538
Data-Display/Capture Objects 4. Position your mouse cursor over the field you are replacing, and click to make the replacement. The SmartSelect representation appears in place of the original fill-in:
5.
An Advisor should now appear and offer to add the Data link from the SmartDataObject to the SmartSelect. Agree to the offer. If no Advisor appears, open the SmartLink Editor and add it yourself. Click on the SmartSelects Menu button and choose Instance Properties from the menu. Configure the instance. See the Configuring a SmartSelect instance section on page 539 for information.
6. 7.
539
OpenEdge Development: AppBuilder Data source This section identifies the SmartDataObject that will feed the SmartSelect object. You cannot enter the filename of the SmartDataObject directly; AppBuilder fills in this field as part of creating the SmartLinks, once you place the SmartDataObject in the viewer workspace. You can subset the data that the SmartSelect displays. Type a subsetting expression into the fieldfor example:
Filter
The SmartSelect will then display only the subset of items that conform to that restriction. Data This section describes the field being replaced, and the identifying characteristics of its replacement: External field Identifies the field in the SmartDataViewer that you are replacing. This identification is read-only, supplied for your information only. Key field If the replacement data stream has more than one field, use this combo box to select the field that will appear in place of the original. Be certain to select the correct one. For example, the State table in the sample database has three fields: State, State-name, and Region. If you use a SmartSelect fed from the State table to update the Customer.State field, the only correct choice for the key field would be State.State, since that is the related field. If you choose State-name or Region instead, confusion is almost certain to result, later. Displayed field If the replacement data stream has more than one field, use this combo box to select the field that the user will see. To continue the State example, you might prefer to display the more recognizable State-name field. That would be a more user-friendly choice than displaying the cryptic two-character post-office abbreviation from the State field itself, even though it is that two-letter code that you will store. Event on change You can declare a name for the event to be experienced when the value of this field changes. This allows you to write an appropriate event-handling procedure. The name you define is local to the object. See OpenEdge Development: ADM and SmartObjects and the for further information.
540
Data-Display/Capture Objects Edit browser columns Active only when the field is to be represented as a Browse widget. Choosing this button opens the standard field-selection dialog box so that you can select the fields to be displayed.
Properties This section presents three important behavioral properties: Enable Normally set. Clearing this box prevents the SmartSelect from enabling itself even when the other fields of the SmartDataViewer enable themselves. Display Normally set. Clearing this box prevents the SmartSelect from displaying data even when the other fields of the SmartDataViewer display data. Sort Normally set. Clearing this box causes the items to appear in unsorted order. Normally the visible fields appear sorted on the displayed field.
Optional This check box is normally cleared. Setting this box means that the associated field need not have a value. You can specify the text that represents that nonvalue; the default is <none>. Note that this text does not necessarily appear at the top of your list of choices. If you wish it to appear as the first item in the list, you must either explicitly make it the first item in the source (for unsorted lists) or begin with some character, such as the angle bracket (<), that the sort operation will move to the top of the list. Visualization This section allows you to specify how the SmartSelect list will represent itself at run time. The choices are: Browser The browser representation is the best choice for handling lists that are known to be very large or are of unknown size. This representation initially appears in a closed state, under an iconic pushbutton next to the current value of the field:
Clicking the button opens the list of items as a browse in a separate window. Click on the Edit Browser Columns button to choose what fields to display. Set the number of lines to display by entering an integer in the Inner Lines field.
541
OpenEdge Development: AppBuilder Combo box Default. This representation is configured as a drop-down list by default. For a description of the three types of representation, see the Combo boxes section on page 551. Set the number of lines to make visible in the list by entering an integer in the Inner Lines field. Selection list Selection lists generally take up more space than combo boxes because you must specify their size at design time. Note that setting the Inner Lines field property has no effect on the visible size of the widget. You must resize it manually by dragging the handles. Radio set Best suited to very small, fixed-size data sets that can be represented as short labels. You can specify a vertical (default) or horizontal orientation.
Displayed field attributes Specify the characteristics of the field you display as a prompt to the user: Label Specify the label, if any, to display with the SmartSelect. The SmartSelect object does not inherit the label of the SmartDataViewer field it replaces. You can set the Data Source check box to use the schema name of the field, or type in a label of your choice. Browse title Active only when browse is the representation type. You can set the title string that the browse widget will display. Datatype Read-only. Displays the underlying data type of the displayed field from the schema definition. Format Displays the field descriptor from the schema definition. Clear the Data Source check box if you have reason to modify this descriptor. Tooltip Enter the string the SmartSelect will display as the MS-Windows Tooltip. Help ID If you will offer context-sensitive help for this object, enter a unique integer identifier here.
Geometry Displays the origin and size of the SmartSelect representation in character units. You can set these values here, or in pixel units in the Advanced Properties dialog box.
542
Data-Display/Capture Objects
3.
Place into the application workspace an instance of the Customer SmartDataObject you just created:
4.
Create the SmartDataObject master that will feed the SmartSelect field. Choose the Salesrep table. Use only the Sales-Rep field from that table. Save the master:
543
OpenEdge Development: AppBuilder 5. Create the SmartDataViewer master that will display the Customer records. Include all four of the fields. Save the master, but leave its workspace open:
6.
Place an instance of the Sales-Rep SmartDataObject into the master SmartDataViewer workspace:
7.
Replace the Sales-Rep field in the SmartDataViewer with a SmartSelect instance. Resize the instance for cosmetic reasons:
8.
Save the changes in the SmartDataViewer. Place an instance of the SmartDataViewer into application workspace:
544
Data-Display/Capture Objects 9. Place Navigation and Update SmartPanels into the application workspace:
10. Run the workspace. You should be able to assign a new sales rep to any account by choosing from the combo box:
545
2.
4.
546
Data-Display/Capture Objects Click on the object to select it, if necessary, and choose ToolsProperty Sheet. The Property Sheet dialog box opens:
Minimal configuration Although you can accept many of the default settings, you might wish to make two changes to individualize this object: Change the identifier to more closely reflect this data browsers role in your application. Add a title string, if you plan to allow the browse to display a title bar.
Query and fields If the Query and Fields buttons are visible, it means you can edit those elements using Query Builder and Column Editor rather than the Section Editor. If the buttons are not visible, you must use the Section Editor, and the balance of this section does not apply to this browse.
547
OpenEdge Development: AppBuilder Since the query is local to this browse, rather than in a separate module, you can make changes both to the terms of the query and to the fields the browse will display. Choosing the Query button will start Query Builder and allow you to modify the terms of the query. See the Defining and editing queries using Query Builder section on page 438 for more information. Choosing the Fields button will start Column Editor and allow you to modify the columns this SmartDataBrowser will display. For information about how to use Column Editor, see the Selecting database fields for browsing section on page 445. By default, all columns can be scrolled horizontally, if there are too many columns to display at once. You can choose to lock the leftmost columns in place, so that scrolling does not affect them. Enter in the Locked Columns box the number of columns you want to freeze in place. Caution: If you lock more columns than will fit in the browses window, you effectively disable the horizontal scroll bar. When displaying a vertical scroll bar, the system tries to size the scroll bars thumb slider to reflect the total number of lines in the data stream. Ideally, the size of the thumb varies inversely with the number of lines (records). In general, the number of records being returned by a query will be larger than the number of lines that can be buffered and, when that is the case, the system cannot begin to correctly size the thumb. If you have a good idea about the total number of records in this data stream, you can improve the accuracy of the scroll bars appearance. Enter your estimate in the Max Data Guess field. Type into the Tooltip field the identifying text that you want the system to display whenever the mouse cursor hovers over this browse.
Geometry You can set the exact XY origin (relative to the containing frame) and size of this browse instance. Set the values, in character units, in the appropriate fields. You can choose whether the origin is measured at the upper-left corner (the default) or the upper-right corner. If you would prefer to use pixels rather than character units, choose the Advanced button and set the values using that dialog box instead.
548
Data-Display/Capture Objects Miscellaneous properties (other settings) You can make a number of changes to the appearance and behavior of this browse instance, if the default settings do not meet your needs: Column scrolling Normally set. Clearing this check box causes the horizontal scrolling granularity to be one character. The default is one field (column). This option applies only when running under MS-Windows. Drop target Normally cleared. Setting this check box causes the system to generate an event when the user drags and drops another object onto this one. You must write code to deal with that event. Enable Normally set. Clearing this check box causes the browse to be insensitive. Expandable Normally set. Clearing this check box prevents stretching the last column to cover any background exposed by scrolling. In general, when Column Scrolling is set, and the Browse window is scrolled all the way to the right, some background will be exposed because it is unlikely that the last n columns will exactly fit the Browse window width. When this option is set, the last column expands cosmetically to the right to mask any exposed background from view. Applies only when running under MS-Windows. Hidden Normally cleared. Setting this check box prevents implicit display of the object. Multiple selection Normally cleared. Setting this check box allows the user to select multiple rows. If any of the fields are updatable, you must also clear the No Row Markers check box. No assign Normally cleared. When set, changes to updatable fields are not automatically written back to the database when the user moves to a different row (record). No box Normally cleared. Setting this check box causes the Browse window to display without a border. Under MS-Windows, this border is a single-pixel black line. No labels Normally cleared. Setting this check box prevents display of the column labels. No tab stop Normally cleared. Setting this check box removes the browse instance from the TAB-traversal list for the containing frame. Under MS-Windows, removing the object from the traversal list has some effects that might confuse the user. No validate Normally cleared. Setting this check box disables all validation conditions specified in the Data Dictionary for fields in this browse.
549
OpenEdge Development: AppBuilder Open the query Normally set. Setting this check box activates the query and populates the fields during initialization. scroll bar vertical Normally set. Clearing this option hides the vertical scroll bar. The user can still scroll using the arrow keys. Separators Normally set. Clearing this check box causes the widget to paint itself without lines separating the rows and columns. Title bar Normally cleared. Setting this check box causes the browse widget to display a full-width frame-like title bar. Specify the title string if you set this option.
Advanced properties Choose the Advanced button. The Advanced Properties dialog box opens:
You can make a number of changes to the browses appearance and behavior by changing the default settings in this dialog box: Help The text in this field is displayed in the status bar of the parent window when the Browse has the focus. If the parent window has no status area, this text never displays. Private data AppBuilder writes the contents of this field out as the value of the attribute. You can write code to use this data in any way that meets your needs.
PRIVATE-DATA
550
Data-Display/Capture Objects Generated code layout unit Controls whether AppBuilder describes the position and size of this Browse in character or pixel units, when it generates source code. Geometry Expresses the origin and size of this widget in pixels. You can set a particular origin and size for the object here rather than interactively, if you wish. You can also choose to have the origin be measured at the upper-right rather than the upper-left corner. Column movable Normally cleared. Setting this check box allows the user to reorder the columns by dragging. Such reordering is cosmetic and has no effect on the actual record. Column resizable Normally cleared. Setting this check box allows the user to resize the columns interactively. Resizing the column has no effect on the actual field widths. Column searching Normally cleared. Setting this check box allows the user to search on a selected column (field). Movable Normally cleared. Setting this check box, together with the Selectable box, allows the user to move the entire browse object around within the bounds of the enclosing frame. Resizable Normally cleared. Setting this check box, together with the Selectable box, allows the user to change the size of the browse object, within the limits of the enclosing frame. Row resizable Normally cleared. Setting this check box allows the user to change the vertical size (height) of the rows by dragging a horizontal separator line. Selectable Normally cleared. Setting this check box allows the use to select the browse object.
Combo boxes
The combo box object combines a fill-in with a selection list. You might use it in cases where: The user will have to choose a single item from a list. A radio-button set is not an appropriate representation.
551
OpenEdge Development: AppBuilder A combo box will generally be a better representation than a radio set when the set of choices is large, varies in size, or involves long strings. A drop-down list or combo box will generally be a better choice than a simple list or combo box when space is at a premium, as is often the case. Drop-down lists/combo boxes also visually emphasize the current choice more than radio sets or simple lists/combo boxes do. AppBuilder offers two different combo box objects for your use: The basic 4GL combo box. An ActiveX (OCX) combo box.
Be sure to select the one shown here. The other Combo Box icon (not shown) represents the OCX version. 2. Move the mouse cursor over a bare spot in your workspace and click to place the new combo box. Configure and size it.
3.
552
Data-Display/Capture Objects
Minimal configuration Although you can accept the default values for many object properties, you should at least make these changes: Change the object identifier and Label to better represent the role of this combo box in your application. Type in the items that will populate the list, one item per line. You might need to change the data type first. See the Define As and Format entries in the Size and style configuration section on page 554. If appropriate, choose the Advanced button and, when the Advanced Properties dialog box opens, enter the Initial Value.
553
OpenEdge Development: AppBuilder Size and style configuration No label Normally cleared. Setting this check box turns off display of any label. Setting this check box does not clear the actual label text; the label string remains visible in the property sheet. The only other effect of setting or clearing this box is to alter the values in the Geometry section so that the combo box stays at the same XY location within the enclosing frame. Inner lines Type in the number of lines to be displayed by the selection-list component when it is open. The default value is 5 lines. Define as Choose the data type from the list. The default type is CHARACTER, but you can choose DATE, DECIMAL, INTEGER, or LOGICAL instead. AppBuilder will seed the list with a single item of that type. Format Enter the formatting string for the data type you have chosen. If you would prefer to pick the format string from a list rather than enter it by hand, choose the Format button. Tooltip This combo box displays any text you enter here whenever the user allows the mouse cursor to hover over it. Help ID If you plan to provide context-sensitive help in your application for this object, type in a unique integer as its identifier. Simple / Drop-down / Drop-down list: Simple In this style, you must explicitly make the selection list component visible at design time, if it is to be visible at all. By default, AppBuilder generates the widget with only the fill-in visible. Drag the bottom handle to reveal as many lines of list as you like. In this style, the fill-in element is editable. Drop-down In this style, the user can open and pick from the list, or type a value into the fill-in component. You can write code to permanently add the typed-in value to the entries in the list, if you wish, or discard the entry after use. Drop-down list (Default) In this style, the fill-in component is read-onlythe user cannot type into it. The user can only open and pick from the list. The choice then appears in the fill-in component. Note that in other major widget taxonomies, a drop-down list is a type of selection list, not a type of combo box. Note, too, that this style is not the default for the ActiveX combo box.
554
Data-Display/Capture Objects Color, type style, popup, string attributes, data field Choose the appropriate button to set these properties. For further information, see Appendix A, Frequently Used Dialogs. Geometry Although it is often more convenient to set the XY origin and size of a widget visually in the workspace, you can set those values explicitly here, if you prefer. You can also choose a particular alignment, though the only effect this has is to change the X origin in the source code. Auto-completion Normally cleared. Setting this box causes the combo box to attempt to complete the entry the user is typing. This option is only meaningful where the fill-in portion of the combo box is editable. Display Normally set. Clearing this box prevents this combo box from automatically populating its fill-in during initialization. Drop target Normally cleared. Setting this box causes this combo box to experience an event whenever the user drags another object onto it. You must write the appropriate event-handling code. Enable Normally set. Clearing this box makes the fill-in part unresponsive to input. Hidden Normally cleared. Setting this box prevents the combo box from responding to implicit requests to display itself. It will only honor explicit requests. No tab stop Normally cleared. Setting this box removes this combo box from the enclosing frames traversal list. Normally, pressing the key causes focus to move from one object to the next in the list. When this box is set, the object can neither lose nor gain focus when the user presses the TAB key. If the widget has the focus, it will ignore the key, and if it does not, focus will cycle through the other members of the traversal list while ignoring this widget. Caution: Making this combo box Movable or Resizable (Advanced Properties) prevents this object from gaining input focus using the mouse. So if you also set No Tab Stop, you effectively prevent the widget from ever gaining input focus. No undo Cleared. Cannot be set. The 4GL Engine will always journal changes to the data in this combo box. Remove from layout Cleared. Cannot be set unless defining an alternate layout.
555
OpenEdge Development: AppBuilder Shared Cleared. Setting this box causes the combo box to be reachable outside the defining procedure. Sort Normally cleared. Setting this box causes the combo box to always display the items in its drop-down list in sorted order, regardless of their real order. Unique match Normally cleared. (This option is not available unless you set Auto-Completion.) Setting this box causes the combo box to wait for a unique substring before completing the entry.
Advanced properties Choose the Advanced button. The Advanced Properties dialog box opens:
You can change any of the values here that do not meet your needs: Initial value You can enter a value here that will appear in the fill-in component of the combo box on startup. Help The text you enter here will display in the status area of the enclosing window, whenever this object has input focus. If you choose to let this combo box inherit the help string defined in the Data Dictionarys schema, you will not be able to enter text here, even if there is no help string in the schema. If the combo box is assigned to a dialog box rather than a window, or if the window has no status area, this text will not display. Private data AppBuilder writes this data out as the value of the PRIVATE-DATA attribute. You can write code to make use of this data in any way that meets your needs.
556
Data-Display/Capture Objects Generated code layout units You can elect to have AppBuilder define this object in character (the default) or pixel units, in the source code it generates. Custom lists The custom lists are macros belonging to the enclosing frame. They allow you to treat many objects alike without having to refer to them individually. You can include this object in any or all of the lists. Geometry You can set the XY origin and closed size of this combo box in pixel units. This section is identical to the corresponding section in the base property sheet apart from the type of units you use. Manual highlight Normally cleared. Setting this box allows you to write code to define a custom highlight effect. Your custom effect will be applied whenever this combo box has input focus. Movable Normally cleared. Setting this box makes it impossible for the user to give this combo box input focus by clicking with the mouse. Instead, the user can use the mouse to drag the combo box bodybut not the label, which stays where it wasto a different position within the bounds of the enclosing frame. Resizable Normally cleared. Setting this box makes it impossible for the user to give this combo box input focus by clicking with the mouse. Instead, if the Selectable box is also set, clicking with the mouse causes handles to appear so that the user can resize the object. Selectable Normally cleared. Setting this box allows the user to select this combo box. Caution: If you make this combo box Movable or Resizable, and you also set the No Tab Stop option in the base Property Sheet, you effectively prevent this object from ever gaining input focus.
557
OpenEdge Development: AppBuilder Clearing the list buffer The list of items is stored as a string, pointed at by the LIST-ITEMS attribute. You can clear the list by assigning the empty string:
comboExample:LIST-ITEMS = "" .
Setting LIST-ITEMS to the empty string clears the buffer immediately. Caution: The combo box widget is created with a single item in its list. You should always clear that item as part of your initialization process. You can also use a loop to delete the line items one by one:
DO WHILE comboExample:DELETE ( 1 ): /* empty statement */ END.
In the example code, the DELETE method is called in a WHILE loop to repeatedly delete line item 1. When the buffer is empty of lines, DELETE will return FALSE and the WHILE loop will terminate. Adding a line item Using the INSERT() method, you can add a line item at any offset in the list, regardless of the Sort option. The ADD-FIRST() and ADD-LAST() methods have a different result depending on whether the Sort option is set. If the option is not set, new items will be added to the top or bottom of the list, depending on which method you call. If the Sort option is set, new items will be inserted in sorted order regardless of which method you call. The INSERT(), ADD-FIRST() and ADD-LAST() methods all return TRUE if they succeed, FALSE if they cannot perform the insertion: Adds a simple item as the new fifth line:
comboExample:INSERT ( "Toy Item", 5 ).
558
Data-Display/Capture Objects Finds the first exact match of "Target Item" and inserts "Toy Item" as a new line above it:
comboExample:INSERT ( "Toy Item", "Target Item" ).
If you are using simple line itemsnot item/value pairsyou can add more than one in a single call by combining them into a comma-separated list: "Item 1, Item 2, . . .,Item n". Adds three simple items as the new 5th, 6th, and 7th lines:
comboExample:INSERT ( "Line 5 text,Line 6 text,Line 7 text", 5 ).
If you are adding item/value pairs, you can only add one line per call. Adds three item/value pairs as the new 5th, 6th, and 7th lines, with values 25, 48, and 16:
comboExample:INSERT ( "Line 5", 25, 5). comboExample:INSERT ( "Line 6", 48, 6). comboExample:INSERT ( "Line 7", 16, 7).
Multiple item/value pairs cannot be added using a single call. This code looks reasonable but would not compile successfully:
comboExample:ADD-FIRST ( "Line 5", 25, 5, "Line 6", 48, 6, "Line 7, 16, 7 ) .
559
OpenEdge Development: AppBuilder Adding a user-supplied line item Although a combo box appears to be a combined fill-in and list, you cannot capture user input as new items. The fill-ins function is only to provide a way to select a list item other than by scrolling to find it. To allow the user to add items to the list, use a separate fill-in to capture the text for the new item or item/value pair and call the appropriate insertion method to add it:
This code, if used as the CHOOSE trigger for the pbAppend pushbutton, will move non-empty strings from the fill-in to the list in the combo box:
IF fiNewItem:SCREEN-VALUE <> "" THEN DO: /* ignore event if field empty */ ASSIGN fiNewItem. /* set the value of the Fill-in*/ cbList:ADD-LAST( fiNewItem ). /* append the new value to list */ fiNewItem:SCREEN-VALUE = "". /* clear Fill-ins image... */ fiNewItem = "" . /* ...and its value */ END.
Deleting a line from the list Deleting a line requires only that you know the line number. This code will delete line 5 if it exists:
comboExample:DELETE ( 5 ).
560
Data-Display/Capture Objects Finding a line or item in the list You can determine the line offset of some item using the LOOKUP() method:
lineoffset = comboExample:LOOKUP( "Line Item of Interest" ).
Note that LOOKUP(): Always finds the first instance of the string, if there are duplicates. Returns 0 (zero) if the string is not found.
You can determine the string value of some item using the ENTRY() method:
strItemValue = comboExample:ENTRY ( 5 ).
Note that ENTRY() will complain and return the undefined value (?) if you pass an argument that does not index an item in the list.
Be sure to select the one shown here. The other combo box icon (not shown) represents the version defined in the 4GL. 2. Move the mouse cursor over a bare spot in your workspace and click to place the new combo box. Configure and size it.
3.
561
References in your code to the native ActiveX properties of the combo box instance must take the indirect form Com-Handle:ActiveX-Identifier:Property-Identifier. Minimal configuration While you can accept many of the default settings, you will need to make some changes: Replace the default object identifier for the control frame with one that more clearly represents the role of this combo box instance in your application. You can do this directly in the main AppBuilder window, when the instance is selected. You need not change the identifier of the actual ActiveX object itself, though you can if you wish. Populate the list of choices that the combo box will use.
562
Data-Display/Capture Objects
To populate the list of choices: 1. Click in the [Custom] property data field to expose the ellipsis button, then choose the button to open the Custom Properties dialog box:
2.
Type in this combo boxs list of items, one item per line. When finished, choose OK to close the dialog box.
563
OpenEdge Development: AppBuilder Additional property configuration Choose from three different styles: 0 Dropdown Combo Default. The user can open and pick from the list, or type a value into the fill-in component. Note that this style is not the default style for the 4GL combo box. 1 Simple Combo In this style, you must explicitly make the selection list component visible at design time, if it is to be visible at all. By default, AppBuilder generates the widget with only the fill-in visible. Drag the bottom handle to reveal as much of the list element as you like. In this style, the fill-in element is editable. 2 Dropdown List In this style, the fill-in component is read-onlythe user cannot type into it. The user can only open and pick from the list. The choice then appears in the fill-in component. Note that, in other taxonomies, a drop-down list is a type of selection list, not a type of combo box configuration
Code configuration When you run a workspace for the first time after placing your first ActiveX (OCX) object in it, AppBuilder creates the control_load procedure. You can inspect that procedure in the Section Editor, but not edit it. In that procedure, AppBuilder creates the variable of type COM-HANDLE that you will use when you write event handlers. The identifier of the variable is the same as the identifier you assign to the control frames Object field, with ch prepended. Thus, if you assign the identifier Example to the control frame, the COM-HANDLE identifier will be chExample. The combo box stores its current string value in the Value property. To determine the index value of that string (the topmost list item is index 0), pass the Value property to the FindStringExact() method.
564
Data-Display/Capture Objects Presuming you use the object identifier Example for the OCX control frame, this toy code will detect the users selection, and print out the string and index values:
/* ** */
DEFINE VARIABLE sSelection AS CHARACTER INITIAL "". DEFINE VARIABLE iSelection AS INTEGER INITIAL 0. /* ** */
ASSIGN sSelection = chExample:CSComboBox:Value iSelection = chExample:CSComboBox:FindStringExact( sSelection, -1 ). MESSAGE "Selection is " sSelection "at index" iSelection .
For further information about events, methods, and properties for the three OCX objects that AppBuilder supplies in the Object Palette, see the online help.
To create and place a basic data viewer object: 1. Click on the basic Data Viewer (DB-Fields) tool icon in the Object Palette:
2.
Click on a bare spot in your workspace to begin the placement process. Query Builder will immediately open. Define the query. See the Defining and editing queries using Query Builder section on page 438 for more information. Note: While you can elect to jump out of Query Builder and create a free-form query, you cannot later use Query Builder to maintain it. Should you change your mind after confirming that you wish to create a free-form query, your only recourse will be to delete the viewer object altogether and create a new one.
3.
4.
When you have defined the query terms and chosen the fields the viewer will display, choose OK to dismiss Query Builder. Your viewer widgets will appear in a single column in your workspace. If the default single-column arrangement does not meet your layout needs, select and move the fields, either individually or in subgroups, into a more appropriate arrangement. Since there is no master object involved, the layout you create will have no effect on any basic data viewers you place in future.
5.
566
Data-Display/Capture Objects
Multi-line editors
The Editor widget provides the ability to capture large amounts of text in a way familiar to and convenient for the user. You might use an editor object to capture, for example, free-form comments of undetermined length. Although they are basic 4GL objects rather than SmartObjects, you can add a considerable amount of additional capability to them through calls to 4GL methods for searching, etc.
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new Editor object. Configure and size it.
3.
567
OpenEdge Development: AppBuilder To configure your editor object, begin by selecting the object and choosing ToolsProperty Sheet. The dialog box opens:
Minimal configuration Although you might choose to accept the other default settings, you should make at least the first of these two changes: Change the default identifier to one that more closely reflects the role of this object in your application. Turn off the Horizontal scroll bar and turn on Word Wrap. The default style produces a single long line of input unless the user explicitly uses the RETURN key. This might not be the most appropriate style for the needs of your application.
Edit-buffer size The default size of an editor widgets buffer is 20KB under MS-Windows. You can reduce memory requirements by forcing a smaller buffer size. Enter the desired value in the Maximum Characters field.
568
Data-Display/Capture Objects Help Add one or both of these help elements: Add a Tooltip string, if appropriate. The editor will display that string whenever the user allows the mouse cursor to hover over the widget. If you will provide context-sensitive help for this object, add a unique integer Help ID.
Geometry AppBuilder allows you to adjust the position and size of your widgets interactively, by dragging their handles. The changes you make in this way are reflected in the Geometry values. You can also change these values explicitly, here. AppBuilder normally generates source code that identifies the upper-left corner of the object as its origin. You can choose to have the upper-right corner identified as the origin instead. This alignment setting does not change the actual position of the object in any way. Miscellaneous properties (other settings) You can change as many of these properties as you like: Auto-indent Normally cleared. Setting this box causes a new line to inherit the indenting of the preceding line. This is now a universal feature in programmers editors, and is often a feature, in some form, in word-processing editors as well. Auto-resize Normally cleared. Setting this box causes the editor to automatically resize, if necessary, to keep the same amount of text in view despite changes in size or style of type. Display Normally set. Clearing this box prevents the editor from making its contents visible when it enables itself for input. The edit buffer will appear to the user to be empty. Drop target Normally cleared. Setting this box causes the editor to experience an event whenever the user drops some other object onto it. You must write code to handle the event. Enable Normally set. Clearing this box prevents this object from accepting the input focus. Hidden Normally cleared. Setting this box prevents this object from displaying itself in response to implicit requests. If you set this box, you will need to include explicit code to make the object visible.
569
OpenEdge Development: AppBuilder Large Normally cleared. Setting this box changes the size of the edit buffer from the 20KB default to some larger size consistent with system resources. Applies only to MS-Windows. No box Normally cleared. Setting this box prevents the editor from displaying an outline and causes it to change its background color to be the same as that of the application. If you also turn off the scroll bars, the object will be nearly invisible. You can restore some visibility by forcing the background color to white. See the Choosing colors section on page A11. No tab stop Normally cleared. Setting this box removes the editor from its parent frames traversal list. An object not in the traversal list can neither gain nor lose focus when the user presses the TAB key. No undo Normally set. Clearing this box causes the editor to journal all changes made to its buffer. Read-only Normally cleared. Setting this box prevents the editor from allowing changes to its buffer contents, even though it will accept the input focus. Remove from layout Cleared. Cannot be set unless editing an alternate layout. Return inserted Normally cleared. When this box is cleared, if the editor is a child of a dialog box that has a default button, a RETURN event chooses the default button. In all other cases, a RETURN event inserts a hard return at the cursor. Applies only to the MS-Windows platform. Scrollbar horizontal/vertical Normally set. Clearing one or both of these boxes turns off the respective scroll bar(s). Turning off the horizontal scroll bar automatically sets the Word Wrap box. Shared Normally cleared. Setting this box makes this widget and its edit buffer available to other procedures. Word wrap Normally cleared. Setting this box causes words to be wrapped to the next line if they would otherwise be clipped by the right edge of the editors client area. This box is set by default when you turn off the horizontal scroll bar.
Advanced properties The editor widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
570
Data-Display/Capture Objects
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object. Configure and size it.
3.
571
OpenEdge Development: AppBuilder To configure your fill-in object, begin by selecting it and choosing ToolsProperty Sheet. The dialog box opens:
Minimal configuration Although you can accept many of the default settings, you should make at least three changes: Change the AppBuilder-generated object identifier to one that more accurately reflects the role of this fill-in in your application. Change the generic label to one that will be meaningful to the users of your application. Or, if appropriate, set the No Label check box to hide the label. Setting this check box does not clear the actual label text; the label string remains visible in the property sheet. The only other effect of setting or clearing this box is to alter the values in the Geometry section so that the fill-in stays at the same XY location within the enclosing frame. Click the Advanced button and set the initial value, if any, that the fill-in is to display. By default, the initial value is empty/undefined.
572
Data-Display/Capture Objects Internal data format You can use a fill-in to capture any data type whose value can be entered from the keyboard and represented on the display as ordinary text. The fill-in will do a limited amount of syntax-checking for you if you appropriately set the values for Define As and Format. Define as Choose the data type from the list. The default type is CHARACTER, but you can choose DATE, DECIMAL, INTEGER, LOGICAL, or RECID instead. RECID fields are internal record identifiers. Format Enter the formatting string for the data type you have chosen. If you would prefer to pick the format string from a list rather than enter it by hand, choose the Format button to open a dialog box specific to the type you have chosen. Shown here is the dialog that displays for type CHARACTER:
Help You can supply helpful information to your users in several ways. Here are two of the most common: Add a Tooltip string. Under MS-Windows, Tooltips display whenever the user allows the mouse cursor to hover for a few seconds over an object for which a Tooltip is defined. Add a unique integer as the identifier for context-sensitive help, if you plan to provide such help as part of your application.
Geometry Reflects the XY origin and size, in character units, of the fill-in. By default, the fill-in is colon-aligned. You can change that to left- or right-alignment, though the only noticeable effect that will have is to change the X origin value.
573
OpenEdge Development: AppBuilder Miscellaneous properties (other settings) These properties modify the widgets appearance or behavior in various ways. You can change as many as you like: Auto-resize Normally cleared. Setting this box causes the object to automatically change its displayed size to agree with the current type size. Auto-return Normally cleared. Setting this box causes focus to move to the next object in the traversal list once this fill-in has accepted as many characters as it can. Blank Normally cleared. Setting this box prevents the fill-in from echoing input back to the display. This is useful for password fields and similar applications. Deblank Normally cleared. Setting this box causes the fill-in to automatically discard any leading blanks from input. Disable auto-zap Normally cleared. Setting this box prevents the fill-in from automatically clearing its input field whenever it gets the focus. Display Normally set. Clearing this box prevents the object from automatically showing the current value of the associated variable during initialization. To the user, the value would appear undefined. Drop target Normally cleared. Setting this box causes the fill-in to experience an event message whenever the user drops another object onto this one. You must write the appropriate event-handling code. Enable Normally set. Clearing this box makes the fill-in unresponsive to input. Hidden Normally cleared. Setting this box prevents the fill-in from responding to implicit requests to display itself. It will only honor explicit requests. Native Normally cleared. Setting this box causes the fill-in to vary its behavior according to the underlying platform (MS-Windows, for example) rather than behaving the same way regardless of platform.
574
Data-Display/Capture Objects No tab stop Normally cleared. Setting this box removes this fill-in from the enclosing frames traversal list. Normally, pressing the key causes focus to move to the next object in the list. When this box is set, the fill-in can neither lose nor gain focus when the user presses the TAB key. If the widget has the focus, it will ignore the key, and if it does not, focus will cycle through the other members of the traversal list while ignoring this widget. Caution: Making this fill-in Movable or Resizable (Advanced Properties) prevents this fill-in from gaining input focus using the mouse. So if you also set this property, you effectively prevent the widget from ever gaining input focus. No undo Normally set. Clearing this box causes the fill-in to journal all changes. Read-only Normally cleared. Setting this box prevents the user from changing the content of the fill-in. Remove from layout Cleared. Cannot be set unless defining an alternate layout. Shared Normally cleared. Setting this box makes the value of this fill-in available to other procedures. View as text Normally cleared. Setting this box causes the fill-in to display itself as though it were static text: read-only, and without any border or 3D effect.
Advanced properties A fill-in widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
575
OpenEdge Development: AppBuilder By default, AppBuilder supplies a set of three buttons, arranged vertically. Using the property sheet, you can easily change the orientation to horizontal, and increase or decrease the number of members in the set.
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object:
3.
Configure and size it. Note that you can change the spacing between the buttons by dragging the group handles.
576
Data-Display/Capture Objects
Minimal configuration Although you can accept many default settings, you should make at least these changes: Object Change the default identifier to one that more clearly reflects the role of this radio set in your application. Define as By default, the radio-set widget represents a variable of type INTEGER. You can choose a different data type, if more appropriate. Open the drop-down list and make your choice. Note that the button definitions in the list above this drop-down change to agree with your choice here. Buttons Each button is defined by a pair of values: Label string, delimited by double quotes. Item value, consistent with the data type.
577
OpenEdge Development: AppBuilder Use a comma as separator between the label string and the item value, and between the item value for one button and the label string for the next button. Changing the number of buttons is very simple. To make a set with fewer buttons, delete the unwanted value pairs. To make a larger set, add value pairs. Initial value By default, the initial value is undefined. That might not be at all obvious because of the way a radio-button set displays itself. It is good programming practice always to explicitly initialize variables, but initialization is particularly important in such cases as this. To set the initial value, click the Advanced button. When the Advanced Properties dialog box opens, type an appropriate value into the Initial Value field. Help You can add one or two types of help here: Tooltip The radio button set will display this string whenever the user allows the mouse cursor to hover over the objects frame. Help ID If you plan to provide context-sensitive help, type in a unique integer identifier.
Geometry Reflects the XY origin and size, in character units, of the widgets bounding box. By default, the objects origin is considered to be the upper-left corner. You can elect to have AppBuilder consider the origin to be the upper-right corner instead, though this will not change the objects position in any way. Miscellaneous properties (other settings) A radio button set has comparatively few properties, but you can change any that do not meet your needs: Display Normally set. Clearing this box prevents the object from automatically displaying its initial value, if you have set an initial value. Note that this class of widget always appears to display an initial value, even if you have not set one. It is good practice always to initialize variables such as this. Drop target Normally cleared. Setting this box causes the radio set to experience an event when the user drops some other object on it. You must write the code to handle the event, and the dropped object.
578
Data-Display/Capture Objects Enable Normally set. Clearing this box prevents the radio set from accepting the input focus when offered. Without the input focus, the user cannot change the radio set value. Expand Normally cleared and not settable. Available only with Horizontal orientation. Setting this box regularizes the space between buttons by using the size of the longest label as the inter-button space. When cleared, the space between buttons varies with the length of each buttons label. Hidden Normally cleared. Setting this box causes the widget to ignore implicit requests to show itself. If you set this box, you must include explicit code in your application to make this object visible to the user. Horizontal Normally cleared. Setting this box changes the orientation of the buttons from vertical to horizontal, and allows you to set the Expand box, if you wish. No tab stop Normally cleared. Setting this box removes this object from the enclosing frames traversal list. An object not in the traversal list can neither gain nor lose the input focus when the user presses the TAB key. No undo Normally set. Clearing this box causes changes to the objects value to be journaled. Remove from layout Cleared. Cannot be set unless defining an alternate layout. Shared Normally cleared. Setting this box makes this objects storage and value available outside the defining procedure.
Advanced properties A radio-set widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
Selection lists
The selection-list widget allows you to present users with a list of values represented by text strings. Selection lists serve a similar function to radio button sets and combo boxes: grouping and presenting a set of potential choices. Unlike those objects, Selection lists permit multiple selection. Selection lists (or combo boxes) are more appropriate than radio-button sets when the number of items in the set cannot be determined in advance, or where long text strings are involved. As with radio button sets, you can assign arbitrary values to the line items in the list. 579
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object. Configure and size it.
3.
580
Data-Display/Capture Objects Minimal configuration Although you can accept many default settings, you should make at least these changes: Object Change the object identifier to one that more clearly relates to the role of this List object in your application. Items versus item pairs Choose whether the selection list object should interpret the content you enter in the field below as independent, listable strings only, or string + value pairs. If you elect Items, the value of the variable will the selected string(s) themselves. If you elect Pairs, the value will be the value portion of the selected item(s). Content Type in the selectable items to be displayed by the object. They can be either strings (Items) or comma-separated string + value pairs (Item Pairs). Type in only one item or item pair per line. If you are using Item Pairs, remember to separate the string from the value by a comma.
Help You can provide your users additional help through these settings: Tooltip The selection list displays this string whenever the user allows the mouse cursor to hover over the objects frame. Help ID If you plan to provide context-sensitive help, type in a unique integer identifier.
Geometry Reflects the XY origin and size, in character units, of the selection lists bounding box. By default, the objects origin is considered to be the upper-left corner. You can elect to have AppBuilder consider the origin to be the upper-right corner instead, though this will not change the objects position in any way. Miscellaneous properties (other settings) There are a number of other changes you can make to the selection lists appearance and behavior, if the default settings do not meet your needs: Auto-resize Normally cleared. Setting this box causes the selection list to change its dimensions to keep the same number of list items in view when, for example, the font changes.
581
OpenEdge Development: AppBuilder Display Normally set. Clearing this box prevents the selection list from automatically displaying its content items during initialization. Drag-enabled Normally set. Clearing this box prevents the user from being able to select a number of consecutive lines by holding down the SHIFT key and dragging the mouse pointer down the list. Drop target Normally cleared. Setting this item causes the selection list to experience an event whenever the user drops another object onto it. You would have to write code to handle the event and deal with the object dropped. Enable Normally set. Clearing this box prevents the selection list from accepting the input focus when offered. Without the input focus, the user cannot select a listed item. Hidden Normally cleared. Setting this box prevents the object from responding to implicit requests to display itself. You must include code to explicitly paint the object, when this box is set. Multiple selection Normally cleared. Setting this box allows the user to select more than one listed item. No tab stop Normally cleared. Setting this box removes the object from the parent frames traversal list. An object not in a traversal list can neither gain nor lose focus when the user presses the TAB key. If the object has focus, it keeps it. If it does not have it, focus circulates among only the objects that are in the traversal list, bypassing the excluded object. No undo Normally set. Clearing this box causes changes to be journaled. Remove from layout Cleared. Cannot be set unless working on an alternate layout. Scrollbar horizontal/vertical Normally Vertical only. Set or clear to change the kind of scroll bar(s) the object displays. Shared Normally cleared. Setting this box makes the selection lists contents and variable available to procedures other than the one in which you defined the object. Sort Normally cleared. Setting this box presents the listed items to the user in sorted order.
582
Data-Display/Capture Objects Advanced properties A selection list widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
Slider controls
The Slider-Control widget is a virtual knob-and-track device with integrated numeric readout. Moving the knob along the track sets the associated INTEGER value to a proportional value within the range you have defined on the track. Conversely, setting the value of the associated variable moves the knob to the corresponding position along the track, offering the user a degree of analog, at-a-glance information that the number displayed by the readout does not.
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object:
3.
583
Minimal configuration Although you can accept many default settings, there are some you should change: Object Change the object identifier to one that more closely matches the role of this slider control in your application. Min/max values By default, the slider control represents the subrange 0100. Unless this already meets your needs, define the subrange you want. The Slider will represent any signed 16-bit integer (32768 to 32767). Initial value By default, the slider control is initialized to 0, or to the lowest value in the subrange if 0 is outside the subrange. To initialize to some other value, click the Advanced button and, when that dialog box opens, type in the initial value you desire. Tic marks By default, the scale (virtual slot) is unmarked. You can choose to add tic marks to either or both sides. If you do, you can also choose the value interval (default is 10, for a 0100 scale).
584
Data-Display/Capture Objects Help You can provide additional help to your users with these settings: Tooltip The slider control displays this string whenever the user allows the mouse cursor to hover over the objects frame. Help ID If you plan to provide context-sensitive help, type in a unique integer identifier.
Geometry Reflects the XY origin and size, in character units, of the slider controls bounding box. By default, the objects origin is considered to be the upper-left corner. You can elect to have AppBuilder consider the origin to be the upper-right corner instead, though this will not change the objects actual position in any way. Miscellaneous properties (other settings) There are a number of changes you can make to the slider controls appearance and behavior if the default settings do not meet your needs: Auto-resize Normally cleared. Setting this box causes the slider control to automatically resize itself as needed. Display Normally set. Clearing this box prevents the slider control from automatically revealing its initial value. Note however that by its nature the object will always give the appearance of having been initialized. Drop target Normally cleared. Setting this box causes the slider control to experience an event whenever the user drops another object onto it. You would have to write the code to handle the event and deal with the object dropped. Enable Normally set. Clearing this box prevents the slider control from accepting the input focus when offered. This would mean the user could not change the slider controls value. Hidden Normally cleared. Setting this box prevents the slider control from responding to implicit requests to show itself. You would have to include code to explicitly request it to appear. Horizontal Normally cleared. Setting this box causes the slider control to orient its track horizontally rather than vertically.
585
OpenEdge Development: AppBuilder Large-to-small Normally cleared. Setting this box reverses the default direction of the values. Normally, the lowest value is at the bottom or left of the track. With this box set, the bottom or left end has the highest value, instead. No current value Normally cleared. Setting this box turns off the integral numeric readout. No tab stop Normally cleared. Setting this box removes this instance from the enclosing frames traversal list. An object not in the traversal list can neither gain nor lose focus when the user presses the TAB key. No undo Normally set. Clearing this box causes this slider control to journal all user changes to its value. Remove from layout Cleared. Cannot be set except when defining an alternate layout. Shared Normally cleared. Setting this box makes the Slider widget and its variable available to other procedures.
Advanced properties A slider control widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
Data-Display/Capture Objects
To create a spin control: 1. Click on the Spin-Control tool icon in the Object Palette:
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object. It will almost certainly be too large, so resize it temporarily:
3.
Configure it, and make final adjustments to its size and position.
587
OpenEdge Development: AppBuilder Minimal configuration Although you can accept many default settings, you should make at least these few changes: Replace the default identifier (shown in AppBuilders main window) with one that more clearly identifies the role of this object in your application. This identifier belongs to the control frame interface. For more information about control frame objects, see the ActiveX control frame properties section on page A3. Max and Min Normally 10000 and 10000. Set these properties to the upper and lower INTEGER bounds of the range you want the spin control to use. You cannot set a value smaller than 10000 or larger than 10000. Note that if you set Min to be larger than Max, the meaning of the buttons will reverse, which may confuse the user. Increment Normally 1. Set this property to be the size of the INTEGER change to be made per button press. This is an unsigned (absolute) value.
Optional configuration You may wish to make changes to some or all of these settings, or to others not discussed here: Value Normally 0. Set this property to initialize the object; read it to detect user changes. Spin rate Normally 10. This property represents the number of increments per second when the user holds down one of the buttons. Thus, if the increment value is 100, and you set the Spin Rate to 12, you can expect the value to change by 1200 over a seconds time, when a button is held down. GetButtons Normally TRUE. Setting this property to FALSE prevents the object from responding to keyboard arrow-key presses. Normally, pressing one of the arrow keys has the same effect as pressing one of the spin control buttons. ValueDisplay Normally AutoSized. Setting this property to None prevents the object from displaying the integrated readout. Turning off the readout in this way is useful if you wish to bind the buttons to some other object for display. Style Normally 3D Vertical. There are four possible settings, combining Normal versus 3D, and Horizontal versus Vertical. Setting this property to Normal flattens out the 3D effect, and setting it to Horizontal changes the orientation of the buttons such that they point left and right rather than up and down.
588
Data-Display/Capture Objects Combining Horizontal orientation with reversed Min and Max meanings may be appropriate in some international contexts. Alignment Normally Right Justify. Applies to how the integrated readout displays the objects INTEGER value. Possible settings are Left Justify, Center, and Right Justify.
2.
Move the mouse cursor over a bare spot in your workspace and click to place the new object:
3.
589
Minimal configuration Although you can accept other default settings, you should make at least three changes: Object Change the object identifier to one that better reflects the role of this toggle box in your application. Label Change the label to a string that will help the user of your application understand what the toggle box selects. Note that it will be better for your users if you do not create cross-connections in their heads: the cleared state should always represent the not/off/false/negative condition, not the default condition. Initialize the box to whatever the default condition is, whether set or cleared. Initial value By default, the toggle box initializes itself to the cleared state. To change that, click the Advanced button, and when the Advanced Properties dialog box opens, type yes into the Initial Value field.
590
Data-Display/Capture Objects Help You can offer additional help to your users via these properties: Tooltip The check box displays this string whenever the user allows the mouse cursor to hover over the objects frame. Help ID If you plan to provide context-sensitive help, type in a unique integer identifier.
Geometry Reflects the XY origin and size, in character units, of the objects bounding box. By default, the objects origin is considered to be the upper-left corner. You can elect to have AppBuilder consider the origin to be the upper-right corner instead, though this will not change the objects position in any way. Miscellaneous properties (other settings) There are a number of changes you can make to the toggle boxs appearance and behavior if the default settings do not meet your needs: Auto-resize Normally cleared. Setting this box causes the toggle box to automatically resize itself as needed. Display Normally set. Clearing this box prevents the toggle box from automatically revealing its initial value. Note however that it always appears to have an initial value. Drop target Normally cleared. Setting this box causes the toggle box to experience an event whenever the user drops another object onto it. You would have to write the code to handle the event and deal with the object dropped. Enable Normally set. Clearing this box prevents the toggle box from accepting the input focus when offered. This would mean the user could not change the boxs value. Hidden Normally cleared. Setting this box prevents the toggle box from responding to implicit requests to show itself. You would have to include code to explicitly request the object to appear. No tab stop Normally cleared. Setting this box removes the toggle box from the enclosing frames traversal list. An object not in the traversal list can neither gain nor lose focus when the user presses the TAB key. This can confuse users.
591
OpenEdge Development: AppBuilder No undo Normally set. Clearing this box causes the toggle box to journal all user changes to its value. Remove from layout Cleared. Cannot be set except when defining an alternate layout. Shared Normally cleared. Setting this box makes the widget and its variable available to other procedures.
Advanced properties A toggle box widget has only the standard advanced properties, but you can change those that do not meet your needs. See the Advanced properties section on page A9 for more information.
592
6
Data-Communication Objects
The world is increasingly a wired one, where the limitations imposed by physical distance are being overcome in part by high-speed, global communication. As more companies partner with customers on the other side of the globe, effective data communication becomes vital to staying in business. This chapter describes the data-transformation and communication objects AppBuilder supplies for your use: SmartB2BObjects SmartSender and SmartReceiver objects SmartRouters SmartProducers and SmartConsumers The message-handling relationship: internal details
SmartB2BObjects
The SmartB2BObject helps you make your applications capable of business-to-business communication. It handles transformation between the internal data representation and the emerging standard for inter-business communication, the eXtended Markup Language (XML). Figure 61 illustrates how the SmartB2BObject fits into an application that can communicate with another business over the Internet.
SmartDataObject SmartB2B SmartConsumer 4GL-JMS API AppServer SonicMQ Adapter SonicMQ Broker
Internet
Figure 61:
XML is related to HTML, the HyperText Markup Language of the Web. Both XML and HTML are descendents of SGML, the Standard Generalized Markup Language used in high-end publication editors.
62
Data-Communication Objects A detailed description of XML is well beyond the scope of this document, but you can find specifications and descriptions in a number of sites on the Web. The standards body for XML, as for HTML, is the WorldWide Web Consortium (W3C), an international organization. The W3C is hosted in the Americas by the Massachusetts Institute of Technology in Cambridge, Massachusetts, USA, in Europe by the Institut National de Recherche en Informatique et en Automatique (INRIA) at several locations in France, and in Asia by Keio University at their Shonan Fujisawa Campus in Japan. The W3C sponsors several ongoing engineering committees, including the XML Schema Working Group. The consortiums Web site has information about these working groups, including instructions for joining them if you want to help with their work. The Web site also has primary instructional materials, standards documents, pointers to tools such as schema validators, and links to other sites. Their URL is http://www.w3.org.
63
OpenEdge Development: AppBuilder Once those mapping files have been created and debugged, communication becomes a relatively straightforward operation. Caution: At present, there is no automatic safeguard against schema version skew. It is possible for a particular schema to be changed without notice, with an updated map file being created only at one end of the communication channel. In that case, miscommunication will certainly occur, possibly in ways that are important but hard to detect. Although you cannot eliminate this problem, you can reduce it by maintaining and checking for version information in any schema you create. Figure 62 illustrates how the schema, the map file, and the data interact in inter-business messaging.
"Surname" "string"
2 4
"Surname" "string"
2
"Surname" "Empl.Surname"
3
"Surname" "Client.FamName"
3
Empl.Surname "Smith"
Client.FamName "Smith"
Figure 62:
On the originating side (the left side in Figure 62), the value for the Surname (family name) field in the Empl table is Smith. The XML schema specifies a Surname field of type string. The map file relates the XML Surname node to the Empl.Surname field.
64
Data-Communication Objects The SmartB2BObject would use that mapping to extract the value Smith from the data and insert it into the message. When the message is received (the right side in the figure), the SmartB2BObject there parses the message, encounters Surname, and checks its own map file, where it sees that Surname maps to the Client.FamName field. It then passes the value Smith to the SmartDataObject handling that table. Note that neither the table nor the field need have the same name on both sides. That is the purpose of XML mapping: to make such differences irrelevant. Figure 62 illustrated the simplest mapping: an XML field to a database field. Figure 63 illustrates a more complex possibility: deriving a value for the message by filtering local data.
"Surname" "string"
4 2
"Surname" "string"
2
"Surname" FamilyName()
3
"Surname" "Client.FamName"
3
Client.FamName "Smith"
Figure 63:
In this example, the node definition in the XML schema is the same as in Figure 62: Surname, defined as type string. Here, though, there is no surname field in the Empl table. The whole name is stored as a single string. The mapping in this case is to a dedicated function FamilyName() that reads the Name field and returns the surname substring. Where does that dedicated function come from? You create it.
65
OpenEdge Development: AppBuilder You can create mappable procedures and functions within the SmartB2BObject itself, or in the SmartBusinessObject or SmartDataObject that cooperates with the SmartB2BObject. In general, good programming practice suggests that you put special procedures and functions inside the object to which they are most closely related. In the illustrated case (Figure 63), that would be the SmartDataObject, since a FamilyName() function would be the logical equivalent of a calculated field.
Mapping options
Mapping is like translating between spoken languages. It can be simple or difficult depending on the complexity of the original document and your skill at preserving the underlying meaning. Caution: No type-checking is performed during the mapping process. You must ensure that the values you produce by mapping or conversion are appropriate and correct. You have a number of mapping options to aid you in your document conversion. You can choose to map a schema node to a: Column being managed by a data-access object. Function you created in the SmartB2BObject itself. Procedure you created within the data-access object. Function you created within the data-access object. Whole data-access object.
These options are discussed more fully in the following sections. Mapping to a column This is the simplest and probably the most common mapping. You can use it whenever a column in the data stream corresponds directly to a schema element. Calculated fields/columns can complicate matters. On the outbound side, mapping a calculated column is identical to mapping an ordinary column. However, since calculated fields have no physical existence in a database, you would have to write special code to make sense of an inbound mapping. Usually, calculated fields are read-only; writing them in a meaningful way requires that you handle the result as a special case, decomposing and folding it back into the original fields in some way that fits your business context.
66
Data-Communication Objects Mapping to a function in the SmartB2BObject If you need to transform or convert a column value in some general way before sending/storing it, you can create a function to do that inside the SmartB2BObject itself. For example, you might create a function to convert dates to some special format, or present an integer value in some unusual base. The Mapping Tool will display any such functions as options when you elect to map to a column. These conversion functions always have a single parameter: For inbound documents, the value of the message element is passed as the parameter and the return value of the function is stored into the data field. For outbound documents, the situation is exactly opposite: the data field is passed as the parameter and the return value of the function is used as the message element.
Mapping to a procedure in the data-access object When you map an XML node to a procedure, you are actually mapping to the procedures parameter. The parameter must be an INPUT parameter for inbound documents and an OUTPUT parameter for outbound documents. It must also be the only parameter. You must handle all 4GL data operations inside the body of the procedure. Mapping to a function in the data-access object When you map to a function, the exact mapping depends on the direction: For inbound documents, you are mapping the schema node to an INPUT parameter. You must handle all assignments to the data field within the body of the function; the return value will be discarded. For outbound documents, you are mapping the return value of the function to the schema node. These functions can have no parameters. Handle all data reads within the body of the function.
Mapping to a whole data-access object. Mapping a whole object to a schema node has a different meaning depending on whether you are creating an inbound or an outbound map. On the outbound side, the meaning is an implied one: iteration.
67
The fields custnum, name, state, and so forth have obvious mappings to fields in the Customer table. To map those fields to these nodes, you must identify as a resource the SmartDataObject that supplies records from the Customer table. If the schema allows multiple instances of the Customer element to be generated, and you map the object itself to the Customer node here, then the SmartB2BObject treats that as a request to fetch all Customer records as part of building the message body. It will loop through all Customer records, extracting values for each of the mapped fields (custnum, name, and so forth) and creating XML for them. The net result of that loop will be multiple Customer record elements, explicitly laid out in the message body. It might look something like this, if the only fields mapped were custnum and name:
<Customer> <custnum> 1 </custnum> <name> Smith </name> </Customer> <Customer> <custnum> 2 </custnum> <name> Garcia </name> </Customer> <Customer> <custnum> 3 </custnum> <name> Hardingfele </name> </Customer>
Which means that, on the inbound side, no loop is requiredsimply going through the message in a linear way will traverse all included elements.
68
Data-Communication Objects On the inbound side, the result of processing the incoming XML is typically operations on a database. When you elect to map a data object to an element, you must identify what sort of operation is desired or acceptable: Update (may exist) Any particular record need not exist. If it does exist, it will be updated and if it does not exist, it will be created. Update (must exist) The record must exist and will be updated as part of the message-consuming process. If the record does not exist, the data handler will report an error. Create only The record must not already exist; it is created as part of the messageconsuming process. If the record already exists, the data handler will report an error. Delete The record must exist; it is deleted as part of the message-consuming process. If the record does not exist, the data handler will report an error. Find This operation is used for positioning the current-record pointer in the database.
Note: It is also possible to identify the operation within a node of the message itself. Exactly how this is to be done is not well-defined and may vary across document schema. If you face this situation, you must write code to handle it as a special case. To continue the example: if on the inbound side you map the Customer object to the Customer element with a type of Create, then every time the receiving SmartB2BObject sees the <Customer> token in the received message, it will build a Create request using field data from <custnum>, <name>, and so forth. When it reaches the </Customer> token, it will forward the request to the local SmartDataObject that manages that table. Note that, in this example, Customer cannot be the root node of the schema tree if you intend to generate multiple records; XML only allows one root node. If Customer were the root node, only data from the current record would be transformed into XML. However, if Customer is not the root node of the schema tree, then all Customer records will be processed. If you want only a subset of all records to be used, you must take steps to ensure that only those records appear in the data stream. Consider using a SmartFilter for that purpose (see the SmartFilters section on page 431 for details). Caution: If you map an object to some field/column that does not necessarily have unique values across all records, Find, Delete, and Update operations will act on the first acceptable record found. That might not be what you intend or desire.
69
Figure 64:
The Mapping Tool window is divided into two spacesa tree view on the left and a tab control with four tabs on the right. The tree view displays the current state of the map file. Each line represents a mappable element of the document. As you make mapping choices, the tree view changes to reflect them. When every node displays a mapping, your map file is complete.
610
Data-Communication Objects The four tabs on the right contain the editing interface: The Map tab is where you will do most of the mapping work. The Schema tab provides read-only information about the current schema file. The Source tab offers a read-only view of the raw schema source. The Object tab allows you to identify the local SmartObjects to use when mapping nodes.
When the Mapping Tool window opens, choose FileOpen and select one of the three types of files the mapping editor understands. Those files are: Outbound map file Identified by the filename extension .xmp (XML Map for Producers). This file is used to transform outgoing data from the local internal representation into XML format for transmission. Inbound map file Identified by the filename extension .xmc (XML Map for Consumers). This file is used to transform incoming data from the XML representation into the local internal format for processing and storage. XML schema file Identified by the filename extension .xsd (XML Schema Document). This file represents the generic, standard, nonproprietary document. It is used by all parties as the basis for creating their inbound and outbound map files. You cannot edit a schema file using the XML Mapping Tool.
Choose FileOpen in AppBuilder and select a map or schema file. AppBuilder will automatically call the Mapping Tool on your behalf. Note: The XML Mapping Tool only supports schema files that conform to the W3C specification. It does not attempt to handle other formats such as Microsofts or BizTalks. Nor does it handle the older Document Type Description (DTD) files.
611
2.
Selecting SmartObjects for mapping The SmartB2BObject always transforms data on behalf of some other object. You must identify at least one such objecttypically a SmartDataObject or SmartBusinessObjectbefore you can begin mapping nodes. Follow these steps: To map SmartObjectsWriter: 1. Choose the Object tab. The view changes:
612
Data-Communication Objects 2. Choose the Add button. Select an object that can serve as a DATA-SOURCE or DATA-TARGET, depending on the type of map file you are creating. Its ObjectName property will appear in the fill-in and its filename will appear in the list box. Note: You can edit any ObjectName here, but no two listed objects can have the same ObjectName. If you change an ObjectName, the new name must be locally unique (in other words, unique within the list you are creating here). 3. Repeat Step 2 until you have identified all the objects you will use. Note: If you intend to use conversion functions that reside in the SmartB2BObject, you must add that object to this list as well. If you make a mistake when adding an object, select it in the list and choose the Remove button. Note that you can remove an object from the list at any time. Even if you have already mapped nodes to the object, the mappings will go away cleanly if you remove the object name from the list. 4. 5. Select the mode of this map file: inbound (consumer) or outbound (producer). Choose the Browse button and identify the SmartContainer that holds the SmartB2BObject that will use this map file. You can omit this step if this is the only document type your application will produce/consume. Choose FileSave to save your work.
6.
You are now ready to begin the mapping process itself. Mapping schema nodes As the SmartB2BObject parses some logical document, it consults the map file you created for that document type. That map file must contain a mapping association for every element of the document. As the SmartB2BObject identifies an element in the document, it creates a transformation based on the association you supplied.
613
To create an association: 1. Select a node in the tree view. Click the Map tab, if necessary:
2.
Pull down the Object list and select the object that will supply the association for this node:
614
Data-Communication Objects 3. Select the appropriate radio button to refine the association. You can choose to map the node to: The whole object, if you intend to loop through multiple records (outbound side) or to CREATE, FIND, or DELETE the node, or UPDATE it or its children (inbound) Some particular field supplied by the object, if the node does not have children Some procedure or function, if the node does not have children
See the Mapping options section on page 66 for more information. 4. The display changes to reflect your choice:
615
OpenEdge Development: AppBuilder Complete the association by selecting the exact mapping (see the Mapping options section on page 66 for more information): If mapping the whole node in an inbound document, select the action to be performed (Update-may exist, Update-must exist, Create only, Delete, Find):
If mapping to or from a column that you will filter through a SmartB2BObject function, select the column identifier before you select the function identifier:
616
Data-Communication Objects If mapping to a procedure, or to a function not in the SmartB2BObject, select it from the list that appears after you choose the radio button.
2.
When the Choose dialog box opens, choose New. Note: You could also start the process by choosing FileNew and selecting the SmartB2BObject item from the list, or by right-clicking the icon in the Object Palette and selecting New SmartB2BObject from the menu that appears.
3.
The new SmartB2BObject master appears immediately. Select it, open the Section Editor, and add all the code needed to complete this custom master. Choose FileSave and give the new master a descriptive filename. Note that SmartB2BObject filenames conventionally begin with sbb.
4.
617
To add a SmartB2BObject instance to your organizer workspace: 1. Click the SmartB2BObject tool icon in the Object Palette. When the Choose dialog box opens, select the appropriate master and click OK. Note: To select the dynamic object, right-click the tool icon instead. The dynamic object is listed last in the menu that appears. 2. The SmartB2BObject has no run-time representation, so you can position it anywhere in the workspace. For your future convenience, consider selecting a spot that will otherwise remain empty. When you have selected a spot, click to release. The design-time representation appears:
3.
AppBuilder opens an Advisor window if it finds opportunities to create SmartLinks to other objects. Accept the Advisor's recommendations, if they seem appropriate. Configure the instance. Save your work.
4.
618
Data-Communication Objects
To configure an instance 1. Change the object identifier to more clearly reveal the role of this object in your application. If you wish to use this object as a placeholder, set the Parameterize as Variable check box. For information about using instances as placeholders, see the Creating a SmartObject placeholder section on page A29. Choose OK and save your work.
2.
3.
You are now ready to configure the instance properties. The SmartB2BObjects instance properties vary depending on whether the object will process incoming or outgoing documents. In either case, begin by clicking the menu button and choosing Instance Properties from the menu that opens. Outgoing instance properties If you have already linked this object to a SmartProducer, the dialog box should open with the Producer tab selected. If not, select it now:
619
To configure outgoing properties: 1. At a minimum, configure these fields to use XML: XML Mapping File Type in the path to the file that this object will use when transforming documents. Destination The logical identifier of the outbound documents destination. At present this must be a queue or topic served by the Progress SonicMQ system.
If you prefer to use a DTD (Document Type Definition) file, set the Use DTD checkbox. This will enable the Public ID and System ID fields. fill them in. Public ID (DTD) (Optional) Enter the global public identifier of the DTD document. System ID (DTD) (Mandatory) Enter the path to the actual DTD file. Click the Browse button if you wish to search for the file.
2.
Examine these fields and change those that do not meet your needs: Reply required Defaults to cleared. Setting this check box will notify recipients that you wish a reply sent to you whenever they receive a document of this type. You must add code to handle these replies. Reply selector If you wish to filter incoming replies according to values in reply-header fields or properties, enter the expression here. The SmartProducer object will perform the test on incoming replies and discard from the inbound Queue/Topic any messages that fail the test. Example: company_name = "Smith" AND priority > 4. A reply from the Smith company with priority of 4 or less would be discarded without notice. The syntax is a subset of the syntax defined in SQL-92.
620
Data-Communication Objects 3. If this SmartB2BObject will create different documents from the same data stream, or send to different real-world or JMS destinations, choose the Multiple Producers pushbutton. Additional fields come into view:
4. 5.
For each document type/destination pair, fill in the fields identified in Step 1 and Step 2. To specify where to find the name reference at run time, set the Document Name Data check box. Three additional fields activate themselves. Change their values as appropriate: Data Object Select the SmartDataObject or other data-handling object that handles the data for the new document type. Column, Function Defaults to Column. Selecting Function means that the Document/Direction Name value is returned by a function in the data object rather than by one of its columns. Column/Function [The label on this fill-in reflects the current radio-button selection.] Select the column or function in the data object that will return the Document/Direction Name.
621
OpenEdge Development: AppBuilder 6. Choose the Save button to add the new document information to the list in the browser widget. Note: If you decide not to add this entry, choose Cancel instead of Save. If you decide you made a mistake in saving an entry, choose the Delete button. 7. 8. To add an additional entry, click the Add button and repeat Step 4 through Step 6. When you have added all the document types/destinations you desire, save your work.
Incoming instance properties If you have already linked this object to a SmartConsumer, the dialog box should open with the Consumer tab selected. If not, select it now:
To configure this object for consuming: 1. 2. Identify the mapping file. Save your work.
622
Data-Communication Objects You can use the SmartSender (or, on the inbound side, the SmartReceiver) in place of the SmartB2BObject if you do not need the SmartB2BObjects special capabilities. The capabilities of the SmartSender and SmartReceiver are whatever you choose to make them. Figure 65 illustrates where the objects fit in with other SmartObjects.
Data destination SmartReceiver SmartConsumer 4GL-JMS API AppServer SonicMQ Adapter SonicMQ Broker
Internet
Figure 65:
The SmartSender and SmartReceiver objects are supplied for your use as templates with stubbed handler routines. After writing 4GL procedures to complete the handler stubs, you can connect these objects to the Smart message-interface objects in exactly the same way you would connect a SmartB2BObject. The SmartSender will then perform any transformation you have included in the handler routines, package the content, and call the SmartProducer to send it off. Similarly, the SmartReceiver will accept an inbound message from the SmartConsumer, perform the handling process you define, and pass the result on to some other SmartObject for storage or further handling. 623
OpenEdge Development: AppBuilder Because you provide the handling logic, you can make these objects as simple or complex in their behavior as you desire. You could handle plain, unformatted text by making your handler routines mere pass-throughs, their only function being to copy the unaltered text into or out of the message body. Or, you could implement special encryption/decryption procedures, graphics reformatting, or even your own special-purpose XML logic. You can implement any handling you like. What you do with a SmartSender/SmartReceiver is entirely up to you.
2.
When the Choose dialog box opens, click the New button. After a moment, a new SmartSender object appears:
3.
receiveReplyHandler
Open the Section Editor and add handler code to complete the sendHandler and procedures. Use calls from the 4GL-JMS API.
The sendHander procedure deals with your outbound messages. Use it to set properties and create message bodies. See the Example of sendHandler code section on page 644. The receiveReplyHandler procedure deals with incoming replies. Use it to extract properties and evaluate message bodies. See the Example of sendHandler override code section on page 645. 4. Save the completed master using a descriptive filename. Note that SmartSender filenames conventionally begin with sms.
624
Data-Communication Objects Creating a SmartReceiver master involves comparable steps, though the names of the handler routines are receiveHandler and sendReplyHandler, respectively. See the Example of receiveHandler code section on page 648 and the Example of sendReplyHandler code section on page 650.
2.
When the Choose dialog box opens, select the master object and click OK. Move your mouse cursor over your workspace and click to release the object. Save your work.
3.
You are now ready to configure the instance. To configure the instance: 1. Click the instances Menu button and choose Properties. When the standard SmartObject Property Sheet opens, change the Object identifier (the instance handle) to more clearly reflect the role of this object in your application. If you wish to use this instance as a placeholder, set the Parameterize as Variable check box. For information about placeholders, see the Creating a SmartObject placeholder section on page A29 and OpenEdge Development: ADM and SmartObjects.
2.
625
OpenEdge Development: AppBuilder 3. Click OK to close the Property Sheet. Click the menu button again and choose Instance Properties. The dialog box opens:
4.
Set the Destination property to the identifier or the SonicMQ Topic (Publish-and-Subscribe) or Queue (Point-to-Point) to which your message is to be sent. You can choose to set two other properties, if you wish: Reply Required Defaults to cleared. Setting this check box notifies the recipient that you wish a reply to your message. Your receiveReplyHandler routine must deal with any such reply. Reply Selector If you wish to filter incoming replies according to values in reply-header fields or properties, enter the expression here. The SmartConsumer object will perform the test on incoming replies and discard from the inbound queue/topic any messages that fail the test. Example: company_name = "ABC" AND priority >= 4. Any reply received from company ABC with a priority of 3 or less will be discarded without notice. The syntax is a subset of the syntax defined in SQL-92.
5.
Placing and configuring a SmartReceiver instance involves comparable steps. The major difference is that the SmartReceiver has no Instance Properties dialog box.
626
Data-Communication Objects
SmartRouters
The SmartRouter object is designed to distribute incoming documents to the appropriate SmartB2BObject for transformation. It is only required in applications that can handle more than one document type. Figure 66 illustrates where the SmartRouter fits into the document-handling process.
SmartDataObject SmartB2B SmartConsumer 4GL-JMS API AppServer SonicMQ Adapter SonicMQ Broker
Internet
Figure 66:
627
Business object
SmartB2BObject
SmartB2BObject
SmartProducer
SmartConsumer
4GL-JMS API
Figure 67:
The business object would typically be a SmartDataObject or SmartBusinessObject. The SmartB2BObjects could also be a SmartSender/SmartReceiver pair. Regardless, the basic layout is very straightforward when all inbound or outbound messages are handled alike. In some business situations, however, you might have to handle several different incoming logical-document typesin Figure 68, purchase order, sales enquiry, and customer support formall packaged identically as XML messages. Since at present each document type is handled by a dedicated SmartB2BObject instance, you would need a way to route them appropriately. The SmartRouter object provides exactly that service.
628
Data-Communication Objects Figure 68 illustrates how the SmartRouter relates to the SmartConsumer and SmartB2B objects.
SmartB2BObject
SmartB2BObject
SmartB2BObject
RUN container and push schema if necessary Push each new message when received
INMESSAGE link carries reply, if any, back to Consumer from B2B object
SmartRouter
SmartConsumer
Schema storage
SonicMQ system
Figure 68:
When a new message comes in, the SmartRouter determines which SmartB2BObject should do the transformation and starts that container, if necessary. It then identifies the SmartB2BObject to the SmartConsumer and hands off the message file to the SmartB2BObject. After that, it has nothing more to do with that message. The SmartConsumer and SmartB2BObject communicate directly from that point onward, as they do when a SmartRouter is not involved.
629
Callable document-handlers
The major difference between using and not using a SmartRouter is in the packaging. As Figure 68 illustrates, the SmartB2BObject/SmartDataObject pairs that handle a particular document type are packaged separately. Similarly, a SmartRouter and SmartConsumer can be packaged together, if desired. The package used in each case is the simple SmartContainer. The simple SmartContainer is a specialized organizer object. It has no run-time representation. You would typically use it only when creating packages such as those illustrated in Figure 68. Being able to package components without a user interface is particularly useful when your message-consuming process is to run in batch mode, without human intervention.
2.
3.
630
Data-Communication Objects 4. Place and configure the transformer and data handler objects that you created. No advisor will appear to offer to create SmartLinks between these objects: they do not communicate using the SmartLink mechanism. Save your work. Repeat this process until you have created a handler for each incoming document type.
5.
2.
Place a SmartConsumer object and configure it to monitor the appropriate inbound queue or topic. See the Creating and placing a SmartConsumer instance section on page 637 and the Configuring a SmartConsumer instance section on page 638 for details.
631
4.
Place the instance in the workspace. An Advisor will appear and offer to create a SmartLink of type ROUTER from the SmartConsumer. Accept the offer. Click the Menu button and choose Instance Properties. The dialog box opens:
5.
6.
Click the Add button. This makes the External Reference field editable. Enter the URL of the schema file for some document type this router link must recognize. Note that the filename of the schema must be the same locally as it appears in the URL, though the paths to them will probably be very different. Click the corresponding Internal Reference field to activate it. Enter the PROPATH-relative path to the corresponding map file. Thus, if the full path is d:\abc\def\mapfile.xmc and PROPATH contains d:\abc, you should enter def\mapfile.xmc here. If you are satisfied with this entry, click the Save button to write the entry out to disk. Otherwise, click Reset to clear the fields, or Cancel to clear the fields and leave edit mode. Repeat Step 6 through Step 8 until you have created entries for each document type this Router instance must recognize. Click OK to close this dialog box. Now, when run, this Router will be able to recognize and appropriately distribute those document types.
7.
8.
9.
10. Save the package using a distinctive filename. Note that filenames for simple SmartContainers conventionally begin with c. 632
Data-Communication Objects
SmartDataObject SmartB2B SmartConsumer 4GL-JMS API AppServer SonicMQ Adapter SonicMQ Broker
Internet
Figure 69:
SonicMQ is Progress Software Corporations implementation of the industry-standard Java Message Service (JMS). The SmartProducer and SmartConsumer communicate with the SonicMQ broker through the 4GL-JMS API.
633
2.
Position the mouse cursor over an empty spot in your workspace and click to place the object. If you have one or more SmartB2BObjects or SmartSenders in place, AppBuilder opens an Advisor dialog box and offers to create OUTMESSAGE SmartLinks. Examine the offers and accept those that are appropriate. Click the object's Menu button and choose Properties. The Property Sheet dialog box opens:
3.
4.
Change the Object identifier (instance handle) to one that more accurately describes the role of this SmartProducer in your application. Configure the instance. Save your work.
5.
634
Data-Communication Objects
2.
Change the default values that do not meet your needs: Domain Defaults to Publish-and-Subscribe. Setting this value to Point-to-Point creates a single copy of the message. Although a number of entities might have access to the message, the first entity to read it removes it from the queue. With the Publish-and-Subscribe mechanism, a single copy of the message can be read by all subscribing entities. This allows implementation of a form of multicasting. You cannot modify the Domain value at run time. JMS partition Select a JMS Partition from the dropdown list. If there are no JMS Partitions listed, you can define as many as you like using the Service Parameter Maintenance Tool, available on the PRO*Tools toolbar. For information about how to use that tool, see the online help. JMS user Set this field to identify the user of the JMS Broker connection. JMS password Set this field to be the password that corresponds to the JMS user identifier.
635
OpenEdge Development: AppBuilder JMS Client ID Set this field to a value unique to this client. This field is used to resolve ambiguities in cases where multiple clients might be using the same subscription and user names. Note: If you do not know the User, Password, and Client ID values at design time, you can check the Prompt-for-JMS-Login box and the values will be collected at run time. Ping interval Defaults to 0 (pinging off). Setting this field to some integer value (representing seconds) causes the connection to the SonicMQ broker to be tested at that rate for the duration of the JMS session. It is good practice not to ping frequently, since pinging decreases overall system performance. Prompt for JMS login Defaults to cleared. Setting this check box causes the messaging object to prompt the user for login. Priority Defaults to 4. The value is read whenever a new message is sent. It establishes the priority for that message in the range 0 (lowest) to 9 (highest). You can modify the value at run time under program control. Time to live Defaults to 0 (no expiration). This field is evaluated for every new message. It establishes the length of time in milliseconds that the message can remain unread before being discarded as stale. You can modify the value at run time under program control. Persistency Defaults to PERSISTENT (message retained in the brokers database). Other values supported are: NON_PERSISTENT (message not retained) NON_PERSISTENT_ASYNC UNKNOWN Message type Defaults to TextMessage. Other types supported are: BytesMessage A stream of raw (uninterpreted) bytes. This is the default type when connecting to a SmartB2BObject; most other types require extra code. HeaderMessage Known simply as type Message within the SonicMQ system. Use for shutdown messages.
636
Data-Communication Objects XMLMessage A string representing an XML tree that can be parsed as a document. Do not use this type when connected to a SmartB2BObject. MapMessage A set of name/value pairs, where names are of type string and values are Java primitives. You can read the entries in sequence or randomly by reference to the name. StreamMessage A stream of Java primitives, read sequentially.
2.
Position your mouse cursor over an empty spot in your workspace and click to place the object. If you have a SmartRouter in place, AppBuilder opens an Advisor dialog box and offers to create a ROUTER SmartLink. If, instead, you have a SmartB2BObject or SmartReceiver in place, the Adviser will offer to create an INMESSAGE link. In either case, accept the offer unless it seems inappropriate. Click the Menu button and choose Properties. The Property Sheet dialog box opens:
3.
637
OpenEdge Development: AppBuilder 4. Change the instance handle to one that more accurately describes the role of this SmartConsumer in your application. Configure the instance. Save your work.
5.
638
Data-Communication Objects 2. Change the default values that do not meet your needs: Domain Defaults to Publish-and-Subscribe. Setting this value to Point-to-Point creates a single copy of the message. Although a number of entities might have access to the message, the first one that reads the message deletes it from the pipeline. With the Publish-and-Subscribe mechanism, all subscribing entities can read the message. This allows implementation of a form of multicasting. The Domain value is not modifiable at run time. JMS partition Select a Partition from those listed. If there are no JMS Partitions listed, you can define as many as you like using the Service Parameter Maintenance Tool available on the PRO*Tools toolbar. For information about how to use that tool, see the online help. Ping interval Defaults to 0 (pinging off). Setting this field to some integer value in seconds causes the connection to the SonicMQ broker to be tested at that rate for the duration of the JMS session. It is good practice not to ping frequently, since pinging decreases system performance. Log file Defaults to empty. Set this field to the pathname of the error-log file that will be used when running in batch mode. Shutdown Defaults to empty. Set this field to the identifier for the Topic (Publish-and-Subscribe) or Queue (Point-to-Point) to be used for shutting down this SmartConsumer instance when running in batch mode. Sending any message to this destination causes this SmartConsumer object to begin the shutdown process. JMS user Set this field to identify the user of the JMS Broker connection. JMS password Set this field to be the password that corresponds to the JMS User identifier. JMS Client ID Set this field to a value unique to this client. This field is used to resolve ambiguities in cases where multiple clients might be using the same subscription and user names. Note: You can supply the User, Password, and Client ID values at design time if you know them. Otherwise, check the Prompt-for-JMS-Login box and the object will prompt the user for them at run time.
639
OpenEdge Development: AppBuilder Prompt for JMS login Defaults to cleared. Setting this check box causes the object to prompt the user for login. Destination Set this field to create/update an identifier for the destination Topic/Queue. Message selector If you wish to filter incoming messages according to values in header fields or properties, enter the expression here. The SmartConsumer object will perform the test on incoming messages and discard from the inbound queue/topic any messages that fail the test. Example: company_name = "ABC" AND priority < 4. Any message received from company ABC with a priority of 3 or less will be discarded without notice. The syntax is a subset of the syntax defined in SQL-92. Durable subscription Defaults to cleared. Enabled only when Domain is Publish-and-Subscribe. Set this check box to preserve the current subscription across JMS sessions. Subscription name Enabled only for Durable Subscriptions. Set this field to create/update a subscription name. Unsubscribe on session close Defaults to cleared. Enabled only for Durable Subscriptions. Setting this check box causes the selected subscription to be cancelled when the JMS session ends.
In the example shown, containerfilename would be the filename of a simple SmartContainer that contains a SmartConsumer object and a SmartRouter object. The values you pass in the parameter string override any values set at design time using the Instance Properties dialog box.
640
Data-Communication Objects Stopping a SmartConsumer The most orderly way to shut down a SmartConsumer object running in batch mode is to send a message to the designated shutdown topic or queue. You identify that topic or queue at design time in the Shutdown property. The shutdown message needs no body; its receipt by the shutdown Queue or Topic is sufficient. When the SmartConsumer detects reception of a message in that Queue/Topic, it sends a shutdown message to its container object. Shutting down the container object shuts down all objects in the container (including the SmartConsumer itself) as well as any containers that were started by the SmartRouter to which the SmartConsumer is connected. To set up and test a shutdown mechanism, follow these general steps: 1. 2. Create a simple SmartContainer Create and place a SmartProducer in the SmartContainer. Set Message Type to HeaderMessage and configure other properties appropriately. Create and place a SmartSender in the SmartContainer. If an Advisor offers to create an OUTMESSAGE link to the SmartProducer, accept the offer; otherwise, create the link using the SmartLinks editor. Set the Destination property to be the shutdown destination for the consumer, for example Shutdown. Any message this SmartProducer sends will then be a shutdown message. Open a Section Editor window and create a local override procedure called Insert this RUN statement as the procedure body:
RUN sendMessage IN THIS-PROCEDURE.
3.
4.
initializeObject.
5.
Save your work using a distinctive filename, for example stopconsumer. To test this shutdown mechanism, enter this statement on the command line:
prowin32 -b -p stopconsumer.w
641
RUN sendMessage() sendHandler() Set up header properties, add message body Return
SmartProducer
Figure 610:
The steps below describe the process. 1. 2. When a message is to be sent, the OMS calls sendMessage in the SmartProducer. The sendMessage() routine in the SmartProducer creates an empty message. It then calls sendHandler() in the OMS, passing the handle of the message it created.
642
Data-Communication Objects 3. The sendHandler() routine in the OMS sets the message header properties, adds a body to the message, and returns. The sendMessage() routine in the SmartProducer now has a complete message to send and calls the relevant routines in the 4GL-JMS API to start the message on its way. When a reply comes in, replyHandler() in the SmartProducer calls replyHandler() in the OMS, passing it the handle of the reply. The replyHandler() routine in the OMS gets the ID of the original message and the reply properties and body. It performs any desired processing on that information and returns.
4.
5.
6.
Inbound message-handling and reply process Receiving a message requires cooperation between the SmartConsumer and an object serving as the INMESSAGE-TARGET (IMT). Generally you would use either a SmartB2BObject or a SmartReceiver as IMT. Figure 611 illustrates this process.
messageHandler()
RUN receiveHandler (hMsg)
receiveHandler()
Get properties, body Process message
If reply required then Create empty reply RUN sendReplyHandler (hReply) Send reply message SmartConsumer
Return
sendReplyHandler()
Set properties, body Return InMessage target
Figure 611:
643
OpenEdge Development: AppBuilder If you use a SmartRouter to distribute incoming messages, the SmartRouter acts as an IMT proxy, accepting calls from the SmartConsumer and passing them on transparently to the real IMT. The brief description below ignores the role of the SmartRouter: 1. When a message is received, the messageHandler() routine in the SmartConsumer calls the receiveHandler() routine in the IMT, passing the handle of the received message. The receiveHandler() routine in the IMT extracts header properties and the message body, performs any desired processing, and returns. If the message requires a reply, the messageHandler() routine in the SmartConsumer creates an empty reply message and calls sendReplyHandler() in the IMT, passing the handle of the reply it created. The sendReplyHandler() routine in the IMT sets the header properties, adds a body, and returns. The messageHandler() routine in the SmartConsumer now has a complete reply message to send and calls the relevant routines in the 4GL-JMS API to start it on its way.
2.
3.
4.
5.
644
Data-Communication Objects
DEFINE INPUT PARAMETER hMessage AS HANDLE NO-UNDO. /* ** Set custom message properties (example only) */ DYNAMIC-FUNCTION('setStringProperty':U IN hMessage, INPUT 'city':U, INPUT cCity). /* ** Run the SmartB2BObject's version of sendHandler ** to assign the body of the message */ RUN SUPER.
645
OpenEdge Development: AppBuilder This is an example of code that performs those functions for some OUTMESSAGE-SOURCE object other than a SmartB2BObject, for example a SmartSender: (1 of 2)
DEFINE INPUT PARAMETER hReply AS HANDLE NO-UNDO. /* ** Declare storage for obtaining the properties */ DEFINE VARIABLE cOriginalMsgID AS CHARACTER NO-UNDO. DEFINE VARIABLE cReplyType AS CHARACTER NO-UNDO. DEFINE VARIABLE cPropertyNames AS CHARACTER NO-UNDO. DEFINE VARIABLE cProperty AS CHARACTER NO-UNDO. DEFINE VARIABLE cPropType AS CHARACTER NO-UNDO. DEFINE VARIABLE iThisProp AS INTEGER NO-UNDO. DEFINE VARAIBLE cCharProp AS CHARACTER NO-UNDO. DEFINE VARIABLE dDecProp AS DECIMAL NO-UNDO. DEFINE VARIABLE iIntProp AS INTEGER NO-UNDO. DEFINE VARIABLE lLogicProp AS LOGICAL NO-UNDO. DEFINE VARIABLE mReplyBody AS MEMPTR NO-UNDO. /* ** Identify the original message using the reply handle, get property names */ cOriginalMsgID = DYNAMIC-FUNCTION('getJMSCorrelationID':U IN hReply). cPropertyNames = DYNAMIC-FUNCTION(getPropertyNames:U IN hReply). /* ** Loop through all properties, extracting their values according to type */ DO iThisProp = 1 TO NUM-ENTRIES(cPropertyNames): cProperty = ENTRY(iThisProp, cPropertyNames). cPropType = DYNAMIC-FUNCTION(getPropertyType:U IN hReply, INPUT cProperty). CASE cPropType: WHEN String:U THEN DO: cCharProp = DYNAMIC-FUNCTION(getCharProperty:U IN hReply, INPUT cProperty). /* ** Insert code here to process this character property */ END. WHEN Boolean:U THEN DO: lLogicProp = DYNAMIC-FUNCTION(getLogicalProperty:U IN hReply, INPUT cProperty). /* ** Insert code here to process this logical property */ END.
646
Data-Communication Objects (2 of 2)
WHEN Byte:U OR WHEN Short OR WHEN Int THEN DO: iIntProp = DYNAMIC-FUNCTION(getIntProperty:U IN hReply, INPUT cProperty). /* ** Insert code here to process this integer property */ END. WHEN Long:U OR WHEN Float OR WHEN Double THEN DO: iDecProp = DYNAMIC-FUNCTION(getDecProperty:U IN hReply, INPUT cProperty). /* ** Insert code here to process this integer property */ END. END. /* case cproptype */ END. /* do iThisProp */ /* ** Identify the reply type */ cReplyType = DYNAMIC-FUNCTION(getMessageType:U IN hReply). /* ** Extract the reply body in the appropriate format */ CASE cReplyType: WHEN BytesMessage:U THEN DO mReplyBody = DYNAMIC-FUNCTION(getMemptr:U IN hReply). END. /* when bytesmessage */ WHEN TextMessage:U OR WHEN XMLMessage:U THEN DO: DO WHILE (DYNAMIC-FUNCTION(endOfStream:U IN hReply) = FALSE: cReplyBody = DYNAMIC-FUNCTION(getTextSegment:U IN hReply). /* ** Insert code here to put returned text segments into a form, ** such as temp-table records, that can be read by the routine ** that will process the body of this reply */ END. /* do while */ END. /* when textmessage */ END. /* case cReplyType */
647
648
Data-Communication Objects (2 of 2)
WHEN Byte:U OR WHEN Short:U OR WHEN Int:U THEN DO: iIntProp = DYNAMIC-FUNCTION(getIntProperty:U IN hMessage, INPUT cProperty). /* ** Insert code for processing an integer property */ END. WHEN Long:U OR WHEN Float:U OR WHEN Double:U THEN DO: dValue = DYNAMIC-FUNCTION(getDecProperty:U IN hMessage, INPUT cProperty). /* ** Insert code for processing a decimal property */ END. /* when decimal */ END. /* case cPropType */ END. /* DO iThisProp */ /* ** Determine message type; extract body appropriately */ cMessageType = DYNAMIC-FUNCTION(getMessageType:U IN hMessage). CASE cMessageType: WHEN BytesMessage:U THEN DO: mMessageBody = DYNAMIC-FUNCTION(getMemptr:U IN hMessage). END. WHEN TextMessage:U OR WHEN XMLMessage:U THEN DO: DO WHILE (DYNAMIC-FUNCTION(endOfStream:U IN hMessage) = FALSE: cMessageBody = DYNAMIC-FUNCTION(getTextSegment:U IN hMessage). /* ** Insert code here to put extracted text segments into a form, ** such as temp-table records, that can be read by the routine ** that will process the body of this message */ END. /* do while */ END. /* when text message */ END. /* case cMessageType */
649
650
Data-Communication Objects
651
652
7
Control Objects
Menus, toolbars, pushbuttons, and similar objects serve as the controls and control panels of an application. They allow the user to navigate through databases, shift between functional layouts, set values for fields, and choose when and whether to make changes to database records. This chapter covers the following: Introduction to control objects SmartToolbars SmartPanels Basic pushbuttons
AppBuilder also offers the basic 4GL pushbutton. You can use it to build your own control groups, if you choose.
SmartToolbars
The SmartToolbar object optionally combines a standard menu bar with a full-width toolbar, and provides access to database navigation and record-management functions. You can use a SmartToolbar in place of the standard menu bar in a SmartWindow, if you wish. The SmartToolbar offers the same functions that the larger, separate Navigation and Update SmartPanel button arrays provide between them.
72
Control Objects The SmartToolbar has some limitations: You can only use the full SmartToolbar in a SmartWindow or SmartFrame. If you place one in a SmartDialog, only the toolbar component will activate, since a dialog cannot have a menu bar even as part of a SmartObject. You can use only one SmartToolbar per organizer instance. If you need additional controls, you must create and group them by hand. The width of a SmartToolbar does not automatically change to agree with changes in the organizer object. You must change the width under program control, or manually. If you use the menu component, you cannot use the standard menu editor to populate it. You must write code to add any additional menu items that you desire.
Placing a SmartToolbar
AppBuilder supplies a single version of the SmartToolbar. If you do not need to add additional functions, using it in your application is very straightforward. To use the SmartToolbar: 1. Click on the SmartToolbar tool icon in the Object Palette:
2.
Move the mouse cursor over a bare spot in your workspace and click to place the object. A menu bar and its corresponding toolbar have a well-defined position in a window, so you need not be careful where you place itit establishes itself in the right place automatically, in some cases even moving other objects out of the way. Configure it, and adjust its size appropriately.
3.
73
OpenEdge Development: AppBuilder Figure 71, Figure 72, and Figure 73 show the SmartToolbar in different states with both components and all supplied functions enabled. The Filter button appears insensitive because there was nothing connected to it at the time these images were taken.
Figure 71:
Figure 72:
Figure 73:
The settings shown by this dialog box produce the toolbar in Figure 71.
74
Control Objects Table 71 describes the property settings: Table 71: SmartToolbar properties Default setting
On
Property
Menu
Meaning Clearing this box turns off the menu-bar component. Turning off the SmartToolbars menu-bar component does not allow you to define or use the menu bar that is a feature of the window widget. Clearing this box turns off the toolbar component. Of course, you might not feel there is much reason to use the SmartToolbar at all, if you turn off this component. Clearing this box turns off the sunken border (implemented using a rectangle) that appears surrounding the toolbar. Clearing this box turns off the four buttons that allow the user to change the current-record pointer. It also removes the entire Navigation menu and the Navigation link to the SmartDataObject, if there is one. Clearing this box turns off the six buttons that allow the user to update records and the database. It removes the corresponding items from the File menu and the TableIO link to the SmartDataViewer, if there is one. Setting this box turns on the Undo and Commit transaction-processing buttons, and adds those items to the File menu. Setting this box activates the Filter button and adds a corresponding item to the File menu. See the Adding a filter-control window section on page 76 for information about making use of this button.
Toolbar
Ont
Show Border
On
Navigation
On
TableIO
On
Commit
Off
Filter
Off
75
76
Control Objects 2. Click on the toolbars menu button and choose Instance Properties. When the dialog box opens, set the Filter check box:
3.
Choose OK to dismiss the dialog box. Create a SmartWindow to be your Filter window. Populate it with a SmartFilter. Click on the Filter instances Menu button and choose Instance Properties. The dialog box opens:
4.
5.
Identify the data source and the filterable fields. For the purposes of this example, accept the default style and view-as settings. Choose OK.
77
OpenEdge Development: AppBuilder 6. Click on the Filter menu button and choose SmartLinks. Add a Filter link from the filter object (represented by the handle identifier) to the window object (represented by THIS-PROCEDURE):
7.
Close the SmartLink editor. Resize the Filter window as necessary. Save it using a distinctive name. Click on the SmartContainer tool in the Object Palette. When the Choose dialog box opens, select the Filter window that you just saved, and choose OK. Place the object on any blank spot in your main window. Allow the Advisor to create the links it suggests. Your result should now look similar to this:
8.
9.
Click on the Menu button of the Filter window instance you just placed. Choose Instance Properties. When the dialog box opens, clear the View check box. This will prevent the Filter window from automatically displaying at startup. Choose OK to dismiss the dialog box.
78
Control Objects 10. Run your sample application. When it starts up, click the Filter button to open the Filter window. Verify that you can filter the data stream:
The Filter button only opens the Filter window. To close the Filter window, you must click the Close button (the X) at the right end of its title bar.
SmartPanels
A SmartPanel is a task-oriented array of pushbuttons that incorporates ADM Smart technology. As is true of all SmartObjects, SmartPanels are modular and communicate with other SmartObjects through SmartLinks. SmartPanel instances are immediately available as precompiled objects from the Object Palette. They are loosely coupled to the SmartObjects they control and, because they are not directly involved in the operation of a data stream, are not based on a master object.
79
OpenEdge Development: AppBuilder Table 72 describes the predefined SmartPanels for your use: Table 72: Style Navigation (with Icon Labels) SmartPanels options Description A four-button array with iconic labels that follow the arrowhead convention made familiar by tape recorders and VCRs. The four buttons select, respectively: the first record in a data stream; the record immediately preceding the current record, if possible; the record immediately following the current record, if possible; the final record in the data stream. The same four-button array, but with text (First, Prev, Next, Last) rather than icon labels. A six-button array with text labels. The six buttons are Save/Update, Reset, Add, Copy, Delete, and Cancel. You must use this SmartPanel, or the equivalent buttons in a SmartToolbar, to enable changes to the database when using a SmartDataViewer for data display. You do not need it to make simple updates when using a SmartDataBrowser; a SmartDataBrowser that allows update will automatically perform the update when the user leaves the changed row. Use an Update SmartPanel with a SmartDataBrowser if you want the user to be able to add and delete records, or make more sophisticated updates. Commit A two-button array used for transaction processing. The two buttons are Commit and Undo. A transaction is any group of operations that must be completed or discarded as an atomic unit. Failing to treat a transactional group atomically generally results in logical rather than physical data corruption. For example, after a credit purchase, successfully updating the inventory and shipping queue without also updating the customers balance will cause an inventory leak. In this example, an update must be performed on all of the tables or on none of them, if the system is to remain in good order.
Note: A SmartDataBrowser provides its own navigational interface with the scroll bar. Adding a navigation array creates the possibility of confusion: since the SmartPanel is not able to communicate with the scroll bar, they can get out-of-sync. If you choose to add a SmartPanel for navigation, consider turning off the scroll bar in the property sheet for the browse widget.
710
Control Objects
2.
When the Choose SmartPanel dialog box opens, select the SmartPanel and choose OK:
Note: If you prefer, you can right-click on the tool icon, instead, and select the desired SmartPanel from the menu that opens there. 3. Position the mouse cursor over a bare spot in your workspace and click to place the object. If you have other SmartObjects in place, AppBuilder might open an Advisor dialog box and offer to create SmartLinks. Examine the offer and accept it if the proposed SmartLinks seem appropriate.
711
OpenEdge Development: AppBuilder 4. Click on the objects menu button and choose Properties. The Property Sheet dialog box opens. The sheet for the iconic Navigation panel is shown here:
5.
Change the object identifier to one that more accurately describes the role of this SmartPanel in your application. The properties for appearance and behavior vary from panel to panel. Click the Edit button to inspect them (you can also reach them directly by choosing Instance Properties from the menu-button menu). Change those that do not meet your needs.
6.
Navigation SmartPanel properties A Navigation SmartPanel has three properties. You can change those that do not meet your needs: Show Border Normally set. Clearing this check box turns off the border (implemented as a rectangle) around the buttons. Edge Pixels Normally 2. You can set the value to as much or as little as you like, with differing visual effects. Note that the number of pixels between the edge of the button and the inner edge of the rectangle does not changethe rectangles border grows inward toward the buttons rather than outward, in other words. Internationalization (Applies only to the iconic Navigation panel.) To conform your software to cultural conventions, you can choose which buttonleftmost or rightmostwill set the pointer to the first record in a data stream. You can often determine the convention for a particular culture by looking at the direction in which the local language is written and read.
712
Control Objects Save/Update SmartPanel properties A Save/Update SmartPanel has only two properties. Change either or both, if you wish: TableIO type Normally Save. Setting this option to Update requires the user to first choose the Update button before the fields will make themselves editable. Save causes the fields to be editable by default. In either case, once the user has edited a field, choosing the Update button (now labelled Save) writes the changes back to the database immediately. If you also have a transaction (Commit/Undo) panel installed, your application will journal the changes so that it can undo them again, if the user elects not to eventually commit. Behavior of Add button Normally prompts for one new record. Setting to Add Multiple causes your application to prompt for an arbitrary number of new records without requiring the user to choose the Add button again.
Transaction SmartPanel properties There are no programmer-modifiable instance properties for the Commit (Transaction) SmartPanel, apart from the object identifier.
Basic pushbuttons
In a GUI, a pushbutton is equivalent in power and generality to a menu item. Indeed, you can construe a pushbutton as being a self-contained, single-item menu. Since pushbuttons are normally always visible, they offer more immediacy and convenience than menu items at the cost of taking up more space. Because they do take up more space, you will probably want to use them sparingly. Because of how they are used in everyday life, pushbuttons in a GUI are associated with invocations, actions, and major state changes, not with minor state changes such as setting a single value. Using them in a way that runs counter to this expectation can make your applications harder and less satisfying for people to use.
713
OpenEdge Development: AppBuilder AppBuilder supplies a default, undefined pushbutton object as well as a number of pushbuttons preconfigured for common applications: View page Applies only to ADM paging (see the Simple SmartContainers section on page 328). Causes objects associated with a certain page number to appear. You supply the number as an argument to the call in the trigger code. Already-visible objects assigned to other ADM pages do not disappear. OK, Cancel Accepts/discards changes and closes the parent dialog box or window. Done Calls the applications shutdown routine. Help Calls the help system. First, Prev, Next, Last Moves the current-record cursor to the record indicated by the button. Custom Size/Color (Default) Creates a generic pushbutton with no action defined on it. You must add the action code yourself in the CHOOSE trigger.
When the menu opens, select the appropriate type of pushbutton. Note: If you prefer to use the default (undefined) pushbutton, simply left-click on the icon instead; no menu will open. 2. Move your mouse cursor over a bare spot in your workspace window and click to place the new pushbutton. Configure, position, and size it appropriately.
3. 714
Control Objects
To begin customizing the pushbuttons appearance, select it and choose ToolsProperty Sheet. The dialog box opens:
Minimum configuration While you can accept many default settings, at a minimum you should: Change the object identifier to one that more closely represents the role of this pushbutton in your application. Set the identifying label to a string or icon that will be meaningful to the user. See the Setting a pushbutton label section on page 718 for instructions.
715
OpenEdge Development: AppBuilder Resize the pushbutton to fit it to its surroundings in a way that minimizes the space it takes up. For the best visual effect, you should make all related pushbuttons the same size, and align them carefully. If one of them is more significant than the others, you can indicate that greater significance by making that pushbutton unmistakably larger in one dimension, as in these examples:
Miscellaneous configuration (other settings) These properties modify appearance or behavior as shown in Table 73. Table 73: Button properties Default setting Off Off Off (1 of 2)
Description Setting this box causes the ENDKEY condition when the user chooses the pushbutton. Setting this box causes the GO condition when the user chooses the pushbutton. Setting this box causes the pushbutton to automatically change size when its label changes size. Setting this box causes a CHOOSE event for this pushbutton when the user presses the ESC key. In other words, when this box is set, pressing the ESC key and choosing this pushbutton are equivalent actions. No matter which the user does, the CHOOSE trigger code you write executes. Only relevant if you use an iconic rather than a text label for this pushbutton. Clearing this box allows the 4GL Engine to modify the colors used by the image you use as a label and use system colors instead. This might produce an undesirable visual effect.
Cancel Button
Off
Convert 3D Colors
On
716
Description Setting this box causes this pushbutton to receive all RETURN key function events, regardless of whether it is selected at the time. Note that, while AppBuilder allows you to set this option for only one pushbutton per frameit clears any earlier settingit cannot detect the same setting in other frames. Setting this box adds the thicker margin around the pushbutton that indicates to the user that the object receives the RETURN key events. Setting this box causes the pushbutton to register an event when the user drags an object onto it. You must write the code needed to handle the event. Clearing this box causes the pushbutton to ignore attempts to choose it. Setting this box causes the pushbutton to display its label without any border indicating the clickable area, except when the cursor is inside that boundary. Setting this box causes the pushbutton not to respond to implicit requests to display itself. It will respond only to explicit requests. Setting this box causes the pushbutton not to indicate that it has the input focus, although the user can select it in the normal way. Setting this box removes the pushbutton from the enclosing frames traversal list. An object with this option set neither gains nor gives up the input focus in response to the user pressing the TAB key.
Default Style
Off
Drop Target
Off
Enable Flat
On Off
Hidden
Off
No Focus
Off
No Tab Stop
Off
Advanced properties The pushbutton object has only the standard advanced properties. See the Advanced properties section on page A9 for further information.
717
OpenEdge Development: AppBuilder Setting a pushbutton label You can choose to label your pushbuttons with text or an iconic image, but you cannot use both on the same object. To use a text label, simply type the new string into the Label field. You can even do this without opening the property sheet, if you wish. For your convenience, AppBuilder displays below the toolbar in its main window both the identifier and the label of a pushbutton object whenever it is selected. To use an icon (and override any text label): 1. Double-click on the square button marked Up. The dialog box opens:
2.
If the image file you wish to use is listed, select it and choose OK. If the Preview check box is on, the image you select will display in the open area to the right of the listing. If you are looking for a particular type of file (.ico, .bmp, etc.) you can choose to filter for only those files by selecting the appropriate item from the File Type drop-down list.
3.
If the image file is not listed, you can choose the Browse button to look for them. If you will often search certain other directories for image files, you can add the other directories to the drop-down list in the Directories combo box. Choose Edit Path to add a directory, or to modify the order in which they are listed.
718
8
Other Objects
This chapter covers the following objects: Simple (undefined) SmartObjects ActiveX (OCX) objects Static images Static text Timer objects (ActiveX)
AppBuilder supplies the unfinished Simple SmartObject to make development quicker and less effortful. You create one by choosing it from the list under FileNew. For detailed instructions about ADM and creating new SmartObjects, see OpenEdge Development: ADM and SmartObjects.
82
Other Objects AppBuilder allows you to select and position ActiveX objects in your GUI workspace in the same way you select and position native Progress 4GL and SmartObjects. To make this work, AppBuilder supplies a two-layer interface between the ActiveX object itself and the Progress 4GL world. The two layers are a control frame widget and a Control-Frame COM object. They translate between the Microsoft and Progress standards. Although the control frame interface is too general a mechanism to make the differences between ActiveX objects and 4GL fully transparent to you, this section provides a general overview of how to create and configure instances. For a full technical discussion of ActiveX objects in OpenEdge applications, see OpenEdge Development: Programming Interfaces manual.
2.
The dialog box that appears lists all ActiveX controls found within your development system. AppBuilder does not know whether the controls it finds are licensed. Before using an OCX object, verify you have a license:
83
OpenEdge Development: AppBuilder 3. Select the object you wish to use, and choose OK. Move your mouse cursor over a bare spot in your workspace and click to place the instance. Configure and size the object.
4.
2. 3.
You must perform some number of tasks that are object-dependent. In general, you must: 1. Assign a meaningful identifier to the objector, more exactly, to its control frame. You need do nothing with the identifier (the Name property) of the OCX object itself. Write the initialize-controls() procedure if you want to do special initialization. Select the events you wish to handle for this object and create procedures to do that. Size and position the object image within the workspace.
2. 3. 4.
The following walkthrough presumes you are placing an instance of the spin control that AppBuilder supplies in the Objects Palette. Follow these steps: 1. Create a window workspace and set the Message Area property, so that the workspace will be able to display messages conveniently. Click on the Spin Control tool icon in the Objects Palette:
2.
84
Other Objects 3. Move your mouse cursor over a bare spot in your workspace and click to place the instance. The default size will probably be too largetemporarily resize it now:
4.
Note that AppBuilders main window displays two object identifiers. Replace the editable identifier (CtrlFrame) with one that is more meaningful in the context of your application. For this example, use iSpinBox:
5.
Press F2 to run the workspace momentarily, which forces AppBuilder to create the
control_load() procedure. (This is not a step you need normally take; it is included here
only for the sake of the example.) Stop the run as soon as you like. Choose Window Code Section Editor. When the editor window opens, select Procedures as the Section, and control_load as the procedure:
85
ASSIGN chiSpinBox = iSpinBox:COM-HANDLE UIB_S = chiSpinBox:LoadControls( OCXFile, "iSpinBox":U ) . RUN initialize-controls IN THIS-PROCEDURE NO-ERROR.
AppBuilder creates the COM-HANDLE identifier by prepending the digraph ch to whatever identifier you assigned to the control frame object. In this case, the control frame identifier is iSpinBox, so the handle is chiSpinBox. AppBuilder initializes the handle by assigning the control frames COM-HANDLE property. AppBuilder then uses that COM-HANDLE to call LoadControls(), and finally inserts a generic call to the optional initialize-controls() routine. 6. Choose the New button. The New Procedure dialog box opens:
7.
Type in initialize-controls as the procedure name. (Be careful not to use an underscore, if you are used to writing C.) Set Type to Procedure, if necessary, and choose OK. Section Editor generates a new stub routine. Insert these lines of code:
8.
ASSIGN chiSpinBox:CSSpin:Value = 5 chiSpinBox:CSSpin:Max = 1000 chiSpinBox:CSSpin:Min = -500 chiSpinBox:CSSpin:Increment = 100. MESSAGE "Control Initialized" .
86
Other Objects Note how the code refers to the properties. The reference is not via the COM-HANDLE variable directly because that refers to the COM object layer in the adaptive interface, not to the ActiveX object itself. You must use an indirect reference, combining the COM-HANDLE , OCX, and property identifiers:
Note: The color-coding and all-caps appearance of certain properties, as shown here, is an artifact of the Section Editor settings. 9. Change Section to Definitions and define a variable to represent the current spin value:
DEFINE VARIABLE iCurrSpinValue AS INTEGER INITIAL 0. /* ** Note the initialization to 0. This is compile-time ** initialization, done for safetys sake. ** It is overridden at run time by the initialization to 5. */
87
OpenEdge Development: AppBuilder 10. Change Section to Triggers, and choose New. The dialog box will open:
11. Select OCX.SpinUp and choose OK. Section Editor generates a new stub event handler. Insert these lines of code to complete it:
12.
Choose New again, and create a trigger for the OCX.SpinDown event. Use the same code.
Run the workspace. You should see the spin control initialized to 5, and your Control Initialized message:
88
Other Objects When you operate the arrowhead buttons in the control, you should see the values change in increments of 100, to the limits 495 and 905:
2.
3. 4.
5.
89
Static images
Static image objects have no behavioral repertoire of their own, though you can use them as labels on pushbuttons and in similar contexts. Consider cultural differences when choosing images, especially when choosing images to use as icons and labels. What is perfectly clear to one person might be mystifying to another, or even offensive. Be especially wary of using visual puns: they almost never translate well. To create and configure a Static image element: 1. Click on the Image tool icon in the Objects Palette:
810
Other Objects 2. Move your mouse cursor to a bare spot in your workspace, and click to place the new Image object. Initially, the Image is undefined and looks like a smudged square:
3.
Select the object and choose ToolsProperty Sheet. The dialog box opens:
Minimal configuration At a minimum, you should do these things: Change the object identifier to one that more clearly conveys the purpose of this image in your application. Identify the actual image file.
811
To identify the image file: 1. Click on the smudge image. The Choose Image Files dialog box opens:
2. 3.
Select the image type desired. AppBuilder supports many different image formats. If the image you want to use is not listed, choose the Browse button to move to the correct directory. Select the filename. You will see a preview of the image, if you have the Preview box checked. For the purpose of this example, the image is that of the Objects Palette:
812
Other Objects Note that Preview shows as much of the image as possible, at the size it will appear when the application runs; AppBuilder does not rescale images here. If the image is the wrong size for your purposes, you must use some tool such as a graphics editor to rescale it before use, or must write code to rescale it under program control. 4. When you have the correct image file identified, choose OK to return to the property sheet. Some portion of the imagenot necessarily the whole thingappears in place of the smudge, as a token that you have successfully identified the image. The fully qualified filename of the image also appears, for your convenience:
5.
Set any other properties you consider appropriate, and choose OK to dismiss the property sheet. Drag the handles of the Image object to size and position it. Note that sizing incorrectly does not deform the Image, it clips it:
6.
813
OpenEdge Development: AppBuilder Help You can include a Tooltip string, if you wish. Under MS-Windows, the image object will display the Tooltip string whenever the user allows the mouse cursor to hover over the image. Geometry If you prefer to set the origin and size of the image explicitly rather than interactively, do so here. Miscellaneous properties (other settings) There are a few other properties you can change, if the default values do not meet your needs: Convert 3D colors Normally cleared. Setting this box causes AppBuilder to substitute platform-specific system colors in place of the actual colors in the Image. This often produces an unwelcome effect. Enable Normally set. Clearing this box causes the Image object to decline the input focus when offered. Hidden Normally cleared. Setting this box prevents the object from responding to implicit requests to show itself. You would have to include an explicit request. Remove from layout Cleared. Cannot be set except when defining an alternate layout. Retain shape Cleared. Can be set only if the option Stretch to Fit is set. Setting this box causes any stretch operation to maintain the original aspect ratio of the image. Does not apply to images that take the .ico file extension. Stretch to fit Normally cleared. Setting this box causes the image to be stretched to fit the available space. If Retain Shape is also set, the stretched image will maintain the original aspect ratio, even at the expense of fitting the space. Does not apply to images that take the .ico file extension. Transparent Normally cleared. Setting this box causes the image to clear all its background pixels to a transparent state, thus revealing whatever is underneath them. The image considers any pixel a background pixel if it is the same color as the pixel in its lower-left corner. Does not apply to images that take the .ico file extension.
Advanced properties The static image object has the normal minimum Advanced Properties. See the Advanced properties section on page A9 for more information.
814
Other Objects
Static text
Static text can play an important role in your application by calling attention to important objects, and by contributing to an overall corporate image, where appropriate. To create and configure a static text element: 1. Click on the Text tool icon in the Objects Palette:
2.
Move your mouse cursor to a bare spot in your workspace, and click to place the new text object. Select the object and choose ToolsProperty Sheet. The dialog box opens:
3.
4. 5.
Type in the text string the object will display. Choose a special typestyle and colors, if appropriate. See the Choosing colors section on page A11 and the Choosing a type style section on page A36 for more information. Add translation information, if necessary. See the String attributes section on page A30. Choose OK to dismiss the property sheet. Select the object and drag its handles to position and size it appropriately.
6.
7.
815
To create and configure a Timer instance: 1. Click on the OCX Timer tool icon in the Objects Palette:
2.
Move your cursor to some bare spot in your workspace and click to place the object. The Timer object has a design-time representation, but is invisible at run time. Change the Object identifier, shown in AppBuilders main window, to one that more clearly identifies the role of this timer in your application. Choose WindowOCX Property Editor to open the timers own property sheet. Set the Interval property to the desired integer frequency, representing thousandths of a second. For example, to get a Tick event every second, set Interval to 1000. For 1/10th of
3.
4. 5.
816
Other Objects a second, set Interval to 100, and for a tick every 5 seconds, set Interval to 5000. Close the window. 6. Open the Section Editor. Set the Section to Triggers, if necessary, and choose the New button to create a new event handler. Select OCX.Tick as the event, and choose OK. AppBuilder will create a stub event handler. Insert the code to perform the task for which you set the timer.
7.
/* ** */
bTickTock = NOT( bTickTock ). /* flip the value */ IF bTickTock THEN /* decide whether to tick or tock */ MESSAGE "Tick". ELSE MESSAGE "Tock".
When run, this toy event handler will alternately, and endlessly, write Tick or Tock to the message area of the window, presuming you have configured your window object to have a message area. The endless, synchronous looping action comes not from any loop code in the handler, but rather from the fact that the Timer itself is bound to the endlessly-operating system clock.
817
818
A
Frequently Used Dialogs
You will repeatedly encounter a number of dialog boxes as you use AppBuilder. While the context might change in which you find them, they themselves generally have a somewhat fixed format. This appendix serves as a reference for their use. This appendix contains the following dialog boxes: ActiveX control frame properties ADM pages manager Advanced procedure settings Advanced properties Colors selector and editor Custom lists naming Database field selector Method library includes list
OpenEdge Development: AppBuilder Procedure settings Properties window SmartLinks editor SmartInfo SmartObject properties String attributes Traversal-path editor Temp-tables maintenance Text style selector and editor
A2
Since control frames are adapters, they have relatively few properties, and not all of those have a perceptible effect. You can set those that exist, if you choose: Object You should change this identifier to better reflect the role of the ActiveX object in your application. Help ID If you plan to provide context-sensitive help for this object, enter a unique integer here as the identifier. Geometry If you prefer not to position and size the object interactively, you can set those values explicitly here instead. This dialog box uses character units; choose the Advanced button to set the same values using pixel units. Hidden Normally cleared. Setting this box prevents the ActiveX object from responding to implicit requests to display itself. No Tab Stop Normally cleared. Setting this box prevents the object from participating in the enclosing frame's traversal group. Unless an object is part of a traversal group, it can neither gain nor lose the input focus as the result of the user pressing the TAB key. Remove from layout Cleared. Cannot be set except when defining an alternate layout. Sensitive Normally set. Clearing this box causes the object to decline the input focus when offered.
A3
OpenEdge Development: AppBuilder Advanced properties Click on the Advanced button to open the Advanced Properties dialog box for this control frame:
The control frame does not have the properties Manual Highlight, Movable, Resizable, or Selectable. Nor does it offer you the ability to set alignment.
ADM paging allows you to multiplex your display space in useful ways. But once you have a complex, paged design in place, managing all the SmartObjects can be quite a difficult task. AppBuilder provides the Pages dialog box to help with that. Using the Pages dialog box, you can: A4 Review the list of SmartObjects assigned to a page. Set the Design and Startup pages. Move SmartObjects from one page to another.
Frequently Used Dialogs Delete SmartObjects from a page. Delete whole pages. Exchange the SmartObject contents of any two pages.
Note: The Pages dialog box only provides help with SmartObjects. Other objects, whether basic 4GL or ActiveX (OCX), are not shown by this dialog box. To open the Pages dialog box, choose ToolsProcedure Settings, or the Procedure Settings button on the toolbar, then choose the Pages button. Figure A1 shows the dialog box.
Show page contents Delete selected page and contents Set design Page Set start page
Figure A1:
Reviewing the list of SmartObjects assigned to a page To see the list of SmartObjects assigned to any page, click on the page number in the page in at the left side, or choose the Page button and enter the desired page number in the small dialog box that opens in response. Note: Choosing to set the page number through the Page button and dialog box only determines which page's contents are displayed in the right-hand list. It does not set the design page as it would do in other circumstances.
A5
OpenEdge Development: AppBuilder Setting the design or startup page The paging system identifies two special pages: Design Page Whenever you place a SmartObject, it always goes onto the current design page. Startup Page Whenever you run an application that uses ADM paging, the startup page is always the initial page displayed.
See the Special pages section on page 333 for a more complete discussion of the relationship between these pages and the default page 0 (zero). To alter where you place future SmartObjects, or which SmartObjects appear at startup, choose the Design... or Start... button as appropriate, and enter the desired number in the dialog box that appears. Note that the dialog boxes are identical apart from the text in their title bars. Be sure you are setting the appropriate value. Moving a SmartObject between two pages To move a SmartObject from one page to another, highlight the object in the listing for its current page, choose the Move to Page... button, enter the destination page number in the Move to Page dialog box, and choose OK. Note that you cannot move the object by cutting and pasting the list entry. Exchanging the contents of two pages To completely exchange the contents of two pages, one of which might be empty, in a single operation, highlight them both (shift-click to highlight the second) and then choose the Swap Pages button. If one of the pages is empty, the swap operation will be equivalent to a move-all operation. Deleting a SmartObject from a page To delete a SmartObject from a page, highlight the object in the listing and choose the Delete SmartObject button. Deleting a page and all its SmartObjects To delete a page and all SmartObjects on it, select the page number in the left-hand list, then choose the Delete button. A question box prompts you for confirmation. On completion, the page number will no longer appear in the list. You can easily recreate the page by assigning some SmartObject to it.
A6
Procedure type AppBuilder sets this by default to match the object type. In other words, when you open this dialog box for a SmartWindow, you will see SmartWindow listed here. If you wish, you can select a procedure type different to the object type, for example a SmartDataBrowser procedure for a SmartWindow type. For more information, see OpenEdge Development: ADM and SmartObjects.
A7
OpenEdge Development: AppBuilder Supported SmartLinks Lists the SmartLink types an object knows how to handle as originator, recipient, or both. As shown in Figure A2, a SmartDialog can handle either end of a Data or Update link, and knows how to be on the receiving end of a Page link. You can add additional link types to this list, if you are prepared to write the code to support them. For further information, see OpenEdge Development: ADM and SmartObjects. File type Determines the filename suffix when the file is saved. For SmartObject sources, this is always .w. Template Normally cleared. Checking this box causes certain information in the file to be automatically stripped out before saving, making the file more generic. If left unchecked, the file is saved as a master file rather than a template. Add Fields to Determines where database fields will be added: to the Frame Query, the procedure's external table, if any, or to neither. Generally you should not alter the default setting, which is Frame Query. Run Option: Persistent Only Normally set. When set, any attempt to run the object nonpersistently fails with an error message. This is true of all SmartObjects except the SmartDialog. Allow Drawing of Determines what sort of objects can be made children of this object. If you clear, for example, the Basic Objects box, AppBuilder will refuse to allow you to place basic 4GL objects onto this workspace. You will be able to choose a 4GL object tool from the Objects Palette, but not release such objects onto the workspace.
A8
Advanced properties
All basic 4GL objects have an Advanced Properties dialog box under the Advanced button in their property sheet. Most advanced properties are the same for all widgets. The Advanced Properties dialog box for a pushbutton is shown here:
Change any of the default settings that do not meet your needs: Help The text you enter here appears in the status area of the enclosing window whenever this object has focus. If you enter no special text, a default string appears instead. If the enclosing window has no status area, no text appears. Private Data AppBuilder writes out the contents of this area as the value for the PRIVATE-DATA attribute. You can write code to use this data in any way that meets your needs. Generated Code Layout Unit Choose whether AppBuilder uses character (the default) or pixel units when it generates the source statements to create and manage this object. Custom Lists Custom lists are a way to refer to many objects with a single identifier. The six lists shown always belong to the nearest supporting frame, not to this object. You can add this object to any or all of the lists, as you choose. If you move this object so that it is supported by a different frame, you will have to create new associations if you want them.
A9
OpenEdge Development: AppBuilder Geometry If you prefer to set the XY origin and size using explicit pixel units, you can do that here. You can also choose whether to align to the left or right, but this has no effect other than to change the number used for the X origin. Manual Highlight Normally cleared. Setting this box allows you to write code to define a custom highlight effect. Your custom effect is applied whenever this object has input focus. Movable Normally cleared. Setting this box makes it impossible for the user to give this object input focus by clicking with the mouse. Instead, the user can use the mouse to drag the object body to a different position within the bounds of the enclosing frame. Note that if the object has a separate label, as in the case of a fill-in, the label does not move. The result is that the object and its label can be visually separated from one another. Resizable Normally cleared. Setting this box makes it impossible for the user to give this object input focus by clicking with the mouse. Instead, if the selectable box is also set, clicking with the mouse causes handles to appear so that the user can resize the object. Sync with Master If this is an alternate layout, choosing this button resets the characteristics of this object in this layout to agree with its characteristics in the main layout. For example, if the width were 12 characters in the alternate layout but 14 in the main layout, choosing Sync would cause the object to be 14 characters wide in both layouts.
Almost every object with a visible run-time representation has a foreground and background color that you can set. Whether your settings will override any system defaults is platform-dependent. For example, you can set the title color for a frame object, but such settings have no effect under MS-Windows. It is good usability practice to be sparing with color. Too much color, or too many colors, can create a recreational or even childlike impression on the user. This might not be the most desirable outcome, if your application is one for office use. But you need not avoid color changes altogether. Used carefully, special color changes can help focus the user's attention in appropriate ways. This improves the usability of your product and, often, its marketability. A10
Frequently Used Dialogs Careful use of color can also be a defining element in a corporate identity program, allowing you to create semicustom software packages with little extra effort. Progress widgets that display data use the foreground and background colors for that purpose. They display their data in the foreground color against the background color. In the case of data browser widgets, you can also choose a color for the internal lines separating rows and columns. Progress widgets such as the rectangle use the foreground color for their border, and the background color for the fill, if filled.
Choosing colors
Select colors with the Color Selector dialog box. To set foreground and background data colors for an object: 1. Select the object and choose ToolsColor, or open the property sheet and choose the Colors button (the crayons). The Color Selector dialog box opens:
Selects set of
colors
Sixteen colors remains the baseline standard under MS-Windows, and those colors occupy slots 0 through 15 in the Progress color table. The boxes labeled with the standard Progress symbol for the unknown value (undefined state)the question mark (?)represent the default colors for the object. The default colors are those assigned by the object's parent, but are most often the colors shown in the example: black (slot 0) foreground and light gray (slot 8) background. 2. Click on a new color for the desired context. If you wish to use a color not in the default set, see the Defining new colors section on page A12. A11
OpenEdge Development: AppBuilder 3. If the object whose colors you are changing must be readable (text, instrumentation, graphs, etc.), verify that you have chosen a good combination by examining the text in the Sample rectangle. Text is always less readable on a monitor than on paper, so it is good practice to change your design choices rather than compromise readability. While good contrast is the most important factor over which you have some control, other factors also come into play, including font size and style. There are also other factors in play over which you as the programmer have no controlthe characteristics of the eventual user's monitor being the most important. For this reason, you should choose the most highly readable combinations whenever possible.
A12
Frequently Used Dialogs Table A1: Slot Progress color table Progress color name (2 of 2) Red-Green-Blue (RGB) values Decimal 9 10 11 12 13 14 15 Blue Green Turquoise Red Pink Yellow White 0 0 0 255 255 255 255 0 255 255 0 0 255 255 255 0 255 0 255 0 255 00 00 00 FF FF FF FF Hex 00 FF FF 00 00 FF FF FF 00 FF 00 FF 00 FF
You can increase the colors available to your applicationfor example, to create a special corporate color schemeby defining colors on slots 16 through 255 (16 through 127 for character mode), although not all objects can accept colors from slots above 15. You can also change the colors defined for slots 0 through 15 (for example, substituting a green for a red), though for compatibility reasons this is discouraged. Note that changes made to the color table are permanent the moment they are made. Clicking Cancel does not discard the changes. To restore earlier colors, you must recreate them. To add a new color to the table: 1. Click the arrowhead button to bring the next set of 16 color slots into view. They are all defined as black, initially.
A13
OpenEdge Development: AppBuilder 2. Double-click the first undefined slot (slot 16, unless you have already defined additional colors for this application, or for another application during this OpenEdge session). It does not matter whether you click the foreground or the background slotthey are really the same slot, and when you define a color, it appears in both places. The standard MS-Windows color-editor dialog box opens:
3.
If none of the existing colors meets your needs, you can modify any or all of the 16 colors in the Custom colors bank. These are not the same 16 colors that appear in the default slots. Click on the color you wish to modify. The color in that cell will immediately appear in the large color/solid swatch, its HSL and RGB values (HSL and RGB are just different color-notation schemes) appears in the readouts, and the cursors showing where the color is in the color space will reposition themselves appropriately, as shown here:
A14
Frequently Used Dialogs 4. To create the new color, you can: Move the cursors to new positions in the rainbow color space. The larger space represents the qualities of Hue (red, green, etc.) and saturation/intensity (bright, rich color versus muted, grayish color). The long, narrow space to the right represents luminance or value (in paint or printer's ink, the amount of white or black (but not both) in the color; on a monitor, the amount of energy exciting the phosphor). Set the HSL or RGB values explicitly. This is a particularly useful method if you are trying to work to a known standard, or reproduce colors for which you know those values.
5.
When the color is correct, click Add to Custom Colors to preserve it:
6.
If you wish to define additional custom colors, select another Custom Color cell and repeat Step 4 and Step 5. When you are finished, select a color cell and click OK. The color editor dialog box closes, and the selected color is assigned to the color table.
A15
Custom lists would be called macros in some other languages, such as C. They provide a convenient way to refer to many objects with a single identifier. Each instance of a procedure or procedure-based object, such as a SmartWindow, has its own set of six custom lists. When the preprocessor encounters a reference to a custom list in source code, it replaces that reference with all the identifiers associated with that particular list.
Figure A3:
The dialog box shown in Figure A3 allows you to give more meaningful names to the lists that belong to a particular procedure. For example, if you create an area within a SmartWindow that has widgets dealing with order entry, and you assign them to the first list, you might give that first list the name OrderEntry or Order_Entry (embedded spaces are not allowed in the names you give) so as to more easily keep track of what you are doing. To change the name of a list, merely type in the new name. Your change will be reflected in the list of lists in the Procedure Settings dialog box, and in the properties dialog boxes for all the basic widgets subordinate to the procedure. To continue the earlier example, if you place a pushbutton widget in the SmartWindow, and open its Advanced Properties dialog box, you will now see Order_Entry as the name of the first Custom List.
A16
The Database Field Selector dialog box allows you to associate a database field with a data-capturing widget such as a fill-in, toggle box, etc. By choosing appropriate widgets for such associations and adding the necessary additional supporting code, you can create layouts that are more subtly informative and helpful than those where you only use, for example, a data browser with its tabular display. To associate a database field with a data-capturing widget: 1. Select the widget and choose ToolsProperty Sheet. When the dialog box opens, choose the Database Field button (the browser with a field coming out). The Field Selector dialog box opens:
A17
OpenEdge Development: AppBuilder 2. Select, as appropriate, a database, a table, and a field to be associated with the widget. Choose OK to dismiss the dialog box. The Data Field Defaults dialog box immediately opens in its place:
3.
Choose the control type: Database Field Default. Causes the widget to be associated with the database field you chose in Step 2. Local Variable Causes the widget to be associated with a local variable. Like [chosen table.field] The chosen table.field shown is the one you selected in Step 2. Choosing the option causes the widget to inherit any triggers defined for the database field. If there are no triggers to inherit, you can define those you need. But if the object inherits even one trigger, you cannot define additional ones.
4.
If you choose Database Field or Like, you can also choose whether to inherit some display characteristics from the data source: Label Creates a label for the widget based on the field name. Format String Ensures that the format of the widget is the same as that of the field. Help String Uses the help string associated with the database field.
5.
Choose OK to dismiss the dialog box. Your widget is now associated with the storage unit (database field or local variable) you chose.
A18
The Method Libraries dialog box lists all the header files relevant to the current external procedure. If you modify the behavior of a SmartObject, you must add references to any additional header files required by your changes. To change the list of include files: 1. Choose ToolsProcedure Settings. When that dialog box opens, click the Method Libraries button (bookcase icon) in the upper-right corner. The Method Libraries dialog box opens:
2.
3.
Enter the filename to be added to the list, or choose the Files button to browse for the file. Note that the curly bracket delimiters are supplied automatically when you add a reference. You might need to use the Move Up/Move Down buttons to adjust the order in which files are included.
To modify an entry, select it and click Modify. A nearly identical editing dialog box opens, with the entry ready for editing. To delete an entry, select it and click Delete. A19
Procedure settings
Broadly speaking, procedure settings deal with the nonvisual aspects of objects that are based on external procedures. In the case of a SmartWindow, for example, they are aggregated into seven groups, each represented by a dialog box discussed in this appendix: Main (this section) Advanced procedure settings Method libraries Custom lists Temp-tables SmartLinks Pages
Other procedure based objects, including other SmartObjects, will have a different number of groups, depending on their nature. For example, a SmartDataObject will not have a Pages button because it is not a SmartContainer and thus does not support a paging context of its own. To open the main Procedure Settings dialog box for a procedure-based object, you must first open the master object itself, if there is one. Choose FileOpen and select the object or, if the object is a SmartObject instance, click the menu button and choose Edit Master.
A20
Frequently Used Dialogs When the master object is open and selected, choose ToolsProcedure Settings, or the Procedure Settings button from the toolbar. A dialog box similar to that in Figure A4 opens.
Figure A4:
The main Procedure Settings dialog box is used for all procedure level objects. Some of the fields will therefore not apply to a particular object type, either because the qualities are predefined and fixed, or because they are entirely irrelevant. The settings shown here are those for a SmartWindow: Type Reflects the type of subprogram being used for this object. Although you can reset this value in the Advanced dialog box, see OpenEdge Development: ADM and SmartObjects for more information. File Name Reflects the name of the .w file on disk. This is undefined until you save the object. You can change this value at any time with the usual MS-Windows toolsthe Explorer file system interface, for example. Description A general-purpose, multi-line field for comments about this object. OCX Binary If you include any ActiveX objects in your SmartContainer's population, their properties are saved in a file, by default the .w file itself. If you prefer, you can specify a different file here. Compile in By default, the .r object file that results from compilation will be stored in the same directory as the .w source. If you prefer, you can specify a different directory here.
A21
OpenEdge Development: AppBuilder Run Persistent from AppBuilder Determines whether the object procedure will preserve their data and interface contexts when the RUN statement that invoked them completes execution. Persistent contexts remain allocated until explicitly released, or until the end of the OpenEdge session. In general, you should check this box for all SmartObjects other than SmartDialog. Compile on Save Determines whether AppBuilder produces an object file when it saves the current source file, rather than recompiling whenever an instance is needed at run time. Checking this box is generally better, but because AppBuilder automatically compiles whenever changes are made, the advantages are not clear-cut. AppServer Aware Determines whether AppBuilder includes the header files required for connecting to an AppServer service, making requests of the service, and later disconnects from the service. In an ADM-compliant application, AppServer awareness is a property of the SmartDataObject, and generally not needed by other objects.
Properties window
To open this dialog box, choose WindowProperties Window. It displays certain properties for the currently selected object. The displayed properties are different for different object types. If more than one object is currently selected, it displays only those property types they have in common (generally no more than their dimensions.) Figure A5 shows the Properties Window for a control frame, such as that automatically supplied by AppBuilder when you place an OCX object. New value Discard change Accept change
Figure A5:
Properties Window
A22
To use this dialog box to make changes to one or more selected objects: 1. 2. 3. Select the object or objects. Choose WindowProperties Window. The dialog box opens. Select the line item you wish to change. If necessary, first click the + sign in the leftmost column to expand and see the values for a category. The current value appears in the fill-in. Depending on the data type, the fill-in might change to a combo box, or display a button at the right side with the ... convention that indicates a dialog box will open. Enter the new value for the field accordingly. Click on the check-mark button to accept the change you made, or on the x-out button to discard it. When finished, click on the Dismiss button at the right side of the title bar to dismiss the dialog box.
4.
5.
6.
SmartLinks editor
The button shown here is available in the Procedure Settings dialog box.
SmartLinks are the well-defined ADM communication pathways between SmartObjects. Although AppBuilder provides Advisor dialog boxes to semiautomatically create links between SmartObjects when you add them to a SmartContainer, there will be times when you will find it desirable or necessary to edit links by hand.
A23
OpenEdge Development: AppBuilder The SmartLinks editor shown in Figure A6 helps you with this task.
Figure A6:
You can open this editor in either of these ways: Click on the menu button of a SmartObject and choose the SmartLinks menu item. Choose ToolsProcedure Settings and then click on the SmartLinks button (the chain-links icon).
Regardless of where you start when you open the editor dialog box, it always displays links from the standpoint of the current SmartContainer. Any references to THIS-PROCEDURE are always references to that current SmartContainer, not to any other SmartObject that might be selected:
A24
Frequently Used Dialogs The SmartLinks dialog box provides extensive filtering capabilities. By default, the editor displays all current links. If the list is confusingly large, you can subset it by filtering on a particular source, link type, or destination, or any combination. You can also choose to sort the list by source, link type, or destination. To add a new SmartLink: 1. Choose the Add button. The Add a SmartLink dialog box opens:
2.
All SmartObjects local to the current SmartContainer, including the SmartContainer itself (THIS-PROCEDURE), are listed as possible sources and targets. Select one of them to be the source of the new SmartLink. If you are not sure what types of SmartLink are supported by the selected object, choose the Info on Source button. The SmartInfo dialog box opens. See the SmartInfo section on page A26 for more information.
3.
Selecting the source of the new SmartLink displays in the LinkType field the SmartLink types for which the selected object can act as source. Choose the type of SmartLink to add. If you choose New, a dialog box opens and requires you to type in the identifier for the new type of SmartLink. You must be prepared to write code to manage such application-specific link types yourself. See OpenEdge Development: ADM and SmartObjects for information about creating and managing new types of SmartLinks.
A25
OpenEdge Development: AppBuilder 4. Choose the target for the new link. If the target you choose cannot deal with links of the type you selected, an Advisor appears asking that you confirm your choice or elect not to create the link:
5.
Repeat Step 2, Step 3, and Step 4 until you have added all the necessary links. Choose OK to dismiss the Add dialog. Your new links appear in the SmartLinks list.
You can modify an existing link by selecting it and choosing the Modify button. The process is otherwise the same. When you dismiss the Modify dialog box, the link you selected will reflect the changes you made. To delete a SmartLink, select it and choose the Remove button.
SmartInfo
AppBuilder provides information about a number of SmartObject properties in the two SmartInfo dialog boxes. You can open the main SmartInfo dialog box in either of these ways: Select the SmartObject, choose ToolsProperty Sheet, and then click the SmartInfo button (the i icon). Click the menu button for the SmartObject, and choose the SmartInfo menu item.
A26
This dialog box provides the filename of the object's master, its class (in the example, SmartDataObject), and a list of supported link types, including directionality. A number of other properties for the selected SmartObject can be inspected by choosing the Properties button. This read-only dialog box opens to present the properties:
A27
SmartObject properties
A SmartObject has few editable properties of its own, although the basic objects that make up its run-time representation, if any, have all the properties associated with their kind. There is no Advanced Properties dialog box for a SmartObject as such, though there is for any widget the object uses for its run-time representation. You can open the Property Sheet for a SmartObject other than a SmartWindow, SmartDialog, or SmartFrame by any of these methods: Clicking its menu button and selecting the Properties menu item. Right-clicking on the object and selecting the Properties menu item. Selecting the object and choosing ToolsProperty Sheet.
This Property Sheet dialog box combines information about both the master object and the particular selected instance. The fields are: Instance handle identifier You should change this to more clearly reflect the role of the object in your application. Object type identifier This is always a read-only field; it merely identifies the class to which this object belongs. Filename of the master Choosing the File pushbutton opens a dialog box that allows you to associate a different master with this instance. Be cautious about using this ability.
A28
Frequently Used Dialogs List of instance properties The nature of the properties varies with the object class. See the relevant chapter of this manual for a description of the instance properties pertaining to a particular SmartObject class. Choose the Edit button to change the editable properties. Parameterize as variable check box Normally cleared. Setting this box causes AppBuilder to treat this object as a placeholder for its class rather than as an instance of a specific master object. By default, every instance of a SmartObject represents a particular master object with a defined set of behaviors. For example, a given SmartDataBrowser instance is constrained to display a certain set of fields, generally from a particular database, and only those fields. Under some circumstances, you might find it advantageous to be able to treat a SmartObject instance as a design-time placeholder, instead. That would allow you to defer the choice of master until run time, when you could choose, load, and run a situation-specific instance under program control. See the Creating a SmartObject placeholder section on page A29 for information about how to do this.
Type in the identifier for the variable you will use to control which master gets loaded at run time. 3. Select the SmartContainer that supports the new placeholder. Open the Section editor to the Definitions area, and define the variable. Add additional code in the appropriate section to resolve the reference.
A29
String attributes
The button shown here is available in the Property Sheet for widgets for which it is relevant.
This dialog box takes different forms, depending on the object. For example, Figure A7 shows the String Attributes dialog box for a static text object, and Figure A8 the same dialog box for a combo box object.
Figure A7:
Figure A8:
The string attributes you include here govern display and translation characteristics for the strings. Note that you also set attributes for the associated help and tooltip strings here.
A30
Frequently Used Dialogs As long as they do not contradict one another, you can include several attributes. The available attributes are: L R C T Orientation: Left, Right, Centered, or Trimmed. Use only 1 of these. The default varies with the role of the string. U Untranslatable. Add this marker to prevent the OpenEdge translation utility from processing the string. By default, the utility processes all strings. 9999 The INTEGER size of the space to be allocated in the literals table for this string. The default size is the length of the string itself, and the maximum size is 5120 characters. If the string is to be translated, and you believe the translation will produce a longer string, you should allow for that increased space here.
To specify one or more values, simply type them into the appropriate field.
Traversal-path editor
The buttons shown here are available in the Property Sheet dialog box for frame and dialog box objects.
Under MS-Windows, repeatedly pressing the TAB key causes the input focus to shift from one widget to another within a frame. The default order in which the widgets are visited is left-to-right, top-to-bottom. You can change this default order using the Tab Editor. The Tab Editor is available through the property sheet for any frame or dialog widget, including the widgets managed by SmartFrames and SmartDialogs.
A31
OpenEdge Development: AppBuilder Choose the Tab Editor button (back-and-forth arrows) to open the Editor dialog box, shown in Figure A9.
Figure A9:
The three areas of interest are: The combo box that displays the current Tabbing Option. The list of widgets that will be traversed. The buttons that control how the items in the list are ordered.
Initially, the Tabbing Option is set to Default. In addition to the Default ordering, there are four predefined orderings, plus Custom. One of the predefined orderings will be the same as the Default order. In English-speaking countries among others, this is the Left-to-Right By Rows order. To impose one of the predefined traversal orderings, select it from the list of options. The order of the widgets in the objects list changes accordingly. To define a special traversal order: 1. 2. Select Custom as the Tabbing Option. This enables the four Move buttons. Use the Move buttons to reorder the widgets in the objects list. The items will be visited in the order in which they appear in this list. Choose OK.
3. A32
Temp-tables maintenance
The button shown here is available in the Procedure Settings dialog box. The editor is also called automatically when you choose to define a temp-table in a SmartDataObject.
Temp-tables are temporary (scratch) tables. You might choose to create and use a temp-table to avoid the overhead of manipulating a large original table. By selecting out only those records that are of interest, and creating from that subset a temp-table, you can make subsequent processing faster or more convenient by some large factor. Temp-tables have these characteristics: Single-user Unlike regular database tables, you cannot make the same temp-table available to more than one user. They are session-bound. Temporary Temp-tables never outlast the session in which they are created, and might have a much shorter lifespan than that. You can choose to make the table: Local (Default). Creates a new local table. A local table is available only to the defining procedure, and is destroyed when that procedure terminates. Shared Specifies that the table is not to be created, but is being shared by the calling procedure that did create it, within the current session. New Shared Creates a new table and allows it to be shared by called procedures in the same session, if they declare the table Shared. New Global Shared Creates a new table and allows it to be shared by all other procedures in the session that also declare the table New Global Shared. Note that although all procedures must use the New syntax, the table is allocated only once.
Temp-tables can be declared NO-UNDO, which improves performance by eliminating the overhead of journaling. In AppBuilder, temp-tables are created NO-UNDO by default. Temporary table storage can be allocated in memory or on disk. There are some differences in the characteristics of a table depending on where it resides. See OpenEdge Development: Progress 4GL Handbook for a discussion of these differences.
A33
To allocate a temp-table: 1. Choose ToolsProcedure Settings. When that dialog box opens, click the Temp-Tables button (the drum icon). The Temp-Table Maintenance dialog box opens:
2.
Click Add to create a temp-table. The Table Selector dialog box opens, showing the currently connected databases:
A34
Frequently Used Dialogs 3. Choose a database, if necessary, and the table you wish to copy from. Click OK. The Selector dialog box closes and your selection appears in the Temp-Table Maintenance dialog box:
Note that AppBuilder always defines the temp-table as being LIKE the reference table. 4. Modify the default properties, if they do not suit your purposes, and click OK. The default properties are: Allocation on disk (temp-table) rather than memory (buffer). Local scope rather than Shared or Global Shared.
NO-UNDO.
Name same as reference-table name. You might wish to change this to more clearly identify the reason you are using a temporary copy of the table. No additional fields. You can define additional fields, but they are not equivalent in all ways to the actual fields in the database records. You cannot refer to additional fields in a query, for example.
Note that this editor does not create code to populate the table. You must do that by hand, if the object in your application expects to find records in the table.
A35
AppBuilder provides a fonts table similar in principle to its color table. Rather than specify each change of type style-font, weight and slant, point size, and attributes such as underlining on the fly, you define them in advance, with each definition occupying a slot in the fonts table. You then apply all characteristics at once by specifying a slot number. As with the use of color, be sparing with font changes. Although at one time it was very common to use many sizes and styles of type in a single composition, today too many font changes can create an unfavorable impression on the user. Used carefully, special changes in the type can help focus the user's attention in a good way. Because of readability issues, fonts need to be selected with even more care than colors if they are to give the desired result. Many companies use one or more particular fonts as part of their corporate identity program. If you are able to use those fonts too, without compromising readability, you might be able to gain a competitive advantage when marketing your software to such a company. Type style selections apply to all text displayed in connection with a given widget. For example, you cannot choose one style for the column labels on a Browse widget and another style for the data it displays. Whatever style you select will be applied to both.
A36
To assign a type style to a widget: 1. Open the property sheet for the widget. If the widget is being displayed and managed by a SmartObject, you must click the object's menu button and choose Edit Master to get access to that widget. When the Property Sheet dialog box opens, click the type style button (the AAa icon). The Choose Font dialog box opens:
2.
3.
If necessary, click on the arrowhead buttons until the font sample you want to use is in view. Click it, and the thick outline appears, indicating selection. Click OK to dismiss the Choose dialog box. Click OK to dismiss the property sheet. You should see your choice of type style reflected in the widget.
4.
A37
To define a new type style or edit an existing one: 1. Open the property sheet for a widget. Click on the Type style button (the AAa icon). The Choose Font dialog box opens:
2.
Unless you also want to change the font being used for the current widget, make a note of which slot is current so that you can restore it before you exit this font-editing session. Slots 0 through 7 have predefined styles that are not editable. You can assign styles to slots 8 through 255. Click the right arrowhead button until slot 8 appears. Double-click slot 8. The Font dialog box opens:
3.
4.
A38
Frequently Used Dialogs 5. Choose a face, a weight and slant, a point size, and attributes (underline, etc.). Unless you are creating an application for a market that requires a special encoding (Greek, Cyrillic, etc.), be sure the Script setting is Western. Caution: Remember that the fonts being presented to you by this dialog box are those you have installed on your development system. The fonts you choose here will not necessarily be available to the users of your application unless you provide them as part of your software distribution package. Unless you are prepared to do that, you should choose only those fonts that you know are supplied with the operating system. 6. Click OK to dismiss the Font dialog box. Your choices are reflected in the sample text in the slot. In this example, it shows the result of choosing 10 point Arial Bold with underlining:
7.
Unless you want your definition discarded at the end of the current AppBuilder session, click Save Font Settings to make your definition permanent. Click on the slot you noted in Step 2. If you want to change the type style for the current widget, click on that slot instead. Click on OK to dismiss the Choose Font dialog box. Click on OK to dismiss the Property Sheet dialog box.
8.
9.
A39
A40
B
Multiple Layouts
This appendix describes how to use multiple layouts to build your applications. In addition, it explains how to use AppBuilder to run and test applications for a character-based user interface. This appendix discusses the following topics: Why use multiple layouts? What is a layout? Two types of layouts Creating alternate layouts Selecting a predefined alternate layout Modifying layouts with layout inheritance How multiple layouts work: a look at the code Alternate layout limitations Switching between layouts at run time Simulating character applications Running character applications Multiple layouts for SmartObjects
For more information on multiple layouts and international considerations, see OpenEdge Development: Internationalizing Applications.
What is a layout?
A layout can be thought of as a collection of objects and associated property settings. These property settings determine how the objects appear when you run the application. Each layout has a name and an associated run-time expression. Run-time expressions evaluate to TRUE or FALSE, and determine which layout is presented during a specific session. Typically the same set of run-time expressions will appear for all procedure files in an application. For SmartObjects, layouts are typically associated with values of the ObjectLayout instance property.
B2
Multiple Layouts When you run a procedure file, it evaluates the run-time expressions (if any) for the available layouts and, if a layouts expression evaluates to TRUE, uses that layout. For a SmartObject, this run-time expression determines the setting of the DefaultLayout property. If the SmartObject has no ObjectLayout property setting, it uses the DefaultLayout property setting to determine the layout. When the procedure file determines that it will use a particular layout, the procedure file executes for that layout a CASE statement that contains all of the property settings assigned for the layout. The AppBuilder generates a CASE statement that contains an entry for each layout in the procedure file. The CASE statement is contained within the internal procedure named {&LAYOUT-VARIABLE} variables. This procedure name resolves to the name of the procedure files window, with -Layouts appended. For example, if the window name is WINDOW-1, the name of this procedure is WINDOW-1-Layouts. For more information about how layouts are implemented within a procedure file, see the How multiple layouts work: a look at the code section on page B12. At design time, a layout is visually manifested in the design window. When you switch between layouts in the design window, the AppBuilder alters the appearance of the design window to match the characteristics of the new layout.
Master layout
The master layout is what the AppBuilder regards as the main layout of the procedure file. When you first create a procedure file, you see the master layout in the design window. If you do not create any alternate layouts, you see the master layout when you run the procedure file. You also see the master layout if the run-time expressions for all of the alternate layouts evaluate to FALSE.
B3
OpenEdge Development: AppBuilder It is helpful to think of the master layout as the compile-time layout, or the layout as it appears to the Progress Compiler. Unlike other layouts, the master layout does not necessarily require additional property assignments. Alternate layouts, in contrast, are implemented solely through the use of run-time property assignments. The master layout consists of the following elements: All of the static widget definitions generated by the AppBuilder in the procedure file. All of the property assignments, if any, in the Runtime Attributes and AppBuilder Settings code section. The procedure files window (a dynamic widget) and any ActiveX control frames. A CASE statement entry for Master Layout.
The master layout never has a run-time expression associated with it. If desirable, you can run the Master Layout entry or any other CASE statement entry from within the procedure file. This allows you to alternate programmatically between layouts at run time. For more information, see the Switching between layouts at run time section on page B19.
Alternate layout
An alternate layout is a layout that you create for a specific run-time instance. For each alternate layout that you create, you supply a name, an optional run-time expression, and the emulation style (graphical or character). At run time, the procedure file tests any run-time expression, and if the expression evaluates to TRUE, the procedure file uses that layout, executing the appropriate CASE statement entry. If the procedure file is a SmartObject that has an ObjectLayout property setting, the SmartObject uses the specified layout, executing the appropriate CASE statement entry. The procedure file thus determines the layout before enabling or displaying any widgets. For more information about creating an alternate layout, see the Creating alternate layouts section on page B7. Standard layouts Standard layouts are alternate layouts with predefined run-time expressions. The AppBuilder predefines these expressions for three primary OpenEdge run-time environments: character, MS-Windows, and MS-WIN95.
B4
Multiple Layouts Table B1 lists the standard layouts. Table B1: Standard layouts and run-time expressions Run-time expression
SESSION:DISPLAY-TYPE = TTY:U SESSION:WINDOW-SYSTEM = MS-WINDOWS:U SESSION:WINDOW-SYSTEM = MS-WIN95:U
If you decide to use a standard layout, you cannot change the layouts name or run-time expression. Layouts at design time When you create or select an alternate layout, the AppBuilder changes the design window to assume the alternate layouts characteristics. The AppBuilder also reflects the characteristics of the layout in the property sheets of its widgets. Once widgets are in an alternate layout, you can then manipulate them within the layout or change their properties. Within an alternate layout, you can modify some but not all of the widgets properties. For more information, see the Alternate layout limitations section on page B17. The changes you make in an alternate layout visually affect that layout only, but there are some exceptions. For more information, see the Modifying layouts with layout inheritance section on page B9. For example, suppose you start with the master layout, as shown in Figure B1.
Figure B1:
Master layout
B5
OpenEdge Development: AppBuilder Now, suppose that you choose the Standard Character layout option in the Alternate Layout dialog box. The AppBuilder now changes the design window to look like the one in Figure B2.
Figure B2:
Notice that image disappears and the buttons appear as text. Also, the grid changes to reflect the number of lines in a character terminal. For more information, see the Simulating character applications section on page B20. All property sheets for the widgets in this layout reflect the characteristics of the new layout. In this example, the property sheet of the window reflects a change in size: character windows are not resizable and have a default size of 80 x 21 character units. Also, since the image does not appear in this layout, you cannot access its property sheet from within the layout. However, you can use the List Objects dialog box to access the images property sheet. For more information about the List Objects dialog box, see the Tool bar section on page 218. In general, when you initially create an alternate layout, the AppBuilder tries to keep all objects and properties unchanged from the prior layout. Alternate layout scope When you create a layout, it is available for all procedure files that you edit in the AppBuilder session. You do not have to define the layout individually for every procedure file that uses it. The AppBuilder maintains a cumulative list of nonstandard layouts for each AppBuilder session. This list expands as you edit procedure files with previously defined layouts. Restarting the AppBuilder resets the list to include only the standard layouts and those alternate layouts used by the procedure files that you open. B6
Multiple Layouts
2.
Choose the New button. The New Layout Name dialog box appears:
3.
Type the name of the layout, then choose OK. The AppBuilder returns to the Alternate Layout dialog box. Activate the GUI-based radio button to create a graphical look for the design window. Activate the Character-based radio button to simulate a character design window.
4.
B7
OpenEdge Development: AppBuilder 5. Type the run-time expression to test in the Expression panel, then choose OK. Any valid Progress expression that resolves to a LOGICAL value is acceptable. However, if you use a character string within the expression, place the string in single quotes ( ) not double quotes ( ). If you need to use embedded quotation marks, escape the quotation marks with the tilde (~) character. This convention helps the AppBuilder to generate code that avoids compiler ambiguities. When you enter an expression, you can optionally enter a comment that describes the alternate layout. The AppBuilder places this comment in the Runtime Properties and AppBuilder Settings section of the procedure file, where other developers can see it. Enter the comment by typing it in the Comment fill-in field in the Custom Layout dialog box. You have finished creating the alternate layout. The AppBuilder redisplays your design window, with the name of the alternate layout in the title bar. Note: The Alternate Layout dialog box allows you to add, delete, or modify only one alternate layout at a time.
2. 3.
If you select a standard layout, you cannot change its expression or name. However, you can modify the expression and name of a nonstandard alternate layout.
B8
Multiple Layouts
B9
OpenEdge Development: AppBuilder When you create a character alternate layout, the AppBuilder changes the appearance of the design window and the widgets within the design window to fit within the limitations of a character environment. Thus, buttons can only be one line high, and the character window has a default width of 80 character units and a height of 21 character units. For more information, see the Simulating character applications section on page B20. Overriding layout inheritance If you change a property of a widget in an alternate layout, that layout no longer inherits the property from the master layout unless you explicitly re-establish layout inheritance. Also, if you insert a widget into an alternate layout, or delete a widget from an alternate layout, you disinherit the widget from the master layout. There are two special cases: If you change either coordinate of a widgets position, the other coordinate is disinherited as well. You must synchronize both coordinates with the master layout to re-establish layout inheritance. If you change either dimension of a widget, the other dimension is disinherited as well. You must synchronize both dimensions to re-establish layout inheritance.
B10
Multiple Layouts
To re-establish layout inheritance: 1. While in an alternate layout, open the advanced property sheet for the widget whose layout inheritance is to be re-established, then choose the Sync With Master button. The Sync With Master dialog box appears:
This dialog box displays, for the current widget, all of the property discrepancies between the master and alternate layout. You can re-establish layout inheritance in two ways: Have the master adopt the properties of the alternate layout. This changes the widgets definition in the master layout. Have the alternate layout adopt the properties of the master layout. This changes the properties of the alternate layout to match those of the master layout.
2. 3.
Select the property to synchronize. Choose the button that indicates how to synchronize the property: If you choose the Alternate Reverts to Master Value button, a greater than symbol (>) appears to the right of the Master Layout Column. This indicates that the alternate layout adopts the property setting from the master layout. If you choose the Master Updates to Alternate Value button, a less than symbol (<) appears to the right of the Master Layout Column. This indicates that the master layout adopts the property setting from the alternate layout. To remove any synchronization choice, choose the center button between the Alternate Reverts to Master Value button and the Master Updates to Alternate Value button. B11
OpenEdge Development: AppBuilder If neither symbol appears, the properties will not be synchronized. An alternate technique to indicate property synchronization is to repeatedly double-click on the property in the selection list. As you double-click on the property, the AppBuilder rotates among the greater than (>) symbol, the less than (<) symbol, and no symbol. 4. When you finish specifying how to synchronize the properties, choose OK. The AppBuilder synchronizes the properties according to the button you choose. The AppBuilder also re-establishes inheritance for the property, with two exceptions: If you change either coordinate of a widgets position, the other coordinate is disinherited as well. You must synchronize both coordinates with the master layout to re-establish layout inheritance. If you change either dimension of a widget, the other dimension is disinherited as well. You must synchronize both dimensions with the master layout to re-establish layout inheritance.
internal procedure.
B12
Multiple Layouts For example, the multi-layout run-time adjustments code appears as follows:
/* _MULTI-LAYOUT-RUN-TIME-ADJUSTMENTS */ /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard Character" CHARACTER SESSION:DISPLAY-TYPE = TTY:U This layout is the standard layout specification for a customized Character based terminal. It is usually selected to modify a window that has a GUI based master layout. */ IF SESSION:DISPLAY-TYPE = TTY:U THEN RUN C-Win-layouts (INPUT Standard Character:U) NO-ERROR. /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard MS Windows" GUI SESSION:WINDOW-SYSTEM = MS-WINDOWS:U This layout is the standard layout specification for a customized MS Windows window. It is usually selected to modify a window that needs to have a standard "MS Windows" look. */ ELSE IF SESSION:WINDOW-SYSTEM = MS-WINDOWS:U THEN RUN C-Win-layouts (INPUT Standard MS Windows:U) NO-ERROR. /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard Windows 95" GUI SESSION:WINDOW-SYSTEM = MS-WIN95:U This layout is the standard layout specification for a customized Windows 95 window. It is usually selected to modify a window that needs to have a standard "Windows 95" look. */ ELSE IF SESSION:WINDOW-SYSTEM = MS-WIN95:U THEN RUN C-Win-layouts (INPUT Standard Windows 95:U) NO-ERROR. /* END-OF-LAYOUT-DEFINITIONS */ IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win) THEN C-Win:HIDDEN = no.
If the expression SESSION:WINDOW-SYSTEM = MS-WINDOWS:U evaluates to TRUE, this IF statement passes the input parameter Standard MS Windows to the layout cases internal procedure. For SmartObjects, the DefaultLayout property is set. This is used to run the appropriate layout case later, when the SmartObject is initialized.
B13
OpenEdge Development: AppBuilder Thus, for SmartObjects, the multi-layout run-time adjustments code appears as follows:
/* _MULTI-LAYOUT-RUN-TIME-ADJUSTMENTS */ /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard Character" CHARACTER SESSION:DISPLAY-TYPE = TTY:U This layout is the standard layout specification for a customized Character based terminal. It is usually selected to modify a window that has a GUI based master layout.
*/ IF SESSION:DISPLAY-TYPE = TTY:U THEN DYNAMIC-FUNCTION(setDefaultLayout:U, Standard Character:U) NO-ERROR. /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard MS Windows" GUI SESSION:WINDOW-SYSTEM = MS-WINDOWS:U This layout is the standard layout specification for a customized MS Windows window. It is usually selected to modify a window that needs to have a standard "MS Windows" look.
*/ ELSE IF SESSION:WINDOW-SYSTEM = MS-WINDOWS:U THEN DYNAMIC-FUNCTION(setDefaultLayout:U, Standard MS Windows:U) NO-ERROR. /* LAYOUT-NAME: LAYOUT-TYPE: EXPRESSION: COMMENT: "Standard Windows 95" GUI SESSION:WINDOW-SYSTEM = MS-WIN95:U This layout is the standard layout specification for a customized Windows 95 window. It is usually selected to modify a window that needs to have a standard "Windows 95" look.
*/ ELSE IF SESSION:WINDOW-SYSTEM = MS-WIN95:U THEN DYNAMIC-FUNCTION(setDefaultLayout:U, Standard Windows 95:U) NO-ERROR. DYNAMIC-FUNCTION(setLayoutOptions:U, "Master Layout,Standard Character,Standard MS Windows,Standard Windows 95":U).
B14
Multiple Layouts The layout cases internal procedure is named {&LAYOUT-VARIABLE} variables, which in this sample resolves to C-Win-layouts: (1 of 2)
PROCEDURE C-Win-layouts: DEFINE INPUT PARAMETER layout AS CHARACTER DEFINE VARIABLE lbl-hndl AS WIDGET-HANDLE DEFINE VARIABLE widg-pos AS DECIMAL NO-UNDO. NO-UNDO. NO-UNDO. */ */
/* Copy the name of the active layout into a variable accessible to /* the rest of this file. C-Win-layout = layout. CASE layout: WHEN "Master Layout" THEN DO: ASSIGN &IF {&WINDOW-SYSTEM} NE TTY:U &THEN C-Win:HIDDEN C-Win:HEIGHT ASSIGN Btn_Done:HIDDEN Btn_Done:HEIGHT Btn_Done:ROW IN Btn_Done:HIDDEN ASSIGN Btn_Help:HIDDEN Btn_Help:HEIGHT Btn_Help:ROW IN Btn_Help:HIDDEN Btn_Help:HIDDEN
= = = =
IN FRAME DEFAULT-FRAME IN FRAME DEFAULT-FRAME FRAME DEFAULT-FRAME IN FRAME DEFAULT-FRAME IN FRAME DEFAULT-FRAME
= = = = =
B15
= = = =
yes 1 4 no NO-ERROR.
= yes = 1 = 3 NO-ERROR.
This sample contains CASE statement entries for two layouts, the master layout and the standard character layout. The Btn_Help button appears in the master layout but not in the standard character layout. The master layout also sets size properties to decimal character units because a graphical environment supports fractions of a character. However, in a character environment, they are set to integer character units.
B16
In this example, the Btn_Photo is enabled only if the standard character layout is not used at run time.
B17
Modifiable properties
Within an alternate layout, you can change some, but not all of the properties that you can change in the master layout.Table B2 lists the properties that you can change. Table B2:
BGCOLOR COLUMN EDGE-PIXELS FGCOLOR FILLED FONT
Note: To exclude a widget from a particular alternate layout, set the Remove from Layout toggle box in the widgets property sheet.
B18
Multiple Layouts
SIZE-TO-FIT setting
The SIZE-TO-FIT setting works only for the initial call to the master layout. In fact, when you change layouts, the width/height of the frame that you see is the design size, not the initial SIZE-TO-FIT size; that is, there is a margin on the right and bottom, even if you choose to set the layout to the master layout.
This statement changes all of the run-time properties to match those of the master layout. This step is necessary because all of the other layouts change their settings relative to the master layout. Thus, before you can switch to a new layout, you should switch back to the master layout. 2. Execute the CASE entry for the layout you want. This sets all of the layouts properties that you specify:
B19
OpenEdge Development: AppBuilder 3. If necessary, write code that correctly enables the widgets in the new layout. If widgets are enabled differently from one layout to another, you cannot execute the procedure to do your enabling. The Enable_UI procedure enables widgets based on WHEN phrases built using the layouts associated run-time expressions. The explicit purpose of these run-time expressions is to identify a unique run-time environment. Since you want to switch layouts only within the same run-time environment, you must write your own code to handle the enabling.
Enable_UI
When you create a new design window or dialog box, the New dialog box appears. Select TTY Window or TTY Dialog to put the master layout in character mode. In general, if you plan to have both character and graphical layouts, make the master layout graphical.
B20
Multiple Layouts
PROSERVE sports
2. 3.
Start the OpenEdge session and connect to the application database in multi-user mode. When you are ready to run your character procedure, choose LayoutAlternate Layout from the AppBuilder main window. On the Alternate Layout box, select Standard Character from the Layout combo box. Choose CompileRun from the main window. AppBuilder disables itself and opens the AppBuilder Character Run Window, which starts a Progress character client session. The Character client first connects to all the databases to which the AppBuilder is connected, then runs your character application.
4. 5.
6.
To return to design mode in AppBuilder, exit the layout in the manner you designed for that layout; for example, by pressing the ESC key in the Character Run Window. The AppBuilder Character Run Window clears the running layout and displays a status message of Procedure complete. Waiting for next run. The AppBuilder enables itself so that you can make further changes to the character layout. Note that the character client session is still running and remains connected to the application databases, so that you can run the procedure again to test your changes.
B21
OpenEdge Development: AppBuilder 7. To close the Character Run Window, choose CompileClose Character Run Window in the AppBuilder Main window. The character client session exits and the Character Run Window closes. Note: If the Character Run Window does not close, you might have to delete the file that the AppBuilder uses to communicate with the Character Run Window. This file has the form pnnnnnm.tty and is located in the OpenEdge temporary file directory (by default, your current directory). When you delete this file, the character session ends and the Character Run window closes.
Double-byte characters
The Character Run window does not support the display of double-byte characters. For more information about double-byte characters, see OpenEdge Development: Internationalizing Applications.
B22
Multiple Layouts
Unlike the run-time expressions used for basic procedure files, the setting of these properties does not immediately affect a SmartObjects layout. Rather, the action of these properties depends on initialization of the SmartObject by its SmartContainer. At run time, the initializeObject() event procedure runs the layout cases internal procedure {&LAYOUT-VARIABLE} variables by running applyLayout. The applyLayout() event procedure uses the value of the ObjectLayout or DefaultLayout property to determine initial visualization for the SmartObject. At any point after initialization, you can choose a different layout for the SmartObject by setting and applying a different value to the ObjectLayout property (from LayoutOptions).
B23
Figure B3:
This example shows the setting for an alternate Layout, Address Information, created for the SmartObject. Note the Dont use Run-time Expression option. This appears only for SmartObjects and is turned on by default. To activate a run-time expression for this layout, turn off the option. The default setting when you turn it off is FALSE.
B24
Multiple Layouts To illustrate working with SmartObject layouts, the rest of this section references a SmartDialog that contains a SmartDataViewer that has three layouts: a master and two alternates. The master layout, shown in Figure B4, contains many of the fields of the sports database Customer table, some of which overlay each other.
Figure B4:
Each of the alternate layouts, shown in Figure B5 and Figure B6, displays or hides different sets of the fields in the master layout.
Figure B5:
B25
Figure B6:
In general, SmartObjects instances inherit the active layout of the parent SmartContainer in the AppBuilder. While the SmartContainer is in an alternate layout, you cannot set the ObjectLayout (or any other instance property) of the SmartObjects that it contains. To set the active layout of a SmartObject instance, the parent SmartContainer must be in the master layout. Also, once set, the layout for a SmartObject instance overrides any subsequent layout setting inherited from the parent SmartContainer. If you want the SmartContainer to change the layout of its SmartObjects dynamically, you can create an override createObjects() event procedure that sets the ObjectLayout properties of the SmartObjects after they are created. Setting layout options for SmartObject instances Several SmartObjects provided with OpenEdge include instance properties dialog boxes that allow you to set run-time options for a SmartObject instance. For more information, see the SmartObject properties section on page A28. You can set instance properties only for a SmartObject displayed in the master layout of the parent SmartContainer, in the example, a SmartDialog.
B26
Multiple Layouts You can access the Properties dialog box for an instance in two ways. One is to click on the instance menu button to display the pop-up menu shown in Figure B7.
Figure B7:
This allows you to go directly to the Instance Properties dialog box by clicking on Instance Properties. Alternatively, you can click on Properties (or double-click on the instance itself) to open the instance property sheet, then click on the Edit button to open the Instance Properties dialog box. For the same SmartObject instance with the parent SmartContainer displayed in an alternate layout, the menu buttons pop-up menu changes to prevent you from modifying any instance properties, as shown in Figure B8.
Figure B8:
B27
OpenEdge Development: AppBuilder In this case, the Instance Properties option is insensitive and the Delete Instance option is replaced with the Remove from Layout option. Both Remove from Layout and Delete Instance hide the SmartObject from view. However, Remove from Layout only hides the SmartObject, while Delete Instance actually deletes it from the SmartContainer. Remove from Layout is used for alternate layouts rather than Delete Instance because the SmartObject instance is still available from the master layout of the SmartContainer. Also, the instance property sheet changes in a SmartContainer alternate layout, as shown in Figure B9.
Figure B9:
This is the property sheet for the SmartDataViewer instance in an alternate layout. Note that the Edit button is insensitive, preventing editing of the instance properties. The Remove from Layout option, the Layout inherited from the SmartContainer, and the Sync with Master button are also added to the property sheet. The Parameterize as Variable option, normally available in the master layout, is also insensitive. This example illustrates how you might have an alternate layout standard for the windows and dialog boxes of an entire application, while maintaining the ability to apply instance-specific layouts (Layout = Balance Information) for SmartObjects contained within these windows and dialog boxes. Thus, you might have two or more application visualizations in which the SmartObject instances retain the same functional layouts.
B28
Multiple Layouts Two supported SmartObjects, SmartDataViewers and SmartDataBrowsers, support ObjectLayout as an instance property. You can set this property in the Instance Properties dialog box using the Layout combo box, as shown in Figure B10. Note: If the SmartObject has no alternate layouts, the Layout combo box is insensitive
Figure B10:
You get this particular Instance Properties dialog box for the SmartDataViewer instance shown in Figure B7, displayed in the SmartContainer master layout. In general, the Layout combo box lists the LayoutOptions property values available for the SmartObject instance. These are the alternate layout names that you define for the SmartObject when you create or edit the SmartObject in the AppBuilder using the Alternate Layout dialog box (Figure B3). If the SmartObject has a visualization for an alternate layout (such as Balance Information), you can make it visible for the instance by selecting the Layout value. Once you select and confirm the layout (by clicking on OK), the visualization for the selected layout appears in the SmartContainer design window for that SmartObject instance (Figure B8). Note the difference in the SmartDataViewer instance layout between Figure B7 and Figure B8. Regardless of which layout you set for the SmartContainer, the SmartObject instance always displays the selected layout, as indicated by the ObjectLayout instance property setting shown in Figure B9. This is true at run time as well as at design time, unless you explicitly create a run-time override of the instance layout. For more information on run-time layout overrides, see the Applying SmartObject layouts at run time section on page B30. If you leave the instance layout setting as [default], the instance in the design window has no layout property setting and displays the SmartObject master layout or the current layout of the SmartContainer, if different. This setting also allows you to specify the initial layout for the instance by the run-time setting of the DefaultLayout property.
B29
Thus, you can set the initial SmartObject layout and change it as often as you like at run time. Setting the initial layout You can dynamically set the initial layout for your SmartObjects by creating a local createObjects() event procedure in the SmartContainer that parents the SmartObjects:
B30
Multiple Layouts The code after the RUN SUPER statement is what you might add to the local createObjects() procedure. This code finds all of the SmartObjects in the SmartContainer (SmartObjects that have Container-Target links to this container). Next, it returns each link handle (the procedure handle for each SmartObject) and sets the ObjectLayout property for the associated SmartObject. Note: Setting a property for a SmartObject that does not recognize the specified property has no effect. In this case, only SmartDataViewers and SmartDataBrowsers respond to the setting of ObjectLayout. The p-layout identifier in this example represents a character-string input parameter to the SmartContainer that holds the initial layout value. This assumes that the SmartContainer is called from some other procedure, perhaps with the actual p-layout value determined at run time. Note that the initial setting of ObjectLayout occurs after the ADM createObjects() procedure executes. Thus, the SmartContainer changes all the SmartObject instance settings of ObjectLayout after the SmartContainer creates its SmartObjects but before it initializes them (using initializeObject()). Changing layouts You can change the layout of a SmartObject with multiple layouts at any time after initialization. For example, you might do this in a user interface trigger that explicitly changes the layout when the user clicks on a button, or in response to an expression value that determines what layout a particular user is permitted to see (for example, a security key). You might have a series of expressions in a CASE statement that sets a varying layout according to a variety of criteria. In all of these cases you execute the following code, where so-handle is your SmartObject procedure handle and chosen-layout is the name that you have assigned to the alternate layout to be applied:
B31
OpenEdge Development: AppBuilder Thus, for the Balance button shown in Figure B8:, you can create a trigger like this:
ON CHOOSE OF bBalance IN FRAME D-Dialog /* Balance */ DO: DYNAMIC-FUNCTION(setObjectLayout:U IN h_v_cust, "Balance Information":U). RUN applyLayout IN h_v_cust. END.
Executing this code immediately redisplays the layout for the SmartObject specified by the h_v_cust handle. This code can execute anywhere inside or outside of the SmartObject as long as it occurs after SmartObject initialization and while the SmartObject is still instantiated.
B32
C
Customizing AppBuilder
This appendix documents two techniques for customizing AppBuilder. It discusses the following topics: Creating custom object files Creating extended features (XFTRs) AppBuilders API Example using AppBuilders API
Note that you can also use ADE hooks to change the behavior of AppBuilder; however, this appendix does not discuss this technique. For information, see the OpenEdge Development: Basic Development Tools manual (character only; information for MS-Windows is in online help). Note: Customizing AppBuilder, especially using XFTR features, is an advanced feature. You do not need to understand the material in this appendix to use AppBuilder effectively.
C2
Customizing AppBuilder OpenEdge supplies different default custom object files depending on your AppBuilder licensing option. Table C1 identifies all the custom files in the current release and the object definitions they contain. The files you have depend on your AppBuilder license. Table C1: Filename
progress.cst
Custom object files and their contents Contents Basic Objects, SmartPanel, SmartFolder, SmartContainer, SmartWindow, SmartDialog, SmartFrame, Method Library, Structured Include, Structured Procedure SmartDataObject SmartDataBrowser and SmartDataViewer CSSpin, CSComboBox, PSTimer CGI Wrapper, Frameset, HTML Mapping, Structured Include, Main, Structured Procedure, Report Template, Table, and Method Library Version 8 SmartObject definitions
smartv8.cst
Note: The ActiveX control definitions that were in the Progress Version 8 cst file are now contained in the activex.cst file.
If you place a comment anywhere else in a custom object file, you will lose data. Custom object files must end with a blank line, otherwise you lose the last line of code.
C3
Entry types
You can add four types of entries to a custom objects file: Add a button to the Object Palette. Add a SmartObject to an Object Palette button pop-up menu. Add a template to the New dialog box. Add a custom widget to an Object Palette button pop-up menu.
{ | | } [
DB-CONNECT
#object-type &Default
[X,Y]
Specifies the name of the bitmap file for object-type when deselected. To fit properly on the Object Palette, the image must be 28 by 28 pixels, including all shadows and highlights.
C4
Customizing AppBuilder
DOWN-IMAGE-FILE bitmap-file
[X,Y]
Specifies the name of the bitmap file for object-type when selected. To fit properly on the Object Palette, the image must be 28 by 28 pixels, including all shadows and highlights.
LABEL label-name
Specifies the text for the label for object-type. This label appears on the Object Palette and in the Object Palette menu.
USE master-file-name
Specifies the name of the SmartObject master file to instantiate when smartobject-type is selected from the Object Palette. If you specify USE, a Choose Object dialog box does not appear.
NEW template-file-name
Specifies the template file that AppBuilder opens when the user performs a New operation from Object Palette. You cannot use this option with the USE option.
DIRECTORY-LIST list
Specifies the directories that appear in the Choose dialog box for object-type.
FILTER filter
Specifies a comma-separated list of file search masks that appear in the Choose dialog box for the current directory.
TITLE title
Specifies the title for the Choose dialog box for object-type.
DB-CONNECT
Specifies whether AppBuilder prompts you to connect a database (if one is not connected) when you select the object-type. This is useful for data-aware objects such as SmartDataViewers, SmartDataObjects, and SmartDataBrowsers.
C5
OpenEdge Development: AppBuilder The sample entry in Figure C1 adds a SmartObject type, specifically a SmartDataBrowser.
Name of SmartObject type Bitmaps for palette icon Label in the palette What template is opened Modify Choose dialog
#Sm ar t Dat aBr owser &Def aul t UP- I M AG E- FI LE adei con/ wp_up 24, 264 DO W N- I M AG E- FI LE adei con/ wp_down 24, 264 LABEL Sm ar t Dat aBr o&wser NEW - TEM PLATE sr c/ adm 2/ t em pl at e/ br owser . w DI RECTO RY- LI ST FI LTER TI TLE . , adm 2 b* . w, b* . r , b* . * , * . * Choose Sm ar t Dat aBr owser
Figure C1:
Note: You can also use the adecomm/_chosobj.w procedure in the src/adecomm.pl procedure library to modify the Choose Object dialog box. For more information, see OpenEdge Development: Basic Development Tools manual (character only; information for MS-Windows is in online help).
{ }
USE master-file
*smartobject-type
Customizing AppBuilder
name
Specifies the name of the object as it appears on the Object Palettes menus.
USE master-file
Specifies the name of the SmartObject master file to instantiate when name is selected from the Object Palette:
DIRECTORY-LIST list
Specifies the directories that appear in the Choose dialog box for smartobject-type.
FILTER filter
Specifies a comma-separated list of file search masks that appears in the Choose dialog box for the current directory.
TITLE title
Specifies the title for the Choose dialog box for smartobject-type. The sample entries in Figure C2 add SmartObject masters from src/template/smart.cst.
Figure C2:
C7
{ | | }
Specifies that the template appears in the New dialog box when the Containers toggle box is selected. A container is a either a window, a dialog box, or a SmartContainer.
*NEW-SMARTOBJECT
Specifies that the template appears in the New dialog box when the SmartObjects toggle box is selected.
TYPE name
Specifies the type of SmartObject. AppBuilder uses this value to determine whether to connect a database when the particular type of SmartObject is created.
*NEW-PROCEDURE
Specifies that the template appears in the New dialog box when the Procedures toggle box is selected. A procedure can be either a structured procedure file, a structured include file, or a method library.
template-name
Specifies the name of the template as it appears in the New dialog box.
NEW-TEMPLATE template-file
Specifies the pathname of the template file that AppBuilder opens when you select the template from the New dialog box.
C8
*NEW-SMARTOBJECT SmartDataBrowser TYPE SmartDataBrowser NEW-TEMPLATE src/adm2/template/browser.w *NEW-CONTAINER NEW-TEMPLATE Smart&Window src/adm2/template/cntnrwin.w
*NEW-PROCEDURE NEW-TEMPLATE
[ DESCRIPTION [ description-text-string ] ] { [ attribute value ] ... [ INHERIT name-of-entry ] ... [ trigger-block ] ... } ...
RUN file-name *widget-type
Specifies the type of custom widget to create. It must be one of the following: BROWSE, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, TEXT, and TOGGLE-BOX.
name
Specifies the display name of the custom widget as it appears on the Palette submenu (or pop-up menu on the Palette). After you choose a widget, AppBuilder displays display-name, followed by widget-type, in the status bar of AppBuilder main window.
C9
description-text-string
Specifies the description of the widget. The description helps another developer to read and understand the intent of each custom widget.
attribute
Specifies an attribute to set for the widget. You can specify any attribute that you can also set from the widgets property sheet. See Table C2, later in this appendix, for a list of the attributes that you can specify and the widgets to which they can apply.
value
Specifies the value for attribute (based on the data type of the attribute).
INHERIT name-of-entry
Specifies the display name of another widget in the custom widgets file. The current widget inherits all of the attribute settings specified for the other widget. If attribute settings conflict, the latter setting applies.
trigger-block
END.
In this syntax, event specifies an event to pair with the custom widget and trigger-code specifies the code statements to execute for the widget/event pair.
RUN file-name
Specifies a procedure to run immediately before the object is created. The procedure file can take two parameters:
INPUT p_id AS INTEGER NO-UNDO OUTPUT p_sct AS CHAR NO-UNDO
You can have multiple RUN statements for a single custom object file; they are run sequentially. Do not end a RUN statement line with a trailing period (.).
C10
Customizing AppBuilder Table C2 describes the attributes you can set in the custom objects file and the widgets to which they apply. In the Data Type column:
C P I L
indicates CHARACTER indicates PIXELS indicates INTEGER indicates LOGICAL Settable attributes for custom widgets Data type
L L L L COMBO BOX BUTTON BUTTON BUTTON, EDITOR, FILL-IN, SELECTION-LIST, TOGGLE-BOX BUTTON, EDITOR, FILL-IN, SELECTION-LIST, SLIDER, TOGGLE-BOX FILL-IN BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX COMBO-BOX, FILL-IN FRAME BUTTON BROWSER COMBO-BOX, FILL-IN, RADIO-SET COMBO-BOX, FILL-IN BUTTON BUTTON
Table C2:
(1 of 6)
Attribute
AUTO-COMPLETION AUTO-END-KEY AUTO-GO AUTO-INDENT
Allowed widgets
AUTO-RESIZE
AUTO-RETURN BGCOLOR
L I
L L L L C L L L
C11
OpenEdge Development: AppBuilder Table C2: Settable attributes for custom widgets Data type
L
(2 of 6)
Attribute
DISPLAY
Allowed widgets
COMBO-BOX, EDITOR, FILL-IN, RADIO-SET, SELECTION-LIST, SLIDER, TOGGLE-BOX FRAME SELECTION-LIST RECTANGLE BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TOGGLE-BOX RADIO-SET BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX RECTANGLE BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, RADIO-SET, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX COMBO-BOX, FILL-IN RECTANGLE BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX BUTTON, COMBO-BOX, EDITOR, FILL-IN, RADIO-SET, SELECTION-LIST, SLIDER, TOGGLE-BOX
L L I L
EXPAND FGCOLOR
L I
FILLED FONT
L I
C L I
HEIGHT-PIXELS
HELP
C12
Customizing AppBuilder Table C2: Settable attributes for custom widgets Data type
L
(3 of 6)
Attribute
HIDDEN
Allowed widgets
BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX RADIO-SET, SLIDER BUTTON BUTTON, IMAGE BUTTON COMBO-BOX, EDITOR, FILL-IN, RADIO-SET, SELECTION-LIST, SLIDER, TOGGLE-BOX COMBO-BOX FRAME BROWSER, BUTTON, COMBO-BOX, FILL-IN, FRAME, TOGGLE-BOX EDITOR BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX COMBO-BOX, RADIO-SET, SELECTION-LIST BROWSER BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX EDITOR BROWSER SLIDER SLIDER
L C C C C
I L C
LARGE LAYOUT-UNIT
L C or P
C I L
I I I I
C13
OpenEdge Development: AppBuilder Table C2: Settable attributes for custom widgets Data type
L
(4 of 6)
Attribute
MOVABLE
Allowed widgets
BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX BROWSER, SELECTION-LIST BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TOGGLE-BOX FILL-IN BROWSER, FRAME FRAME COMBO-BOX, FILL-IN BROWSER, FRAME FRAME COMBO-BOX, EDITOR, FILL-IN, RADIO-SET, SELECTION-LIST, SLIDER, TOGGLE-BOX FRAME BROWSER, FRAME FRAME FRAME FRAME BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX RADIO-SET EDITOR
MULTIPLE NAME
L C
L L L L L L L
L L L L L C
RADIO-BUTTONS READ-ONLY
C L
C14
Customizing AppBuilder Table C2: Settable attributes for custom widgets Data type
L
(5 of 6)
Attribute
RESIZABLE
Allowed widgets
BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX FRAME EDITOR FRAME EDITOR, SELECTION-LIST EDITOR, SELECTION-LIST BUTTON, COMBO-BOX, EDITOR, FILL-IN, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TOGGLE-BOX FRAME BROWSER BROWSER, COMBO-BOX, EDITOR, FILL-IN, FRAME, RADIO-SET, SELECTION-LIST, SLIDER, TOGGLE-BOX FRAME COMBO-BOX, SELECTION-LIST BROWSER, FRAME BROWSER, FRAME FRAME FRAME FRAME COMBO BOX BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX
I L L L L L
L L L
L L L L I I L L L
C15
OpenEdge Development: AppBuilder Table C2: Settable attributes for custom widgets Data type
L I I I I I FILL-IN FRAME FRAME FRAME FRAME BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX BROWSER, BUTTON, COMBO-BOX, EDITOR, FILL-IN, FRAME, IMAGE, RADIO-SET, RECTANGLE, SELECTION-LIST, SLIDER, TEXT, TOGGLE-BOX EDITOR
(6 of 6)
Attribute
VIEW-AS-TEXT VIRTUAL-HEIGHT VIRTUAL-HEIGHT-PIXELS VIRTUAL-WIDTH VIRTUAL-WIDTH-PIXELS WIDTH
Allowed widgets
WIDTH-PIXELS
WORD-WRAP
The RADIO-BUTTONS attribute represents the labels and values for the individual buttons in a set, arranged in a comma-separated list.The following example identifies this format: label, value, label, value, label, value, and so forth. One label/value pair is defined for each button identified in a set.
C16
Customizing AppBuilder Sample widget entry The following sample entry is in the src/template/progress.cst file:
*BUTTON Ne&xt DESCRIPTION Simple Navigation Button INHERIT C&ustom Size/Color LABEL &Next NAME Btn_Next TRIGGER CHOOSE DO: &IF "{&PROCEDURE-TYPE}" EQ "SmartPanel" &THEN &IF "{&ADM-VERSION}" EQ "ADM1.1" &THEN RUN notify IN THIS-PROCEDURE ("get-next") NO-ERROR. &ELSE PUBLISH "fetchNext":U. &ENDIF &ELSEIF "{&TABLES-IN-QUERY-{&FRAME-NAME}}" NE "" &THEN /* ** This is a simple NEXT RECORD navigation button, useful for building ** test screens quickly. NOTE: if there are no tables in the query, ** then this code will not compile so use the preprocessor to skip it. */ GET NEXT {&FRAME-NAME}. IF NOT AVAILABLE {&FIRST-TABLE-IN-QUERY-{&FRAME-NAME}} THEN GET LAST {&FRAME-NAME}. IF AVAILABLE {&FIRST-TABLE-IN-QUERY-{&FRAME-NAME}} THEN DO: DISPLAY {&FIELDS-IN-QUERY-{&FRAME-NAME}} WITH FRAME {&FRAME-NAME}. {&OPEN-BROWSERS-IN-QUERY-{&FRAME-NAME}} END. &ENDIF END TRIGGER
If you analyze this sample entry one section at a time, you can see how to write your own custom widget entry. In this example: The first line specifies the widget type BUTTON and the display name for the widget:
*BUTTON Ne&xt
AppBuilder displays this name in the appropriate Object Palette menus. The ampersand (&) specifies that the x is the mnemonic on the Object Palette menu.
C17
OpenEdge Development: AppBuilder The second line describes the buttons functionality:
AppBuilder does nothing with this description. The description is meant as a summary for someone reading the custom object file. The third line names another custom widget (Custom Size/Color) in the progress.cst file by using the widgets display name:
The current widget (Next) inherits all of the attribute settings for the Custom Size/Color button. Where you place the INHERIT keyword affects how attributes are set. Later definitions override earlier definitions. The fourth line specifies the label of the button:
LABEL &Next
The ampersand (&) specifies that N is the mnemonic for the button. The fifth line specifies the widget name that AppBuilder uses internally to refer to the button:
NAME Btn_Next
C18
Customizing AppBuilder An XFTR can be self-modifying; that is, change itself based on user action. Figure C4 shows a sample XFTR.
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _XFTR "SmartDataBrowserWizard" bTableWin _INLINE /* Actions: adm2/support/_wizard.w ? ? ? adm2/support/_wizdel.p */ /* SmartDataBrowser Wizard Welcome to the SmartDataBrowser Wizard! During the next few steps, the wizard will lead you through creating a SmartDataBrowser object. First you will choose a DataSource to supply data to the SmartDataBrowser, then you can specify the columns that will be displayed in the SmartDataBrowser. Press Next to proceed. adm2/support/_wizntro.w,adm2/support/_wizds.w,adm2/support/_wizdfld.w,adm2/ support/_wizend.w */ /* _UIB-CODE-BLOCK-END */ &ANALYZE-RESUME
Figure C4:
This code does not, by itself, perform any customized processing. However, it points to other 4GL procedures (adm2/support/_wizard.w and adm2/support/_wizdel.p) that do perform customized processing. AppBuilder calls these procedures when significant AppBuilder events occur; for example, when a design window is realized or code is generated. Consequently, these procedures are called XFTR event handlers. An XFTR can reference up to five such procedures for AppBuilder events (see Table C3). As this example illustrates, an XFTR has five sections: An opening &ANALYZE-SUSPEND directive (required). A comment that maps event types to event handlers (required). A comment that contains code passed to the event handlers (optional). A comment that closes the code block (required). A closing &ANALYZE-RESUME directive (required).
C19
The name value is a quoted string that specifies the name of the XFTR. The object value is an unquoted string with no embedded spaces that specifies a window name; if the procedure file has no window, specify this value as Procedure.
/*
XFTR- handl er s:
*/
34 5
Figure C5:
Components 0 and 7 are standard comment delimiters. Component 1, which must end in a colon, is simply a title for the comment. Components 2 through 6 are space-delimited procedure names for the XFTR event handlers; each maps to a particular AppBuilder event, as follows: Position 2 maps to the Realize event. Position 3 maps to the Edit event. Position 4 maps to the Destroy event. Position 5 maps to the Read event. Position 6 maps to the Write event.
C20
Customizing AppBuilder For example, in Figure C5, if an AppBuilder Realize event occurs, AppBuilder calls the adm2/support/_wizard.w event. Note that a question mark indicates that no event handler is specified for the corresponding event. Table C3 summarizes AppBuilder events that you can map to XFTR event handlers. Table C3: AppBuilder event Realize AppBuilder events
User actions Opening a procedure file, creating a new procedure file, changing layouts, or changing size of a window. Selecting an XFTR code section from the Section Editors List Sections dialog box. Closing a design window.
Edit
Occurs when AppBuilder presents an XFTR code block for editing. Occurs when a procedure file is closed, or when AppBuilder closes a design window. Occurs when AppBuilder has finished opening a procedure file. Occurs when AppBuilder generates code and saves it to a procedure file. Specifically, occurs when the XFTR is encountered at code generation.
Destroy
Read Write
C21
/* _UIB-CODE-BLOCK-END */
&ANALYZE-RESUME
Make sure that your XFTR event handler can accept these parameters.
AppBuilders API
Once AppBuilder runs an XFTR event handler, the event handler can access AppBuilders API. This allows the XFTR event handlers to interact with AppBuilder to provide customized processing that is coordinated with AppBuilders standard processing.
C22
Customizing AppBuilder
Context IDs
AppBuilders API allows XFTR event handlers to gather information about all of the widgets, procedure files, SmartObject instances, and user-editable code sections in AppBuilder. Each of these different objects is stored in a separate record in AppBuilders internal temporary tables. The context ID provides a unique reference for each type of object. Although AppBuilders API allows you to reference some objects by name or by handle, you should use the context ID to reference objects. Context IDs have the following advantages: They are guaranteed to be unique for each AppBuilder session. They generally provide faster access to the available objects.
Naming convention
All of the parameter names used in AppBuilders API begin with the letter p (for parameter), which is followed by a second letter that specifies the data type, as indicated in Table C4. Table C4: Character
c d h i l Character Decimal Handle Integer Logical
C23
API procedure
adeuib/_ablink.p adeuib/_accsect.p adeuib/_dbtbnam.p
adeuib/_uibinfo.p
C24
Customizing AppBuilder Input parameters The adeuib/_accsect.p procedure takes the following input parameters:
pc_operation
- Adds the link identified by the pc_linkname parameter. - Removes the link identified by the pc_linkname parameter.
REMOVE
pc_sourcecontext
The context ID for the object at the originating (source) end of the link. If the operation is REMOVE, you can use the question mark (?) character to refer to THIS-PROCEDURE. If the operation is REMOVE and the target context argument represents a single destination object, you can use: The context ID for a single source object. A comma-separated list of context IDs, representing multiple source objects. The star (*) character, representing all source objects.
pc_linkname
A quoted character string identifying the type of link to be added (ADD) or removed (REMOVE). For example FILTER
pc_targetcontext
The context ID for the object at the destination (target) end of the link. If the operation is REMOVE, use the question mark (?) to refer to THIS-PROCEDURE.
C25
OpenEdge Development: AppBuilder If the operation is REMOVE and the source context argument is a single object, use: The context ID for a single destination object. A comma-separated list of context IDs, representing multiple destination objects. The star (*) character, representing all destination objects.
Note: Either the source context or the target context must represent a single object. You cannot have multiple objects at both the source and target ends. If the operation is ADD, both source and target must be single objects.
Example The following code purges all Navigation links originating at the caller:
/* ** Get own context ID. Example presumes handle of ** current procedure previously stored in phSelf */ RUN adeuib/_uibinfo.p ( INPUT ?, INPUT "HANDLE " + STRING( phSelf ), INPUT "CONTEXT":U, OUTPUT cContextID ). /* ** Remove all Nav links */ RUN adeuib/_ablink.p ( INPUT "REMOVE":U, INPUT cContextID, INPUT "NAVIGATION":U, INPUT "*":U ).
C26
Customizing AppBuilder
Input parameters The adeuib/_accsect.p procedure takes the following input parameters:
pc_mode
A quoted character string that specifies the mode of operation. Valid values are:
GET SET
Reads the contents of the section or returns unknown (?). Writes the contents of the section. Deletes the current section.
DELETE
You cannot actually delete either the MAIN-CODE-BLOCK or the DEFINITIONS sections (see pc_section below). The DELETE value empties the section but does not also remove the stub.
pi_context
The context ID of the object to access. If unknown (?), AppBuilder assumes the current window or procedure.
pc_section
C27
(For example, PROCEDURE:mytest:maintain.p. See the Examples section below for a description of how you can use this.)
FUNCTION:name XFTR:xftr-name
When you have a TRIGGER, then pi_context refers to a widget. In all other cases, pi_context points to the procedure. If pi_srecid is unknown (?), then pi_context and pc_section are used to identify an existing section. If pi_srecid is known, then pc_section is ignored. Input-output parameters The adeuib/_accsect.p procedure uses the following INPUT-OUTPUT parameters:
pi_srecid
The context ID of the current section. If its value is other than unknown, pc_section is ignored.
pc_code
The contents of the trigger or other code section. Return values This procedure returns:
Error
Indicates that pi_context is not specified and there is no current procedure or window.
C28
Customizing AppBuilder Examples The following code resets the MAIN-CODE-BLOCK to an include file:
/* Get the current value */ pi_srecid=?. RUN adeuib/_accsect.p ("GET", ?, "MAIN-CODE-BLOCK", INPUT-OUTPUT srecid INPUT-OUTPUT code). IF RETURN-VALUE NE "Error" THEN DO: IF code ne "{include.i}" THEN DO: code = "{include.i}". RUN adeuib/_accsect.p ("SET", ?, ?, INPUT-OUTPUT srecid, INPUT-OUTPUT code). END. END.
The following example creates a AppBuilder-maintained procedure: a procedure that the Code Section Editor displays as a READ-ONLY procedure. The following code fragment calls adeuib/_accsect.p:
DEF VAR section_id as INTEGER INITIAL ?. DEF VAR code AS CHAR . RUN adeuib/_accsect.p(INPUT "SET":U, INPUT ?, INPUT "PROCEDURE:mytest:maintain.p", INPUT-OUTPUT section_id, INPUT-OUTPUT code).
In this example: The first INPUT parameter, SET:U, specifies SET mode; SET mode tells adeuib/_accsect.p to write or create a code section. The second INPUT parameter, ?, specifies the context ID of the object to access. By default, interprets the unknown value (?) to be the context ID of the current window or procedure.
adeuib/_accsect.p
C29
OpenEdge Development: AppBuilder The third INPUT parameter, PROCEDURE:mytest:maintain.p, specifies the following: The type of section to create is an internal procedure. The name of the internal procedure is mytest. The procedure maintain.p handles generating the code for the internal procedure.
The first INPUT-OUTPUT parameter specifies the context ID of the section; this value must be unknown (?) or pc_section is ignored. The final INPUT-OUTPUT is a character string that holds the contents of the section.
This maintain.p procedure generates the code for the mytest internal procedure:
/*---------------------------------------------------------------------File: maintain.p Description: Sample procedure showing how a developer procedure can maintain a AppBuilder Code Section. Input Parameters: p_id - (INTEGER) context ID of the current procedure Output Parameters: p_Code - (CHAR) code to return. (Including "END PROCEDURE." ). ------------------------------------------------------------------------*/ DEFINE INPUT PARAMETER p_id AS INTEGER NO-UNDO. DEFINE OUTPUT PARAMETER p_code AS CHAR NO-UNDO. DEFINE VAR ch AS CHAR NO-UNDO. /* Line for comments. */ &Scoped-define COMMENT-LINE ----------------------------------------------------------------------/* Standard End-of-line character */ &Scoped-define EOL CHR(10) /* Get some info about the current procedure. */ RUN adeuib/_uibinfo.p (p_id, ?, "FILE-NAME", OUTPUT ch). p_code = "/*{&COMMENT-LINE}" + {&EOL} + " Purpose: Sample code for file " + ch + {&EOL} + " Parameters: <none>" + {&EOL} + "{&COMMENT-LINE}*/" + {&EOL} + {&EOL} + " MESSAGE Hello World!:U." + {&EOL} + {&EOL} + "END PROCEDURE.".
C30
Customizing AppBuilder The maintain.p procedure generates a mytest procedure that the Code Section Editor displays as read only. Here are the contents of the generated mytest procedure:
/*----------------------------------------------------------------------Purpose: Sample code for file C:\WORK\V-CUST.W Parameters: <none> ------------------------------------------------------------------------*/ MESSAGE Hello World!:U. END PROCEDURE.
AppBuilder-maintained procedures provide an alternative to traditional XFTR use. They basically fill the role of an XFTR with only a single WRITE handler. The advantages of AppBuilder-maintained procedures overusing XFTR are: You can add and delete them programmatically using adeuib/_accsect.p. They are visible to you, the developer, so that you can see the code being generated.
Their disadvantages are: They can be deleted by the user from the Code Section Editor menu (Edit/Delete Procedure). They cannot store data in comments used to rebuild the code section. That is, the contents of the AppBuilder-maintained procedure must be derived totally from external sources or calls to adeuib/_uibinfo.p. For example, an XFTR handler can read a section and have it affect what it generates; however, an AppBuilder-maintained procedure can only write code.
C31
OpenEdge Development: AppBuilder Input parameters The adeuib/_dbtbnam.p procedure uses the following input parameters:
pi_context
The context ID of the current procedure (to obtain this ID, use adeuib/_uibinfo.p).
pc_name_in
A table name. This name might or might not be qualified with a database name. Output parameter The adeuib/_dbtbnam.p procedure uses the following output parameter:
pc_name_out
A table name that meets the settings of the Qualify Database Fields with Database Names user preference. Example
DEFINE VAR DEFINE VAR DEFINE VAR db-tbl proc-id ch AS CHAR AS INTEGER AS CHAR NO-UNDO. NO-UNDO. NO-UNDO.
/* ** Get the context of the current procedure. */ RUN adeuib/_uibinfo.p (INPUT ?, INPUT ?, INPUT "PROCEDURE":U, OUTPUT ch). proc-id = INTEGER (ch). /* ** The user may have wanted to suppress the db name in AppBuilder. ** Ask AppBuilder to set up the database/table name. */ RUN adeuib/_dbtbnam.p (proc-id, "Sports.Customer":U, OUTPUT db-tbl). MESSAGE db-tbl.
C32
Customizing AppBuilder
Input parameters The adeuib/_uibinfo.p procedure takes the following input parameters:
pi_context
The context ID of the widget, SmartObject instance, code section, or procedure to access. If unknown (?), AppBuilder assumes the current procedure. The value of pi_context can be the context ID for any of the following: An object. For example, you can obtain the context of a button, Btn_OK, with the following code:
A procedure. For example, you can obtain the context for the current procedure with the following code:
RUN
A SmartObject instance. For example, you can obtain the context of a SmartObject instance with the following code:
RUN
C33
OpenEdge Development: AppBuilder A code section. For example, you can obtain the context ID and contents of the MAIN-CODE-BLOCK section with the following code:
A quoted character string that specifies the name of an object. This string has the following syntax: Syntax
object
[ [ | [ [ | }
IN FRAME frame-name
] ]
IN WINDOW window-name
] ]
IN PROCEDURE file-name
HANDLE handle
In this syntax:
object
is the name of the widget or SmartObject instance. is the name of its parent frame. is the name of its parent window.
frame-name
is either the widget-handle of a widget or the procedure handle for a SmartObject instance.
If you omit the FRAME or WINDOW option, the current window and current frame are assumed. If an object is unique in a window, you can refer to it as object IN WINDOW window-name.
C34
Customizing AppBuilder To refer to a window or frame, preface the object with the type. For example, to find frame f:
FRAME f IN WINDOW w
To find window w:
WINDOW w
PROCEDURE p.w
Gets the current object (shown in the AppBuilders main window) Gets the current frame. Gets the current window. Gets the current procedure.
FRAME ?
WINDOW ?
PROCEDURE ?
If you use the HANDLE handle to reference an object, the handle can be either a WIDGET-HANDLE of the object or PROCEDURE-HANDLE for a SmartObject (converted to a STRING).
PALETTE object
pc_request
A quoted character string that specifies what to request. Valid requests are:
NAME
Returns the name of the object. Returns a string with all of the attributes read from the cst file.
ATTRIBUTES PROCEDURE
FILE-NAME Returns the name of the parent procedure file as last saved by AppBuilder; if not saved, returns ?.
C35
template.
TYPE
Returns the type of object. Returns either the widget-handle of the object or the of a SmartObject. Returns the procedure handle of a SmartObject.
HANDLE
adm-object-handle
PROCEDURE-HANDLE CONTEXT
CONTAINS contains-phrase Returns all objects contained in the current context (of a type or with key toggle boxes set). By default, returns the context ID of the items that match the filter, but you can ask for the list of names. The asterisk (*) returns all objects.
{ *| [ {
object-list
} DISPLAY | ENABLE | MANUAL-HIGHLIGHT | MOVABLE | RESIZABLE | SELECTABLE | SHARED | VISIBLE | LIST-1 | LIST-2 | LIST-3 | LIST-4 | LIST-5 |
FALSE/NO
LIST-6
} { TRUE/YES | ] [
RETURN
} }]
CONTEXT
NAME
In this syntax, object-list is a comma-separated list (with no spaces) of object types. C36
FRAMES Returns all frames (in a window). This is shorthand for CONTAINS FRAME RETURN NAME. FIELDS
Returns dbfields in frame or dbfields in browse. Returns the list of external tables for a procedure.
EXTERNAL-TABLES TABLES
The tables used by the query of a FRAME, BROWSE, or QUERY object. The 4GL query for the query of a FRAME, BROWSE, or QUERY object.
4GL-QUERY
Customizing AppBuilder
WBX-FILE-NAME
The name of the .wrx in which to save run-time attributes for the OCXs in a procedure. The directory where the procedure file is compiled.
COMPILE-INTO-DIR
&FRAME-NAME [RETURN NAME] The context ID or name of the FRAME-NAME, or ?. &QUERY-NAME [RETURN NAME]
RUN adeuib/_uibinfo.p (INPUT ?, INPUT "SESSION", INPUT "PROCEDURES RETURN NAME", OUTPUT name-list).
The following returns the same list but uses context IDs instead of names:
RUN adeuib/_uibinfo.p (INPUT ?, INPUT "SESSION", INPUT "PROCEDURES RETURN CONTEXT", OUTPUT name-list).
/* /* /* /*
SECTIONS function You can ask a procedure for the list of internal procedures and functions defined in AppBuilder. The list can return the names or context IDs of the procedure and function sections, which you can use in adeuib/_accsect.p to get, modify, or delete the contents of code blocks: Syntax
SECTIONS PROCEDURE
,FUNCTION
RETURN
CONTEXT
NAME
] } ]
If you do not specify either RETURN CONTEXT or RETURN NAME, it returns the list in context ID order.
C37
OpenEdge Development: AppBuilder To obtain a list of all internal procedures in a file by name, use the following:
To obtain all of the procedures and functions defined in a file, use the following:
SECTIONS PROCEDURE,FUNCTION
This returns the list in context ID order. HTML-FILE-NAME Returns the HTML filename associated with an HTML mapping object procedure. BROKERURL Returns the broker URL set in Web preferences:
REMOTE Returns TRUE if the Remote File Management button in AppBuilder is set to Remote, otherwise returns FALSE:
WEBBROWSER Returns the Web browser set in Web preferences. DATAOBJECT Returns the SmartDataObject associated with the procedure:
C38
Customizing AppBuilder DATAOBJECT-INCLUDE Returns the name of the include file associated with the SmartDataObject of the procedure:
PALETTE-ITEM For a given custom definition in a .cst file, returns the settings for ATTRIBUTES, LABEL, and FILES:
TEMPLATE,
Syntax
PALETTE-ITEM cst-obj-name
ATTRIBUTES
LABEL
TEMPLATE
FILES
RUN adeuib/_uibinfo.p ( INPUT ?, INPUT "PALETTE-ITEM SmartDataObject":U, INPUT "ATTRIBUTES":U, OUTPUT Attributes).
Output parameter The adeuib/_uibinfo.p procedure uses the following output parameter:
pc_info
C39
Calling sequence
RUN adeuib/_uib_crt.p ( INPUT pi_parent , INPUT pc_type , INPUT pc_custom , INPUT pd_Row , INPUT pd_Column , INPUT pd_height , INPUT pd_width , OUTPUT pi_context ) .
Input parameters The adeuib/_uib_crt.p procedure takes the following input parameters:
pi_parent
The context ID of the parent of the object to create. If this is unknown (?), the parent is assumed to be the current frame. If there is no current frame, then the current window is assumed.
pc_type
The name of the custom object type (for example, OK Button). If this is unknown (?), the &Default object is created. This is of the form:
"case:value"
C40
Customizing AppBuilder Special cases of pc_custom Here are some special cases of the pc_custom parameter:
"Custom:name"
The name of the custom object defined in custom files. This draws a Next button:
Custom:&Next
"SmartObject:object-file"
SmartObject: C:/Progra~1/Progress/gui/object/p-nav.w
"SPECIAL:attributes-values"
This is similar to creating a new custom object file entry temporarily. The attributes and values are parsed the same way as entries in the custom object file. Blank lines are ignored. You must separate lines with a carriage return (that is, CHR(10)). For example:
pd_ROW
The HEIGHT of the object in characters; if unknown (?), the default height is used.
pd_WIDTH
The WIDTH of the object in characters; if unknown (?), the default width is used.
C41
OpenEdge Development: AppBuilder Output parameter The adeuib/_uib_crt.p procedure uses the following output parameter:
pi_context
The context ID of the object created. If the creation fails, this is unknown (?). You can use this value as the object context ID for the companion programs, which are adeuib/_accsect.p, adeuib/_uibinfo.p, and adeuib/_uib_del.p. Return values The adeuib/_uib_crt.p procedure returns:
"Error"
Input parameter The adeuib/_uib_del.p procedure takes the following input parameter:
pi_context
The context ID of the object to delete. There is no default value for this; you must pass a valid context ID. This value is the same value returned by adeuib/_uibinfo.p. Return values This procedure returns:
"Error"
C42
Customizing AppBuilder
"Fail"
Input parameters The adeuib/_uib_dlg.p procedure takes the following input parameters:
pi_context
The context ID of the object to which the dialog box will apply.
pc_dname
A quoted character string that specifies the name of the AppBuilder dialog box to call. Valid values are:
QUERY BUILDER COLUMN EDITOR
The context ID must be for a query, frame, or browse. The context ID must be for a browse. The context ID must be for a procedure.
EXTERNAL-TABLES
Input/output parameters The adeuib/_uib_dlg.p procedure uses the following input/output parameters:
pc_args
A character string to send to the dialog box. For the Column Editor or the External Tables dialog box, you can send a table-list, which is a comma-separated list of tables. For the Query Builder, you can specify a mode, which is a comma-separated list having the following syntax:
C43
Syntax
NORMAL
QUERY-ONLY
CHECK-FIELDS
NO-FREEFORM-QUERY
? The default. Changes the Query Builder to NORMAL mode. For queries, this means that the Fields button is disabled; for browsers, it means that all fields that are Query Builder options are enabled. NORMAL
Changes the Query Builder to NORMAL mode. For queries, this means that the Fields button is disabled; for browsers, it means that all fields that are Query Builder options are enabled.
QUERY-ONLY
Specifies that the Query Builder be in QUERY-ONLY mode. This means that the fields button is disabled. Specifies that the Query Builder be in CHECK-FIELDS mode. This means that if you try to leave the Query Builder and have not selected any fields, you are prompted to select fields. Specifies that the Freeform Query button must be
CHECK-FIELDS
NO-FREEFORM-QUERY
disabled.
C44
Customizing AppBuilder Whenever you modify something in the design window that will be reflected in its saved procedure file, call adeuib/_winsave.p to set the flag to FALSE: Calling sequence
RUN adeuib/_winsave.p ( INPUT ph_handle , INPUT pl_saved ) .
Input parameters The adeuib/_winsave.p procedure takes the following input parameters:
ph_handle
A logical value that indicates that the window has been saved or opened since it was last modified. Example
RUN adeuib/_winsave.p(h_deswin, FALSE).
C45
OpenEdge Development: AppBuilder Input parameters The adeuib/_namespc.p procedure takes the following input parameters:
pi_context
The context of the procedure object to access. If this is unknown (?), then get the current procedure. If a procedure object cannot be found, returns ERROR.
pc_mode
A comma-separated list of names to add or remove. If you try to reserve a name that is already in use, warnings are generated; however, the reservation is made, so that if you delete the widget that uses the name, you cannot use it again. You can unreserve any name, even one that it not reserved, but no warning is generated.
C46
Customizing AppBuilder
/* Get the context-id of the radio-set called rs-discounts */ RUN adeuib/_uibinfo.p (INPUT ?, /* We dont have the context id but the radio-set is in the current design window */ INPUT "rs-disc", /* The name of the radio-set */ INPUT "CONTEXT", /* Please return the context id */ OUTPUT my-widget). /* This is the context-id we need */ /* Fetch the trigger code to be modified */ trig-context = ?. /* This is IMPORTANT, otherwise _accsect.p will attempt to use this trig-context instead of my-widget and TRIGGER:VALUE-CHANGED */ RUN adeuib/_accsect.p (INPUT "GET", /* We want to read the code */ INPUT INTEGER(my-widget), /* The context id from above */ INPUT "TRIGGER:VALUE-CHANGED", /* The trigger we want */ INPUT-OUTPUT trig-context, /* The trigger context so we can reference this block directly in the future. IMPORTANT: This must be ? intially or _accsect will attempt to use it instead of parameter 2 */ INPUT-OUTPUT trig-code). /* The code block */ /* Replace the string */ trig-code = REPLACE(trig-code, "v-credit", "v-debit").
C47
*/ */ */ */ */ */ */ */ */ */ */ */
C48
Index
A
Actions check source-code syntax 211 choose colors for current object 213 close character-mode test window 211 configure alternate layouts 215 connect to database 213 copy selected object 210 create new ADM class 212 create new object file 27 cut selected object 210 debug current workspace 211 delete an object instance 210 disconnect database 213 edit file-level properties 213 edit traversal list 210 edit widget properties 212 export an object 210 hide tool buttons 220 hide/show Objects Palette 217 insert whole file 210 modify database connections 213 open ActiveX property sheet 217 open error-message window 217 open existing object file 28 open online help window 217 open Section Editor window 216 paste object 210 place object in workspace 224 place several objects of same type 224 print object source 29
review recent Cue Cards 218 review recent messages 218 run current workspace 211 save all open files 28 save object source file 28 save object source under another name 28 set Design Page 210 set preferences 214 start non-AppBuilder editor 212 stop or undo object placement 225 toggle layout-grid stickiness 214 toggle layout-grid visibility 214 undo latest operation 29 view/modify common properties 217 ActiveX (OCX) object 82 adaptive interface 83 configuring 84 creating and placing 83 event handlers generic 89 in master layout B4 properties stored in file 810 tool 222 using in application requires licence 82, 83 ActiveX (OCX) Spin Buttons example of use 84 ActiveX (OCX) Timer 816
OpenEdge Development: AppBuilder ActiveX object property references in code 562 activex.cst C3 ADM 13 architecture components 13 current version 13 paging 332 ADM Pages manager A4 deleting a whole page A6 deleting an object from a page A6 exchanging contents of pages A6 Advanced Procedure Settings A7 Advanced Procedure settings child objects, specifying allowed A8 Alternate layout definition B4 Alternate layouts. See Layouts AppBuilder-maintained procedures C31 API add/remove SmartLinks C24 AppBuilder API C22 to C47 add/remove SmartLinks C24 context IDs C23 create objects C39 create reserved identifiers C45 delete objects C42 generate table references C31 get widget information C33 invoke certain dialogs C43 list of procedures in C24 manage code sections C27 set window-modified flag C44 character-mode layout, support for B20 concepts & terminology 14 external procedures 14 objects 14 custom object files C2 customizing 120, 225, 226, 230, C2 default function type 228 double-click 227 Application design considerations single vs multi-window 116 Application Development Model. See ADM AppServer enabling support for A22 Attributes, object. See Properties introduction to C2 layout grid 229 objects in object files C3 designing for character environments B20 event handling C20 exiting 23 main window 24 programming interface C22 setting personal preferences 226 starting 23 testing character-mode designs B21 version number 218 WebSpeed, for 24 working with 116, 118 AppBuilder main window buttons 218 current object fields 25 menu bar 26 status bar 26 tool bar 218
B
B2B messaging creating consumer instances 637 message types 636 SmartConsumers 633 SmartProducers 633 SonicMQ domains 639 Batch mode containers for 328 operating in 640 SmartConsumers 640
Index2
Index Broker URL C38 Buttons AppBuilder main window 218 Child objects in workspaces specifying which are allowed A8 Code testing 256 Code base single, for different environments B2 Code sections navigating 240 reading and writing C27 to C31 Runtime attributes and AppBuilder settings B12 Colors choosing A11 defining new A12 how they are applied A11 table of pre-defined A12 Combo Box 551 ActiveX (OCX) configuring 562 creating and placing 561 tool 223 basic 4GL configuring 553 creating and placing 552 initial value of 556 tool 222 Drop-down style, defined 554, 564 Simple style, defined 554, 564 Common properties displaying in a dialog A22 Compiling and running 211 Configuring SmartB2BObject instances 618 SmartBusinessObjects 422, 428 SmartConsumer instances 638 SmartProducer instances 635 Context IDs C23 Control-frame properties A3 Copying text Section Editor 241 Index3
C
Calculated fields creating 448 Caution guard against version skew 64 mapping to non-unique values 69 must use static data object 418 no type-checking in maps 66 objects incompatible 421 users might be confused 430 visible objects in non-visible container 329 Cautions data validation 415 input focus 575 preventing object from gaining 534, 557 race condition 816 too many events to handle 816 Changing the data stream 437 Character applications in AppBuilder B20, B21 Character client B22 Character mode designing for 117 Character-mode layouts double byte characters B22 limitations on inheritance in B9 running B21 simulating B20 Check Box 589 See also Toggle Box Checking syntax 211
OpenEdge Development: AppBuilder Creating document-handling packages 630 document-routing packages 631 master SmartB2BObjects 617 Simple SmartContainers 328 SmartB2BObject instances 617 SmartBusinessObjects 421 SmartConsumer instances 637 SmartProducer instances 634 SmartSender instances 624 XML map file 612 Current object fields AppBuilder main window 25 Custom Lists assigning meaningful names A16 Custom object files 225, C2 to C47 Custom objects settable properties C11 to C17 Customizing AppBuilder C2 to C47 Cutting text Section Editor 241 editing query and fields 547 tool 221 Smart 54 configuring 54, 512 creating and placing 54, 519 creating master 57 editing data stream in master 517 tool 223 Data fields differences in appearance 526 Data Fields. See Data Viewer Data pump Smart example of use 119 tool 223 DATA SmartLinks 423 Data stream allowing user to filter 431 changing 517 changing contents of 437 preserving integrity of 115 selecting fields for browsing 445 Data transfer SmartProducers/SmartConsumers 633 Data transformation SmartB2BObjects 62 SmartSenders/SmartReceivers 622 Data validation limitation with SmartDataObject 415 Data Viewer basic 4GL 565 configuring 566 creating and placing 566 tool 221 Smart 522 adding/removing fields 528 appearance of fields 526 configuring 529 creating master 523 example of use 119, 339 tool 223
D
Data access AppServer connections 429 client-only object versions filenames end in _cl 43 client-only version 43 efficiency versus completeness 423 foreign-field mapping 426 generic/general-purpose 44 partitions 428, 429 reducing complexity 419 relational mapping 426 single-transaction updates 419 synchronizing 420 Data Browser basic 4GL 545 configuring 546 creating and placing 546
Index4
Index Database add, modify, remove connections 213 connections for character-mode clients B22 field names in Section Editor 245 selecting fields for browsing 445 Database tables working copies A33 Default Page 334 at startup 334 Deleting whole procedure, trigger, etc. 245 Design Page limitations 333 Design windows 237 Development mode switch. See Remote development button Dialog Box basic 4GL configuring 323 creating new 27 Smart configuring 316 creating new 27 file-level properties, configuring 319 Dialogs, frequently-used ActiveX (OCX) control frame properties A3 ADM Pages manager A4 advanced file-level properties A7 Advanced Procedure Settings A7 base procedure type A7 method-libraries reminder, avoiding A7 supported SmartLinks A8 Color Selector and editor A10 database field selector A17 method library include-files list A19 naming custom lists A16 Procedure Settings A20 Properties Window A22 SmartInfo A26 SmartLinks editor A23 String Attributes A30 Temp-tables Maintenance A33 Text-style selector and editor A36 Traversal-path editor A31 Documents XML mapping 63 Drop-down List as style of Combo Box 554, 564 defined 554 Dynamic SmartDataObjects 42 to 418
E
Edit menus 311 Editing ActiveX object properties 217 importance of using Section Editor 239 object properties 254 open editor window 216 Editor object multi-line buffer size 568, 570 configuring 567 creating and placing 567 tool 222 single-line configuring 571 creating and placing 571 tool 222 Editor object, single-line 571 Ending AppBuilder session 23 Environment character designing for 117 Event handlers for XFTRs C20 to C22
Index5
OpenEdge Development: AppBuilder Event names in Section Editor 246 Examining procedure files 254 Example of use data pump Smart 119 Data Viewer Smart 119, 339 Pushbutton 120, 339, 341 Smart 119 Radio Set 339 Rectangle 119, 339 SmartContainer tool 341 SmartDataField 543 SmartDataObject 119 SmartDataViewer 119, 339, 543 SmartFilter 76 SmartFolder 335 SmartLinks 119, 120 SmartPanel 119, 335, 339 SmartSelect 543 SmartWindow 119, 335 Spin Buttons (ActiveX) 84 Static Text 120 Extended features C18 reserving names C45 Filenames Section Editor 253 Files custom object, contents of C3 custom object, listed C3 database tables working copies A33 Fill-in 571 configuring 571 creating and placing 571 tool 222 Filtering incoming messages 620, 626 Frame basic 4GL configuring 324 tool 221 creating 323 Smart configuring 320 creating new 27 Functions listing C37
H
Help 217 review recent Cue Cards 218 review recent messages 218 see AppBuilder version 218 see system resources 218 with message numbers 217 HTML Mapping Object C38
F
Field lists specifying 444 Fields creating calculated 448 selecting for browsing 445 Field-selector dialog A17 File-level properties A20 Filename conventions SmartB2BObjects 617 SmartBusinessObjects 422 SmartContainers 632 SmartSenders 625
I
Image object 810 See also Static Image Include-files list of A19
Index6
Index Inheritance of layouts preventing B10 INMESSAGE SmartLinks 637 Instances getting information C31 to C39 Inter-business communication 633 Internal procedures listing C37 Internationalization no-translation attribute A30 specifying extra space in literals table A30 Layouts alternate B17 Combo Boxes in B18 modifiable properties in B18 Static Text objects in B18 design time view B5 how they work internally B12 inheritance from master B9 to B12 limitations B9 preventing B9, B10 restoring B9, B10 limitations in alternate B17 master re-establishing inheritance from B10 propagation of master changes B9 to B12 run-time customization B19 SmartObject applying at run time B30 changing at run time B31 creating B24 initial run time B30 instance options B26 modifying B24 SmartObjectLayouts B23 switching at run time B19 Limitations data validation 415 double-byte characters B22 ObjectNames in resource list 613 of data-stream integration 419 of static SmartDataObjects 44 SmartFolder 336 SmartRouters/SmartReceivers 630 SmartToolbar 73 XML mapping support 611 Line object using Rectangle to simulate 324 List button AppBuilder main window 219 Lock status for inserting objects 219
J
Java-based messaging 633 JMS Partitions 639 Joins queries 441
L
Layout align objects automatically 215, 216 alternate creating B7 definition B4 configure alternate 215 definition B2 master definition B3 elements of B4 multiplexing 332 paging 332 selecting pre-defined alternate B8 standard B4 toggle grid stickiness 214 toggle grid visibility 214
Index7
OpenEdge Development: AppBuilder Look-and-feel 3D 310 automatic resizing 533, 569 border thickness 326, 327 borders between rows and columns 550 column width 517 display as static text 534, 575 equal spacing 579 extend final column 514, 549 flat, unbordered style 717 hide scrollbar 515, 550, 582 horizontal vs vertical layout 579, 585 iconic label 718 keep existing layering of children 310 max button in title bar 310 message area 310 min button in title bar 310 minimal title bar 311 number of lines 554 numeric readout 586 re-arranging fields 530 remove from layout 534, 555, 570, 575, 579, 582, 586, 592, 814, A3 reset to master layout properties A10 re-using part of the window 332 reverse value progression 586 scroll bars 311 show border 515, 549, 75 show column labels 515, 549 show filled 326 show internal borders 515 show label 533, 542, 554 show title bar 515, 550 sorted data 541, 582 special highlighting 322, 327, 535, 557, A10 state determines appearance 526 status area 311 sync with master layout 315 system colors instead of exact colors 716, 814 text label 718 thicker default-button border 717 title bar 310, 321 toolbar component 75 type of widget used 541, 554, 564 undefined value 541 visible border 321 visible signs of focus 717
M
Macros A16 Master layout See also Layouts definition B3 elements of B4 Menu creating 311 popup, creating 311 Menu bar AppBuilder main window 26 creating 311 Message destination identifiers 620 Message system login 639, 640 Message types 636 Message-handling algorithms 642 code samples 642 inbound process 643 internal details 642 outbound process 642 Multi-line Editor 567 Multiple document types 628 Multiple document types/destinations 621 Multiple layouts See also Layouts coding B12 internals B12 reason for using B2
N
New object 27
Index8
Index
O
Object ActiveX (OCX) configuring 84 creating and placing 83 introduction to 82 ActiveX (OCX) timer 816 Check Box 589 choose colors 213 Combo Box 551 Combo Box (ActiveX) configuring 562 creating 561 Combo Box (basic 4GL) configuring 553 creating 552 Data Browser (basic 4GL) 545 configuring 546 creating and placing 546 Data Browser (Smart) 54 configuring 54, 512 creating and placing 54, 519 creating master 57 editing data stream in master 517 Data Fields 565 Data Viewer (basic 4GL) 565 configuring 566 creating and placing 566 Data Viewer (Smart) 522 adding/removing fields 528 configuring 528, 529 creating master 523 data-capture introduction to 53 data-display introduction to 53 deleting instance 225 Dialog Box (Smart) configuring 316 file-level properties 319 Drop-down List 551 editing file-level properties 213 editing properties 254 Editor (multi-line) 567 configuring 567 creating and placing 567
Fill-in 571 configuring 571 creating and placing 571 Frame (basic 4GL) configuring 324 creating and placing 323 Frame (Smart) configuring 320 names in Section Editor 252 open 4GL Property Sheet 212 participating in traversal list 717 Pushbutton 713 configuring 715 creating and placing 714 Smart array 79 Query 438 creating 438 Radio Set 575 configuring 577 creating and placing 576 initial value 578 Rectangle configuring 325 creating and placing 324 repeating a placement 224 Selection List 579 configuring 580 creating and placing 580 single-line Editor 571 Slider Control 583 boundary values 584 configuring 584 creating and placing 583 initial value 584 tic marks 584 Smart, data-driven list 537 SmartDataBrowser 54 configuring 54, 512 creating and placing 519 creating master 57 dynamic 54 editing master 517 static 57 SmartDataField 535 placing and configuring 536 SmartDataObject 42 configuring 413 creating master 44
Index9
OpenEdge Development: AppBuilder SmartDataViewer 522 adding/removing fields 528 configuring 529 creating master 523 SmartDialog configuring 316 creating instance 35 SmartFilter 431 SmartFrame configuring 320 creating instance 35 SmartObject template 82 SmartPanel configuring 711 creating and placing 711 SmartSelect 537 configuring 539 creating and placing 538 SmartToolbar 72 configuring 74 creating and placing 73 creating new master 76 SmartWindow configuring 37 creating instance 35 opening property sheet for 37 special-purpose, where to find 224 Spin Buttons example of use 84 Spin Control (ActiveX) configuring 587 creating and placing 586 Spin Control (ActiveX) 586 Static Text 815 Toggle Box 589 configuring 590 creating and placing 589 Window (Smart) configuring 37 workspace 237 Object behavior accept dropped objects 310, 514, 533, 549, 555, 569, 574, 578, 582, 585, 591, 717 allow automatic re-sizing 533, 569, 574, 581, 585, 591 allow multiple selections 514, 549, 582 Index10 allow navigation between records 75 allow transactions 75 allow undefined value 541 allow user to change column width 517, 551 allow user to edit data 514, 534, 570, 575, 75 allow user to move 322, 327, 517, 535, 551, 557, A10 allow user to re-order columns 516, 551 allow user to re-size 310, 322, 328, 517, 535, 551, 557, A10 allow user to search on columns 517, 551 allow user to select 322, 328, 517, 535, 551, 557 appear at specific location 310 automatically clear field for input 533, 574 automatically populate fields 318, 515, 533, 541, 550, 555 automatically sort data 541, 556 automatically validate input 318, 515, 549 automatically wrap lines 570 automatically write out data changes 515, 549 cause ENDKEY condition 716 cause GO condition 716 change object scope 534, 556, 570, 575, 579, 582, 586, 592 create scrollbars when needed 311 data type 554, 573, 577, 581 decline input focus 311, 326, 533, 541, 549, 555, 569, 574, 579, 582, 585, 591, 717, 814, A3 disallow min/max resizing 311 discard leading spaces 533, 574 display as (widget type) 541 display context-sensitive help A3 display data type from schema 542 display field descriptor from schema 542 display MESSAGE output 310 display minimized in/above taskbar 311 display special help string 516, 550, 556 display status messages 311
Index display tooltip 542, 554, 569, 573, 578, 581, 585, 591, 814 emulate platform-native object 533, 574 format display 554, 573 indent next line 569 indicate input focus 717 initialize in hidden state 310, 327, 514, 533, 549, 555, 569, 574, 579, 582, 585, 591, 717, 814, A3 initialize with hidden data 569, 574, 582, 585, 591 interpret ESC as CHOOSE 716 journal changes 534, 555, 570, 575, 579, 582, 586, 592 maintain child-object layering 310 minimize to icon 310 move to next field when full 533, 574 page between different layouts 332 page length 321 participate in traversal list 515, 534, 549, 555, 570, 575, 579, 582, 586, 591, A3 predict user input 555, 556 prevent input echo 533, 574 provide scrollbars 515, 570 receive all RETURN events 717 resize to full screen 310 scroll by character or whole field 514, 549 stay in front of other objects 315 support SmartFilter in separate window 75 use help strings and validation from dictionary 318 use help strings and validation rules from dictionary 515, 549 Objects action control listed 15, 17, 110 ActiveX (OCX) listed 110 adding template to New-object dialog C8 adding to a tool menu C6 basic 4GL listed 15 control introduction to 72 creating and placing 224 data-access listed 18 data-display and -capture listed 15, 19, 110 defined 113 Dialog Boxes basic 4GL 323 Smart 316 for controlling actions 72 Frames basic 4GL 323 Smart 319 organizer creating procedure-based instance 35 introduction to 33 listed 15, 18 roles 34 other listed 17, 110 Rectangles 324 Smart listed 18 SmartDialogs 316 SmartFrames 319 SmartPanel 79 SmartWindows 36 Static Image 810 visible vs non-visible 112 Windows basic 4GL 322 Smart 36 Objects Palette 219 ActiveX (OCX) tool 222 cancelling tool selection 225 Check-Box tool See Toggle Box Combo-Box tool ActiveX 223 basic 4GL 222 customizing 225 Data-Browser tool basic 4GL 221 Smart 223 Data-Fields tool 221
Index11
OpenEdge Development: AppBuilder Data-pump tool Smart 223 Data-Viewer tool basic 4GL 221 Smart 223 Dialog Box tool basic 4GL 219 Smart 219 Editor (multi-line) tool 222 Editor (single-line) tool 222 Fill-in tool 222 Frame tool basic 4GL 221 Smart 219 hide tool buttons 220, 225 hide/show 217 keep in front 225 multiple placement 224 options 225 pointer tool 221 Pushbutton tool basic 4GL 222 Smart array 223 Query filtering tool smart 223 Query tool 221 Radio-Set tool 221 Rectangle tool 221 save current position, shape as default 225 Selection-List tool 222 Slider-Control tool 222 SmartContainer tool 224 SmartDataBrowser tool 223 SmartDataField tool 223 SmartDataObject tool 223 SmartDataViewer tool 223 SmartDialog tool 219 SmartFilter tool 223 SmartFolder tool 223 SmartFrame tool 219 SmartObject tool 223, 82 SmartPanel tool 223 SmartToolbar tool 224 SmartWindow tool 219 Spin-Buttons tool ActiveX 222 Static-Image tool 221 Static-Text tool 222 Index12 Timer tool ActiveX 223 Toggle-Box tool 221 Tool 223 tools not on basic 4GL Dialog Box 219 basic 4GL Window 219 SmartDialog 219 SmartFrame 219 SmartWindow 219 using 224 Window tool basic 4GL 219 Smart 219 OCX (ActiveX) object 82 Open existing object 28 Organizer Smart example of use 119 Organizers Simple SmartContainer 328 OUTMESSAGE SmartLinks 634, 641
P
Page 0 (Zero) always displayed 334 role of 334 Paged layouts creating 332 creating pages 333 deleting pages 333 designing without SmartFolder 339 identifying pages 333 see all pages together 334 using whole windows 341 Paging ADM Pages dialog deleting objects A6 moving objects between pages A6 setting the Design Page A6 setting the Startup Page A6
Index Design Page 333 Design Page, setting A6 listing a page's objects A5 moving objects between pages A6 Page 0 is default page 334 placing objects 333 SmartFolder 335 limitations 336 Startup Page setting A6 startup page 334 whole-window 341 without SmartFolder 339 Partitions configuring 429 JMS 635, 639 on AppServers 429 Pasting Section Editor 241 Persistence enabling A22 Pick List. See Selection List Placeholder design-time A29 SmartObject A29 Pointer 219, 221 Preferences default function type 228 double-click 227 layout grid 229 printing 230 Section Editor 230 setting 214, 226 Preprocessor names Section Editor 250 Procedure settings A20 Property sheet SmartDataObject 411 Pushbutton 713 creating and placing 714 example of use 120, 339, 341 labeling 718 Smart array 79 example of use 119 tool basic 4GL 222 Smart array 223 types supplied 714 close dialog or window 714 end application session 714 generic 714 invoke help system 714 move current-record pointer 714 view ADM page 714 Procedure-based object AppServer support, enabling A22 descriptive comments field A21 location of ActiveX (OCX) properties A21 location of executable A21 persistence specifying A22 Procedures files inspecting code 254 running 256 saving 257 in AppBuilder API C24 marking as modified C44 Section Editor 247 progress.cst C3 sample entry in C17 Properties viewing and editing 254 Properties Window A22
Index13
Q
Queries building 439 establishing join criteria 440, 441 establishing search criteria 442 establishing sort criteria 443 modifying 439 Section Editor 251 setting options 444 Query allowing user to filter 431 creating 438 filtering tool Smart 223 tool 221 Query Builder join mode 441 options mode 444 sort mode 443 table mode 439 using 438 where mode 442 Query Tuning options panel 445 Query-By-Example 431
Remote file management C38 Reserved names C45 ROUTER SmartLinks 637 Routing incoming documents 627 Run-time customization of user interface B19 Run-time expressions standard layouts B5
S
Save object 28 Section Editor 239 cutting, copying, pasting 241 database-field names 245 event names in 246 filenames/pathnames 253 invoking 239 navigating code sections 240 object names 252 preprocessor names 250 procedure/function calls 247 query definition 251 text-file insertion 243 using 241 Selection List 579 configuring 580 creating and placing 580 list of choices 581 tool 222 value of selection 581 value types 581 shared.cst C3 Simple SmartContainers 328 to 332 Single-line Editor 571 configuring 571 creating and placing 571
R
Radio Set 575 configuring 577 creating and placing 576 example of use 339 initial value 578 tool 221 Rectangle configuring 325 creating and placing 324 example of use 119, 339 tool 221 Remote development AppBuilder main window 218 saving files 257
Index14
Index Slider Control 583 bounds, upper and lower 584 configuring 584 creating and placing 583 initial value 584 scale markings 584 tool 222 upper and lower value limits 584 Smart defined 111 smart.cst C3 SmartB2BObjects 62 to 622 4GL/XML 62 configuring instances 618 creating instances 617 creating masters 617 do not use XMLMessage type 637 dynamic master 617 filename convention 617 instance properties incoming 622 multiple producers 621 outgoing 619 inter-business messaging 62 selecting dynamic version 618 transformation 62 SmartBusinessObjects and partitions 429 as DATA-TARGETs 424 bind connections to AppServers 429 can reduce complexity 419 configuration tasks 422 configuring 422, 428 creating and placing 421 filename convention 422 in Web applications 419 integration limit 419 whole-stream validation 423 SmartConsumers 633 to 642 configuring instances 638 creating instance 637 in batch mode 640 JMS Partitions 639 shutdown 639 SonicMQ domains 639 stopping when in batch mode 641 SmartContainer tool 224 SmartContainers design-time appearance 331 simple configuring 330 creating 328 instance properties 332 simple non-visible 328 SmartDataBrowser 54 creating and placing 519 dynamic 54 creating and placing 54 display/update rules 56 editing master 517 navigation in 710 static 57 configuring 512 creating master 57 tool 223 SmartDataField 535 example of use 543 SmartSelect 537 tool 223 SmartDataObject 42, 411 as placeholder 413 configuring 413 connectionless 413 creating and placing 411 data validation limitation 415 designing 45 example of use 119 master creating 44 editing 410 tool 223
Index15
OpenEdge Development: AppBuilder SmartDataObjects and DATA links 423 client-only version 43 dynamic and WebClient 44 as generic data pumps 44 limitation 44 static limitation 44 synchronizing 423 SmartDataViewer 522 adding/removing fields 528 configuring 528, 529, 530 fields layout 530 help string 534 initial value 534 creating master 523 example of use 119, 339, 543 state determines appearance 526 tool 223 SmartDialog configuring 316 creating instance 35 SmartFilter 431 configuring 432 displaying in separate window 76 example of use 76 tool 223 SmartFolder example of use 335 limitations 336 paging with 335 tool 223 SmartFrame configuring 320 creating instance 35 SmartInfo dialog A26 SmartLink types DATA 423 INMESSAGE 637 OUTMESSAGE 634, 641 ROUTER 637 SmartLinks adding, removing, modifying A23 API routine to add, remove C24 example of use 119, 120 list of A23 SmartLinks editor A23 SmartObject creating new 27 placeholder, creating as A29 property sheet A28 tool 223, 82 SmartObject template 82 SmartObjects advantages in using 111 creating under program control C39 to C42 deleting under program control C42 listed 18 menu-button menu 112 multiple layouts B23 non-visible example of 112 synchronizing 115 ventilator-button menu 112 visible vs non-visible 112 what Smart means 111 SmartPanel 79 configuring 711 creating and placing 711 example of use 119, 335, 339 tool 223 types supplied 710 SmartProducers 633 to 642 JMS Partitions 635 message persistence 636 message types 636 SonicMQ domains 635 SmartReceivers 622 to 626 SmartRouters 627 to 633 role in message-handling 629
Index16
Index SmartSelect 537 configuring 539 creating and placing 538 example of use 543 filtering the data 540 SmartSenders 622 to 626 creating instances 624 filename conventions 625 SmartToolbar 72 configuring 74 creating and placing 73 creating new master 76 limitations 73 tool 224 SmartWindow configuring 37 creating instance 35 example of use 119, 335 Source code examining 211 Spin Buttons tool ActiveX 222 Spin Control (ActiveX) 586 configuring 587 creating and placing 586 Starting AppBuilder 23 Static Image object 810 Static Text example of use 120 style selector and editor A36 tool 222 Static Text object 815 Status bar AppBuilder main window 26 Stop button AppBuilder main window 256 String literals specifying space allocation A30 String-Attributes dialog A30 Subscriptions persistence 636 preserving across sessions 640 Synchronizing with master layout B10
T
Templates adding to New-object list C8 Temp-tables defining and maintaining A33 Text tool 222 Text style choosing A36 defining A37 Timer tool ActiveX 223 Timer object interrupt-driven 816 Toggle Box 589 configuring 590 creating and placing 589 initial value 590 tool 221 Tool ActiveX (OCX) object 222 Check-Box. See Toggle Box Combo-Box ActiveX 223 basic 4GL 222 Data-Browser basic 4GL 221 smart 223
Index17
OpenEdge Development: AppBuilder Data-pump Smart 223 Data-Viewer basic 4GL 221 Smart 223 Editor, multi-line 222 Editor, single-line 222 Fill-in 222 Frame basic 4GL 221 Image 221 pointer 221 Pushbutton basic 4GL 222 smart array 223 Query 221 Query-filtering smart 223 Radio-Set 221 Rectangle 221 Selection-List 222 Slider-Control 222 SmartContainer 224 SmartDataBrowser 223 SmartDataField 223 SmartDataObject 223 SmartDataViewer 223 SmartFilter 223 SmartFolder 223 SmartObject 223, 82 SmartPanel 223 SmartToolbar 224 Spin-Buttons ActiveX 222 Text 222 Timer ActiveX 223 Toggle-Box 221 Tool bar AppBuilder main window 218 Tool icons adding to Objects Palette C4 Tools cancelling selection 225 latching and unlatching 224 list of 221 SmartB2BObject 617 SmartBusinessObject 421 SmartConsumer 637 SmartContainer 331 SmartProducer 634 SmartSender 624, 625 using 224 XML Schema Mapper PRO*Tool 611 Traversal path editing A31 Tree view 238
U
Undoing changes Section Editor 244 Usability avoid cross-connections 590 be sparing with colors A11 be sparing with font changes A39 fonts as corporate-identity signifier A36 neatness 334 role of Pushbutton 713 role of Toggle Boxes vs Radio Set 589 use fonts sparingly A36 violating expectations causes confusion 341
W
Web browser C38 Web preferences C38 web.cst C3 WebSpeed AppBuilder for 24 Widget open Property Sheet for 212
Index18
Index Widgets See also Objects adding to custom object file C9 capturing changes made by user 114 defined 113 reading & writing 113 showing changes made by program 114 Window basic 4GL configuring 322 creating new 27 opening Property Sheet for 37 Smart configuring 37 creating new 27 Workspaces 237 allowed objects in A8 for non-visible objects 238 saving 257 testing 256 defined 62 schema and mapping files 63 standards 62 standards committee 63 XML mapping consumer map file extension 611 creating a map file 612 creating a record 69 deleting a record 69 editor 610 editor PRO*Tool 610 external references 632 finding a record 69 illustration 64, 65 inbound/outbound files different 610 internal references 632 iteration 67 mapping schema nodes 613 node to data column 66 with conversion 66 node to function 66 node to procedure 66 node to whole data object 67 options 66 producer map file extension 611 schema file extension 611 selecting resources 612 starting editor PRO*Tool 611 .xmp file type 611 .xsd file type 611
X
XFTRs. See Extended features .xmc file type 611 XML and HTML 62 and W3C 62
Index19
Index20