Τετάρτη 19 Ιανουαρίου 2022

Ανανθεώρηση 52, Έκδοση 10 (Νέο Listbox με πολλές στήλες).

Σε αυτήν την αναθεώρηση εκτός άλλων έκανα μια μεγάλη μεταμόρφωση στο βασικό σύστημα φορμών της Μ2000. Οι φόρμες της Μ2000, αυτές που φτιάχνει ο χρήστης, έχουν ένα και μόνο ένα βασικό στοιχείο, ένα αντικείμενο glist4. Αυτό το αντικείμενο είναι ένα listbox, το οποίο είναι γραμμένο από το μηδέν, ως ένα User Control της Visual Basic 6. Όλα τα στοιχεία ελέγχου έχουν φτιαχτεί με βάσει αυτό το στοιχείο. Ακόμα και ο επεξεργαστής κειμένου, πάνω στη βασική φόρμα της Μ2000 (τη κονσόλα) έχει από κάτω αυτό το αντικείμενο. Στην ουσία αυτό που ήθελα ήταν να έχω έναν φορέα που θα στέλνει τα κατάλληλα γεγονότα. Στο ερώτημα, γιατί να έπρεπε να φτιάξω κάτι από το μηδέν η απάντηση είναι ότι ήθελα ορισμένα πράγματα που δεν τα εύρισκα αλλού, ειδικά την πληθώρα γεγονότων.

Το στοιχείο λέγεται glist4, το g από το George και το 4 επειδή αυτό είναι το τέταρτο, και καλύτερο. Καλύτερο ως προς την δυνατότητα επέκτασης. Το πρώτο που είχα φτιάξει δεν ήταν Unicode, είχε οριζόντια και κάθετη μπάρα ολίσθησης και είχε εσωτερικά σύστημα χρωματισμού, και στην πράξη ήταν ένα Editbox. Μετά έφτιαξα μια μπάρα ολίσθησης πιο ειδική, ώστε να μην έχει "άνοιγμα" 32768 σημεία, αλλά εκατομμύρια, και την έβαλα με ένα απλό listbox που έφτιαξα για να την δοκιμάσω. Από εκείνο το σημείο ξεκινάει να γράφεται με σωστό τρόπο το στοιχείο glist  (υπήρξε το 2 το 3 και το 4). Αυτό που ήθελα ήταν να μην έχει flickering (δυστυχώς τα στοιχεία της VB6 είχαν θέμα flickering). To flickering είναι αναλαμπές που φαίνονται λόγω κακής χρήσης του χρόνου, για να δοθεί η ανανέωση της προβαλλόμενης εικόνας του στοιχείου. Έχει σημασία το πότε παράγονται γεγονότα σε σχέση με το πότε σχεδιάζεται η εικόνα. Επίσης για ελάφρυνση, υπάρχει τρόπος να συσσωρευθούν ενέργειες μέσω χρονιστή (timer) ώστε σε επαναλαμβανόμενες ενέργειες πχ μια μετακίνηση της μπάρας ολίσθησης από κάτω προς τα πάνω να γίνει χωρίς  να εμφανιστούν όλα τα στοιχεία της λίστας αλλά βάσει χρόνου να ανανεώνεται το στοιχείο δείχνοντας νέες γραμμές με δεδομένα μέχρι αυτά στην κορυφή, τόσα ώστε να  νιώθουμε ότι έγιναν συνεχόμενα, με τη ταχύτητα που κουνήσαμε το χέρι μας. Να μην υπάρχουν δηλαδή καθυστερήσεις, τερμοπαίγματα, κολλήματα!

Οι στόχοι από σχεδιασμό ήταν:

  • Χρήση Unicode (έγινε πράγματι, και μπήκε και η χρήση RTL κειμένου, που γράφεται από δεξιά προς τα αριστερά). Επιπλέον μπορούν να εμφανιστούν και Unicode χαρακτήρες τύπου surrogates (με αριθμό μεγαλύτερο από 65535 που χωράει ο βασικός 16bit στο UTF16LE).. 
  • Διαφάνεια. Να μπορούμε δηλαδή να έχουμε φόντο την όποια εικόνα πάνω στην φόρμα. Και αυτό έγινε. Η διαφάνεια γίνεται με αντιγραφή στην εικόνα του στοιχείου της εικόνας της φόρμας (στο μέρος που το στοιχείο "πατάει" στη φόρμα. Υπάρχει παράδειγμα με φόρμες που ζωγραφίζουμε πίσω από ένα κουμπί (στοιχείο ΠΛΗΚΤΡΟ ή BUTTON) και δεν ξεχωρίζουμε το για πότε έγινε η αντιγραφή στο στοιχείο. Αυτό συμβαίνει γιατί "συγχρονίζονται" τα στοιχεία με τη φόρμα και όλα μαζί "ανανεώνονται".
  • Να μπορούμε στα στοιχεία της λίστας να "διορθώνουμε" με απλό τρόπο (δηλαδή να εμφανίζεται κατ΄επιλογή μας η γραμμή για εισαγωγή κειμένου). Αυτό έγινε για κείμενο με στοίχιση αριστερά και κέντρο (ακόμα δεν έχει φτιαχτεί για δεξιά στοίχιση, δεν ήταν στο σχεδιασμό, αλλά στην επόμενη αναθεώρηση σκοπεύω να γίνει και αυτό).
  • Να μπορεί η λίστα να έχει ή δικά της στοιχεία, δηλαδή σε δικό της σύστημα καταχώρηση, ή να δέχεται εξωτερικά, μέσα από εκπομπές γεγονότων. Ένα γεγονός είναι μια κλήση, για την οποία το αντικείμενο δεν γνωρίζει το πώς και το αν θα ανταποκριθεί ο "εξυπηρετητής" της. Αυτό που γνωρίζει είναι το τι θα κάνει με την επιστροφή των στοιχείων (αν πάρει στοιχεία). Στην ουσία με τα γεγονότα το αντικείμενο "Εκθέτει" ένα μέρος του, και με τις συναρτήσεις εξυπηρέτησης γεγονότων, το χειριζόμαστε. Αυτή είναι μια μορφή "subclassing". Πράγματι όλα τα στοιχεία των φορμών της Μ2000 είναι αντικείμενα που πάνω σε αυτά "πέφτουν" τα γεγονότα των glist4. Προγραμματιστικά, όταν ορίζουμε ένα στοιχείο σε μια φόρμα, το σύστημα δημιουργεί δυο αντικείμενα, το ένα πάνω στη φόρμα ως glist4 (το combo έχει δυο glist4, το δεύτερο σε νέα φόρμα, για να εμφανίζεται η "αναδυόμενη" λίστα) και το άλλο είναι αυτό που χειριζόμαστε μέσα από το πρόγραμμα της Μ2000. Και τα δύο παράγουν γεγονότα, αλλά όχι τα ίδια.
  • Επιπλέον ως "εξωτερικά" στοιχεία μπορεί να είναι περιεχόμενο (το κείμενο στο στη γραμμή της λίστας) ή η εικόνα. Δηλαδή, αντί να πάρει το κείμενο και να το "γράψει" το glist4, το παίρνει έτοιμο ως τελική εικόνα (αφού δώσει το φόντο, που μπορεί να είναι μέρος από την εικόνα του φόντου). Έτσι δουλεύει το EditBox, όπου εμφανίζει χρωματισμένο κείμενο (χρωματισμός κώδικα). Αυτό δεν γίνεται μέσα στο glist4, όμως επειδή αυτό ξέρει το "πλάτος" του, δέχεται παραγράφους για να τις "σπάσει" σε γραμμές, όπως επίσης μέσω των χειρισμών μας πάνω στο glist4, ακολουθεί το EditBox να στέλνει τις κατάλληλες έτοιμες εικόνες. Το EditBox εκτός από το glist4 και τα γεγονότα του έχει και το Document αντικείμενα, με δικά του γεγονότα. Στο Document βρίσκεται το κείμενο αλλά και η πληροφορία για το χρωματισμό. Όταν "ζητάει" το glist4 να φτιάξει την εικόνα του, το EditBox παίρνει στοιχεία από το Document, και παράγει τις εικόνες-απαντήσεις. Ο δρομέας που "αναβοσβήνει" στο κείμενο είναι μέρος της λογικής του glist4, και το EditBox το κατευθύνει ανάλογα.
  • Στο σχεδιασμό του glist4 ήταν και η χρήση στοιχείων του ως Radio Button και ως Επιλογές με "τσεκάρισμα". Και μια πιο προχωρημένη, για πολλαπλή επιλογή που γίνεται στις φόρμες διαλόγου για τα αρχεία και τους φάκελους (όπου και εκεί το ίδιο στοιχείο είναι από κάτω) . Το Combo είναι ένα στοιχείο που χρησιμοποιείται για μενού (αλλά και το Listbox μπορεί να φτιάξει λίστες επιλογής, χωρίς να είναι αναδυόμενο).
  • Λειτουργία σπρωξίματος της λίστας στο κατακόρυφο, και σπρωξίματος στο οριζόντιο (αυτό το τελευταίο ήθελα να μοιάζει σαν τις λίστες στο android, που αντί να δίνουμε διπλό κλικ τραβάμε την λεζάντα δεξιά. Αυτό πράγματι μπορούμε να το κάνουμε και αν θέλουμε το ενεργοποιούμε ή όχι. Στα μενού του Combo έχει μπει αυτή η λειτουργία. Στο Editbox ολισθαίνουμε το κείμενο με σπρώξιμο και είναι πολύ ωραίο και φυσικό σαν να τραβάμε λίγο πάνω το κείμενο για να διαβάσουμε και το ξανακατεβάζουμε, χωρίς να πάνε στη μπάρα ολίσθησης που κάνει μεγάλες μετακινήσεις, ή αν πάμε στα άκρα της να δώσουμε δυο τρια κλικ στο κάτω σημείο και μετά πάλι δυο τρια κλικ στο πάνω σημείο για να κάνουμε το ίδιο πράγμα (αλλά πιο κουραστηκό το πήγαινε έλα με το ποντικί).
  • Η κάθετη μπάρα ολίσθησης κρύβεται, και εμφανίζεται είτε όταν σπρώχνουμε το κείμενο (για να πάμε γρήγορα σε άλλα σημεία) είτε όταν περνάει από το χώρο της ο δείκτης του ποντικιού. Στις παλιότερες εκδόσεις δεν μπορούσε να αλλάξει χρώματα, όπως στις νεότερες. Στο κενό χώρο της μπάρας βλέπουμε το κείμενο! Η μπάρα "σχεδιάζεται" μέσα στο glist4, δεν αποτελεί ξεχωριστό στοιχείο ελέγχου. Σε μια παλιότερη έκδοση είχα και οριζόντια αλλά καταργήθηκε γιατί η οριζόντια μετακίνηση είτε γίνεται ως σπρώξιμο (δες προηγούμενη παράγραφο) είτε σε εγγραφή κειμένου γίνεται αυτόματη μετακίνηση βάσει της θέσης του δρομέα, και με animation. Αν στον διορθωτή της Μ2000 γράψουμε μια πολύ μεγάλη γραμμή (και δεν έχουμε το Word Wrap, αναδίπλωση λέξεων - αυτόι αλλάζει με το F1), και πατήσουμε HOME/END διαδοχικά θα δούμε την γραμμή να πηγαινοέρχεται, όμορφα!
Στην αναθεώρηση 52, άλλαξα τον τρόπο που το glist4 καταχωρεί τα στοιχεία του, έτσι ώστε να έχω και σε αυτήν την αναθεώρηση αλλά και σε επόμενες την ευχέρια να προσθέτω πράγματα χωρίς να χαλάω ότι ήδη έχω φτιάξει. Εδώ λοιπόν έβαλα ένα jsonobject αντικείμενο. Οι δομές json με ενδιέφεραν και έφτιαξα δικό μου αντικείμενο (στην ουσία είναι δυο, ο JsonArray και το JsonObject). Η παλιά δομή ήταν ένας UDT πίνακας. UDT σημαίνει User defined type, δηλαδή ένας τύπος μεταβλητής που ορίζεται από μένα. Δεν είναι αντικείμενο αλλά "μνήμη" με πεδία. Το προ της 52 αναθεώρηση UDT είχε 16 bytes το ελάχιστο για κάθε γραμμή (αν χρησιμοποιούσαμε την εσωτερική δομή), όπου δυο long (32bit, 4bytes) ήταν για αλφαριθμητικά το περιεχόμενο (content) και το επιπλέον (contentID) για τα μενού, ένα όνομα για επιστροφή τιμής, ανεξάρτητα από τη θέση).

Δείτε τη παλιά δομή. Ενας boolean εδώ είναι 16bit (ισόβαθμος με integer). To Line έλεγε αν θα μπει γραμμή αντί για κείμενο (οπότε δεν μπορεί να επιλεχθεί και ο "δρομέας" της λίστας, κατακόρυφος περνάει πάνω από τέτοιες γραμμές, αν υπάρχει κείμενο μπαίνει "μη ενεργό" κείμενο αντί για γραμμή.) Κανονικά θα έπρεπε το Line να είναι πριν το content, για να είναι οι 32bit αριθμοί σε όρια καθαρών 32 bit περιοχών, αλλά δεν με χάλαγε όπως ήταν, αφού έκανα τη δουλειά μου.

Private Type itemlist
selected As Boolean
checked As Boolean
radiobutton As Boolean
content As String
contentID As String
Line As Boolean
End Type

Τώρα η νέα δομή είναι αυτή, με μόλις 8 bytes: Αν έχουμε κενό στοιχείο στη λίστα δεν θα φορτωθεί το content το αντικείμενο JsonObject. Το Flags προς το παρόν χρησιμοποιείται ως προς τα 5 λιγότερα σημαντικά bits. Δηλαδή τώρα χρησιμοποιώ bit για τους boolean, και εδώ έχει προστεθεί ένα ακόμα που λέει ότι η γραμμή είναι κενή γιατί ανήκει απλά σε κάτι προηγούμενο

Το morerows, λέει στο σύστημα του glist4, ότι η γραμμή αυτή έχει επιπλέον γραμμές. Αυτό μπήκε νέο σε αυτή την υλοποίηση. Μπορούμε να έχουμε δυο ή περισσότερες γραμμές σαν μια γραμμή. Αν και το glist4 δεν είχε ως στόχο να έχει στοιχεία με διαφορετικό ύψος (εκτός από την επικεφαλίδα), με το σύστημα με το morerows μπορεί μια γραμμή να έχει ύψος σε ακέραια πολλαπλάσια. Αυτό είχε δυο τρεις επιπτώσεις στο κώδικα, που αντιμετωπίστηκαν, όπως η ταξινόμηση. Στη ταξινόμηση η λύση ήταν απλή, πριν την ταξινόμηση μαζεύουμε σε μια συνέχεια μόνο τις γραμμές που δεν "ανήκουν" σε άλλες. κάνουμε την ταξινόμηση και μετά απλώνουμε τα στοιχεία βάζοντας τόσες "κενές" γραμμές όσες μας λέει το morerows.  Επειδή όλα τα "βαριά" στοιχεία είναι στο JsonObect, η μετακίνηση των itemlist είναι άνευ πρακτικής καθυστέρησης (αντιγράφονται μόνο τα 8bytes). To morerows έχει ανώτερη θετική τιμή το 32767, αλλά δεν υπάρχει περίπτωση να καλυφθεί κάτι τέτοιο. Αν μια λίστα έχει ύψος σε σειρές, πχ 10 ή 20 τότε ένα στοιχείο ύψους πάνω από 20 θα σήμαινε ότι δεν θα μπορεί κανείς να δει όλα τα στοιχεία του (αν είναι γεμάτο) σε μια όψη της λίστας, αλλά θα έπρεπε να ολισθαίνει την λίστα για να βλέπει. Εδώ να κατανοήσει ο αναγνώστης ότι το στοιχείο glist4 ολισθαίνει τη λίστα όχι κατά pixel αλλά κατά γραμμή.  Μπορεί να είναι ωραία η κατά pixel κάθετη ολίσθηση, αλλά προς το παρόν, δεν γίνεται κάτι τέτοιο. Αυτό που γίνεται είναι ότι αν κρατήσουμε πατημένο το αριστερό πλήκτρο και σπρώξουμε την λίστα πάνω ή κάτω και αυτή ακολουθεί, και αν συνεχίσουμε μπαίνει αυτοματισμός και τρέχει η λίστα προς την κατεύθυνση που "σπρώχνουμε" (αυτό δεν το κάνουν στοιχεία της VB6, και παλαιότερα το έκανε ο Firefox για να σπρώχνεις τη σελίδα με το ποντίκι, και σου έδειχνε έναν κύκλο και ένα βελάκι). Το να έχουμε και ολίσθηση κατά pixel για κάτι που μας ενδιαφέρει να τρέχει γρήγορα, δεν λέει, αφού πρακτικά λόγω ταχύτητας θα χαθεί αυτή η "ελάχιστη ολίσθηση".


Private Type itemlist
Flags As Integer
morerows As Integer
content As JsonObject
End Type

Τι είναι λοιπόν το JsonObject και γιατί βοηθάει εδώ; Κάθε στοιχείο στο JsonObject έχει ένα κλειδί και μια τιμή. Η τιμή μπορεί να είναι μια από τα στοιχεία: null, true, false, αριθμός, αλφαριθμητικό, jsonObject, jsonArray. Το JsonArray έχει και αυτό στοιχεία αλλά δεν έχει κλειδιά, αλλά δείκτη, με αρχή το 0. Αν ο πίνακας δεν έχει στοιχεία (γίνεται) και δώσουμε ότι το 5ο στοιχείο (4 στο δείκτη) είναι το 100, τότε θα φτιαχτεί το [null, null, null, null, 100], δηλαδή οι τιμές που δεν δόθηκαν θα είναι null. Γενικά ότι ζητάμε και δεν υπάρχει επιστρέφει τιμή null. Έτσι αν έχω γράψει τις δυο πρώτες στήλες σε μια γραμμή (από το 1 έως το 2) θα έχει το [null, "πρώτη στήλη", "δεύτερη στήλη"] με τη διαφορά ότι δεν θα βλέπω τα ελληνικά (θα είναι κωδικωποιημένα ώστε στο αλφαριθμητικό να είναι μόνο χαρακτήρες ASCII κάτω από το 128). Κατά την εμφάνιση πχ 5 στηλών, οι τρεις που λείπουν θα επιστρέφουν null, και δεν θα απασχολούν μνήμη. Αν γράψω όμως στην πέμπτη στήλη τότε η 3η και η 4η θα πάρουν το null ως εγγραφή. Το JSON σημαίνει "JavaScript object notation", δηλαδή είναι ο τρόπος που αποθηκεύει στοιχεία η javascript (και μπορούν να εμφανιστούν δεδομένα ως κείμενο, τα οποία βολεύει η δομή για την μεταφορά τους μέσω διαδικτύου). H M2000 έχει και αντικείμενο XML. Το έχω γράψει και αυτό! Δεν με συμφέρει όμως η χρήση του εδώ. Το XML είναι και αυτός ένας τρόπος αποθήκευσης στοιχείων, που δίνει κείμενο ως εξαγώμενο. Υπάρχει διαφορά μεταξύ Json και XML. Το json έχει μια τη χρήση του μονοπατιού. Δηλαδή το μονοπάτι (το βάζω σε "αυτάκια" όπως λέμε τα διπλά εισαγωγικά) "C.1.[ALFA BETA]" λέει ότι στο JsonObject στο κλειδί "C" περιμένω ένα JsonArray και ειδικότερα στο δεύτερο στοιχείο του (το 1 είναι το δεύτερο) περιμένω ένα JsonObject, με κλειδί ALFA BETA (έχει διάστημα και για το λόγο αυτό το έβαλα σε τετράγωνες αγκύλες []). Αν περιμένω να πάρω τιμή και δεν υπάρχει όλη αυτή η δομή θα πάρω το null, αφού δώσω το ItemPath(). Αν θέλω να γράψω στο μονοπάτι αυτό την τιμή 100 τότε θα το φτιάξει άμεσα με μια AssignPath. Αν δεν ξέρω τι έχει το μονοπάτι τότε θα το ψάξω! (υπάρχουν εντολές). Το XML  είναι διαφορετικό αρκετά. Αρχικά υπάρχει μια λίστα από στοιχεία σε διάταξη. Κάθε στοιχείο του XML είναι ένα άλλο XML ή απλά είναι κείμενο (το οποίο είναι ό,τι θέλουμε να είναι). Δεν υπάρχει διάταξη με άμεση αναζήτηση με κλειδί όπως το json (πίνακας κατακερματισμού). Στο json τα κλειδιά είναι μοναδικά. Στο XML δεν υπάρχουν κλειδιά! Τα στοιχεία είναι σε μια διάταξη τύπου συλλογής (collection). Κάθε στοιχείο λέγεται child. Η σειρά μετράει. Αν θέλουμε να "μαρκάρουμε" κάποιο στοιχείο, τότε θα δώσουμε ένα χαρακτηριστικό (attribute) το οποίο έχει μοναδικό όνομα για το στοιχείο, και έχει τιμή που γράφεται σε αλφαριθμητικό (μπορεί να είναι αριθμός) αλλά δεν μπορεί να είναι XML. Έτσι το XML ομαδοποιεί τα στοιχεία, σε μια σειρά και τα διαφοροποιεί πέρα από το περιεχόμενό τους και με βάσει τα χαρακτηριστηκά που έχουμε επιλέξει. Το HTML λειτουργεί ως ένα XML. Στο XML δεν έχουμε ευρετήριο εκτός και αν το φτιάξουμε με άλλη δομή. Δεν συζητώ για το XML ως κείμενο. Στο αντικείμενο XMLdata της M2000, κάθε τελικό στοιχείο (έχει μόνο κείμενο ως δεδομένα αλλά και μια σειρά από χαρακτηριστικά) είναι ένα node, ένας κόμβος (εδώ είναι τερματικός). Κάθε node είναι αντικείμενο, και έτσι μπορούμε αντί να αντιγράψουμε τα στοιχεία από το XML να πάρουμε μόνο τους δείκτες του και να τους "καρφώσουμε" σε μια άλλη δομή, για επιλεγμένα σοτιχεία που θέλουμε και με τον τρόπο που μας βολεύει. Έτσι οι δυνατότητες του XML είναι πάνω στη μετέπειτα επεξεργασία, και όχι ειδικά πάνω στην βασική δομή του! Σε αντίθεση το JSON είναι φτιαγμένο για να δουλεύει άμεσα, να γράφουμε και να αλλάζουμε τιμές! Στο JsonObject δεν θα βάλουμε ποτέ ένα JsonArray σε δυο σημεία, αν χρησιμοποιούμε τα AssignPath. Στο XML αν θέλουμε βάζουμε το ίδιο στοιχείο εκατό φορές, δηλαδή το δείκτη του "μοναδικού" στοιχείου, μπορούμε να το γράψουμε σε άλλες 99 θέσεις χωρίς πρόβλημα! Στην παραγωγή του "κειμένου" θα έχουμε 100 φορές το στοιχείο. Αν τώρα από το κείμενο πάρουμε πάλι το XML θα έχουμε 100 διαφορετικά αντικείμενα εκτός αν έχουμε τόσο καλό parser, που βρει τα όμοια και δημιουργήσει το αρχικό. ένα συν 99 αντίγραφα δείκτη. Στο Json δεν γίνεται αυτό. Η "serialize" μορφή (το κείμενο) δίνει πάντα το ίδιο αποτύπωμα όταν περάσει στη δομή, στο αντικείμενο, με αυτό που έκανε την παραγωγή του. Στο Xml επειδή "παίζουμε" με δείκτες συνέχεια γίνεται να έχουμε μπερδέματα όπου ο δείκτης του αντικειμένου είναι και μέρος του, στοιχείο του. Έχει προβλεφθεί στο κώδικα για το XML στη Μ2000 ο έλεγχος "κύκλου" κατά το serialize του XML. Στο json δεν παίζουμε με δείκτες (αν και μπορούμε πρόσκαιρα να πάρουμε ένα αντικείμενο σε δείκτη), αλλά παίρνουμε το κείμενο (τη serialize μορφή) και σε ένα νέο εισάγουμε τα δεδομένα και αυτό τα κάνει πάλι "δυαδικά" με νέους δείκτες. Μια διαφορά μεταξύ json και xml είναι ότι στο xml μπορούμε εύκολα να αλλάξουμε διάταξη στοιχείων (επειδή είναι collection, και μπαίνει και βγαίνει εύκολα στοιχείο), σε αντίθεση, στο JsonObject δεν υπάρχει διάταξη (μόνο κλειδιά), ενώ στο JsonArray, η παρεμβολή/διαγραφή στοιχείου, σημαίνει μετακινήσεις (για μικρούς πίνακες δεν μας χαλάει αυτό). Θα μπορούσε κανείς να υλοποιήσει το JsonArray με collection, αλλά στην ουσία, η σωστή χρήση του πίνακα ως πίνακα του δίνει πλεονέκτημα. Το νιοστό στοιχείο διαβάζεται άμεσα, ενώ για το collection,  που μπορεί να είναι ένα btree, ή κάτι ανάλογο, θέλει κάποιες "επισκέψεις" σε σελίδες. Γενικά όπου αλλάζουν περισσότερο τα δεδομένα και λιγότερο η δομή, βάζουμε json. Πχ για έναν επεξεργαστή κειμένου η μορφή XML θα βοήθαγε περισσότερο γιατί προσθέτουμε παραγράφους ή άλλα "αντικείμενα", σε μια διάταξη και μπορούμε να πάμε στο μέσον και να σβήσουμε. Στο αντικείμενο Document δεν έβαλα XML (δεν το ήξερα τότε, είναι παλιό αντικείμενο, η βάση του είναι 15+ ετών, πολύ πριν φτιαχτεί το glist4, το χρησιμοποιούσα στο αντικείμενο Εγγραφο), αλλά μια διπλή συνδεδεμένη λίστα. σε πίνακες (!!) με τον para() να έχει UDT το οποίο έχει άλλους δυο πίνακες 

Ο τύπος Paragraph έχει από 4 bytes δείκτης σε πίνακα (όταν τον φτιάξουμε), επί δύο, αφού έχουμε δυο πίνακες, και δυο ακόμα 32bit αριθμούς. Τα colordata() και startfrom μπήκαν για τον χρωματισμό κώδικα. Ο πίνακας content() έχει "σπασμένη" την παράγραφο βάσει του πλάτους του στοιχείου προβολής ή είναι ολόκληρη η παράγραφος στο πρώτο στοιχείο του πίνακα αν το έγγραφο δεν είναι συνδεδεμένο με στοιχείο προβολής, ή αν έχει βγει το Word Wrap (κουμπί F1)/ Για να "σπάσει" τη παράγραφο το αντικείμενο "σηκώνει" ένα γεγονός. Αν αυτό είναι συνδεδεμένο τότε γίνεται το σπάσιμο αλλιώς λέμε "Στο Καιρό" και δεν κάνει κάτι άλλο, τοποθετεί το στοιχείο σε μια γραμμή, στη πρώτη.
Τα πλήκτρα  F6, F7, F8 στον διορθωτή και στο EditBox, δουλεύουν σαν σελιδοδείκτες (Εγγραφή της παραγράφου και του δρομέα αν δεν υπάρχει προορισμός, μετακίνηση αν δεν είναι ο δρομέας στο προορισμό, και διαγραφή αν είναι στο προορισμό, όλα με ένα κουμπί). Στην ουσία ο σελιδοδείκτης δείχνει στο Para() άμεσα. Αν έχει διαγραφεί τότε  το lines θα είναι 0, οπότε είναι άκυρος ο δείκτης, και αυτό το ελέγχει εύκολα το πρόγραμμα και βγάζει τα "σινιάλα", απενεργοποιεί τον σελιδοδείκτη. Αν είχαμε XML δεν θα είχε νόημα ένα νούμερο σειράς, που εύκολα έχουμε σε αυτό (αφού μπορούν να παρεμβληθούν άλλες παράγραφοι), παρά μόνο ο δείκτης στο αντικείμενο, και θα μπορούσε αυτός να καταχωρηθεί. σε ένα πίνακα "σελιδοδεικτών". Σε κάθε διαγραφή παραγράφου θα κοιτάζαμε μήπως την έχουμε στο πίνακα για να την αφαιρέσουμε. Το αντικείμενο Document έχει και ένα εκπληκτικό τρόπο να βρίσκει τον αριθμό λέξεων σε χιλιοστά δευτερολέπτου! Πχ βρήκε ότι το Info.gsb έχει 164322 λέξεις, άμεσα, σε ένα κείμενο 34535 παραγράφων.(πατάμε το F9 και μας δίνει το νούμερο). Επίσης μπορούμε να πάρουμε και όλες τις λέξεις με την αριθμό εμφάνισης. (είναι ένας εκπληκτικός κώδικας, που κρατάει δείκτες και κάνει δυαδική αναζήτηση, για να βρει τις λέξεις, δεν φτιάχνει αλφαριθμητικά, που θα ήταν χρονοβόρο και θα έκανε την μνήμη κομμάτια. Γράφτηκε πριν φτιάξω το αντικείμενο FastCollection με Πίνακα κατακερματισμού) (δείτε το Private Function CountWords2(a$, uLCID As Long) As Long στο myDoc.cls στο git) (είναι εκπληκτική η Visual Basic 6, γιατί μπορεί να παίζεις με δείκτες όπως στη c, και επιπλέον μπορείς να εκτελείς την Μ2000 και να την σταματάς να γράφεις κώδικα και να συνεχίζεις την εκτέλεση, μέχρι να διορθώσεις όλα τα λάθη ή να διαμορφώσεις το αποτέλεσμα όπως θα έπρεπε να ήταν και δεν είναι).

Private Type Paragraph
content() As String
colordata() As Long
startfrom As Long
lines As Long 
End Type

Dim DocParaBack() As Long, DocParaNext() As Long, para() As Paragraph

Στo glist4, σε μια γραμμή, στο JsonObject μπαίνουν κλειδιά όπως το C και το P, το C.1 είναι το μονοπάτι για το περιεχόμενο της 1ης στήλης στη συγκεκριμένη σειρά, ή γραμμή. Το P.1 αν υπάρχει έχει ιδιότητες για το C.1.   Όταν θέλει να εμφανίσει τη στήλη 1 το glist4, τότε κοιτάει για τις ιδιότητες. Κοιτάει αν υπάρχει στο στοιχείο, αν όχι τότε αν υπάρχει στη σειρά (στο P.0), αν όχι τότε αν υπάρχει για όλο, και αν όχι τότε σίγουρα είναι false. Μπορεί όμως να προκύψει true σε κάποιο προηγούμενο. Προς το παρόν όταν έχουμε μια μόνο στήλη δεν κοιτάει αυτά τα πράγματα το glist4. Μπορούμε να έχουμε δυο στήλες αλλά η δεύτερη να μην φαίνεται (να έχει πλάτος 0). Δεν θα απασχοληθεί καθόλου μνήμη για την δεύτερη στήλη σε κάθε σειρά!

Προς το παρόν χρειάζεται ακόμα συμπλήρωση ο κώδικας, αλλά προτίμησα να ανεβάσω την 52, γιατί ήδη αρκετές αλλαγές και θα προκύψουν και άλλες, και ίσως κάτι να αλλαχθεί (δεν είμαι και θεός να τα κάνω όλα με τη μία). Παράλληλα με αυτή την εργασία (που κάνω αφιλοκερδώς), έτυχε στις πρώτες μέρες του Ιανουαρίου να βοηθήσω στην κατασκευή μιας αυτόματης πόρτας, γράφοντας κώδικα σε c++ για μικρο-ελεγκτή τύπου ARDUINO.


Δείτε αυτό το παράδειγμα, Καντε αλλαγές να δείτε πως πάει, δεν έχω βάλει γεγονότα από τη λίστα1 για να μην γίνει ακόμα πιο βαρύ. Δείχνει πως προσθέτουμε στήλες, πως αλλάζουμε ύψος γραμμής (σε πολλαπλάσιο του ύψους γραμμής), Πως βρίσκουμε μια γραμμή από το όνομα στη πρώτη στήλη. Πώς βάζουμε επικεφαλίδα που δεν ακολουθεί την ολίσθηση. Πως αλλάζουμε προγραμματιστικά το πλάτος στήλης, πώς κρύβουμε μια στήλη, πως αλλάζουμε μέγεθος με το ποντίκι μιας στήλης (με δεξί κλικ ή με shift αλλάζουμε το μέγεθος δυο συνεχόμενων στηλών ενώ κρατάμε το συνολικό μέγεθος αυτών το ίδιο),

Σταθερή ΣτοίχισηΚέντρο=2

στήλη$={Header 1
Paris
Athens
Rome
Tirana
Nicosia
Brussels
Copenhagen
Berlin
Dublin
Luxembourg
One More
}
στήλη2$={Header 2
100
}
Όρισε Φόρμα1 Φόρμα
Με Φόρμα1, "title" ως οΤίτλοςμου$
Επίπεδο Φόρμα1 {
Διάστιχο 60
Γραμματοσειρά "Arial Black"
Παράθυρο 16, 12000,6000
Φόντο 11, 1, 0
Δρομέας 0, Ύψος Δια 2
Αναφορά ΣτοίχισηΚέντρο,"Hello World"
}
Όρισε Λίστα1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστα1, "move", 1000,1000,7900,4500
Μέθοδος Λίστα1, "Colors", 0,1,,0,7
Με Λίστα1, "Column" ως Λίστα1.Στήλη, "Edit" ως Διόρθωση.Στοιχείου, "Transparent", Αληθές
Με Λίστα1, "maychange", Αληθές, "NarrowSelect", Αληθές, "Edit", Ψευδές, "ColumnWidth" ως ΠλάτοςΣτήλης()
Με Λίστα1,"text", στήλη$, "BorderStyle", 1 , "Default", Αληθές, "TopRows", 2, "Columns" ως ΣτήλεςΛίστας
Με Λίστα1, "Find" ως Βρες(), "List" Ως Λιστα$(), "TextColumn" Ως Στήλη$(), "AdjustColumns", Αληθές
Με Λίστα1, "ListIndex" ως Επιλεγμένο.Λίστας, "ListCount" ως Στοιχεία.Λίστας , "ShowAlways",Αληθές
Μέθοδος Λίστα1, "SetGrid", Αληθές, 5
Επιλεγμένο.Λίστας=0
Μέθοδος Λίστα1, "AppendColumn", 1,1
ΠλάτοςΣτήλης(1)=3000
ΠλάτοςΣτήλης(2)=3000
Στήλη$(2)=Στήλη2$
Αναφορά Στήλη$(1)
Επιλεγμένο.Λίστας=4
Μέθοδος Λίστα1, "insert", "**New**"
Μέθοδος Λίστα1, "Delete", Στοιχεία.Λίστας-1
Μέθοδος Λίστα1, "Delete", Στοιχεία.Λίστας-1
Μέθοδος Λίστα1, "InsertColumn", 2,2
ΠλάτοςΣτήλης(2)=600
ΠλάτοςΣτήλης(3)=600
Στήλη$(2)={Εμβόλιμη1
}
Στήλη$(3)={Εμβόλιμη2
}
Επιλεγμένο.Λίστας=0
Μέθοδος Λίστα1, "addheight", 1
εκεί=Βρες("Rome")
Αν εκεί>-1 τότε
Επιλεγμένο.Λίστας=εκεί
Μέθοδος Λίστα1, "addheight", 1
Τελος Αν
// Θέλουμε η φόρμα να αλλάζει μέγεθος. Από κάτω δεξιά.
Με Φόρμα1,"Sizable", Αληθές, "SizerWidth", 6*πλάτος.σημείου
Συνάρτηση Φόρμα1.Unload {
      Πληκτρολόγιο "!"   \\ like press !
}
Συνάρτηση Φόρμα1.click {
ΠλάτοςΣτήλης(Τυχαίος(2, 3))=Αν(Τυχαίος<.3->0, 600)
Μέθοδος Λίστα1, "sort",,,1, 2
}
Συνάρτηση Φόρμα1.Resize {
Επίπεδο Φόρμα1 {
Τύπος 16
Φόντο 11, 1, 0
Δρομέας 0, Ύψος Δια 2
Αναφορά ΣτοίχισηΚέντρο,"Hello World"
}
Επίπεδο { Ανανέωση }
Μέθοδος Φόρμα1, "refreshALL"
}
Μέθοδος Φόρμα1, "Show"
α$=Κομ$
Όρισε Φόρμα1 Τίποτα



Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.