Seite 1 von 4

Modul Named GadgetData

Verfasst: 08.11.2015 15:29
von mk-soft
Mit GadgetData kann man ja leider nur ein Wert zu einen Gadget zuweisen.
Manchmal möchte man aber mehrere Werte (Properties) ablegen. Dazu werden die Werte in einer Map hinterlegt.

Hier mal ein Beispiel mit einen BindGadgetEvent für das CalendarGadget

Update v1.03

Update v1.04
Räumt jetzt automatisch die Daten bei CloseWindow oder bei FreeGadget von ContainerGadget auf
Geht leider nicht unter Mac :cry:

Bugreport http://www.purebasic.fr/english/viewtop ... 24&t=63979

Code: Alles auswählen

Update v1.05
- Fixed: Läuft jetzt auch unter MacOS
- Added: Überprüfung von PanelGadget (RemoveGadgetItem)

Code: Alles auswählen

;-Begin

; Comment: Named GadgetData
; Author : mk-soft
; Version: v1.05
; Created: 08.11.2015
; Updated: 26.11.2015
; Link   : http://www.purebasic.fr/english/viewtopic.php?f=12&t=63937

; ***************************************************************************************

DeclareModule MyGadgetData
  
  Declare   InitGadgetData(event = #PB_Event_FirstCustomValue + 10001)
  Declare   SetGadgetDataValue(gadget, *value, property.s = "Default")
  Declare   GetGadgetDataValue(gadget, property.s = "Default")
  Declare   SetGadgetDataString(gadget, text.s, property.s = "Default")
  Declare.s GetGadgetDataString(gadget, property.s = "Default")
  Declare   FreeGadgetData(gadget)
  Declare   DebugGadgetData(gadget)
  Declare   RemoveGadgetItemEx(gadget, position)
  Declare   FreeGadgetEx(gadget)
  Declare   CloseWindowEx(window)
  
EndDeclareModule

Module MyGadgetData
  
  EnableExplicit
  
  Structure udtMyGadgetData
    value.i
    text.s
  EndStructure
  
  Structure udtMyGadgetDataSet
    gadget.i
    Map ds.udtMyGadgetData()
  EndStructure
  
  Global NewList GadgetData.udtMyGadgetDataSet()
  Global event_update
  
  Declare UpdateGadgetData()
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure InitGadgetData(event = #PB_Event_FirstCustomValue + 10001)
    
    BindEvent(event, @UpdateGadgetData())
    event_update = event
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure SetGadgetDataValue(gadget, *value, property.s = "Default")
    
    Protected *map.udtMyGadgetDataSet
    
    *map = GetGadgetData(gadget)
    If *map = 0
      *map = AddElement(GadgetData())
      If *map
        *map\gadget = gadget
        *map\ds(property)\value = *value
        SetGadgetData(gadget, *map)
      EndIf
    Else
      *map\ds(property)\value = *value
    EndIf
      
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure GetGadgetDataValue(gadget, property.s = "Default")
    
    Protected *map.udtMyGadgetDataSet
    
    *map = GetGadgetData(gadget)
    If *map
      ProcedureReturn *map\ds(property)\value
    Else
      ProcedureReturn 0
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure SetGadgetDataString(gadget, text.s, property.s = "Default")
    
    Protected *map.udtMyGadgetDataSet
    
    *map = GetGadgetData(gadget)
    If *map = 0
      *map = AddElement(GadgetData())
      If *map
        *map\gadget = gadget
        *map\ds(property)\text = text
        SetGadgetData(gadget, *map)
      EndIf
    Else
      *map\ds(property)\text = text
    EndIf
      
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure.s GetGadgetDataString(gadget, property.s = "Default")
    
    Protected *map.udtMyGadgetDataSet
    
    *map = GetGadgetData(gadget)
    If *map
      ProcedureReturn *map\ds(property)\text
    Else
      ProcedureReturn ""
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure FreeGadgetData(gadget)
    
    Protected *map.udtMyGadgetDataSet
    
    ForEach GadgetData()
      If GadgetData()\gadget = gadget
        DeleteElement(GadgetData(), 1)
      EndIf
    Next
    SetGadgetData(gadget, 0)
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure DebugGadgetData(gadget)
    
    Protected *map.udtMyGadgetDataSet
    
    *map = GetGadgetData(gadget)
    If *map
      ForEach *map\ds()
        Debug "Property('" + MapKey(*map\ds()) + "') = " + *map\ds()\value + " : " + *map\ds()\text
      Next
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure UpdateGadgetData()
    
    ForEach GadgetData()
      If Not IsGadget(GadgetData()\gadget)
        DeleteElement(GadgetData(), 1)
      EndIf
    Next
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure RemoveGadgetItemEx(gadget, position)
    
    RemoveGadgetItem(gadget, position)
    If GadgetType(gadget) = #PB_GadgetType_Panel
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
        PostEvent(event_update)
      CompilerElse
        UpdateGadgetData()
      CompilerEndIf
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure FreeGadgetEx(gadget)
    
    If gadget = #PB_All
      FreeGadget(#PB_All)
      ClearList(GadgetData())
    Else
      FreeGadget(gadget)
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
        PostEvent(event_update)
      CompilerElse
        UpdateGadgetData()
      CompilerEndIf
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  Procedure CloseWindowEx(window)
    
    If window = #PB_All
      CloseWindow(#PB_All)
      ClearList(GadgetData())
    Else
      CloseWindow(window)
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
        PostEvent(event_update)
      CompilerElse
        UpdateGadgetData()
      CompilerEndIf
    EndIf
    
  EndProcedure
  
  ; ---------------------------------------------------------------------------------------
  
  
EndModule

; ***************************************************************************************

;-Init

UseModule MyGadgetData

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  InitGadgetData()
CompilerEndIf

Macro SetGadgetData(gadget, value, property = "Default")
  SetGadgetDataValue(gadget, value, property)
EndMacro

Macro GetGadgetData(gadget, property = "Default")
  GetGadgetDataValue(gadget, property)
EndMacro

Macro RemoveGadgetItem(gadget, position)
  RemoveGadgetItemEx(gadget, position)
EndMacro

Macro FreeGadget(gadget)
  FreeGadgetEx(gadget)
EndMacro

Macro CloseWindow(window)
  CloseWindowEx(window)
EndMacro

;-End Named GadgetData

; ***************************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  ; CalendarGadget Events
  
  Procedure EventHandler_Calendar()
    
    Protected gadget, datetime, date, lastdate
    
    gadget = EventGadget()
    
    If EventType() <> #PB_EventType_Change 
      datetime = GetGadgetState(gadget)
      date = datetime / 86400
      lastdate = GetGadgetData(gadget, "EventData")
      If date <> lastdate
        lastdate = date
        SetGadgetData(gadget, lastdate, "EventData")
        PostEvent(#PB_Event_Gadget, EventWindow(), gadget, #PB_EventType_Change, datetime)
      EndIf
      
    EndIf
    
  EndProcedure
  
  Procedure Init_Calendar(gadget, first = #False)
    
    SetGadgetData(Gadget, Date() / 86400, "EventData")
    If first
      PostEvent(#PB_Event_Gadget, EventWindow(), gadget, #PB_EventType_Change, Date())
    EndIf
    BindGadgetEvent(Gadget, @EventHandler_Calendar())
    
  EndProcedure
  
  Procedure Main()
    
    Protected event
    
    If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Hello")
      CalendarGadget(0, 10, 10, 200, 200)  
      CalendarGadget(1, 220, 10, 200, 200)  
    EndIf
    Init_Calendar(0, #True)
    Init_Calendar(1, #True)
    
    Repeat
      event = WaitWindowEvent()
      Select event
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Select EventType()
                Case #PB_EventType_Change
                  Debug "New date 0: " + FormatDate("%dd.%mm.%yyyy", EventData())
                  cnt = GetGadgetData(0) + 1
                  SetGadgetData(0, cnt)
                  SetGadgetDataString(0, FormatDate("%dd.%mm.%yyyy", EventData()), "Date")
                  DebugGadgetData(0)
                  
              EndSelect
              
            Case 1
              Select EventType()
                Case #PB_EventType_Change
                  Debug "New date 1: " + FormatDate("%dd.%mm.%yyyy", EventData())
                  cnt = GetGadgetData(1) + 1
                  SetGadgetData(1, cnt)
                  SetGadgetDataString(1, FormatDate("%dd.%mm.%yyyy", EventData()), "Date")
                  DebugGadgetData(1)
                  
              EndSelect
            
          EndSelect
      EndSelect
      
    ForEver
    
  EndProcedure : Main()
  
CompilerEndIf

Re: Named GadgetData

Verfasst: 08.11.2015 15:51
von Bisonte
Im Grunde nicht verkehrt. Nur SetGadgetData() wird damit hinfällig.
Ja, ich sehe, dass es per Makro umgebogen wird...

Sinnvoller finde ich dann aber die Verwendung per Modul, wo eine Globale Map die Daten speichert,
wobei dann der "MapKeyName" die GadgetID ist. (Wobei man das auch auf viele andere Sachen
ausweiten kann... Windows, Statusbar, Images usw...)
Drei Funktionen (Get/Set/Remove) und fertig. Somit entfällen die Makros, und es wird kein Speicher mehr per
Allocate... erstellt, den man vergessen könnte zu löschen. Und nebenbei verhält es sich dann wie die
WindowsAPI SetProp_(), GetProp_(), RemoveProp_(). Das man die Sachen die man erstellt auch selbstständig
wieder freigibt, sollte eigentlich jedem klar sein.

Ich wollte jetzt nicht deine Leistung schmälern... nur meine Meinung kundtun.

Re: Named GadgetData

Verfasst: 08.11.2015 16:06
von ts-soft
Ich kann mich da Bisonte nur anschließen, so im grossen und ganzen. Vor allem stört mich, das Get/SetGadgetData genutzt
wird, was einer universellen Verwendung im Wege steht.
Globale Liste, am besten in einem Modul wäre da praktischer.

Aber als Codebeispiel sicher für viele erstmal anregend :allright:

Re: Named GadgetData

Verfasst: 08.11.2015 16:13
von mk-soft
Danke für die Anregungen :wink:
Vor allem stört mich, das Get/SetGadgetData genutzt
wird, was einer universellen Verwendung im Wege steht.
Vielleicht nicht erkannt.
Aber aus dem Grund das Get/SetGadgetData weiterhin universal genutzt werden kann habe ich dieses so geschrieben.
Diese Werte werden in der Map unter Default abgelegt.

P.S.
Somit nur mit einen weiteren Parameter erweitert.

SetProp(...) und GetProp(...) sind auch eine gute Anregung.

P.P.S.
Werde es noch so erweitern das auch mit CloseWindow die Ressourcen freigegeben werden...


:wink:

Re: Named GadgetData

Verfasst: 08.11.2015 16:28
von ts-soft
mk-soft hat geschrieben:SetProp(...) und GetProp(...) sind auch eine gute Anregung.
http://www.purebasic.fr/german/viewtopi ... 21#p320821 :wink:

Re: Named GadgetData

Verfasst: 08.11.2015 18:08
von mk-soft
Hatte ich so in Erinnerung das es schon ein Modul gibt :allright:

Re: Modul Named GadgetData

Verfasst: 08.11.2015 21:13
von mk-soft
Ich dachte das mit CloseWindow auch die interne Liste von Gadgets bereinigt wird. Dem ist aber so nicht.
Somit geht es leider auch nicht die Ressourcen automatisch mit CloseWindow zu bereinigen.

Kleines Update und alles ein wenig im Modul gekapselt.

Re: Modul Named GadgetData

Verfasst: 08.11.2015 21:46
von GPI
Übrigends, wenn du in Windows programmiert: Jedes Gadget (in der Windows-Api Control genannt) schickt normalerweise eine "ich sterbe jetzt" - Nachricht, wenn es abgemeldet wird. So könntest du den Speicher automatisch wieder freigeben. Funktioniert unter Linux/Mac dann natürlich nicht.

Re: Modul Named GadgetData

Verfasst: 08.11.2015 21:54
von mk-soft
Ich bin seit etwas über ein Jahr mit Mac OS X unterwegs. Seit dem versuche ich immer alles Plattformunabhängig zu programmieren.

Re: Modul Named GadgetData

Verfasst: 08.11.2015 22:54
von Bisonte
mk-soft hat geschrieben:Ich dachte das mit CloseWindow auch die interne Liste von Gadgets bereinigt wird. Dem ist aber so nicht.
Somit geht es leider auch nicht die Ressourcen automatisch mit CloseWindow zu bereinigen.
Mit Umwegen geht das schon.

Das OpenWindow() per Makro umbiegen und in der Prozedur das #PB_Event_CloseWindow abfragen, wenn eingetreten, freigeben aller Gadgets.
Das bedarf dann allerdings noch der Zuordnung der Gadgets zu einem Window.

Wenn das auf allen OS mit dem PB_EnumerateObject Zeugs klappt, wäre das einfach.