Skip to content

User Guide : Client Data

Martin Corino edited this page Mar 19, 2024 · 2 revisions
     About      HowTo      FAQ      Reference documentation

Client/User data with wxRuby

Introduction

The wxWidgets library has widespread support for attaching arbitrary client (or user) data to GUI elements like windows (all event handlers actually), window items, sizer items etc. To cater to various C++ use cases in most instances this support covers both specific wxWidgets defined types (like wxClientData and wxObject instances) and untyped data pointers (represented as void *) with subtle but essential differences.

wxRuby implements a fully compatible version of this support.

Everything is an Object

As Ruby does not do untyped data (everything is an Object), and having two different options is confusing anyway, wxRuby provides only a single option and more or less unifies the interface across the entire library. In Ruby anywhere the original wxWidgets library supports some type of client (or user) data attachment wxRuby will support the attachment of any arbitrary Ruby Object by either the method #set_client_object (where C++ supports SetClientData and SetClientObject) or #set_user_data (where C++ supports SetUserData). Data retrieval is supported by complementary #get_client_object or #get_user_data methods in all cases. Wherever C++ supports SetClientObject wxRuby also provides the method aliases #set_client_data and #get_client_data.

Another difference with C++ is that for typed client data in wxWidgets developers could leverage object destruction as callback trigger (through the implementation of virtual destructors) to handle any required 'unlinking' logic. This obviously does not apply to untyped data (one of the 'subtle' differences). As Ruby does not provide any usable object destruction hooks this does not work there. Ruby however has 'Duck-typing' which is what wxRuby uses to provide support for a unlinking callback 'hook' for attached client data.

Any attached Ruby Object implementing (responding to) the method #client_data_unlinked will have that method called after the attached object has been detached from the element it was attached to (either because of data replacement or element deletion).

Regard the following example.

    frame = Wx::Frame.new(nil, Wx::ID_ANY)
    
    # attach a hash with user data  
    frame.set_client_data({ text: 'A string', float: 3.14 })
    
    # ... do something with frame
    
    # replace the user data
    frame.set_client_data([1,2,3,4])

    # ... do something else with frame

In this case standard Ruby objects are attached. After attachment the object can be retrieved using a call to get_client_data anywhere access to the frame instance is available.

Using a specially derived (or adapted) object a developer can handle specific logic after the object has been unlinked like in this example:

    # define a user data class
    class MyUserData
      def initialize(payload)
        @payload = payload
      end
      attr_reader :payload
      
      def client_data_unlinked
        # handle some logic
      end
    end

    # ...

    # attach data to some window
    win.set_client_data(MyUserData.new(some_payload_data)) 

    # ...
    
    # reset user data for some reason (will call MyUserData#client_data_unlinked after replacement)
    win.set_client_data(nil)

CommandEvent data

wxRuby also fully supports the propagation of attached client data to Wx::CommandEvent objects (see Wx::CommandEvent#get_client_object and Wx::CommandEvent#set_client_object). As mentioned above wxRuby provides the method aliases #set_client_data and #get_client_data here also.

Clone this wiki locally