A hyper is a binary relation between two objects. Hypers are, like connection objects, guarded automatically against destruction of one of the related objects. Special methods allow for easy communication between hypered objects.
Hypers form an adequate answer if objects need to be related that depend temporary and incidentally on each other. It is possible to be informed of the destruction of hypers, which enables a hypered object to keep track of its environment. Good examples for the usage of hypers are to express the relation between multiple frame objects working together to form a single application or maintaining the relation between an application object (persistent object, model) and its visualisation (controller).
Of course relations between objects can be maintained using instance-variables, but this process requires awareness from both related objects as well as significant bookkeeping.
The example of this section demonstrates a common existence
relationship. If the `main' object is destroyed, all related `part'
objects should be destroyed too, but if a part is destroyed, the main
should not be destroyed. This semantic is expressed using a refinement
of class hyper that can be found
library(hyper) of the
:- pce_begin_class(partof_hyper, hyper, "<-to is a part of <-from"). unlink_from(H) :-> "->destroy the <-to part":: get(H, to, Part), ( object(Part), send(Part, has_send_method, destroy) -> send(Part, destroy) ; free(Part) ), free(H). :- pce_end_class.
This hyper is demonstrated in the following application. We have an application for editing a graphical representation. The colour of the objects can be modified by double-clicking an object and selecting a colour in a dialog window. In this example we do not use a modal dialog and using the hyper serves two purposes. First of all it tells the dialog what object should be changed, but second, it ensures the dialog is destroyed if the box is.
:- use_module(library(hyper)). :- pce_begin_class(link_demo, picture). initialise(P) :-> send_super(P, initialise, 'Link Demo'), send(P, recogniser, click_gesture(left, '', single, message(P, add_box, @event?position))). add_box(P, At:point) :-> send(P, display, new(link_box), At). :- pce_end_class(link_demo). :- pce_begin_class(link_box, box). handle(w/2, 0, link, north). handle(w/2, h, link, south). handle(0, h/2, link, west). handle(w, h/2, link, east). initialise(B) :-> send_super(B, initialise, 100, 50), send_list(B, recogniser, [ click_gesture(left, '', double, message(B, edit)), new(connect_gesture), new(move_gesture) ]). colour(red). colour(green). colour(blue). colour(yellow). edit(B) :-> "Allow changing colour":: new(D, dialog('Select colour')), send(D, append, new(M, menu(colour, choice, message(?(D, hypered, box), fill_pattern, @arg1)))), ( colour(Colour), send(M, append, menu_item(colour(Colour), @default, pixmap(@nil, background := Colour, width := 32, height := 16))), fail ; true ), send(D, append, button(done, message(D, destroy))), new(_, partof_hyper(B, D, dialog, box)), get(B, display_position, PosB), get(PosB, plus, point(20,100), PosD), send(D, open, PosD). :- pce_end_class(link_box).
<-from side of the hyper is being destroyed. May be refined.
<-to side of the hyper is being destroyed. May be refined.
Below are the two most commonly used methods dealing with hypers and defined on class object. XPCE defines various other methods for deleting and inspecting the hyper structure. Use the online manual for details.
<-hypered objects. Similar to
<-get_hyper, but does not stop if the method is received successfully. Succeeds if at least one hypered object accepted the message.
|@arg2||The hyper object|
|@arg3||The object at the other end of the hyper|