Κυριακή, 22 Ιανουαρίου 2017

Αναθεώρηση 13 (έκδοση 8.2)

Revision 13, for version 8.2

\\ This is an advanced example of using events, and references
\\ M2000 never expose actual references.
\\ All items are searched by a hash function internal,
\\ using name of item and module name
\\ (maybe that name changed internal from interpreter)
\\ function weak$() return the internal name of any item included array item.
\\
\\ To run this write in M2000 CLI> edit a <enter> and then copy this
\\ press Esc and write a <enter> to run
\\ use Save pr1 <enter> to save it

\\ Nothing is static in M2000, except for "running" code.
\\ so Module deep1 isn't exist until first we make it a module to call
\\ and then when we call it, make anything as it runs
\\ Three steps: part of a source - source with a name - call that name
\\ M2000 interpreter use always source, never made any code of it.
\\ Using the source M2000 makes real objects and execute command on those.
\\
\\ Groups are static objects as list of items (we can reference specific item)
\\ ... like variables, modules, functions, events, lambdas, etc
\\ Here the task is to raise an event from an object (Call Event)
\\ and sending a value to this and to another object, calling functions
\\ and each function read a property y (a variable in the group)
\\ We test the raise of event when we pass the object (group)
\\ by value, by referenec, by weak reference
\\ and then we put copies of these groups in an array, and return it
\\ Then we fix the references, in the new copied array, and test again
\\ the raise of event from stored group (in array) and from passing
\\ with weak reference to another module.

Module deep1 {
      Group aa {
            y=123
            Event b { Read x }
            Function aa { Read x : Print x+.y }
            Module callme {
                  Call Event .b, number
            }
      }
      Group bb {
            y=456
            Function bb { Read x : Print x+.y}
      }
      Event aa.b New aa.aa(), bb.bb()
      Print "From Module a"
      aa.callme 5
      Module testme {
            Read c
            Print "From testme inside Module Deep1"
            c.callme
      }
      \\ Here we copy aa Group to c
      testme aa, 5
      \\  133
      \\ 466
      \\ 128
      \\ 461  (here is the fix, old versions print 128)
      \\ passing by reference was ok
      Module testme2 {
            Read &c
            Print "From testme2 inside Module Deep1"
            c.callme
      }
      testme2 &aa, 5
      \\ using weak reference was ok too
      \\ no copy or reference for each element in Group aa
      \\ just Call it like it is a global Module (using c$ as prefix value)
      Module testme3 {
            Read c$
            Print "From testme3 inside Module Deep1"
            c$.callme
      }
      testme3 &aa, 5
     
      \\ we can put copies of static objects in arrays items
      Print "Test Event from object in item in array"
      Dim A(10)
      A(0)=aa
      A(0).y=1000
      A(0).callme 5
      testme3 weak$(A(0)), 5
      \\ if array returned from this Module then event find error
      \\ because group bb deleted.
      A(1)=bb
      push A()
}
Deep1
\\ now all modules and variables in Deep1 are destroyed
\\ except stack values. And in stack we have an array
Print StackType$(1) \\ print mArray - the inside object for arrays in M2000
Print Match("A") \\ Print -1 (True), is Array
Dim A()
\\ first we create the array and then we put the object on it
Read A()
Print "From exported array"
\\ need to restore weak reference
For A(0) {
      \\ this block make A(0) static with a hidden name
      \\ and this name used every time
      Event .b Clear \\ clear all functions in event chain
      \\ here we don't need to give a lazy$() function.
      Event .b New .aa()
      \\ function lazy$() return an anonymus function with lazy evaluation
      \\ when this anonymus function run, set the module name to A
      \\ so A(1) can be found, also we have to write the parameters to pass
      Event .b New lazy$(A(1).bb(number))
     \\ this happen because we can't get reference from array items.
    
}
\\ Now we Call a non static group
Print "From Module a"
A(0).callme 15
Module testme3 {
      Read c$
      Print "From testme3 inside Module a"
      c$.callme
}
\\ Now we send it to module testme3 (module's deep1 modules are erased)
testme3 Weak$(A(0)), 15
\\ so now we have two objects, non static, but for this momemt they have
\\ one point static...the name of the array (A() is inside the module a)
\\ event b is calling from A(0) and opens A(1) reading variabe (property) y.
\\ Events may have by reference values as parameters and this works with multicast

Σάββατο, 21 Ιανουαρίου 2017

Αναθεώρηση 12 (έκδοση 8,2)

Προσθήκη στη γλώσσα για τους πίνακες ακεραίων και αλφαριθμητικών:
Μπορούμε να βάλουμε πίνακα στη θέση στοιχείου:


Dim a$(10)="No"
Dim b$(5)="Yes"
a$(0)=b$()
Print a$(0)(0) \\ Yes
a$(0)(1)="Hello"
Print a$(0)(1), a$(1) \\ Hello No

Dim a%(10)
a%(0)=function({{=10,11,12,13,14,15,16}})
Print a%(0)(3) \\13
a%(0)(3)+=1000
Print a%(0)(3) \\1013

Για πραγματικούς λειτουργούσε και στην αναθεώρηση 11

Dim a(10)
a(0)=function({{=10,11,12,13,14,15,16}})
Print a(0)(3) \\13
a(0)(3)+=1000
Print a(0)(3) \\1013
 

Στη Μ2000 όταν επιστρέφουμε δυο ή περισσότερες τιμές σε συνάρτηση τότε αυτές γράφονται σε πίνακα και επιστρέφει ο πίνακας. Η συνάρτηση function() δέχεται σαν όρισμα όνομα συνάρτησης και χωριστά τις παραμέτρους, ή ανώνυμη συνάρτηση. Μια ανώνυμη συνάρτηση είναι ένα αλφαριθμητικό με πρώτο χαρακτήρα μια αγκύλη. Τα αλφαριθμητικά στη Μ2000 μπαίνουν ή με διπλό εισαγωγικό αρχή και τέλος ή με αγκύλες { }. Εδώ η πρώτη αγκύλη δηλώνει ότι ακολουθεί αλφαριθμητικό, και η δεύτερη δηλώνει ότι έχει συνάρτηση (αυτό το καταλαβαίνει η function() ή συνάρτηση()). Μέσα στις διπλές αγκύλες έχουμε μόνο το = στην αρχή της εντολής (σημαίνει επιστροφή τιμής) και ακολουθούν εκφράσεις -εδώ αριθμοί- χωρισμένοι με κόμματα. Υπάρχει και η function$() για να επιστρέφει αλφαριθμητικά.

Έχει ενημερωθεί το git και το dropbox.

 

Πέμπτη, 19 Ιανουαρίου 2017

Ύψωση σε δύναμη και πρόσημο!


Στο παράδειγμα έχουμε τρεις μεταβλητές και τυπώνουμε το περιεχόμενό τους, όπως το έχουμε διαμορφώσει από ισάριθμες εντολές καταχώρησης του τύπου μεταβλητή = έκφραση.
a=-9**2
? a \\ 81
b
=0+-9**2
? b \\ 81
c
=0-9**2
? c \\ -81
Το -9 στη δευτέρα (-9 ** 2) είναι το -9 * -9 άρα το 81 (θετικό πρόσημο), στην a φαίνεται ξεκάθαρα. Στην b έχουμε δυο πρόσημα, το + και το -. Το πρώτο πρόσημο λέει να προσθέσουμε το επόμενο και το επόμενο είναι το -9**2 άρα το 81. Στο c έχουμε το – που σημαίνει “Αφαίρεσε” το 9**2 από το 0. άρα δίνει το 0-81 ή -81.
b1=0+(-9**2)
? b1
Εδώ στο b1 φαίνεται πως ο εκτιμητής παραστάσεων ενεργεί με παρενθέσεις, και είναι το ίδιο με το 0+-9**2, όπου το + επειδή είναι μετά το 0 λέει απλά “πρόσθεσε το παρακάτω -9**2”
Στη Μ2000 η ύψωση σε δύναμη γίνεται και με τον χαρακτήρα ^ (shift 6)
a=-9^2
? a \\ 81
b=0+-9^2
? b \\ 81
b1=0+(-9^2)
? b1
c=0-9^2
? c \\ -81

Μπορούμε στο μέρος της δύναμης να βάλουμε παρενθέσεις αλλά όχι πρόσημο πριν την παρένθεση θα χαθεί! Μέσα στην παρένθεση βάζουμε όποια έκφραση θέλουμε, ακόμα και αρνητικό (με μηδέν μας δίνει 1, ότι υψώσουμε σε 0 θα δώσει 1)
? 2-3**(2), 2-3**(-4)
Το ? 0^0 δίνει 1
Άλλα παραδείγματα:
? 2**-2,3*2**-2, 3/2**2 \\ .25, .75, .75
? (3/2)**2 , 3**2/2**2 \\ 2.25, 2.25
? 3**2-2**2+1 \\6
? (3**2)-(2**2)+1 \\6

Δευτέρα, 16 Ιανουαρίου 2017

Προγραμματισμός για αρχάριους!

θα δούμε πως με τρεις αριθμούς μπορούμε με απλό τρόπο να τους βάλουμε σε μια σειρά από τον μικρότερο στον μεγαλύτερο!

Ξεκινάμε τη γλώσσα (κλικ στο m2000.exe) και γράφουμε μετά το >
>edit A 
και ανοίγει ο διορθωτής και αντιγράφουμε το παρακάτω:


Read a, b, c
Local mx, md, mn
If a>b Then {
      If a>c Then {
            mx=a : If b>c Then { md=b : mn=c } Else { md=c : mn=b }
      } Else {mx=c : md=a : mn=b}
} Else.if a>c Then {
      mx=b : md=a : mn=c
} Else.if b>c Then {
      mx=b : md=c : mn=a
} Else {
      mx=c : md=b : mn=a
}
Print "min", mn
Print "middle", md
Print "max", mx


με πλήκτρο Esc γυρνάμε στη γραμμή εντολών
δοκιμάζουμε με το A και τρια νούμερα (χωρίζοντάς τα με κόμμα ",")
>A 1,4,3


Παραλαγή χωρίς τη χρήση τοπικών μεταβλητών, αλλά με τη χρήση του σωρού. Η εντολή Push (Βάλε) βάζει πάντα στην κορυφή, οπότε Push 1,2 θα έχει το 2 στην κορυφή (τελευταίο που μπαίνει θα βγαίνει πρώτο LIFO)

>edit b
Read a, b, c
If a>b Then {
      If a>c Then {
            Push a : If b>c Then { Push b,c } Else Push c,b
      } Else Push c, a, b
} Else.if a>c Then {
      Push b, a, c
} Else.if b>c Then {
      Push b, c, a
} Else Push c, b, a
Print "min", Number
Print "middle", Number
Print "max", Number


με πλήκτρο Esc γυρνάμε στη γραμμή εντολών
>B 4,100,24

Παρατηρούμε ότι και στα δυο προγράμματα οι λύσεις είναι έξι, και αν προσέξουμε το κάθε πρόγραμμα θα τις δούμε. Παρακάτω με πλάγια γράμματα. (το πρώτο Push a θα μπορούσε να πάει στα άλλα δύο ως Push a,b,c  και Push a,c,b)
Πράγματι δεν μπορούμε να έχουμε περισσότερους συνδυασμούς (λύσεις) για τρια νούμερα.

Read a, b, c
If a>b Then {
      If a>c Then {
            If b>c Then { Push α,b,c } Else Push α,c,b
      } Else Push c, a, b
} Else.if a>c Then {
      Push b, a, c
} Else.if b>c Then {
      Push b, c, a
} Else Push c, b, a
Print "min", Number
Print "middle", Number
Print "max", Number


Ο Σωρός τιμών κρατάει τις τιμές μέχρι να τις πάρουμε ή να τον αδειάσουμε. Εδώ δίνουμε εντολές στη γραμμή εντολών της Μ2000: (μετά το σήμα > )
>Push 1,2,3
>Stack
   3   2   1
>Read A
>Print A
  3
>Stack
   2  1
>Flush
>Stack

δεν μας δείχνει τίποτα (κενή γραμμή), οι τιμές 2 και 1 χάθηκαν πια.
Παρατηρούμε ότι τα προγράμματα Α και Β διαφέρουν ουσιαστικά στην χρήση ή μη τριών μεταβλητών, των mx, md, mn. Δηλώνονται τοπικές στη Β  με έναν απλό τρόπο με την εντολή local. Ουσιαστικά το Α έχει τρεις τοπικές, τις a,b,c ενώ το B έχει έξι (a,b,c,mx,md,mn).


Στη Β γίνεται χρήση του σωρού τιμών, του ίδιου σωρού που περνάμε τιμές στη B (ή το τμήμα B κατά την ορολογία της Μ2000). Κάθε φορά που θέλουμε να διαβάσουμε το νούμερο-αποτέλεσμα χρησιμοποιούμε την Number (Αριθμός) η οποία βγάζει την κορυφή του σωρού (Δίνει λάθος αν ο σωρός είναι άδειος ή αν η κορυφή δεν είναι αριθμός).


Ο Σωρός τιμών στην Μ2000 παίρνει διάφορα είδη εκτός από αριθμούς και δεν λέγεται στοίβα που φαίνεται να είναι καταλληλότερη ονομασία ως LIFO, γιατί είναι πιο σύνθετος, για τέσσερις λόγους: Πρώτον έχει FIFO λειτουργία άμεσα, δεύτερον έχει ανάγνωση από θέση, τρίτον έχει μετακίνηση από και προς την κορυφή οποιουδήποτε στοιχείου, ή ομάδα στοιχείων, και τέλος τέταρτον τα στοιχεία μποορεί να μην είναι ίδιου είδους. Στοιχείο μπορεί να είναι αριθμός, αλφαριθμητικό, έγγραφο (είδος αντικειμένου), ομάδα (το βασικό αντικείμενο της Μ2000), λάμδα συνάρτηση, γεγονός (άλλο αντικείμενο), πίνακας, κατάσταση (είδος λίστας), διάρθρωση (είδος λίστας). Για το λόγο αυτό λέμε ότι έχουμε Σωρό τιμών και όχι στοίβα. Παρόλα αυτά στα αγγλικά χρησιμοποιώ την εντολή Σωρός ως Stack (στοίβα). Αυτό δεν είναι απαραίτητα λάθος. Στα αναγνωριστικά των εντολών δεν παίζει άμεσο ρόλο η ερμηνεία ενός λεξικού αλλά η ερμηνεία του εγχειριδίου της γλώσσας.

>Flush
>Push 1,2,3
Μπορούμε να χρησιμοποιούμε το ? για Print ή Τύπωσε
>? stackitem(1), stackitem(2)
      3       2
Διαβάσαμε με δείκτη (η κορυφή είναι πάντα στο 1), αλλά δεν σηκώσαμε κάτι
>Drop
>? stackitem(1), stackitem(2)
     2       1
Τώρα πετάξαμε τη κορυφή 3 και έχουμε νέα κορυφή το 2 και ακολουθεί το 1
>Data 0, -1
>Stack
2 1 0 -1
Η εντολή Data βάζει πάντα στο τέλος! Οπότε το τελευταίο που βάζει θα είναι τελευταίο στο σωρό (ή στοίβα αν θέλετε)

Τώρα το Α θα το αλλάξουμε έτσι:

Local mx, md, mn
If stackitem(1)>stackitem(2) Then {
      If stackitem(1)>stackitem(3) Then {
            read mx : If stackitem(1)>stackitem(2) Then { read md, mn } Else { read mn, md }
      } Else { read md, mn, mx}
} Else.if stackitem(1)>stackitem(3) Then {
      read md, mx, mn
} Else.if stackitem(2)>stackitem(3) Then {
      read mn, mx, md
} Else {
      read mn, md,mx
}
Print "min", mn
Print "middle", md
Print "max", mx

Βλέπουμε ότι δεν διαβάζουμε τα a,b,c και τα αφήνουμε όπως έχουν για να τα διαβάσουμε στις τελικές μεταβλητές mn, md, mx

Μπορούμε όμως να μην χρησιμοποιήσουμε ούτε τις τρεις μεταβλητές, παρά μόνο το σωρό τιμών! Την κορυφή την σηκώνουμε με την Number αλλά την διαβάζουμε με την stacitem(1), και μπορούμε με την shift να την μεταθέσουμε στην Ν θέση, και με την shiftback να φέρουμε ως κορυφή το στοιχείο στη Ν θέση (δεύτερη παράμετρος σημαίνει πόσες φορές θέλουμε να γίνει)

Μπορούμε να γράψουμε το τμήμα c

>edit c
If stackitem(1)>stackitem(2) Then {
      If stackitem(1)>stackitem(3) Then {
            shiftback 3 : If stackitem(1)>stackitem(2) then shiftback 2
      } Else { shiftback 2}
} Else.if stackitem(1)>stackitem(3) Then {
      shiftback 2,2
} Else.if stackitem(2)>stackitem(3) Then {
      shift 3
      shiftback 2
}
Print "min", Number
Print "middle", Number
Print "max", Number

με Esc βγαίνουμε από τον διορθωτή
΄Φαίνεται πιο μαζεμένος ο κώδικας, αλλά σίγουρα πιο δυσνόητος. Αφαιρέσαμε πολλά ονόματα και αντικαταστήσαμε με ονόματα με δείκτες.
βάλτε εντολές Stack να δείτε τις μετακινήσεις μετά από τις Shift και ShiftBack.

Μπορείτε να σώσεται ότι έχετε γράψει, να το σβήσετε στον μεταφραστή, να αδειάσετε τον σωρό και να το ξαναφορτώσετε. (με Ctrl + A ξανασώνουμε ό,τι έχουμε φορτώσει με την Load)
>Save example1
>New
>Flush
>Load example1
>Modules ?

Επίσης κάθε τμήμα που τρέχουμε μπορεί να τρέξει με την Test  (έστω  ονομάσαμε c το τελευταίο τμήμα)
>Test c 1,4,2

Θα ανοίξει μια φόρμα και κάνουμε βηματική εκκίνηση. Παρατηρούμε το σωρό (αν κάνουμε αριστερό κλικ πάνω στην επιγραφή Next θα αλλάξει η προβολή από σωρό σε κώδικα που εκτελείται, ενώ στα κίτρινα "πλήκτρα", το Next Step κάνει εκτέλεση του επόμενου βήματος).




(Μπορούμε να αλλάζουμε τη φόρμα του τερματικού της Μ2000 σε αριθμό γραμμών και χαρακτήρων με την εντολή  Form. Πχ Form 80,60 θα δώσει φόρμα με 80 χαρακτήρες με 60 γραμμές)




Παρασκευή, 23 Δεκεμβρίου 2016

Classic Spaceship Example (OOP)

Παρακάτω είναι το κλασικό παράδειγμα με το διαστημόπλοιο, το οποίο σε C++ έχει πρόβλημα, γιατί οι συναρτήσεις μπορούν να καθοριστούν με overload να δουλέψουν για διαφορετικά αντικείμενα αλλά αυτό γίνεται την ώρα που κάνουμε compile, οπότε χάνουμε την δυναμική συμπεριφορά όταν αλλάζουμε interface.
Στη Μ2000 δεν έχουμε πολλαπλά interface, αλλά κάνουμε χρήση του αντικειμένου Ομάδα (Group) τα οποία μπορούμε να φτιάξουμε είτε απευθείας με την εντολή Ομάδα ή με συνάρτηση που γυρίζει Ομάδα και φτιάχνεται με την εντολή Κλάση. Οι κλάσεις στην Μ2000 είναι συναρτήσεις που δίνουν αντικείμενα ενός και μόνο τύπου: Ομάδα. Εδώ για να ξεχωρίσουμε τύπους, βάζουμε σε κάθε περίπτωση ένα όνομα τύπου σε μια "συμφωνημένη" ιδιότητα (μεταβλητή στην ομάδα), εδώ Iam$.
Αντί να κάνουμε Overload στο τμήμα (module) το οποίο δεν έχει νόημα στην Μ2000, δίνουμε μια παράμετρο Α η οποία όμως πρέπει να είναι ομάδα. Κάθε φορά ελέγχουμε το Iam$ για να κάνουμε αυτό που θέλουμε στη συγκεκριμένη ομάδα. Εδώ το πέρασμα της ομάδας γίνεται με αντιγραφή (by value). Αν χρεισιμοποιούσαμε το &Α τότε θα έπρεπε στην κλήση του τμήματος (module) να δώσουμε το χαρακτήρα & μπροστά από το όνομα της ομάδας για να την περάσουμε με αναφορά.


\\ M2000 has no types for classes
\\ so for this example we use property Iam$ for indicator of type
\\ A Class is a function which return an object (Group named in M2000)
\\ In M2000 modules and functions are open to include any list of parameters
\\ list of parameters added to a special stack
\\ functions clear this stack at the end
\\ modules use the same special stack to return values also
\\ Here we use module Collide only with one parameter
\\ But module SpaceShip (Look class SpaceShip) is a constructor and can be called
\\ as a function and return an object and this is the real constructor
\\ or as an object module for manipulating (we can add temporary functions or modules)

\\ This is an example from https://en.wikipedia.org/wiki/Double_dispatch#Classic_Spaceship_Example
\\
Class ApolloSpacecraft {
      Iam$="ApolloSpacecraft"
}
Class Asteroid {
      Iam$="Asteroid"
      Module CollideWith {
            \\ A is a Group (object in m2000)
           Read A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "Asteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "Asteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }
 
}
Class SpaceShip {
      Iam$="SpaceShip"
      module SpaceShip {
            \\ this is module but stand for a construction function for Class
            If match("G") then {
                  \\ if we provide an object (Group) then we can use it
                  read A
                  \\ in next statement we copy A properties to this
                  \\ so we copy a new value for Iam$
                  this=A
            }
      }
}
Class ExplodingAsteroid {
      Iam$="ExplodingAsteroid"
      Module CollideWith {
           Read A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "ExplodingAsteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "ExplodingAsteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }      
}
\\ at the left side we make a group from the function at the right
\\ inside interpreter push an unamed object to a register and then
\\ all elements (variables, functions, modules, etc) get name prefix and became static in this module
theAsteroid=Asteroid()
theSpaceShip=SpaceShip()
theApolloSpacecraft=SpaceShip(ApolloSpacecraft())
theAsteroid.CollideWith theSpaceShip
theAsteroid.CollideWith theApolloSpacecraft
\\ ok
theExplodingAsteroid=ExplodingAsteroid()
theExplodingAsteroid.CollideWith theSpaceShip
theExplodingAsteroid.CollideWith theApolloSpacecraft
\\ ok
\\ link make all variables of theExplodingAsteroid references to a new group
\\ named theAsteroidReference. Second reference for a name is an error.
link theExplodingAsteroid to theAsteroidReference
theAsteroidReference.CollideWith theSpaceShip
theAsteroidReference.CollideWith theApolloSpacecraft
\\ ok
link theApolloSpacecraft to theSpaceShipReference
theAsteroid.CollideWith theSpaceShipReference
theAsteroidReference.CollideWith theSpaceShipReference
\\ ok
\\ print  Asteroid hit an ApolloSpacecraft
\\ and   ExplodingAsteroid hit an ApolloSpacecraft


anotherSpaceShip=SpaceShip()
theAsteroid.CollideWith anotherSpaceShip
theAsteroidReference.CollideWith anotherSpaceShip
\\ prints  Asteroid hit a SpaceShip
\\ and     ExplodingAsteroid hit a SpaceShip
\\ We put a join of theApolloSpacecraft to anotherSpaceShip
\\ if anotherSpaceShip has some other items then these are also there.
\\ so only the same items changed and for the example Iam$ is changed too.
anotherSpaceShip=theApolloSpacecraft
theAsteroid.CollideWith anotherSpaceShip
theAsteroidReference.CollideWith anotherSpaceShip
\\ prints  Asteroid hit an ApolloSpacecraft
\\ and     ExplodingAsteroid hit an ApolloSpacecraft
finalSpaceShip=SpaceShip(theApolloSpacecraft)
theAsteroid.CollideWith finalSpaceShip
theAsteroidReference.CollideWith finalSpaceShip
\\ prints  Asteroid hit an ApolloSpacecraft
\\ and     ExplodingAsteroid hit an ApolloSpacecraft

In an new module we place the program bellow. Here we simulating the visitor pattern. We place a module to SpaceShip.
Class ApolloSpacecraft {
      Iam$="ApolloSpacecraft"
}
Class Asteroid {
      Iam$="Asteroid"
      Module CollideWith {
            \\ A is a Group (object in m2000)
           Read A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "Asteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "Asteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }
   
}
Class SpaceShip {
      Iam$="SpaceShip"
      module SpaceShip {
            \\ this is module but stand for a construction function for Class
            If match("G") then {
                  \\ if we provide an object (Group) then we can use it
                  read A
                  \\ in next statement we copy A properties to this
                  \\ so we copy a new value for Iam$
                  this=A
            }
      }
      module CollideWith {
            Read &inAsteroid
            inAsteroid.CollideWith this
      }
}
Class ExplodingAsteroid {
      Iam$="ExplodingAsteroid"
      Module CollideWith {
           Read A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "ExplodingAsteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "ExplodingAsteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }      
}
theAsteroid=Asteroid()
theSpaceShip=SpaceShip()
theApolloSpacecraft=SpaceShip(ApolloSpacecraft())
theExplodingAsteroid=ExplodingAsteroid()

link theApolloSpacecraft to theSpaceShipReference
link theExplodingAsteroid to theAsteroidReference
theSpaceShipReference.CollideWith &theAsteroid
theSpaceShipReference.CollideWith &theAsteroidReference
\\ prints  Asteroid hit an ApolloSpacecraft
\\ and     ExplodingAsteroid hit an ApolloSpacecraft



Now all calls to CollideWith need a group (object) by reference. I put (&) in the first parameter in Link statement (is optional). We have the same output.

Class ApolloSpacecraft {
      Iam$="ApolloSpacecraft"
}
Class Asteroid {
      Iam$="Asteroid"
      Module CollideWith {
            \\ A is a Group (object in m2000)
           Read &A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "Asteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "Asteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }
    
}
Class SpaceShip {
      Iam$="SpaceShip"
      module SpaceShip {
            \\ this is module but stand for a construction function for Class
            If match("G") then {
                  \\ if we provide an object (Group) then we can use it
                  read A
                  \\ in next statement we copy A properties to this
                  \\ so we copy a new value for Iam$
                  this=A
            }
      }
      module CollideWith {
            Read &inAsteroid
            inAsteroid.CollideWith &this
      }
}
Class ExplodingAsteroid {
      Iam$="ExplodingAsteroid"
      Module CollideWith {
           Read &A
           Select case A.Iam$
           Case "SpaceShip"
                 Print "ExplodingAsteroid hit a SpaceShip"
           Case "ApolloSpacecraft"
                 Print "ExplodingAsteroid hit an ApolloSpacecraft"
           Else
                 Print "???"
           End Select
      }      
}
theAsteroid=Asteroid()
theSpaceShip=SpaceShip()
theApolloSpacecraft=SpaceShip(ApolloSpacecraft())
theExplodingAsteroid=ExplodingAsteroid()

link &theApolloSpacecraft to theSpaceShipReference
link &theExplodingAsteroid to theAsteroidReference
theSpaceShipReference.CollideWith &theAsteroid
theSpaceShipReference.CollideWith &theAsteroidReference

Σάββατο, 3 Σεπτεμβρίου 2016

Τα νέα μου: Σεπτέμβριος 2016!

Πολλές αλλαγές τελευταία στη ζωή μου. Από υγεία καλά, ευτυχώς. Το πρώτο νέο (κακό) είναι ότι έχασα τον πατέρα μου 85 χρονών. Το τελευταίο χρόνο δεν πήγαινε καλά, και ήταν αναμενόμενο, αν και λυπηρό. Άφησε δυο παιδιά και πέντε εγγόνια.

Το δεύτερο καλό! Τα παιδιά μου είναι πια στην Αθήνα, και τα τρία σε ένα σπίτι (είναι όλα ενήλικα) και δυο εξ αυτών εργάζονται (ένα στο δημόσιο). Το μικρότερο η Φωτεινούλα αποφάσισε να μάθει τέχνη, και μάλιστα επειδή πιάνει το χέρι της θα γίνει μια καταπληκτική αισθητικός!

Το τρίτο "άγνωστο ή θα δείξει"...Μετακόμισα στη Πρέβεζα και πάω για μια νέα αρχή! Προς το παρόν η Μ2000 μένει πίσω για άλλες εργασίες άσχετες με το προγραμματισμό!

ΓΚ.


Πέμπτη, 11 Αυγούστου 2016

Εγχειρίδιο της Μ2000 - Τεύχος 29ο

17. Αντικείμενα γραφικού περιβάλλοντος (GUI)  της Μ2000. 
Ο διερμηνευτής της Μ2000 είναι γραμμένος σε γλώσσα που δίνει την δυνατότητα χρήσης παραθύρων, που έχουν προκαθοριστεί με τα στοιχεία που θέλουμε πριν την μετάφραση σε εκτελέσιμο αρχείο. Έτσι δεν είναι δυνατόν να δώσει η Μ2000 τις φόρμες και τα στοιχεία της Visual Basic, καθώς και να φορτώνει "ξένα" στοιχεία (τύπου ocx, activeX δηλαδή). Μετά την ενσωμάτωση γεγονότων στη  γλώσσα και επειδή όλα τα στοιχεία για τις σταθερές φόρμες στηρίζονται σε ένα στοιχείο χρήστη (user control), βρέθηκε μια διέξοδος, που έδωσε πραγματικά φόρμες με στοιχεία που θα μπορούσε να ορίσει ο χρήστης καθώς τρέχει το εκτελέσιμο του διερμηνευτή. Το πρόβλημα που παλαιότερα δεν επέτρεπε να φτιαχτεί κάτι τέτοιοι ήταν η ανάγνωση των γεγονότων από την γλώσσα. Αυτό λύθηκε με την ένταξη των γεγονότων (Events) στη γλώσσα. 

Πώς λειτουργεί το γραφικό περιβάλλον:

Ουσιαστικά κάθε φόρμα που φτιάχνουμε είναι αντίγραφο μιας φόρμας GuiM2000, και πάνω σε αυτήν υπάρχουν δυο στοιχεία, η επικεφαλίδα και ένα μικρό πλαίσιο για να τραβάμε τη φόρμα από την κάτω δεξιά γωνία. Η επικεφαλίδα είναι ένα στοιχείο glist το οποίο είναι και το μοναδικό user control που φτιάχνει όλες τα πλαίσια διαλόγου της Μ2000 (όπως το πλαίσιο διαλόγου Ρυθμίσεις, ή το Έλεγχος), αλλά και το αντικείμενο επεξεργασίας κειμένου. Ουσιαστικά το glist πάνω στη φόρμα GuiM2000 μπορεί να φορτωθεί πολλές φορές. Με το παρακάτω παράδειγμα μπαίνει κανείς στο νόημα:

Αν έχουμε μια φόρμα ΑΛΦΑ (δώσαμε αυτό το όνομα με την Όρισε) και θέλουμε να βάλουμε ένα στοιχείο Πλήκτρο (Button), τότε ένα νέο στοιχείο glist φορτώνεται σε μια φόρμα GuiM2000 (ξέρουμε ποια φόρμα είναι, γιατί το όνομα ΑΛΦΑ είναι αναφορά στη φόρμα) και σε ένα νέο αντικείμενο GuiButton παρέχεται η αναφορά στο στοιχείο glist και μια αναφορά στη φόρμα με όνομα Callback, και στο GuiControls της φόρμας GuiM2000, προστίθεται μια αναφορά για το GuiButton (το οποίο δεν  είναι Gui, αλλά κάνει sub classing το glist). Όταν κάνουμε κλικ στο glist (το πραγματικό αντικείμενο) τότε το σήμα πάει στο GuiButton  και αυτό καλεί την μέθοδο CallBack του αντικειμένου CallBack (είναι η αναφορά στο GuiM2000 μέσα στο GuiButton). Η μέθοδος CallBack ανήκει στο GuiM2000 και το μήνυμα πηγαίνει εκεί που έχει οριστεί κατά την Όρισε που δήλωσε τη φόρμα. Πριν η φόρμα καταστραφεί, (unload), πριν ορίσουμε  να είναι "τίποτα", τότε αποδεσμεύονται οι αναφορές μεταξύ στοιχείων γραφικών glist και GuiM2000 και του στοιχείου GuiButton. Για το λόγο αυτό χρησιμοποιείται η λίστα GuiControls στην φόρμα GuiM2000 η οποία έχει αναφορές στο GuiButton, και σε κάθε στοιχείο καλεί τη μέθοδο deconstruct

Αν δει κανείς το κώδικα του διερμηνευτή θα δει ότι οι φόρμες GuiM2000 είναι πιο πολύπλοκες από την παραπάνω περιγραφή και αυτό συμβαίνει γιατί πρέπει να εξυπηρετούν ορισμένους σκοπούς  όπως την διαδοχική (πολυεπίπεδη) χρήση Modals (modal είναι η φόρμα που ανοίγει ενώ κάνει μη προσβάσιμες τις άλλες φόρμες που είναι προσβάσιμες μέχρι στη στιγμή εκείνη, μέχρι να κλείσει).
Επίσης η πολυπλοκότητα υπάρχει και σε άλλο επίπεδο: Μπορούμε να έχουμε πίνακες με φόρμες, που σημαίνει ότι τα μηνύματα από φόρμες γυρίζουν και τον αριθμό φόρμας. Και επειδή μπορούμε να έχουμε και πίνακες με στοιχεία, και πίνακες με φόρμες, μπορούμε να έχουμε με μια συνάρτηση εξυπηρέτηση γεγονότος μια εξυπηρέτηση για πολλές φόρμες και πολλά στοιχεία στη κάθε φόρμα. (Στη Visual Basic 6 δεν έχουμε πίνακες φορμών, μόνο πίνακες στοιχείων, αλλά εδώ γίνεται αφού υπάρχει προσθήκη λογικής για να διαχειρίζεται αυτό το ζήτημα).

Τα μηνύματα από τη φόρμα GuiM2000 μπορούν να είναι απλά μιας εκπομπής, ή αν χρησιμοποιούμε ειδικό στοιχείο γεγονός να είναι πολλαπλής εκπομπής (multicast), και τα δύο όμως δεν επιστρέφουν τιμές στο αντικείμενο, που έστειλε τα μηνύματα.  Υπάρχουν όμως μηνύματα για το GuiM2000 που δεν εκτελούνται με τον "απλό" τρόπο αλλά με άλλο ξεχωριστό κανάλι, κλήσεων (CallBackNow) ο οποίος περνάει by reference (μέθοδος copy in - copy out) τις τιμές.

Μια διαφορά με άλλα συστήματα για γεγονότα είναι ότι δεν χρειάζεται να γνωρίζει ο διερμηνευτής ποια γεγονότα θα εξυπηρετήσουμε. Για όλα τα γεγονότα υπάρχει εκπομπή, και αν δεν υπάρχει ανταπόκριση τότε το μήνυμα χάνεται (διαγράφεται). Με την χρήση του απλού τρόπου μπορούμε να μαζεύουμε τα μηνύματα για να τα ικανοποιήσουμε ποιο μετά!  Ο άμεσος τρόπος (CallBackNow) δεν μπορεί να "μαζευτεί" αλλά αν έχουμε ανταπόκριση (συνάρτηση με το όνομα της φόρμας και το όνομα_μηνύματος) τότε θα έχουμε επιστροφή κατάστασης διαφορετικής από την "τωρινή" (δηλαδή αυτή που περιγράφουν οι τιμές που συνοδεύουν το μήνυμα).



17.1.  Φόρμες Χρήστη

Οι φόρμες χρήστη, είναι παράθυρα που δημιουργεί ο χρήστης, και έχουν τα παρακάτω βασικά χαρακτηριστικά:

  • Τίτλο  (Ιδιότητα "Title"). Το πλαίσιο του τίτλου μετακινεί το παράθυρο αν με το ποντίκι κρατήσουμε πατημένο το αριστερό πλήκτρο. Η πάνω αριστερή γωνία δεν μπορεί να βγει εκτός επιφάνειας εργασίας. Στο πλαίσιο αυτό υπάρχει αριστερά το πλαίσιο για το κλείσιμο (απόκρυψη) του παραθύρου. Όταν επιλέγουμε ένα παράθυρο τότε εμφανίζεται ο τίτλος ως τίτλος της εφαρμογής. Αν ο τίτλος δεν χωράει στο πλάτος του πλαισίου του, τότε αναδιπλώνει όσες γραμμές χρειάζεται αλλά δεν μεγαλώνει το πλαίσιο. Μπορούμε να αλλάξουμε μέγεθος γραμμάτων στο τίτλο, και να μεγαλώσουμε το πλαίσιό του (θα δούμε παράδειγμα σε αυτό). Υπάρχει τρόπος να επιλέξουμε το αντικείμενο του πλαισίου του τίτλου και να το "εξαφανίσουμε".
  • Επίπεδο. Είναι η επιφάνεια κάτω από το πλαίσιο, η οποία μπορεί να χρησιμοποιηθεί ως οθόνη και έχει δυνατότητα για χωριστή οθόνη (το κάτω μέρος να κάνει ολίσθηση, scroll), χωρίς να κρατάει στοιχεία που χάνονται στην ολίσθηση. Όλες οι εντολές γραφικών λειτουργούν (εκτός από τα hardware sprites, γιατί αυτά υπάρχουν μόνο για την κονσόλα, το επίπεδο πίσω από τα παράθυρα, το οποίο μπορούμε να το έχουμε φανερό ή όχι). Επίσης δεν επιτρέπονται οι εντολές για εισαγωγή. Για εισαγωγή τιμών χρησιμοποιούμε μόνο στοιχεία φορμών όπως θα δούμε παρακάτω. Με την εντολή Παράθυρο μπορούμε να δώσουμε το μέγεθος των γραμμάτων και το μέγεθος της φόρμας σε twips, μέσα από την εντολή επίπεδο. Και η εντολή φόρμα μπορεί να δώσει συγκεκριμένο αριθμό χαρακτήρων και γραμμών στη φόρμα χρήστη.
  • Μέγεθος Επιπέδου. Αν έχουμε επιλέξει την ιδιότητα "Resizable" να είναι αληθείς τότε είναι ενεργό ένα μικρό στοιχείο στην κάτω δεξιά γωνία, με το οποίο μπορούμε να αλλάξουμε μέγεθος στη φόρμα και να στείλουμε το γεγονός "Resize" ώστε να ετοιμάσουμε κατάλληλα το επίπεδο.
  • Διαφάνεια. Υπάρχει η μέθοδος"Opacity" η οποία αλλάζει την διαπερατότητα, αλλά επίσης δηλώνει και το χρώμα που θα είναι πάντα 100% διαπερατό.
  • Μέθοδος Εμφάνισης κατά τύπο Modal. Μπορούμε να επιλέξουμε την εμφάνιση της φόρμας με ταυτόχρονο πάγωμα των άλλων φορμών (μπορούν να ανανεώνουν στοιχεία, αλλά δεν μπορούμε να τα μετακινήσουμε ή να τα επιλέξουμε). Η μέθοδος εμφάνισης λέγεται "Show" και μια μη μηδενική τιμή δηλώνει ότι θα είναι Modal.
  • Μέθοδος μετακίνησης και μεγέθους. Μπορούμε με την μέθοδο "move" να μετακινήσουμε προγραμματιστικά την φόρμα μας και να δώσουμε (προαιρετικά) το μέγεθός της. (υπάρχει εξ ορισμού ένα μέγεθος, σε twips 8000 X 5000.
  • Μέθοδος για άμεσο κλείσιμο: "CloseNow".
  • Μέθοδος για ανανέωση όλων των στοιχείων: "RefreshALL"
  • Μέθοδος εμφάνισης: "Show". Καθορίζει το πώς θα εμφανιστεί μια φόρμα. (δες παραπάνω την αναφορά στο τύπο εμφάνισης Modal).
  • Μέθοδος για εμφάνιση όλων των στοιχείων: "ShowmeALL" (αν το οποιοδήποτε στοιχείο έχει την ιδιότητα enable αληθές τότε δίνει το σύστημα μια εντολή σχεδιασμού, αυτή η εντολή είναι μέρος της "Show"
  • Ιδιότητα που δείχνει αν είναι ορατή ή όχι η φόρμα: "Visible"
  • Ιδιότητα για το ύψος του τίτλου: "TitleHeight"
  • Μέθοδος για τη ρύθμιση γραμματοσειράς τίτλου: "FontAttr", δέχεται τρεις παραμέτρους, μια για τη γραμματοσειρά και προαιρετικά το μέγεθος και αν είναι φαρδιά ή όχι (εξ ορισμού είναι στην επιλογή Φαρδιά).
  • Μέθοδος για τη ρύθμιση γραμματοσειράς στοιχείων: "CtrlFontAttr" (ομοίως όπως το προηγούμενο)
  • Ιδιότητες για την γραμματοσειρά στα στοιχεία (μόνο ανάγνωση, για να δούμε τι έχουμε στα στοιχεία): "CtrlFontName", "CtrlFontsize", CtrlFontBold"
  • Άνοιγμα πρόσκαιρης φόρμας πάνω στη φόρμα με την μέθοδο "PopUp". Αν κάνουμε κλικ σε άλλη φόρμα ή στην αρχική τότε η φόρμα τύπου popup αυτόματα κλείνει. Παίρνει τρεις παραμέτρους, τη φόρμα που θα χρησιμοποιήσουμε ως Popup και δυο μεταβλητές για την θέση Χ και Υ του δείκτη την στιγμή που κάνουμε κλικ πάνω στη φόρμα (παράγεται γεγονός που μας δίνει αυτά τα στοιχεία καθώς και πιο πλήκτρο του δείκτη - ποντίκι- έχουμε πατήσει, αν έχουμε πατήσει).
  • Ιδιότητα για εμφάνιση του τίτλου και του πλαισίου για μετακίνηση: "Header", δέχεται αληθές ή ψευδές (true/false), και είναι και για ανάγνωση και για εγγραφή
Παράδειγμα με φόρμα που όταν κάνουμε κλικ εξαφανίζεται και εμφανίζεται διαδοχικά. Στο παράδειγμα μπορούμε να αφαιρέσουμε από τη πρώτη γραμμή το Γεγονός Ένα (ώστε να χρησιμοποιηθεί ένα αυτόματα αποδιδόμενο), καθώς και παρακάτω η συνάρτηση Μία και η εντολή Γεγονός που συνδέει αυτή τη συνάρτηση. Όταν βάζουμε ένα δικό μας αντικείμενο γεγονός τότε μπορούμε να παίρνουμε "ανάδραση" ή να επεκτείνουμε τον έλεγχο, αφού τα μηνύματα από τη φόρμα θα περάσουν από αυτή τη συνάρτηση. Εδώ να υπενθυμίσω ότι τα μηνύματα που δέχονται απάντηση/επιστροφή, (έχουν πέρασμα τιμών με αναφορά) δεν μπαίνουν από αυτό το γεγονός αλλά πάντα εκτελούνται με άμεσο τρόπο (δεν είναι φανερός στο χρήστη).

Στη φόρμα, στο παράδειγμα, δεν βάλαμε κάποιο στοιχείο ελέγχου. Όμως βλέπουμε τον τίτλο και το τετραγωνάκι αριστερά που κλείνει τη φόρμα (αυτό παράγει το μήνυμα Unload, και είναι άμεσο, δέχεται δηλαδή επιστροφή σε μια μεταβλητή οκ. Αν δεν είχαμε καμία χρήση του οκ στο τμήμα, τότε δεν θα υπήρχε θέμα με μια απλή Διάβασε. Αν όμως υπάρχει η οκ, τότε θα έχουμε θέμα επειδή δεν μπορούμε να αποδώσουμε νέα αναφορά σε μεταβλητή που ήδη δείχνει κάπου. Η χρήση της Διάβασε Νέο κάνει κάτι άλλο, δημιουργεί μια μεταβλητή οκ ακόμα και αν υπάρχει ήδη, και δίνει την αναφορά, και μόλις τερματίσει η συνάρτηση Απλό.unload διαγράφεται η τελευταία οκ, αυτή που δημιουργήθηκε. Να θυμίσω εδώ ότι ενώ στις κανονικές κλήσεις συναρτήσεων οι μεταβλητές σχετίζονται με τα ονόματα συναρτήσεων, σε αυτές που καλούνται από γεγονότα (αυτό το κάνει η συνάρτηση οκν$()) οι κλήσεις είναι σαν να έγιναν στο τμήμα, και για το λόγο αυτό μπορεί να προκύψει πρόβλημα, αν δεν χρησιμοποιήσουμε σωστά τις Διάβασε και τα ονόματα των μεταβλητών. 

Στην συνάρτηση Μία φαίνεται πως καλούμε μια συνάρτηση τοπικά, (η συνάρτηση μαζί με τα περιεχόμενα-παραμέτρους είναι σε αλφαριθμητικό). Εσωτερικά ο μεταφραστής αλλάζει το όνομα της συνάρτησης με το όνομα της Μία, το οποίο όμως έχει ήδη αλλάξει με μια εντολή Τμήμα που έβαλε στο κώδικα η συνάρτηση οκν$() στην εντολή Γεγονός όπου συνδέσαμε το γεγονός με την συνάρτηση! (Στα γεγονότα μπορούμε να συνδέουμε περισσότερες από μια συναρτήσεις, και αυτό είναι το λεγόμενο multicast)

Στο πρόγραμμα θέλω να φανεί το πώς συνδέουμε μια μεταβλητή με ένα αντικείμενο-ιδιότητα. Δηλαδή με την εντολή Με Απλό, "visible" ως ορατό δημιουργούμε ένα αντικείμενο propreference (έτσι ονομάζεται μέσα στο κώδικα της Μ2000 και έτσι εμφανίζεται ως τύπος) το οποίο συνδέει την ιδιότητα  ενός συγκεκριμένου αντικείμενου με ένα όνομα . Η μεταβλητή ορατό δεν είναι μια απλή μεταβλητή, και δεν μπορούμε να την χειριστούμε ως απλή μεταβλητή, αλλά έχει την ιδιότητα της εγγραφής και της ανάγνωσης (αν πράγματι το παρέχει το αντικείμενο), και η γραφή γίνεται με το ίσον (ως αντικατάσταση τιμής) και η ανάγνωση απλά με το όνομα στο δεξί μέρος.

Όρισε Απλό Φόρμα Γεγονός Ένα
Επίπεδο Απλό {
      Διάστιχο 0 \\ 30, 60, ...
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 8000,6000 \\ μέγεθος γραμμάτων, Χ, Υ σε twips
      \\ τα πραγματικά Χ και Υ θα είναι εδώ Χ.Σημεία και Υ.Σημεία
      \\ Η εντολή Παράθυρο κόβει ανάλογα για να κρατήσει το πλάτος όσο ακριβώς το κείμενο
      Οθόνη 1,0 \\ χρώμα όπως #AAFF22 ή Χρώμα(r,g,b), αριθμός χωρίσματος οθόνης
      Δρομέας 0, Ύψος Δια 2 \\ Ύψος Πλάτος είναι σε χαρακτήρες
      Αναφορά 2,"Hello World"
}
Μέθοδος Απλό, "Show"
Με Απλό , "visible" ως ορατό
\\ τα γεγονότα και οι μέθοδοι είναι σε μία γλώσσα, αγγλική
Συνάρτηση Απλό.Unload {
             Διάβασε Νέο &οκ
             οκ=Αληθές
}
Στη Κ=Ψευδές
Συνάρτηση Απλό.Click {
      Με Απλό, "Title", "Πάτα άλλη μια"
      Τύπωσε ορατό
      Αν Κ Τότε Πληκτρολόγιο "Α"
      Κ~
}
Συνάρτηση Μία {
      Διάβασε μνμ$
      Σημ 1 : Τύπωσε μνμ$
      Δες {Κάλεσε τοπικά μνμ$}
}
Γεγονός Ένα Νέο οκν$(&Μία())
Τύπωσε ορατό
α$=Κομ$ \\ περιμένει να πατήσουμε κάτι
Γεγονός Ένα Κράτησε \\ τώρα δεν ακούει
ορατό=Ψευδές
Τύπωσε ορατό
Για ι=1 εώς 10 {
      \\ δεν υποστηρίζει αυτό ορατό~
      \\ πρέπει να το δώσουμε κανονικά με ορατό = όχι ορατό
      \\ η ορατό είναι ειδικό αντικείμενο, που συνδέει ένα όνομα με μια ιδιότητα
      ορατό= όχι ορατό
      ανανέωση
      Αναμονή 500
}
Τύπωσε Τύπος$(ορατό)
Όρισε Απλό Τίποτα


Στο παρακάτω παράδειγμα δημιουργούμε μια απλή φόρμα με δυνατότητα να αλλάξουμε τις διαστάσεις της με το ποντίκι, από τη κάτω δεξιά γωνία:

Όρισε Απλό Φόρμα
Επίπεδο Απλό {
      Διάστιχο 0
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 8000,6000
      Οθόνη 1,0
      Δρομέας 0, Ύψος Δια 2
      Αναφορά 2,"Γειά σου Κόσμε"
}
Με Απλό,"Sizable", Αληθές
Function Απλό.Resize {
      Επίπεδο Απλό {
            Τύπος 16
            Cls 1,0
            Οθόνη 1,0
            Δρομέας 0, Ύψος Δια 2
            Αναφορά 2,"Γειά σου Κόσμε"
      }
}
Μέθοδος Απλό, "Show",1
Όρισε Απλό Τίποτα


Δείτε επίσης ότι έχουμε ανοίξει τη φόρμα με τύπο modal (αυτό κάνει το 1 που δίνουμε στη "Show")

Συνεχίζεται...