un tout petit moteur inachevé de défilement pour possible rich text, et fourre-tout graphique

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

un tout petit moteur inachevé de défilement pour possible rich text, et fourre-tout graphique

Message par Ollivier »

Bonjour à tous,

il y a quelques mois je commençais ce programme pour me faire mon propre éditeur de texte multi-taille (par opposition au monofont).

Depuis, le temps a manqué, avec la concentration nécessaire. Alors, au lieu de l'expédier dans la case des oublis, ou celle des << demain peut-être >>, je prends le risque de vous le poster et que plusieurs se posent la question de l'utilité d'un tel code.

La réponse est simple et sera toujours celle-là : parce que les esprits suffisamment éprouvés y verront d'eux-mêmes le côté utile.

Le programme en lui-même ne fait vraiment pas grand chose. Ce sont 64 bandes horizontales qui miment des lignes de texte de hauteur différente chacune.

Donc, il n'y a donc que 3 touches : haut bas et échap.
* flèches haut/bas : monte ou descend le curseur pour mimer un déplacement dans un texte
* Echap = quitte
Et la molette souris pour défiler aussi vers le haut comme vers le bas.

Ce qui m'a cassé dans ce projet c'est que je souhaitais rendre dynamique le nombre total de lignes qui s'élève ici à 64 (de 0 à 63) pour permettre d'augmenter le nombre en cas de zoom arrière, ou de libérer la mémoire en cas de zoom avant. Le problème c'est qu'il faut en plus de traiter les x types de mesures de hauteur (en pixels, en lignes de texte, ainsi qu'en coefficients visible/invisible en cours et en coefficients invisible en cours/invisible total : bref, c'est de la virtualisation de 3D iso sans rotation pour ne perdre ni en ressource CPU ni en mémoire) traiter la qualité des images qui doit être nécessairement amoindrie en cas de zoom arrière (sinon ça bouffe en mémoire).

Ça peut sembler bizarre de buter sur des broutilles, mais le but était (et est) d'être sans limite sur les y et sur les z. J'ai déjà fait un programme sur opengl qui fonctionnait bien mais il était monofont. Et la virtualisation c'était opengl qui la gèrait complètement. Là, j'avais préféré m'en occuper.

Donc voici cette "poubelle". Voyez-là comme une oeuvre d'art insignifiante dont le but est juste de voir une simple mécanique de défilement bien fonctionner, pour quiconque a l'envie de fabriquer son propre éditeur de texte, il y a deux ou trois "engrenages" dedans qui peuvent vraiment inspirer. Chaque ligne (ou case) est une image. Aucune mise à jour de ces images n'est traitée pour "sortir" de ce ruban qui a donc ici, fin et début liés.

Tout est dans la seule structure "gbl" (GloBaL) et les noms des champs dont les termes sont réduits à 3 lettres, c'est une astuce que j'ai empruntée dans mes habitudes de prog sur smartphone car j'ai programmé un éditeur monofont fonctionnel sur Smartphone dans un autre langage. Et le smartphone, pour programmer dessus, il vaut mieux faire court avec les noms de variables vu la petite taille de l'écran... Etrangement, 3 lettres ça me rappelle direct les extensions de fichier et donc ma mémoire s'en familiarise. Et pour l'absence de français, désolé, je ne me fais pas à une langue française sans accents donc je reste à l'anglaise.

Une fois qu'on a ce genre de petit outil, on a un peu une sorte de fourre-tout graphique : éditeur de texte, console, explorateur de fichier. Et ainsi, on n'est plus à la merci de délires d'interface qui font perdre un temps fou, et de systèmes qui changent constamment.

Personnellement, le temps informatique va s'annuler pour moi sans prévision de durée.

Donc, à vos molettes de souris (et vos touches haut et bas), bon défilement !

Code : Tout sélectionner

;- Enumerations

Enumeration
    
    #docEsc = 1             ; document : menu item code for escape
    #docLastLine            ; document : menu item code for last line move
    #docNextLine            ; document : menu item code for next line move
    
EndEnumeration

;- Structures

Structure gbl
    
    ;- gbl doc                                                  ('§' <=> default value)
    
    docHei          .D      ; document : height                 (double)
    
    docVisX         .D      ; document : visible X position     (double § = 0.0)
    docVisY         .D      ; document : visible Y position     (double § = 0.0)
    
    docVisWid       .D      ; document : visible width          (double § = 800.0)
    docVisHei       .D      ; document : visible height         (double § = 600.0)
    
    docNam          .S{80}  ; document : name                   (char*80 § = 'UNTITLED')
    docWinHnd       .I      ; document : window handle          (integer)
    docWinFlg       .I      ; document : window flags           (integer § = BORDERLESS | SCREENCENTERED)
    docCanHnd       .I      ; document : canvas handle          (integer)
    docCanWhl       .I      ; document : canvas wheel delta     (integer)
    
    docMosX         .D      ; document : mouse X position       (integer)
    docMosY         .D      ; document : mouse Y position       (integer)
    docMosOldX      .D      ; document : mouse old X position   (integer)
    docMosOldY      .D      ; document : mouse old Y position   (integer)
    
    docEvt          .I      ; document : real-time event        (integer)
    docEvtTyp       .I      ; document : real-time event type   (integer)
    docEvtGdt       .I      ; document : real-time event gadget (integer)
    docEvtMnu       .I      ; document : real-time event menu   (integer)
    
    ;- gbl dli    
    
    dliMinHei       .D      ; document line : minimum height    (double § = 24.0)
    
    dliImgHnd       .I[64]  ; document line : image handle      (integer*64)
    dliImgWid       .D[64]  ; document line : image width       (double*64)
    dliImgHei       .D[64]  ; document line : image height      (double*64)
    
    dliGdtHnd       .I[64]  ; document line : gadget handle     (integer*64)
    dliGdtX         .D[64]  ; document line : gadget X position (double*64)
    dliGdtY         .D[64]  ; document line : gadget Y position (double*64)
    
    ;- gbl crs
    
    crsWinHnd       .I      ; cursor window handle              (integer)
    crsWinFlg       .I      ; cursor window flags               (integer)
    crsWid          .D      ; cursor width                      (double § = 2.0)
    crsHei          .D      ; cursor height                     (double)
    crsVisDli       .I      ; on which visible doc line it is   (integer § = -1)
    crsVisDliChg    .I      ; to which visible doc line it goes (integer § = 1)
    
EndStructure

;- Procedures

Procedure gblCreate()
    Define *this.gbl
    With *this
        *this = AllocateMemory(SizeOf(gbl) )
        \docVisX = 0.0
        \docVisY = 0.0
        \docVisWid = 800.0
        \docVisHei = 600.0
        \crsWid = 2.0
        ProcedureReturn *this
    EndWith
EndProcedure

;-

Procedure gblScrollUp(*this.gbl, delta.D)
    Define x.D
    Define y.D
    Define i.I
    With *this
        Delay(14)
        For i = 0 To 63
            x = \dliGdtX[i]
            y = \dliGdtY[i] - delta ; \dliMinHei
            If y + \dliImgHei[i] < 0
                y + \docHei
            EndIf
            ResizeGadget(\dliGdtHnd[i], x, y, #PB_Ignore, #PB_Ignore)
            \dliGdtY[i] = y
        Next
    EndWith    
EndProcedure

;- 

Procedure gblScrollDown(*this.gbl, delta.D)
    Define x.D
    Define y.D
    Define i.I
    Define j.I
    With *this
        Delay(14)
        For i = 0 To 63
            x = \dliGdtX[i]
            y = \dliGdtY[i] + delta ; \dliMinHei
            If y + \dliImgHei[i] > \docHei
                y - \docHei
            EndIf
            ResizeGadget(\dliGdtHnd[i], x, y, #PB_Ignore, #PB_Ignore)
            \dliGdtY[i] = y
        Next
    EndWith    
EndProcedure

;- 

Procedure gblSyncCursor(*this.gbl)
    Define delta.D ; /!\ 2 uses !
    Define x.D
    Define y.D
    Define w.D
    Define h.D
    Define *this.gbl
    With *this
        If \crsVisDliChg
            \crsVisDli + \crsVisDliChg
            \crsVisDli & 63
            x = WindowX(\docWinHnd) + 64
            y = WindowY(\docWinHnd) + 4 + \dliGdtY[\crsVisDli]
            w = \crsWid
            h = \dliImgHei[\crsVisDli] - 8
            If \crsVisDliChg > 0
                delta = \dliGdtY[\crsVisDli] + \dliImgHei[\crsVisDli] - \docVisHei
                If delta > 0        
                    gblScrollUp(*this, delta)
                    y - delta
                EndIf
            EndIf
            If \crsVisDliChg < 0
                delta = \dliGdtY[\crsVisDli]
                If delta < 0
                    gblScrollDown(*this, - delta)
                    y - delta
                EndIf
                If delta + \dliImgHei[\crsVisDli] > \docVisHei
                    gblScrollDown(*this, \dliImgHei[\crsVisDli] )
                    y - delta
                EndIf                
            EndIf
            ResizeWindow(\crsWinHnd, x, y, w, h)
            \crsVisDliChg = 0
        EndIf
    EndWith
EndProcedure

;-

Procedure gblNewDoc(*this.gbl)
    Define i.I
    Define x.D
    Define y.D
    Define w.D
    Define h.D
    With *this
        \dliMinHei = 24.0
        x = \docVisX
        y = \docVisY
        For i = 0 To 63
            \dliImgWid[i] = \docVisWid
            coef = (1 + Random(3) )
            \dliImgHei[i] = \dliMinHei * coef
;            \dliImgHei[i] = (4 + Random(91) )
            \dliImgHnd[i] = CreateImage(#PB_Any, \dliImgWid[i], \dliImgHei[i], 32, RGBA(0, 0, 0, 0) )
            If 1
                StartDrawing(ImageOutput(\dliImgHnd[i] ) )
                w = OutputWidth()
                h = OutputHeight()
                DrawingMode(#PB_2DDrawing_AllChannels)
                Box(0, 0, w, h, RGBA(0, 0, 0, 255) )
                Box(1, 1, w - 2, h - 2, RGBA(255, 255, 255, 255) )
                DrawingMode(#PB_2DDrawing_Transparent)
                DrawText(0, 0, Str(i) + "    " + Str(coef), RGB(0, 0, 0) )
                StopDrawing()
            EndIf
            \dliGdtX[i] = x
            \dliGdtY[i] = y
            \dliGdtHnd[i] = ImageGadget(#PB_Any, x, y, \dliImgWid[i], \dliImgHei[i], ImageID(\dliImgHnd[i] ) )
            y + \dliImgHei[i]
        Next
        \docHei = y
        
        \crsWinFlg = #PB_Window_BorderLess | #PB_Window_NoActivate
        \crsWinHnd = OpenWindow(#PB_Any, 0, 0, 1, 1, "", \crsWinFlg, WindowID(\docWinHnd) )
        SetWindowColor(\crsWinHnd, #Red)
        \crsVisDli = -1
        \crsVisDliChg = 1
        gblSyncCursor(*this)
    EndWith    
EndProcedure

;-

Procedure main()
    Define *this.gbl = gblCreate()
    With *this
        \docNam = "Untitled"
        \docWinFlg = #PB_Window_BorderLess | #PB_Window_ScreenCentered
        \docWinHnd = OpenWindow(#PB_Any, 0, 0, \docVisWid, \docVisHei, \docNam, \docWinFlg)
        SetWindowData(\docWinHnd, *this)
        \docCanHnd = CanvasGadget(#PB_Any, 0, 0, 1, 1, #PB_Canvas_Keyboard)
        gblNewDoc(*this)
        
        AddKeyboardShortcut(\docWinHnd, #PB_Shortcut_Escape, #docEsc)
        AddKeyboardShortcut(\docWinHnd, #PB_Shortcut_Up, #docLastLine)
        AddKeyboardShortcut(\docWinHnd, #PB_Shortcut_Down, #docNextLine)
        SetActiveGadget(\docCanHnd)
        Repeat
            \docMosOldX = \docMosX
            \docMosOldY = \docMosY
            \docMosX = WindowMouseX(\docWinHnd)
            \docMosY = WindowMouseY(\docWinHnd)
            If \docMosX <> \docMosOldX Or \docMosY <> \docMosOldY
                ResizeGadget(\docCanHnd, \docMosX, \docMosY, #PB_Ignore, #PB_Ignore)
            EndIf
            \docEvt = WaitWindowEvent()
            \docEvtTyp = EventType()
            Select \docEvt
                Case #PB_Event_Menu: \docEvtMnu = EventMenu()
                    Select \docEvtMnu
                        Case #docLastLine
                            \crsVisDliChg = - 1
                            gblSyncCursor(*this)
                        Case #docNextLine
                            \crsVisDliChg = 1
                            gblSyncCursor(*this)
                    EndSelect
                Case #PB_Event_ActivateWindow
                    ;Debug "YES !"
                Case #PB_Event_Gadget: \docEvtGdt = EventGadget()
                    If \docEvtGdt = \docCanHnd
                        If \docEvtTyp = #PB_EventType_MouseWheel
                            \docCanWhl = GetGadgetAttribute(\docCanHnd, #PB_Canvas_WheelDelta)
                            If \docCanWhl
                                For i = 1 To Abs(\docCanWhl)
                                    \crsVisDliChg = - Sign(\docCanWhl)
                                    gblSyncCursor(*this)
                                Next
                            EndIf
                        EndIf
                    EndIf
            EndSelect
        Until \docEvtMnu = #docEsc
    EndWith
EndProcedure

;- *** Start ***

main()