[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference marin::forte-ft

Title:Forte' Field Test Conference
Notice:Forte R3 is due in summer...with lots of NEW features
Moderator:MARIN::ARVIND
Created:Wed Aug 04 1993
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:919
Total number of notes:3356

908.0. "Dynamic Windows experience ?" by UTROP1::STEENIS_M (Martin van Steenis @UTO) Wed Mar 12 1997 13:04

    Hi,
    
    
    Just spoke to a customer in Holland. 
    
    They currently have a 'in house' developed development system 
    which features a primitive character cell menu generator offering 
    menu-driven GUI development (creating Windows from predefined 
    elements) and set-up of dynamic menu-bars and pop-up menu's based 
    on pre-defined profiles in a database.
    
    They've separated the meta-definitions of the application into a 
    RDBMS which builds the GUI based on tabledriven rules from the 
    database at run-time.
    Pre- and post conditions with a simple scripting language are used 
    to 'assemble' business logic from defined components and hook it 
    up to the GUI.
    Changing the GUI-rules and Business-Rule parameters in the 
    database, dynamically changes the application run-time behavior.
    This strong concept enabled them to develop a system in 1 month 
    instead of several (productivity increase more than 200%).
    
    
    Now the question is: Can we do this with Forte ?
    Specifically, can we implement a table-driven system that creates 
    menu's, menu bars, pop-up menu's, buttons, list boxes, 
    arrayfields, listfields, textfields, in short all widgets/compound 
    widgets at run-time ?
    
    I know we can use the Display Framework Widgets and control their 
    behavior and influence behavior and content at run-time.
    Express is not the answer, because the dynamic GUI aspects are 
    handled in the development environment and propagation of changes 
    need a new generation of code.
    
    My request is: 
    
    Who can give me a headstart and point me towards someone or a 
    company that has experience in developing and deploying a complete 
    dynamic GUI environment and is willing to talk about it ?
    
    Who can tell me what limitations I will run into ?
    
    Who can supply me with some examples ?
    
    
    I know at least one company is working on/with this somewhere in 
    France. Another is seriously doing implementation work in the U.S. 
    and my customer finds it a necessary feature.
    
    All pointers, examples, tips are welcome.
    
    Thanks in advance,
    Martin van Steenis@UTO
    [email protected]
    NSIS The Netherlands
    DTN 838-4998 or 4856
    
T.RTitleUserPersonal
Name
DateLines
908.1Classes yes, forms noNSIC00::KLERKThunderbirds are GoThu Mar 13 1997 00:589

  Unlike Visual Basic where you can save forms in a text format, Forte
  only offers PEX files in which forms themselves are stored in some
  sort of uu-encoded format, i.e. totally unreadable and inaccessible.
  You can insert/modify class definitions, but forms themselves seem
  impossible at this stage.

  Theo
908.2Here is a quick example I put togetherALFSS1::NESTERFri Mar 14 1997 06:45493
	I have another customer who is just starting to look into doing 
    something like this. So I began playing around yesterday and the attached 
    PEX file is what I came up with it. It is defintely not fancy but it
    does have examples of adding: labels, datafields, radiolists, dropdown,
    pushbuttons, submenus and menu items. Since pop-ups aren't
    supported in V2 I didn't mess with them but under V3 you should be able 
    to do them as well.
    
        Again,  this is very simple example but points out how to do
    several things like how to know when a dynamically created button is
    clicked as well as when a dynamically created menu itme is activated.
    
    Have Fun!
    
    Jeff
    
    
    
begin TOOL dynoscreen;

includes DisplayProject;
includes Framework;

-- START FORWARD CLASS DECLARATIONS
forward main is mapped;
-- END FORWARD CLASS DECLARATIONS

-- START FORWARD CURSOR DECLARATIONS
-- END FORWARD CURSOR DECLARATIONS

-- START CONSTANT DEFINITIONS
-- END CONSTANT DEFINITIONS

-- START C DATA TYPE DEFINITIONS
-- END C DATA TYPE DEFINITIONS

-- START CLASS DEFINITIONS

class main is mapped inherits from DisplayProject.UserWindow


has public  event addedfield;
has public  event getval;

has public  method Init;
has public  method Display;
has public  method CheckIfFieldExists(input FieldName: Framework.TextData): boolean;

has property
	shared=(allow=on, override=on, default=off);
	transactional=(allow=on, override=on, default=off);
	monitored=(allow=on, override=on, default=off);
	distributed=(allow=off, override=off);

has
+515146310000109800000d5a9fe4010100002101020000000002020600940800
+1d009fff010104210f1011120101011700009fff000000000900000bb80fa000
+000000000000000000010160600000000000000000009d0bb89d0fa000000105
+030301fffd0000000000000c0405000600000201000100004b000001000b0300
+0021010200000000050400001c01000506007a08004d009fff010101010f1011
+120101011700009fff010000000900005dc05dc0000000000303030300020404
+a0a00000000000000000009d5dc09d5dc000000105066b010000005dc05dc000
+060006000021010200000000070706007c08000d009fff010104010f10111201
+01011700009fff34000000097d4b094f0df70000000003030303000501016060
+0000000000000000009d094f9d0df700000105081001000000094f0df7000402
+01009fff009fff0001010000090000000404000000020a000b0c080000210202
+000000000a0b0906000302010000006400000a06007c08000d009fff01010401
+0f1011120101011700009fff3500000009000006830df7000100010303030300
+07010160600000000000000000009d06839d0df7000001050d10010000000683
+0df700040201009fff009fff00010100000e0000000404000000020f0010000d
+0000210202000000000f100e06000302010000000000000f06007c08000d009f
+ff010104010f1011120101011700009fff36000000099d01340003410b8e0001
+000103030303000a010160600000000000000000009d03419d0b8e0000010511
+100100000003410b8e00040102009fff009fff00010100001200000004040000
+0002131415001100002102020000000013151206000302010000006400001306
+007c08000d000000010104010f1011120101011700009fff3a00000009000002
+dd05f50001000103030303000f010160600000000000000000009d02dd9d05f5
+0000010516100100000002dd05f500040202009fff009fff0001010000170000
+000004040000000002001819001a001b00160000210302000000001a191b1706
+000302010000000000001806000302070000000000001906007c08000d009fff
+010104010f1011120101011700009fff3b000000099d02790000a7037c000100
+02030303030013010160600000000000000000009ca79d037c000001051c1001
+00000000a7037c00040101009fff009fff00010100001d000004040000021e00
+1c0000210102000000001e1d06000302010000000000001e060092080081029f
+ff21210401212121212121212100009fff3c00000009000000a7037c00010001
+0303030300190101a0a00000000000000000009ca79d037c0000010301091f02
+0100009e00442094001f00001c0113135768696368206669656c6420746f2067
+65740a1a06007808020102080867657476616c75650102042121212121212121
+1700019fff0e00000009009d013d010b0279000200010303030300130101a0a0
+0000000000000000009d010b9d02790000010909096765742076616c75650002
+011b0600b008000902080877686963686f6e6501020421212121210101011700
+020808746578746461746114000000099d03209ca70237022e00020002030303
+030013010180a00000000000000000009d02379d022e00000103020103200300
+03042000002104020001a60121222324210001a6010125002500001c0103034f
+6e65220001a6010226002600001c01030354776f230001a6010327002700001c
+0105055468726565240001a6010428002800001c010404466f75721406000302
+070000000000001506007c08000d000000010104010f1011120101011700009f
+ff3d000000099d05f564021505990001000203030303000f0101606000000000
+00000000009d02159d0599000001052910010000000215059900040201009fff
+009fff00010100002a0000000404000000022b002c0029000021020200000000
+2b2c2a06000302010000000000002b06007c08000d000000010104010f101112
+0101011700009fff3e000000091100014d057000010001030303030015010160
+600000000000000000009d014d9d0570000001052d1001000000014d05700004
+0201009fff009fff00010100002e0000000404000000022f0030002d00002102
+0200000000302f2e06000302010000000000002f06007c08000d009fff010104
+010f1011120101011700009fff4000000009000000a705700001000103030303
+002b010160600000000000000000009ca79d05700000010531100100000000a7
+057000040102009fff009fff0001010000320000000404000000023300340031
+000021020200000000333432060003020100000000006433060092080081029f
+ff21210401212121212121212100009fff4100000009000000a7027100010001
+03030303002f0101a0a00000000000000000009ca79d02710000010301093502
+0100009e00442094003500001c010b0b526f7720746f205573650a3406009208
+0081029fff21210401212121212121212100009fff42000000099d02d50000a7
+02370001000203030303002f0101a0a00000000000000000009ca79d02370000
+0103010936020100009e00442094003600001c010b0b436f6c20746f20557365
+0a3006009208008102000021210401212121212121212100009fff3f00000009
+9d01669ca700a702a30002000103030303002b0101a0a0000000000000000000
+9ca79d02a300000103010937020100009e00442094003700001c010d0d496e73
+6572742057686572650a2c06007c08000d000000010104010f10111201010117
+00009fff4300000009009d014d00c80599000200010303030300150101606000
+00000000000000009cc89d05990000010538100100000000c805990004010200
+9fff009fff0001010000390000000404000000023a003b003800002102020000
+00003a3b3906000302010000000000003a0600f6080089020303726f7701020b
+21212121210101011700030707496e74656765721000000009000000c802cd00
+01000103030303002c010280a00000000000000000009cc89d02cd0000010302
+0107000a000009ff8100009e004000240301003b0600f6080089020606636f6c
+756d6e01020b21212121210101011700040707496e746567657211000000099d
+02cd0000c802cd0001000203030303002c010280a00000000000000000009cc8
+9d02cd00000103020107000a000009ff8100009e004000240301001006007c08
+000d000707427574746f6e73010104010f1011120101011700059fff2e000000
+09009d034103410df70002000103030303000a01016060000000000000000000
+9d03419d0df7000001053c100100000003410df700040304009fff009fff0001
+0100003d00000000000000040400000000000000023e000000000000003f0040
+004100420000004300440000003c00002107020000000041423f3e4043443d06
+0003020100000000001e3e060092080081029fff212104012121212121212121
+00009fff44000000090000012c0279000100010303030300100101a0a0000000
+0000000000009d012c9d027900000103010945020100009e0044209400450000
+1c0115154669656c64204e616d650a546f204372656174650a3f0600f6080089
+0209096669656c646e616d6501020b2121212121010101170008080854657874
+446174612200000009199d014d00c8023f00020001030303030010010280a000
+00000000000000009cc89d023f000001030201070008000009ff8100009e0040
+0014030100400600780802010209096d616b656c6162656c0102042121212121
+2121211700099fff31000000099d02d59d012c010b02dd000200020303030300
+100101a0a00000000000000000009d010b9d02dd000001090a0a6d616b65206c
+6162656c00020141060078080201020d0d6d616b65646174616669656c640102
+0421212121212121211700069fff0c000000099d06409d012c010b037c000200
+030303030300100101a0a00000000000000000009d010b9d037c000001090d0d
+6d616b65646174616669656c6400020142060078080201020c0c6d616b656472
+6f70646f776e01020421212121212121211700079fff15000000099d0a179d01
+2c010b03be000200040303030300100101a0a00000000000000000009d010b9d
+03be000001090c0c6d616b6564726f70646f776e00020143060078080201020d
+0d6d616b65726164696f6c697374010204212121212121212117000a9fff3200
+0000099d029b9d0237010b0352000300020303030300100101a0a00000000000
+000000009d010b9d0352000001090d0d6d616b65726164696f6c697374000201
+44060078080201020e0e6d616b6570757368627574746f6e0102042121212121
+21212117000b9fff33000000099d060e9d0237010b03e8000300030303030300
+100101a0a00000000000000000009d010b9d03e8000001090e0e6d616b657075
+7368627574746f6e0002010b06007c08000d0008084d61696e47726964010104
+010f10111201010117000c9fff0d00000009009d06e702050205000200010303
+03030007010160600000000000000000009d02059d020500000105461001ffff
+0001f401f400040000009fff009fff0001010000470404024600002100020000
+00004706000302010000000000000c0600030209000000000000471a7e898f9c
+e29ced9d015a9d01669d01729d01df9d01eb9d01f79d02669d02729d027e9d02
+f19d02fe9d030a9d03169d03809d038b9d03979d03e99d04039d04619d04c29d
+04d09d04d89d04e29d04ea9d04f49d04fc9d05089d05109d051b9d05279d0596
+9d05a29d05ae9d061b9d06279d06339d069f9d06ab9d06b79d07099d071b9d07
+6f9d07819d07d69d07ea9d08589d08649d08709d08d39d093b9d09cd9d09de9d
+09ea9d0a3d9d0a599d0ac59d0b279d0b909d0bf79d0c609d0ccb9d0d389d0d42
+9d0d4e9d0d5a9cd9191a385e5f6b7e88898d8f9cad9cd39cd49ce09ce29cec9c
+ed9d010b9d01319d01329d013e9d01559d015a9d01649d01669d01729d01909d
+01b69d01b79d01c39d01da9d01df9d01e99d01eb9d01f79d02159d023d9d023e
+9d024a9d02619d02669d02709d02729d027e9d029c9d02c29d02c39d02cf9d02
+e89d02f19d02fb9d02fe9d030a9d03169d03349d035b9d035c9d03689d037d9d
+03809d038a9d038b9d03979d03b59d03da9d03db9d03dd9d03e99d03ed9d0403
+9d04299d04519d04529d04619d048f9d04b89d04b99d04bc9d04c09d04c29d04
+cc9d04d09d04d89d04dc9d04e29d04ea9d04ee9d04f49d04fc9d05009d05089d
+05109d05149d051b9d05279d05459d056d9d056e9d057a9d05919d05969d05a0
+9d05a29d05ae9d05cc9d05f29d05f39d05ff9d06169d061b9d06259d06279d06
+339d06519d06769d06779d06839d069a9d069f9d06a99d06ab9d06b79d06d59d
+06fa9d06fb9d06fd9d07099d070d9d071b9d07399d07609d07619d07639d076f
+9d07739d07819d079f9d07c79d07c89d07ca9d07d69d07da9d07ea9d08089d08
+2f9d08309d083c9d08539d08589d08629d08649d08709d08989d08bd9d08be9d
+08c19d08c69d08d39d08fe9d09259d09269d09299d092e9d093b9d09609d0988
+9d09899d09959d09b49d09cd9d09d79d09de9d09ea9d0a089d0a2e9d0a2f9d0a
+319d0a3d9d0a419d0a599d0a889d0aaf9d0ab09d0ab39d0ab89d0ac59d0aec9d
+0b169d0b179d0b279d0b529d0b7c9d0b7d9d0b909d0bba9d0be49d0be59d0bf7
+9d0c229d0c4c9d0c4d9d0c609d0c8c9d0cb69d0cb79d0ccb9d0cf19d0d199d0d
+1a9d0d269d0d379d0d389d0d429d0d429d0d4e9d0d5a0000
-20caa1f1


end class;
-- END CLASS DEFINITIONS

-- START SERVICE OBJECT DEFINITIONS
-- END SERVICE OBJECT DEFINITIONS

-- START CURSOR DEFINITIONS
-- END CURSOR DEFINITIONS

-- START TYPEDEF DEFINITIONS
-- END TYPEDEF DEFINITIONS

-- START METHOD DEFINITIONS

------------------------------------------------------------
method main.Init
begin
super.Init();
row = 1;
column = 1;
whichone = new;
fieldname = new;
whichone = new;
end method;

------------------------------------------------------------
method main.Display
begin
//
// Sample code to generate and work with a dyanmic screen.
//
// What we are basically doing is to create new widgets and
// parent them to a grid that is on the display. My grid
// is called MainGrid.
//
//
// Author: Jeff Nester 
// Phone:  (423)989-9515
///////////////////////////////////////////////////////////
self.Open();
//
// Set up a counter to use when creating labels.
//
TextGraphicCounter : integerdata = new(value=1);
//
// The following is setting up a Submenu called Jeff
// that has doit as an item. If you do not have a menu bar
// already you must instantiate one. My example is starting
// without a menu
//
window.menu = new;          // create the necessary holder for the menu
smenu :submenu = new;       // create a submenu
smenu.name = 'mFile';        // Name it mFile
smenu.text ='File';          // and display the item File
smenu.parent = self.window.menu; // put it on the screen

mitem : menucommand = new;  // create an item
mitem.name = 'mExit';       // the name is mExit
mitem.text = 'Exit';        // and the display message is Exit
mitem.parent = smenu;       // add it to the sub menu we set up

event loop
//
// Post the addedfield event so the screen will start with
// the correct data in the list of fields field.
    post addedfield;
    
	when task.Shutdown do
		exit;

// Make a label
//		
	when <makelabel>.click do
//
// Labels are of type textgraphic
//
  	    newfield : textgraphic = new;
	    newfield.text = fieldname.value; // set the label
//	    
// I am going to generate a unique name for the labels
//
	    n : textdata = new;
	    n.replaceparameters('Label %1',TextGraphicCounter);
	    TextGraphicCounter.setvalue(TextGraphicCounter.value + 1);
	    newfield.name = n; // set the widgets name
//
// To position the field into the appropriate cell in the
// grid we must set the row and column.
//
	    newfield.row = row;
	    newfield.column = column;
	    newfield.parent = <MainGrid>; // set grid as parent
	    column = column + 1;
        post addedfield; // Notify the screen that a field was added

//
// Add a pushbutton
//
	when <makepushbutton>.click do
//
// Verify if the field name already exists if it does
// don't let them add it again.
//
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;	    
	    newfield : pushbutton = new; // Create the button widget
	    newfield.label = fieldname.value; // set its label
	    newfield.name = fieldname.value;  // set its name
//
// To position the field into the appropriate cell in the
// grid we must set the row and column.
//
	    newfield.row = row;
	    newfield.column = column;
	    newfield.height = 250;  // set button height
	    newfield.parent = <MainGrid>; // set grid as parent
	    column = column + 1;
        post addedfield; // notify form that it has added a field
//
// Make a DataField
//
	when <makedatafield>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : datafield = new;
	    newfield.name = fieldname.value; // set the field name
	    newfield.textvalue = 'test';     // set a default value
	    newfield.row = row;              // set location to insert
	    newfield.column = column;
	    newfield.parent = <MainGrid>;    // define parent
	    column = column + 1;	    
        post addedfield;                 // notify the list of fields field

//
// Make a drop down list
//
	when <makedropdown>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : droplist = new;  // create the new widget
	    newfield.name=fieldname.value; // set its name
//
// The next several lines are to create the array of listelements
// to set the droplist to
//
	    tmp : listelement = new; 
	    tmp.textvalue='One';
	    tmparray : array of listelement = new;
	    tmparray.appendrow(tmp);
	    tmp = new;
	    tmp.textvalue  ='Two';
	    tmparray.appendrow(tmp);
//	    
	    newfield.setelementlist(tmparray); // set the element list
	    newfield.row = row; // set the insert point
	    newfield.column = column;
	    newfield.textvalue = tmparray[1].textvalue;
	    newfield.parent = <MainGrid>;  // define the parent
	    column = column + 1;   
        post addedfield;  // notify the list all fields field
        
//
// Make a radio list
//        
	when <makeradiolist>.click do
	    if CheckIfFieldExists(fieldname) then
	       self.window.messagedialog('Field with name already exists!');
	       continue;
	    end if;
	    newfield : radiolist  = new;  // create new widget
	    newfield.name=fieldname.value;// set its name
//
// Set up the array of listelements that we need for the 
// radio button
//
	    tmp : listelement = new;
	    tmp.textvalue='One';
	    tmp.integervalue = 1;
	    tmparray : array of listelement = new;
	    tmparray.appendrow(tmp);
	    tmp = new;
	    tmp.textvalue  ='Two';
	    tmparray.appendrow(tmp);
//
	    newfield.setelementlist(tmparray); // set the widget
	    newfield.row = row;			       // define the insert position
	    newfield.column = column;
	    newfield.parent = <MainGrid>;      // set the parent
	    column = column + 1;   
        post addedfield; 			    // notify the list all fields field
//
// When you double click on the list of fields or select
// one and click on the getvalue button we want to go get
// the data associated with the field
//
    when <whichone>.doubleclick do
       post getval;
	when <getvalue>.click do
 	   post getval;
//
// This code actually retrieves the data that is stored in the
// field
//
 	when getval do
       tmp : textdata = new;
//
// Use GetFieldByName to retrieve the particular fieldwidget
       fieldobj : fieldwidget = <maingrid>.getfieldbyname(whichone);
//
// Since different kind of widgets store their data differently
// you must cast the object to get to the appropriate attributes
//
       if fieldobj <> NIL then
          if fieldobj.isa(datafield) then
             self.window.messagedialog((datafield)(fieldobj).textvalue);
          elseif fieldobj.isa(droplist) then
             self.window.messagedialog((droplist)(fieldobj).textvalue);
          elseif fieldobj.isa(radiolist) then
              self.window.messagedialog((radiolist)(fieldobj).textvalue); 
          elseif fieldobj.isa(textgraphic) then
              self.window.messagedialog((textgraphic)(fieldobj).text);
          elseif fieldobj.isa(pushbutton) then
              self.window.messagedialog((pushbutton)(fieldobj).label);         
          else
             self.Window.messagedialog('Dont know the field type');
          end if;
       else
          self.window.messagedialog ('No such field');
       end if;
//
// To trap a click on a dynamic button you must catch ChildClick
// on the grid and then evaluate what was clicked on and then take
// appropriate action
//
    when <maingrid>.ChildClick (DE=eventInfo, FW=child, x=x, y=y, mod=modifier, Node=node, row=row, col=column) do
       if fw.isa(pushbutton) then
          tmp : textdata = new;
          tmp.ReplaceParameters(
                'PushButton: %1 was pushed.',
                (pushbutton)(fw).name);
          self.window.messagedialog(tmp);
       end if;
//
// The addedfield event tells us to update the whichone field
// this field is where I show the list of fields. I am updating
// it this way to show how to run through all of the fields in the
// grid.
//
    when addedfield do
       tmp : array of listelement = new;
       tmp2 : listelement;
//
// Performing a For loop through <grid>.Children will return
// all children of the grid.
//
       for fw in <maingrid>.children do
          tmp2 = new;
          tmp2.textvalue.setvalue(fw.name);
          tmp.appendrow(tmp2);
       end for;
       <whichone>.setelementlist( tmp );
//
// To catch activation of the dyanmically created menu bars you
// have to listen for menu.childactivate and then determine
// which one was activated and then take what ever action you 
// need to
//
    when self.window.menu.childactivate (m = child ) do
        if (m.name.isequal('mExit')) then
           post task.shutdown;
        end if;
end event;
self.Close();
end method;

------------------------------------------------------------
method main.CheckIfFieldExists(input FieldName: Framework.TextData): boolean
begin
       fieldobj : fieldwidget = <maingrid>.getfieldbyname(FieldName);
       if fieldobj <> NIL then
          return TRUE;
       end if;
       return FALSE;

end method;
-- END METHOD DEFINITIONS
HAS PROPERTY
	CompatibilityLevel = 0;
	ProjectType = APPLICATION;
	Restricted = FALSE;
	MultiThreaded = TRUE;
	LibraryName = 'dynoscre';
	StartingMethod = (class = main, method = Display);


end dynoscreen;