Python Notifier Example

From The Foundry MODO SDK wiki
Jump to: navigation, search

This example from Tim Vazquez shows how to create a command notifier in Python. The sample creates a custom notifier and 2 commands. If you add notify.send and notify.recv to a form, pressing notify.send will force notify.recv to display a random number on the button.

Notifier Implementation

The MyNotifier class implements the notifier server. Notifiers are instanced once for a given set of arguments.

Name() simply returns the internal name of the server, and is the same as the one passed to lx.bless().

AddClients() is called when a new client is added to the notifier. These want to be alerted when the notifier sends a notification. For example, the Form View will add itself as a client to all of the notifiers for each command it contains. Here, we simply add its object to our list of clients.

RemoveClients() is called to remove an existing client from the notifier, indicating that it no longer wants to listen for notifications. A Form View, for example, will do this when the view is destroyed or the commands within it are changed. Here we just remove the object from our list of clients.

Notify() loops through the list of client objects, gets it as a CommandEvent object and calls the Event() method with the flags provided. These flags are defined as CMDNOTIFY flags, and can be any combination of VALUE (control's value changed), LABEL (control's label changed), DISABLE (enabled/disabled state changed) or DATATYPE (the control type itself changed). These tell the Form View how to update the controls, with DATATYPE forcing the entire form to be rebuilt so that it can recreate all of the controls (this is commonly used by Form Command Lists, or when the queried argument's datatype has changed and thus a different kind of control needs to be displayed).

If we wanted to, we could also implement Args() and SetArgs(). These would allow the notifier to take arguments that would determine how it operates. For example, notifier.itemContainingChannel takes the name of the channel to listen for changes on, and only sends notifications when that specific channel has changed.

No more than a single instance of each notifier with a given set of arguments exists at any given time. Since this notifier takes no arguments, only one instance of it will be created by the underlying notifier system, and it will be reused for all clients that want to add themselves to it.

#!/usr/bin/env python
 
import lx
import lxifc
import lxu.command
import random
 
class MyNotifier(lxifc.Notifier):
    masterList = {}
 
    def noti_Name(self):
        return "my.notifier"
 
    def noti_AddClient(self,event):
        self.masterList[event.__peekobj__()] = event
 
    def noti_RemoveClient(self,event):
        del self.masterList[event.__peekobj__()]
 
    def Notify(self, flags):
        for event in self.masterList:
            evt = lx.object.CommandEvent(self.masterList[event])
            evt.Event(flags)
 
lx.bless(MyNotifier,"my.notifier")

Example Commands

These two commands demonstrate the notifier.

notify.send

notify.send is very simple, and just sends a LABEL invalidation on the notifier when it is executed.

class notify_Send(lxu.command.BasicCommand):
 
    def __init__(self):
        lxu.command.BasicCommand.__init__(self)
 
    def basic_Execute(self, msg, flags):
        notifier = MyNotifier()
        notifier.Notify(lx.symbol.fCMDNOTIFY_LABEL)
 
    def basic_Enable(self,msg):
        return True
 
lx.bless(notify_Send, "notify.send")

notify.recv

notify.recv simply generates a random number and displays it as the label in the form via ButtonName(). It uses UIValueHints() to return my.notifier with no arguments so that the Form View will refresh the view and get a new label when notify.send sends its LABEL notification. If the notifier took arguments, we could pass those in place of an empty string in the self._notifiers array.

class CmdNotifiers(lxu.command.BasicHints):
 
    def __init__(self):
        self._notifiers = [('my.notifier','')]
 
class notify_Receiver(lxu.command.BasicCommand):
 
    def __init__(self):
        lxu.command.BasicCommand.__init__(self)
 
    def basic_Execute(self, msg, flags):
        pass
 
    def arg_UIValueHints(self, index):
        return CmdNotifiers()    
 
    def basic_ButtonName(self):
        return str(random.randrange(1000,10000))
 
    def basic_Enable(self,msg):
        return True
 
lx.bless(notify_Receiver, "notify.recv")

See Also