lanciare messaggi

__send_cmd( cmd,…)

E’ usato per richiamare una funzione CLB_messenger::send(….) con una facilitazione: la macro send_cmd  inserisce automaticamente _$end a fine lista, come atteso  dalla CLB_messenger::send(..).  Per usare la send_cmd:

il messaggio è trasmesso a tutti gli oggetti connessi  (vedi CLB_regs(..)) ed esistono due diverse modalità d’uso, a seconda che si mandi il messaggio da un oggetto dato il suo putatore obj, o da una funzione della classe

  • per un oggetto obj:    obj->send_cmd(pars, ..) dove obj è un puntatore ad una istanza CLB_messenger (ad esempio un qualunque WIDGET)
  • per una chiamata da dentro una funzione della classe: send_cmd(pars, ..)
__send_cmd_to_obj(w_plot, _$get, _$selected, _$document, doc);
...
obj->__send_cmd_to_obj(w_plot, _$get, _$selected, _$document, doc);

__send_cmd_to_obj(receiver,…)

E’  usato per richiamare una funzione CLB_messenger::send_to_obj(….)
la macro send_cmd(..) inserisce automaticamente _$end a fine lista, come richiesto dalla send(..)
anche in questo caso come per  per usare la send_cmd:
per un oggetto obj:  obj->__send_cmd_to_obj(pars, ..)
per una chiamata da dentro una funzione della classe: __send_cmd_to_obj(pars, ..)

Il primo parametro del comando è l’oggetto CLB_messenger che deve ricevere il comando:

/** WIDGET *w_plot   // assegnato in precedenza..
*/
CURVE curva;
__send_cmd_to_obj(w_plot, _$get, _$selected, _$curve, &curva);
...

Le due macro permettono la spedizione di un comando da parte di una classe con interfaccia CLM_messenger verso altri oggetti con la stessa interfaccia. I comandi usano, per trasferire il comando un dei due metodi di CLB_messenger:

bool CLB_messenger::send(__arg_value cmd, ...);

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

Comunque il messaggio, attraverso i due metodi, se il destinatario è correttamente definito, arrivera alla funzione  slot_messenger della classe derivata: la funzione, essendo virtuale, sarà stata riscritta per ciascuna classe, e sarà in grado, utilizzando altre macro di CLB_lang, di estrarre il messaggio ed effettuare le scelte conseguenti:

	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;
	}

L’esempio di codice  è già stato riportato in questo articolo.  Lo riprendiamo per spiegare nei particolari il metodo di costruzione delle funzioni slot_messenger.

La funzione slot_messenger contiene nella dichiarazione dei parametri la macro _received_data;  dovrà sempre essere in questa forma, poichè la macro con è altro che un’ istanza test_request  (_requ_) usata all’interno delle macro di analisi del messaggio utilizzabili all’interno della funzione.

 #define _received_data test_request &_requ_

descriviamo ora le macro di analisi del messaggio usate, sapendo che contengono inplicitamente la istanza  _requ_  parametro della funzione slot_messenger.

_is_request(…)

#define __is_request(...) if (_requ_.is( __VA_ARGS__,0))

la macro , che ha come argomenti la frase del messaggio ( __is_request(_$get,_$selected, _$curve) ) utilizza la funzione  test_request::is(..) per testare il significato del  messaggio ricevuto; se il messaggio è quello testato, allora il blocco di codice che segue viene eseguito;

Nel blocco troviamo il comando CLB_lang  __pop_p(cv, CURVE); che estrae dallo stack del messaggio il successivo parametro, che per la sintassi attesa deve essere un CURVE * (vedi poco sopra questo esempio..)

__pop_p(ptr,type)

#define __pop_p(ptr,type) type *ptr=(type *)_requ_.pop_param();

la macro costruisce un pointer ptr  di tipo type (nel caso in esempio CURVE *cv ) richiamando al suo interno la  test_request::pop_param();   (notare che l’istanza di questa classe usata è proprio  la  _requ_ passata alla funzione con la macro _received_data..)

Ovviamente la sequenza di estrazione del parametro obbedisce all’ordine di trasmissione definito nel comando  lanciato dal sender. 

la macro _is_request(…) verrà usata tante volte quante sono le frasi di ricezione accettate dalla classe; le frasi non riconosciute corrisponderanno a messaggi non intercettati, e non avranno alcun effetto sulla classe; questo permette ad esempio che più istanze CLB_messenger, connesse ad una classe mediante la funzione CLB_messenger::regs(..) intercetteranno solo i messaggi (le frasi)  analizzati in slot_messenger, quindi classi diverse registrate possono intercettare messaggi diversi; notare che la stessa frase ovviamente potrà essere intercettata da classi diverse, purchè  registrate nel sender.

per concludere questa esposizione, di seguito è riportato un altro esempio di slot_messenger, relativo ad un’altra classe, la WIDGET_DOCUMENT, dove si potrà osservare l’uso più volte delle due macro __pop_p e __is_request per intercettare diversi tipi di messaggio e parametri mandati dall’oggetto chiamante (definito qui sender)

		bool WIDGET_DOCUMENT::slot_messenger(_received_data)
		{
			__getstr

			__is_request(_$attach, _$dock_navigator)
			{
				SETBIT(NAVIGATOR,true)
			}

			__is_request(_$display, _$area)
			{
				__pop_p(r, RectF);
				$obj->ZoomArea(r->X, r->Y, r->Width, r->Height); 
			}

			__is_request(_$zoom, _$area)
			{
				__pop_p(sender, void)
				if (sender == this)
					return false;		// è il chiamante ..
				__pop_p(org, PointF);
				__pop_p(scale, float);

				if (_MAPPER.Zoom(*scale) && _MAPPER.SetOrig(*org))
				{

					PointF *orgig = _MAPPER.GetOrig();

					INVALIDATE_SV_AREA(CANVAS, 1)
					PAINT(CANVAS)
					PAINT(_$str->scr_vert)
					PAINT(_$str->scr_horz)
					PAINT(_$str->h_ruler);
					PAINT(_$str->v_ruler);
				}
			}

			return false;
		}

Nota: il programmatore che progetterà una classe derivata da CLB_messenger, potrà comunque definire messaggi basati su keyword personali: ad esempio potrà lanciare comandi che contengono la keyword _$myDefin (=L”my definition word”) . In questo caso si consiglia di utilizzare almento una lettera maiuscola ed evitare le definizioni tutte minuscolo, per evitare conflitti con eventuali keyword di CLB_lang (che sono tutte, appunto minuscolo).

Pages: 1 2

Leave a Reply

Skip to toolbar