Modul Named GadgetData

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Modul Named GadgetData

Beitrag 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
Zuletzt geändert von mk-soft am 13.12.2015 01:18, insgesamt 4-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Bisonte
Beiträge: 2430
Registriert: 01.04.2007 20:18

Re: Named GadgetData

Beitrag 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.
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Named GadgetData

Beitrag 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:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Named GadgetData

Beitrag 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:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Named GadgetData

Beitrag von ts-soft »

mk-soft hat geschrieben:SetProp(...) und GetProp(...) sind auch eine gute Anregung.
http://www.purebasic.fr/german/viewtopi ... 21#p320821 :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Named GadgetData

Beitrag von mk-soft »

Hatte ich so in Erinnerung das es schon ein Modul gibt :allright:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Modul Named GadgetData

Beitrag 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.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Modul Named GadgetData

Beitrag 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.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
mk-soft
Beiträge: 3701
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Modul Named GadgetData

Beitrag 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.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Bisonte
Beiträge: 2430
Registriert: 01.04.2007 20:18

Re: Modul Named GadgetData

Beitrag 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.
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Antworten