Τρίτη, 26 Απριλίου 2016

Αναθεώρηση 221, περισσότερη ταχύτητα!

Στην Αναθεώρηση 221, έβαλα και άλλες εντολές να καλούνται εσωτερικά με δείκτη σε συνάρτηση, αντί να αναζητούνται σε ένα selcet case, ώστε να έχουμε σταθερό χρόνο απόκρισης. Μια εντολή βρίσκεται με το πολύ δυο συγκρίσεις, λόγω του πίνακα κατακερματισμού που κάνει το εξής: Βγάζει με μαθηματικό τύπο τη θέση του εντολής σε έναν πίνακα, ένα νούμερο, και αν δεν το βρει εκεί, το στοιχείο που είναι εκεί έχει μια δική του λίστα στοιχείων με ίδιο νούμερο. 

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

Επίσης ένα άλλο σημείο που με απασχόλησε (και μου πήρε δυο μέρες να το φέρω στα ίσα, να δουλεύει για όλες τις περιπτώσεις)  είναι η δυνατότητα να ανοίγουν διαδοχικά modal παράθυρα. Δεν υπάρχει λέξη που να δηλώνει τι  λέμε modal, αλλά περιγραφικά σημαίνει να ανοίγουμε ένα παράθυρο κάνοντας πρόσκαιρα ανενεργά τα παράθυρα της εφαρμογή μας. Ένα παράδειγμα απλού modal παραθύρου είναι το MessageBox, όπου στη Μ2000 βγαίνει με την συνάρτηση Ρώτα() ή Ask().

Δεν είναι εύκολο να κατανοήσουμε την δυσκολία του Modal. Διότι το πρόβλημα είναι σε πια κατάσταση θα μεταβαίνει κάθε παράθυρο όταν ένα Χ παράθυρο ανοίξει ως modal και πάλι σε πια κατάσταση θα μεταβαίνει κάθε παράθυρο όταν αυτό το Χ παράθυρο κλείσει. Αν έχουμε ένα μόνο βαθμό για άνοιγμα Modal παραθύρου, το πρόβλημα και πάλι δεν είναι εύκολο γιατί μπορεί ένα παράθυρο να είναι ήδη ανενεργό,. Δηλαδή αν αποφασίσουμε ό,τι είναι ενεργό να το κάνουμε ανενεργό τότε στην φάση που θα τα ενεργοποιήσουμε ξανά, επειδή έκλεισε το modal, τότε ενδέχεται να ενεργοποιήσουμε και εκείνο που δεν ήταν από πριν ενεργό. Μια λύση είναι να μαρκάρουμε πια κάναμε ανενεργά και μετά να τα ενεργοποιήσουμε. Αν έχουμε πολλά παράθυρα Modal, τότε κάθε φορά που επιστρέφουμε από ένα Modal, πέφτουμε στο προηγούμενο, μέχρι να φτάσουμε στο τελευταίο. Το πρόβλημα δυσκολεύει περισσότερο αν σκεφτούμε ότι ένα modal παράθυρο μπορεί να ανοίξει άλλα παράθυρα που δεν είναι Modal...αλλά δεν μπορεί να τα μπλοκάρει. Όλο αυτό το μπέρδεμα καταστάσεων το βγάζει σε πέρας αυτό που έχω γράψει.

Κάθε φορά που ανοίγουμε ένα modal σταματάει η ροή εκτέλεσης εντολών...στο νήμα (εδώ χρησιμοποιούμε την AFTER {}  που κάνει αυτόματα ένα νήμα να τρέξει μια μόνο φορά μετά από συγκεκριμένο χρόνο. Όταν έχουμε ανοίξει και το πέμπτο παράθυρο..έχουμε σταματήσει τον κώδικα της Μ2000 σε πέντε σημεία. Παρόλα αυτά το νήμα που γράφει στην οθόνη (κονσόλα της Μ2000) συνεχίζει να τρέχει. Δοκιμάστε με ΧΧ=0 για να φτιάξει τέσσερα παράθυρα κανονικά πάνω από το πρώτο Modal. Το τελευταίο παράθυρο ανοίγει με κλικ ένα messagebox, το οποίο απενεργοποιεί όλα τα παράθυρα και στην επιστροφή ενεργοποιεί όπως πρέπει και πάλι το πρώτο παράθυρο είναι Modal αν έχει ανοίξει τα άλλα με XX=0 δηλαδή κανονικά, τότε μπορεί να έρθει και μπροστά από αυτά. Ενώ κανονικά ένα Modal όταν είναι ενεργό είναι πάντα μπροστά. Εδώ αν ανοίξει ένα μη modal μπορούν να αλλάζουν θέση, να έρχεται μπροστά αυτό που θέλουμε. 

Τα modal παράθυρα εξ ορισμού δεν χάνονται όταν κλείνουν από το χρήστη, έτσι ώστε να ανοίξουν και άλλη φορά. Αν θέλουμε όμως και στα μη Modal να τα κρατάμε φορτωμένα, θα πρέπει στο κλείσιμο να τα κρύβουμε, και αυτό γίνεται στο simple.unload με την μέθοδο "Hide".

Δείτε επίσης ότι η simple.click  εκτελείται και ίσως να φτιάξει ένα νήμα, αλλά το νήμα δεν τρέχει μέσα στη συνάρτηση, έχουμε δώσει χρόνο και αυτός αρκεί για να τρέξει το νήμα όταν αυτή τερματίσει. Με τον τρόπο αυτό τερματίζουμε την εξυπηρέτηση του clik, και αφήνουμε το σύστημα να "παίξει" στην ώρα του την επόμενη "Ασύγχρονη" εντολή, ή μπλοκ εντολών

Επίσης δείτε ότι το πρόγραμμα σταματάει στην εμφάνιση της πρώτης φόρμας και από εκείνο το σημείο παίζουν μόνο τα μηνύματα. Αν κλείσουμε την πρώτη φόρμα...τότε μια εντολή τερματίζει όλα τα νήματα και διαγράφει τις φόρμες.

\\ An example of modal show
\\ use XX=1 for non modal after first modal
\\ also note that messagebox is a modal window and popup by Ask() Function
Global XX=1
Declare Simple(5) form
For i=0 to 4
      Method Simple(i), "FontAttr", "Arial Black", 18
      Layer Simple(i) {
            Linespace 30
            Window 12, 10000,8000
            Cls 1,0
            Form 30,20 \\ make 30X20 chars*lines calculating new font size.
            Cursor 0,3
            Print width, height
            Print "01234567890123456789"
      }
Next i
Function simple.unload {
      If XX<>0 then exit
      read new index, &cancel
      method Simple(index), "Hide"
      cancel=true
}


k=0
\\ this is the background task
Thread {
      k++
      Print k
} As anything Interval 20


Function simple.click {
      Threads
      Read New index
      Select Case index
      Case 0
      {
            After 50 {
                  Method Simple(1), "Show" , XX
                  Print "end case 0"
            }
        }
      Case 1
      {
            After 50 {
                  Method Simple(2), "Show" , XX
                  Print "end case 1"
                  }
      }
      Case 2
      {
            After 50 {
                  Method Simple(3), "Show" , XX
                  Print "end case 2"
                  }
      }
      Case 3
      {
            After 50 {
                  Method Simple(4), "Show" , XX
                  Print "end case 3"
                  }
      }
      Case 4
      {
            After 50 {
                  Print Ask("ok")
                  Print "end case 4"
                  }
      }
      End Select
      Threads
}
Method Simple(0), "Show" ,1
Print "Finish"
Threads Erase
Declare simple() Nothing
Show  \\ set focus to M2000 console