SpinGadgetFloat()

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Jacobus
Messages : 1638
Inscription : mar. 06/avr./2004 10:35
Contact :

SpinGadgetFloat()

Message par Jacobus »

Hello,
j'avais besoin d'un spingadget capable de gérer les nombres flottants.
Pour ceux que cela peut intéresser, voici une version possible... :)

Code : Tout sélectionner

;-TOP
;======================================
; SpinGadgetFloat()
; Jacobus 21/06/2026 PB 6.40 (x64)
; Windows 11 64bits
; Création d'un SpinGadget() pour nombres flottants
;======================================

Enumeration
  #WIN = 0
  ;1er gadget:
    #StringFloat
    #SpinFloat
  ;2ème gadget:
    #StringFloat2
    #SpinFloat2
EndEnumeration

Procedure SpinGadgetFloat(GadgetString.i, GadgetSpin.i, x, y, w, h, ValInit$)
  
  StringGadget(GadgetString, x, y, w, h, ValInit$, #PB_String_ReadOnly)
  
  SpinGadget(GadgetSpin, x + w, y, 12, h, 0, 1) ; le mini à 0 et le maxi à 1 au minimum, sinon le spingadget est désactivé... 
  
EndProcedure

Procedure SpinGadgetFloatEvent(GadgetString.i, Unit.f, NbDec.l)
  
  Select EventType() 
      
    Case #PB_EventType_Up
      level$ = GetGadgetText(GadgetString)
      levelUp.f = ValF(level$)
      SetGadgetText(GadgetString, StrF(levelUp + Unit, NbDec))     
      
    Case #PB_EventType_Down
      level$ = GetGadgetText(GadgetString)
      levelDown.f = ValF(level$)
      SetGadgetText(GadgetString, StrF(levelDown - Unit, NbDec))  
      
  EndSelect
  
EndProcedure


;-Fenêtre
If OpenWindow(#WIN, 0, 0, 150, 100, "SpinGadgetFloat()", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  SpinGadgetFloat(#StringFloat, #SpinFloat, 50, 20, 40, 20, "1.0"); 1 chiffre après la virgule

  SpinGadgetFloat(#StringFloat2, #SpinFloat2, 50, 50, 40, 20, "1.00") ; 2 chiffre après la virgule 
  
  Repeat 
    Event = WaitWindowEvent()
    Select Event
        
        ;-Event Gadgets     
      Case #PB_Event_Gadget
        
        Select EventGadget()
            
          Case #SpinFloat : SpinGadgetFloatEvent(#StringFloat, 0.1, 1)
            
          Case #SpinFloat2 : SpinGadgetFloatEvent(#StringFloat2, 0.01, 2)
            
        EndSelect
        ;-Close window     
      Case #PB_Event_CloseWindow
        Select EventWindow()     
          Case #WIN : Quit = 1                     
        EndSelect
        
    EndSelect
    
  Until Quit = 1
  End 
EndIf
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
falsam
Messages : 7417
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: SpinGadgetFloat()

Message par falsam »

Sympa ce gadget qui mériterait deux nouvelles fonctionnalités.
- Int GetSpingadgetFloat(#Gadget)
- Int SetSpinGadgetFloat(#Gadget, Value.i)

Merci pour ce gadget.
Configuration : Windows 11 Famille 64-bit - PB 6.23 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Jacobus
Messages : 1638
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: SpinGadgetFloat()

Message par Jacobus »

falsam a écrit : dim. 21/juin/2026 12:20 Sympa ce gadget qui mériterait deux nouvelles fonctionnalités.
- Int GetSpingadgetFloat(#Gadget)
- Int SetSpinGadgetFloat(#Gadget, Value.i)
J'aime bien l'idée de pousser un peu plus.
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
Jacobus
Messages : 1638
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: SpinGadgetFloat()

Message par Jacobus »

J'ai publié ce gadget sur le forum anglais où il a été proposé une version différente qui est, certes plus conforme à la création d'un gadget(), mais qui est quand même réservé aux codeurs avancés. L'usage de la mémoire structurée n'est peut-être pas à la portée de tous... Vous pouvez voir cela ici https://www.purebasic.fr/english/viewtopic.php?t=89130

Mais comme je suis têtu, j'ai poursuivi mon idée initiale qui, pour ce qui est de mon usage, plus facile à manipuler et modulable. J'ai d'ailleurs ajouté un SpinGadgetString() qui n'est pas une copie de ComboBoxGadget() mais qui pourrait le paraître. Bref, voici le code mis à jour avec de nouvelles fonctions, notamment une version de celles suggérées par Falsam. Tout cela pourra peut-être vous servir... :)

Code : Tout sélectionner

;-TOP
;======================================
; SpinGadgetFloat() & SpinGadgetString()
; Jacobus 21/06/2026 PB 6.40 (x64) and Windows 11 64bits
; Updated June 27, 2026 - Mise à jour du 27/06/2026
; 
; Création d'un SpinGadget() pour nombres flottants et Chaînes de caractères

;======================================
; https://www.purebasic.fr/english/viewtopic.php?t=89130


Enumeration
  #WIN = 0
  ;1er gadget:
    #StringFloat1 : #SpinFloat1
  ;2ème gadget:
    #StringFloat2 : #SpinFloat2
  ;3ème gadget:  
    #StringFloat3 : #SpinFloat3
    
    #BtnReset
    
    #StringFloat4 : #SpinFloat4
EndEnumeration

;-==============================
;-SpinGadgetFloat
;-==============================
Procedure SpinGadgetFloat(GadgetString.i, GadgetSpin.i, x, y, w, h, ValInit$)
  
  ; GadgetString.i:..........StringGadget() qui servira de champ d'affichage au SpinGadgetFloat() / StringGadget() which will serve as the display field for SpinGadgetFloat()
  ; GadgetSpin.i:............SpinGadget() réduit à ses deux boutons qui serviront au SpinGadgetFloat() / SpinGadget() reduced to its two buttons which will be used for SpinGadgetFloat()
  ; x et y:..................Position x et y du StringGadget() sur la fenêtre, bases pour la position du SpinGadget() / Position x and y of the StringGadget() on the window, basis for the position of the SpinGadget()
  ; w et h:..................Largeur et hauteur du StringGadget(), bases pour la position et la taille du SpinGadget() / Width and height of the StringGadget(), bases for the position and size of the SpinGadget()
  ; ValInit$:................Unité initiale affiché dans le SpinGadget() au démarrage. / Initial unit displayed in SpinGadget() at startup.
  ; 12 :.....................Largeur nécessaire pour n'afficher que les deux boutons du SpinGadget() / Width needed to display only the two buttons of the SpinGadget()
  ; 0  :.....................Minimum du SpinGadget()
  ; 1  :.....................Maximum du SpinGadget() pour qu'il soit affiché et activé (si à 0, il sera désactivé) / for it to be displayed and activated (if it is 0, it will be deactivated)
  
  StringGadget(GadgetString, x, y, w, h, ValInit$, #PB_String_PlaceHolder) ; permet d'afficher un message informatif, ici le type d'unité du spingadget / allows you to display an informative message, in this case the unit type of the SpinGadget()
  
  SpinGadget(GadgetSpin, x + w, y, 12, h, 0, 1) ; le mini à 0 et le maxi à 1 au minimum, sinon le spingadget est désactivé... / The minimum should be 0 and the maximum 1 minimum, otherwise the springadget is disabled...
  
EndProcedure

Procedure.f GetSpingadgetFloat(GadgetString.i)
  
  ; GadgetString.i :...............StringGadget() du SpinGadgetFloat() courant
  
  level$ = GetGadgetText(GadgetString)
  levelUp.f = ValF(level$)
  
  ProcedureReturn levelUp
  
EndProcedure

Procedure SetSpinGadgetFloat(GadgetString.i, TextValue.s)
  
  ; GadgetString.i :...............StringGadget() du SpinGadgetFloat() courant
  ; TextValue.s    :...............Chaîne de la Valeur retournée par GetSpingadgetFloat(GadgetString.i) du SpinGadgetFloat() courant / String of the value returned by GetSpingadgetFloat(GadgetString.i) of the current SpinGadgetFloat()
  
  SetGadgetText(GadgetString, TextValue)
  
EndProcedure

Procedure SpinGadgetFloatEvent(GadgetString.i, Unit.f, NbDec.l, Min.i, Max.i)
  
  ; GadgetString.i :...............StringGadget() du SpinGadgetFloat() courant
  ; Unit.f         :...............Unité de base pour le SpinGadgetFloat() courant / Base unit for the current SpinGadgetFloat()
  ; NbDec.l        :...............Nombre de décimales après la virgule affichées par le SpinGadgetFloat() courant / Number of decimal places displayed by the current SpinGadgetFloat()
  ; Min.i          :...............Valeur minimale du SpinGadget(), qui peut être un nombre négatif / Minimum value of SpinGadget(), which can be a negative number
  ; Max.i          :...............Valeur maximale du SpinGadget()
  
  Protected Value.f
  
  Select EventType() 
      
    Case #PB_EventType_Up
      Value.f = GetSpingadgetFloat(GadgetString) + Unit
      If Value > Max : Value = Max : EndIf   ; Pour contenir la valeur du SpinGadgetFloat() dans les valeurs min et max définies    
      TextValue.s = StrF(Value, NbDec)
   
    Case #PB_EventType_Down
      Value.f = GetSpingadgetFloat(GadgetString) - Unit
      If Value < Min : Value = Min : EndIf   ; To keep the value of SpinGadgetFloat() within the defined min and max values
      TextValue.s = StrF(Value, NbDec)
    
  EndSelect
  SetSpinGadgetFloat(GadgetString, TextValue)
 
EndProcedure

;-==============================
;-SpinGadgetString
;-==============================
; Associer une valeur numérique à une chaîne de caractères, accessible via un SpinGadget() et les fleches Up et Down
; Assigning a numerical value to a string of characters, accessible via SpinGadget() and the Up and Down arrows
Procedure SpinGadgetString(GadgetString.i, GadgetSpin.i, x, y, w, h, Min.i, Max.i, ValInit$)
  
  ; GadgetString.i:..........StringGadget() qui servira de champ d'affichage au SpinGadgetFloat() / StringGadget() which will serve as the display field for SpinGadgetString()
  ; GadgetSpin.i:............SpinGadget() réduit à ses deux boutons qui serviront au SpinGadgetString() / SpinGadget() reduced to its two buttons which will be used for SpinGadgetString()
  ; x et y:..................Position x et y du StringGadget() sur la fenêtre, bases pour la position du SpinGadget() / Position x and y of the StringGadget() on the window, basis for the position of the SpinGadget()
  ; w et h:..................Largeur et hauteur du StringGadget(), bases pour la position et la taille du SpinGadget() / Width and height of the StringGadget(), bases for the position and size of the SpinGadget()
  ; Min.i, Max.i:............Obligation d'indiquer un minimum et un maximum dans le cas présent / Obligation to indicate a minimum and a maximum in this case
  ; ValInit$:................Unité initiale affiché dans le SpinGadget() au démarrage. / Initial unit displayed in SpinGadget() at startup.
 
  StringGadget(GadgetString, x, y, w, h, ValInit$, #PB_String_PlaceHolder) ; permet d'afficher un message informatif, ici le type d'unité du spingadget / allows you to display an informative message, in this case the unit type of the SpinGadget()
  
  SpinGadget(GadgetSpin, x + w, y, 12, h, Min, Max)  ; 12 = Largeur nécessaire pour n'afficher que les deux boutons du SpinGadget() / Width needed to display only the two buttons of the SpinGadget()
  
EndProcedure

Procedure.i GetSpingadgetString(GadgetSpin.i)
   
  level.i = GetGadgetState(GadgetSpin)
  
  ProcedureReturn level
  
EndProcedure

Procedure.s SelectStringSpinGadget(spinVal.i)
; Ceci est un exemple de chargement de texte, mais en production
; il existe d'autres moyens plus pertinents (dataSection; fichier texte; autres...) 
  Protected SelectedString.s
  Select spinVal  
    Case 0  : SelectedString.s = "Zero"
    Case 1  : SelectedString.s = "One"
    Case 2  : SelectedString.s = "Two"
    Case 3  : SelectedString.s = "Three"
    Case 4  : SelectedString.s = "Four"
    Case 5  : SelectedString.s = "Five"
    Case 6  : SelectedString.s = "Six"
    Case 7  : SelectedString.s = "Seven"
    Case 8  : SelectedString.s = "Eight"
    Case 9  : SelectedString.s = "Nine"
    Case 10 : SelectedString.s = "Ten" 
  EndSelect
  ProcedureReturn SelectedString.s 
  
EndProcedure

Procedure SetSpinGadgetString(GadgetString.i, TextValue.s)
  
  ; GadgetString.i :...............StringGadget() du SpinGadgetFloat() courant
  ; TextValue.s    :...............Chaîne de la Valeur retournée par GetSpingadgetFloat(GadgetString.i) du SpinGadgetString() courant / String of the value returned by GetSpingadgetFloat(GadgetString.i) of the current SpinGadgetFloat()
  
  SetGadgetText(GadgetString, TextValue)
  
EndProcedure

Procedure SpinGadgetStringEvent(GadgetSpin.i, GadgetString.i, Unit.f, Min.i, Max.i)
  
  ; GadgetSpin.i   :...............SpinGadget() réduit à ses deux boutons qui serviront au SpinGadgetString() / SpinGadget() reduced to its two buttons which will be used for SpinGadgetString()
  ; GadgetString.i :...............StringGadget() du SpinGadgetString() courant
  ; Unit.f         :...............Unité de base pour le SpinGadgetString() courant / Base unit for the current SpinGadgetString()
  ; NbDec.l        :...............Nombre de décimales après la virgule affichées par le SpinGadgetString() courant / Number of decimal places displayed by the current SpinGadgetString()
  ; Min.i          :...............Valeur minimale du SpinGadget(), qui peut être un nombre négatif / Minimum value of SpinGadget(), which can be a negative number
  ; Max.i          :...............Valeur maximale du SpinGadget()
  
  Protected spinVal.i, TextValue.s
  
  Select EventType() 
      
    Case #PB_EventType_Up
      spinVal = GetSpingadgetString(GadgetSpin.i) 
      If spinVal > Max : spinVal = Max : EndIf   ; Pour contenir la valeur du SpinGadgetString() dans les valeurs min et max définies         
      TextValue.s = SelectStringSpinGadget(spinVal) 
   
    Case #PB_EventType_Down
      spinVal = GetSpingadgetString(GadgetSpin.i)
      If spinVal < Min : spinVal = Min : EndIf   ; To keep the value of SpinGadgetString() within the defined min and max values
      TextValue.s = SelectStringSpinGadget(spinVal) 
    
  EndSelect
  SetSpinGadgetString(GadgetString, TextValue)
 
EndProcedure


Procedure ResetSpinGadgetFloat()
  SetGadgetText(#StringFloat1, "")
  SetGadgetText(#StringFloat2, "")
  SetGadgetText(#StringFloat3, "")
  SetGadgetText(#StringFloat4, "")
EndProcedure

;-Fenêtre
If OpenWindow(#WIN, 0, 0, 150, 180, "SpinGadgetFloat()", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  SpinGadgetFloat(#StringFloat1, #SpinFloat1, 50, 20, 60, 20, "Unit 0.1")    ; 1 chiffre après la virgule
  
  SpinGadgetFloat(#StringFloat2, #SpinFloat2, 50, 50, 60, 20, "Unit 0.01")   ; 2 chiffres après la virgule
  
  SpinGadgetFloat(#StringFloat3, #SpinFloat3, 50, 80, 60, 20, "Unit 1")      ; 0 chiffre après la virgule 
  
  SpinGadgetString(#StringFloat4, #SpinFloat4, 50, 110, 80, 20, 0, 10, "Select Num") ; This is not a ComboBoxGadget() !
  
  ButtonGadget(#BtnReset, 50, 140, 72, 20, "Reset") : GadgetToolTip(#BtnReset, "Reset input fields")
                
  Repeat 
    Event = WaitWindowEvent()
    Select Event
        
        ;-Event Gadgets     
      Case #PB_Event_Gadget
        
        Select EventGadget()
            
          Case #SpinFloat1 : SpinGadgetFloatEvent(#StringFloat1, 0.1, 1, 0, 100)   ; 1 digit after the decimal point
            
          Case #SpinFloat2 : SpinGadgetFloatEvent(#StringFloat2, 0.01, 2, 0, 100)  ; 2 digits after the decimal point 
            
          Case #SpinFloat3 : SpinGadgetFloatEvent(#StringFloat3, 1, 0, -25, 25)    ; 0 digit after the decimal point 
            
          Case #BtnReset   : ResetSpinGadgetFloat()
            
          Case #SpinFloat4 : SpinGadgetStringEvent(#SpinFloat4, #StringFloat4, 1, 0, 10) ; 10 mots ou phrases de 1 en 1
            
        EndSelect
        ;-Close window     
      Case #PB_Event_CloseWindow
        Select EventWindow()     
          Case #WIN : Quit = 1                     
        EndSelect
        
    EndSelect
    
  Until Quit = 1
  End 
EndIf
Dernière modification par Jacobus le dim. 28/juin/2026 10:33, modifié 1 fois.
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
MLD
Messages : 1134
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: SpinGadgetFloat()

Message par MLD »

Merci jacobus pour le partage
Je trouve que tu as des idées très pertinentes.
A+
Avatar de l’utilisateur
Jacobus
Messages : 1638
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: SpinGadgetFloat()

Message par Jacobus »

Merci MLD,
je suis toujours à l'affût, à la recherche d'une idée lorsque je me retrouve bloqué ou ralenti. J'avoue que j'aime bien ça. :D
Si en plus cela peut aider d'autres codeurs...
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
venom
Messages : 3218
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: SpinGadgetFloat()

Message par venom »

Jacobus a écrit : dim. 28/juin/2026 10:38je suis toujours à l'affût, à la recherche d'une idée lorsque je me retrouve bloqué ou ralenti.
Vivement les prochains blocages alors :roll: :lol: :wink:






@++
Windows 10 x64, PureBasic 6.30 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
MLD
Messages : 1134
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: SpinGadgetFloat()

Message par MLD »

Salut a tous
Moi aussi il arrive que je bloque sur un problème.
Un jour j'ai fait ceci

Code : Tout sélectionner

;MLD le 9/11/2012
; change un texte entre deux limiteurs
;PB5 et +
Procedure.s ChangeStringField(chaine$,Index,Delimiteur$,texte$)
nbd.w = 0 : lenG = 0 : lenD = 0
If chaine$ <> ""
 For i.w = 1 To Len(chaine$)
  If Mid(chaine$,i,1) = Delimiteur$
   nbd = nbd + 1
   If nbd = index -1
    lenG = i
   EndIf
   If nbd = Index
    lenDd = i
   EndIf
   lenD = i - lenDd  
  EndIf 
 Next
 If nbd => Index ;vérif qu'il y a bien le nombre de délimiteur nécéssaire pour l'appel de la fonction
  ProcedureReturn Left(chaine$,lenG) + texte$ + Right(chaine$,lenD+1)
 EndIf
EndIf    
EndProcedure

chaine$ = "Super *belle *cette *fille*"
Debug chaine$
a$ = StringField(chaine$,1,"*") + StringField(chaine$,2,"*")+StringField(chaine$,3,"*")+StringField(chaine$,4,"*")
Debug a$
chaine$ = ChangeStringField(chaine$,2,"*","moche ")
Debug chaine$
b$ = StringField(chaine$,1,"*") + StringField(chaine$,2,"*")+StringField(chaine$,3,"*")+StringField(chaine$,4,"*")
Debug b$
Bonne journée
Avatar de l’utilisateur
Jacobus
Messages : 1638
Inscription : mar. 06/avr./2004 10:35
Contact :

Re: SpinGadgetFloat()

Message par Jacobus »

Pas mal, c'est ce que j'aime, en se grattant un peu la tête on peut trouver une solution. :)
Je ne sais pas s'il y avait toutes les fonctions de la bibliothèque "String" lorsque tu as créé celle-ci, mais aujourd'hui on pourrait faire comme cela :

Code : Tout sélectionner

chaine$ = "Super *belle et mignone *cette *fille*"
Debug chaine$
Global Nbindex = CountString(Chaine$, "*")

Procedure.s ChangeStringField(chaine$, Index, Delimiteur$, texte$)
  
  If Index > 0 And Index <= Nbindex
    ChaineCherchee$ = StringField(chaine$, Index, Delimiteur$)
    NewString.s = ReplaceString(Chaine$, ChaineCherchee$, texte$, #PB_String_CaseSensitive, 1, 1)
    ProcedureReturn NewString.s
  Else 
    ProcedureReturn "Erreur!"
  EndIf 
  
EndProcedure

Debug ChangeStringField(chaine$, 2, "*", "cageot de boudins ")
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Avatar de l’utilisateur
MLD
Messages : 1134
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: SpinGadgetFloat()

Message par MLD »

@Jacobus
Non a l'époque ReplaceString n'existait pas
A+
Avatar de l’utilisateur
falsam
Messages : 7417
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: SpinGadgetFloat()

Message par falsam »

Merci pour ce nouveau code avec ces deux nouvelles fonctionnalités :
GetSpingadgetFloat(GadgetString.i)
SetSpinGadgetFloat(GadgetString.i, TextValue.s)
Configuration : Windows 11 Famille 64-bit - PB 6.23 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
venom
Messages : 3218
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: SpinGadgetFloat()

Message par venom »

falsam a écrit : lun. 29/juin/2026 10:36 Merci pour ce nouveau code avec ces deux nouvelles fonctionnalités :
GetSpingadgetFloat(GadgetString.i)
SetSpinGadgetFloat(GadgetString.i, TextValue.s)
Ce genre de fonction pourrait être directement ajouter aux futurs version purebasic ?

Je veux dire, Fred peut prendre tel quel le code et l'ajouter aux prochains compilateur ?

Car si ça peut aider purebasic via la communauté c'est top 8) Comme via Github.







@++
Windows 10 x64, PureBasic 6.30 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre