Programming the Ostendo Interface Kit (OIK) by Bryce Schroeder The Ostendo Interface Kit is designed to allow programmers to easily make graphical user interfaces for pygame-based games using the Ostendo Resource Manager. It is intended to be easy to use and pythonic. The basic paradigm for specifiying the interface is declarative, which is to say that instead of saying things in an imperative fashion like this: create a window create a button add the button to the window set the button's clicked action to this function add the window to the window manager display the window You say, in a declarative model: there is a window in the window manager. there is a button in the window that does this when clicked The mechanism for impelmenting specific functionality (non-generic responses to events like clicking or key presses) of widgets is usually subclassing from a more generic class of widget, rather than using callback functions, which I felt were not very object oriented. (Python being dynamic, you can still use the callback function method to change object functionality dynamically if you want. You probably shouldn't need to do that.) As a quick example, here's the obligatory friendly button using Oik: class HelloButton(interface.button.ITextButton) p_text = "Hello!" def handle_unclick(self, lx, ly): print "Hello, world!" We can see that the specific response of the button to being clicked (technically, being 'unclicked', meaning that the button was clicked and then the mouse button was released over it, triggering this) has been determined by overloading a method of the generic text button object. To create a HelloButton object, assuming we already have a window named foo_win, we might do this: HelloButton(foo_win, x=2, y=2, h=2, w=2) Many widgets have parameters other than the x and y position (which are measured in 16 * 16 tiles, just like h and w). For instance, a text button has a parameter 'text' which does what you'd think. In this case, we don't pass a text parameter because we have already set an acceptable default value for the text of a HelloButton by defining the class attribute p_text. (Attributes of the form p_* set default values for parameters.) Windows can themselves be added to window managers. Generally, you should create interfaces using the Ostendo Interface resource. -------- Kinds of Events -------- The kinds of events the widgets can receive are: mouse (motion of the mouse) click (click of the left button) unclick (release of the left button) rightclick (click of the right mouse button or control+left.) rightunclick (release of a right click) drop (droping of a dragged item.) key (press of a key) Each widget has a function named accept_* where the star is replaced by one of the events named above. This function acts as a filter, determining when the widget will accept an event. Usually, you will not have to replace the accept method unless you are making a new basic kind of widget, and often not even then. There is also a set of methods named handle_* which describe the responses of the object to certain events. Expect to replace these methods frequently in your derrived classes. Certain specialized widgets also replace the methods process_*. You shouldn't be doing that unless you know unless you really what you're doing, consult the code for examples of how to do this. You don't have to worry about handling appearnce changes for mouse-over and so forth; these things are taken care of internally. If your widget needs some kind of freakish behavior in this regard, read the funciton 'transition' in the code and look at how it is used. -------- Making Widgets -------- Although the line between making custom widgets and using the toolkit normally is somewhat blury (because we make our specific widgets via inheritence, and by the same mechanism we make generic widgets from the base class IObj or other more generic widgets), if your widget requires a custom apperence, it is probably a custom widget. To alter the apperence of a widget, replace the method render_self. Consult the code for more information, it is documented with pydoc and numerous examples. On no account overload the 'render' method. The method to be replaced for custom_widgets is 'render_self'. When you create a widget, you pass in parameters to it. You can set defaults for these parameters by creating class attributes of the form p_*, where * is the name of the parameter. These are identified via introspection and placed into the parameter dictionary self.p. You can also use self.p.get(name, default). A few very fundimental properties have default values stored in IObj's "defaults" dictionary. You can link widgets one to another using the 'link' parameter. Then, when something interesting happens to the widget, it will send a message (a call to get_message) to the linked widget. This is used for things such as scroll bars. -------- Learning More -------- Read the code, which is documented with pydoc, and look at the examples. -------- Doing Drag and Drop: an example -------- class DragSpawn(interface.button.ITextButton): def handle_unclick(self, lx, ly): self.start_drag(self.p.get("thing")) class DragReceptor(interface.button.ITextButton): drop_destination = True def handle_drop(self, item): print "this was dropped:", item