CLB_messenger

La classe appartiene al namespace CLB::Messaging; il namespace CLB, contenuto nella dll CLB_000 è destinato a contenere tutte le classi di nuova generazione di Colibri, dalla versione 8 in poi.

CLB_messenger  permette la messaggistica bidirezionale fra oggetti; introdotta  dalla data 20 febb 2019,  ha lo scopo di facilitare la comunicazione fra oggetti.

Il paradigma è molto semplice:

  • Tutte le classi che vengono connesse sono derivate da CLB_messenger;  in pratica, attraverso la dichiarazione public CLB_messenger la classe  eredita l’interfaccia che permetterà la trasmissione diretta di comandi e parametri (vedremo come)
  • Sono definite funzioni send(..) e send_to_obj(..)  per la trasmissione di un messaggio ad oggetto di cui si conosce il nome globale, o nel secondo caso del quale si conosce l’indirizzo (puntatore).
  • Viene  riscritta per ogni classe derivata la funzione virtuale  slot_messenger(..) che costituisce il parser dei comandi ricevuti;  è compito di questa funzione filtrare i comandi secondo le specifiche costruttive (vederemo che è possibile interrogare le classi per ottenere una lista delle specifiche di comando, più o meno  come avviene con i servizi web..)
  • Se una istanza CLB_messenger A  viene registrata  attraverso la funzione CLB_messenger::regs(..) di un’altra istanza B di CLB_messenger, essa riceverà in slot_messenger(..) tutte le notifiche dei comandi lanciati dall’oggetto B, fino ad una eventuale chiamata  B->unregs(A);
  • Tutte le istanze allocate delle classi di interfaccia CLB_messenger vengono automaticamente registrate in una lista di accesso, fino alla loro distruzione; questo permette un accesso all’oggetto attraverso il nome proprio, un identificatore univoco dell’istanza; descriveremo di seguito come gestire questa eventualità.

Nota: In pratica, una classe derivata da  CLB_messenger potrebbe solo possedere una funzione slot_messenger(..) per potere ricevere comandi da un qualunque oggetto creato nel framework..

 

Questo è il codice di dichiarazione della classe:

class AFX_EXT_CLASS CLB_messenger
{
public:

	bool regs(CLB_messenger *robj);
	bool unregs(CLB_messenger *robj);

	bool registered(CLB_messenger *robj);

	CLB_messenger();
	~CLB_messenger();

	virtual bool slot_messenger(_received_data);

	bool send(__arg_value cmd, ...);

	bool send_to_obj(CLB_messenger *receiver, __arg_value pars, ...);

	__use_private_struct
};

bool regs(CLB_messenger *robj)

registrazione di una classe come oggetto ricevente. Questa funzione permette di registrare l’oggetto robj come ricevente automatico della messaggistica (comandi) della classe.  In pratica tutti i comandi mandati attraverso la funzione Send() del sender saranno ricevuti dagli oggetti
registrati.  E’ possibile registrare un numero qualunque di istanze receiver, e tutti questi oggetti potranno mandare anche messaggi all’oggetto sul quale sono stati registrati.

bool unregs(CLB_messenger *robj)

 rimozione dell’oggetto registrato.  L‘oggetto viene comunque automaticamente rimosso quando distrutta la classe, e l’operazione è fatta dal distruttore di CLB_messenger dal quale deriva. Dopo la sua de-registrazione l’oggetto non riceverà più comandi dalla classe alla quale era collegato cod la funzione regs.

bool registered(CLB_messenger *robj)

Testa che la istanza robj sia stata registrata nella classe; in questo caso rimanda true;

bool send(__arg_value cmd, …)

Manda un comando e parametri relativi a tutti gli oggetti registrati come receiver attraverso la funzione regs; l’ultimo elemento della var_list passata deve essere necessariamente _$end:

bool send_to_obj(CLB_messenger *receiver, __arg_value pars, …)

manda un comando e parametri ad uno specifico oggetto  receiver. l’ultimo elemento della var_list passata deve essere necessariamente _$end;

in questo caso non è necessario che receiver sia stato registrato basta sia un puntatore a un CLB_messenger (vedi l’esempio di codice precedente relativo allo slot di DOCK_document_navigator)

virtual bool slot_messenger(_received_data)

Questa funzione deve essere riscritta per ogni classe derivata da CLB_messenger, perchè corrisponde al parser dei comandi ricevuti. Strutturalmente non è molto diverso dalla definizione di uno slot di ricezione messaggi di OPERATION_CALL prima descritto per DOCK_document_navigator).

Si riporta ad esempio la funzione scritta per la classe Widget_plotter

	bool Widget_plotter::slot_messenger(_received_data)
	{
		__getstr
		__is_request(_$get,_$selected, _$curve)
		{
			__pop_p(cv, CURVE);
			_$str->edit->get_selected_curve(cv);
		}
		return true;
	}

come parametro passato alla funzione, in conformità con la dichiarazione della stessa, c’è sempre la macro _received_data :

#define _received_data test_request &_requ_

questo è un modo per rendere immediatamente utilizzabili le macro __is_request (incontrata prima descrivendo la classe test_request) e __pop_v , una macro equivalente alla  __pop_param 

nel nostro esempio _$get,_$selected, _$curve 

è il comando che richiede un puntatore ad un oggetto CURVE contenuto nella classe; l’oggetto è trasferito nel parametro CURVE *cv estratto dallo stack dei comandi e parametri con __pop_p. La funzione chiamante riceverà questa informazione, come si vede nel codice che segue e che ha effettuato la chiamata..

				// funzione di ricezione dei messaggi da CLB_messenger
				bool slot_messenger(_received_data)
				{
					if (!_$str->layout)
						return false;
					__is_sender(w_plot)
					{
						__is_request(_$get, _$image, _$background)
						{
							__pop_p(img, IMAGE*);
							Layer_color *mrc = _$str->layout->Get_selected_layer();
							if (mrc)
								*img=mrc->get_background_image();
							return true;
						}


						__is_request(_$modified, _$function)
						{
							Layer_color *mrc = _$str->layout->Get_selected_layer();
							if (mrc)
							{

								CURVE *curva = mrc->get_curva();
								__send_cmd_to_obj(w_plot, _$get, _$selected, _$curve, curva);		// estrae la curva modificata
								mrc->calculate_layer_image();			// ricalcola lìimmagine di propagazione
								igrp->calculate_prop_image();
								_paint_result();
							}
						}
					}
					return true;
				}

il codice della classe cui appartiene la funzione, ha ricevuto un messaggio che analizza e decide quali azioni compiere:  __is_sender(w_plot) è una macro che controlla se il sender del comando è w_plot , già noto alla classe ovviamente, in questo caso se ha ricevuto il comando $modified, _$function decide, fra le altre cose, di richiedere la curva per usarla internamente; possiamo osservare che il puntatore curva è passato, come già spiegato, quale parametro nel comando.

 

 

 

Pages: 1 2 3

Leave a Reply

Skip to toolbar