Login ProductsSalesSupportDownloadsAbout |
Home » Technical Support » Elevate Web Builder Technical Support » Support Forums » Elevate Web Builder General » View Thread |
Messages 1 to 7 of 7 total |
Inter-Component Communication |
Thu, Jun 8 2017 3:52 AM | Permanent Link |
Mark Brooks Slikware | Has anybody found a neat way of "messaging" between component instances? For example, if I have a number of TXYZ component instances, is it possible for one to broadcast a message to the others, perhaps indicating its state change or similar?
I can do this in some cases, when all of the TXYZ instances are owned by a common parent, just by iterating the parent children, although it's a bit messy. I know that Tim has mentioned the existing component messaging mechanism previously, but looking at the source, it's not clear to me exactly how that works and how I might (safely) utilise it for my own purposes. Thanks Mark |
Thu, Jun 8 2017 7:42 AM | Permanent Link |
Matthew Jones | Mark Brooks wrote:
> Has anybody found a neat way of "messaging" between component instances? For example, if I have a number of TXYZ component instances, is it possible for one to broadcast a message to the others, perhaps indicating its state change or similar? > > I can do this in some cases, when all of the TXYZ instances are owned by a common parent, just by iterating the parent children, although it's a bit messy. > > I know that Tim has mentioned the existing component messaging mechanism previously, but looking at the source, it's not clear to me exactly how that works and how I might (safely) utilise it for my own purposes. Indeed, I looked at the standard mechanism, and decided it wasn't what I wanted. But it showed what was possible, and I quickly wrote my own. It has been so liberating not having to go around trees of data to send a notification. Plus you can do it async if you don't need it asap. I've included the full unit below. The consts are the events I wanted to broadcast - change as appropriate. Any object can register for any event ID (and unregister). g_xNotifications.NotifyRegister(EVENT_ITEM_HEADER_SIZED, OnHeaderResize); function TfrmOutline.OnHeaderResize(Sender: TObject; nEventID: Integer; xData: TObject): Boolean; var nLoop : Integer; begin result := true; // carry on processing ... end; g_xNotifications.NotifyListenersAsync(self, EVENT_ITEM_HEADER_SIZED, nil); -- Matthew Jones unit uNotifications; interface uses WebCore; {$DEFINE xDEBUG_NOTIFICATIONS} const EVENT_RESOURCE_HEADER_SIZED = 1; EVENT_RESOURCE_HEADER_SIZED_MAX = 5; EVENT_CLEAR_MOUSE_OVER_MAIN = 6; EVENT_CLEAR_MOUSE_OVER_RESOURCE = 7; EVENT_ITEM_HEADER_SIZED = 8; EVENT_ITEM_DETAILS_CHANGE = 9; type TNotificationEvent = function (Sender: TObject; nEventID: Integer; xData: TObject): Boolean of object; TNotifications = class private m_axEvents : array of TNotificationEvent; m_anIDs : array of Integer; m_nEventMax : Integer; public constructor Create; override; function NotifyRegister(nEventID : Integer; xEvent : TNotificationEvent) : Integer; procedure NotifyUnregister(nRegisterHandle : Integer); procedure NotifyListeners(Sender: TObject; nEventID: Integer; xData: TObject); procedure NotifyListenersAsync(Sender: TObject; nEventID: Integer; xData: TObject); end; var g_xNotifications : TNotifications; implementation uses uDebugReport; const ALLOCATE_BUMP = 6; constructor TNotifications.Create; var nLoop : Integer; begin inherited Create; m_nEventMax := ALLOCATE_BUMP; SetLength(m_axEvents, m_nEventMax); SetLength(m_anIDs, m_nEventMax); for nLoop := 0 to m_nEventMax - 1 do begin m_anIDs[nLoop] := -1; end; end; function TNotifications.NotifyRegister(nEventID : Integer; xEvent : TNotificationEvent) : Integer; var nLoop : Integer; nOldMax : Integer; begin {$IFDEF DEBUG_NOTIFICATIONS} DebugReport('NotifyRegister ' + IntToStr(nEventID)); {$ENDIF} for nLoop := 0 to m_nEventMax - 1 do begin if m_anIDs[nLoop] = -1 then begin m_anIDs[nLoop] := nEventID; m_axEvents[nLoop] := xEvent; Result := nLoop; {$IFDEF DEBUG_NOTIFICATIONS} DebugReport('NotifyRegister ' + IntToStr(nEventID) + ' at ' + IntToStr(nLoop)); {$ENDIF} exit; end; end; // not enough room, so make more nOldMax := m_nEventMax; m_nEventMax := m_nEventMax + ALLOCATE_BUMP; {$IFDEF DEBUG_NOTIFICATIONS} DebugReport('Adding more slots ' + IntToStr(nOldMax) + ' to ' + IntToStr(m_nEventMax)); {$ENDIF} SetLength(m_axEvents, m_nEventMax); SetLength(m_anIDs, m_nEventMax); for nLoop := nOldMax to m_nEventMax - 1 do begin m_anIDs[nLoop] := -1; end; Result := NotifyRegister(nEventID, xEvent); end; procedure TNotifications.NotifyUnregister(nRegisterHandle : Integer); begin if (nRegisterHandle >= 0) and (nRegisterHandle < m_nEventMax) then begin m_anIDs[nRegisterHandle] := -1; m_axEvents[nRegisterHandle] := nil; end; end; procedure TNotifications.NotifyListeners(Sender: TObject; nEventID: Integer; xData: TObject); var nLoop : Integer; begin for nLoop := 0 to m_nEventMax - 1 do begin {$IFDEF DEBUG_NOTIFICATIONS} DebugReport('NotifyListeners ' + IntToStr(nEventID) + ' [' + IntToStr(nLoop) + '] = ' + IntToStr(m_anIDs[nLoop])); {$ENDIF} if m_anIDs[nLoop] = nEventID then begin if not m_axEvents[nLoop](Sender, nEventID, xData) then // return false to stop further processing begin {$IFDEF DEBUG_NOTIFICATIONS} DebugReport('NotifyListeners stop processing'); {$ENDIF} exit; end; end; end; end; procedure TNotifications.NotifyListenersAsync(Sender: TObject; nEventID: Integer; xData: TObject); begin async NotifyListeners(Sender, nEventID, xData); end; initialization g_xNotifications := TNotifications.Create; end. |
Thu, Jun 8 2017 9:20 AM | Permanent Link |
Mark Brooks Slikware | Appreciated Mathew - will review as "bedtime reading" !
|
Wed, Jun 14 2017 1:27 PM | Permanent Link |
Tim Young [Elevate Software] Elevate Software, Inc. timyoung@elevatesoft.com | Mark,
<, I know that Tim has mentioned the existing component messaging mechanism previously, but looking at the source, it's not clear to me exactly how that works and how I might (safely) utilise it for my own purposes. >> Everything you need is in the WebCore unit for the TComponent class. The key methods are: protected ... function Notification(Sender: TComponent; ID: Integer; Data: TObject): Boolean; virtual; procedure Notify(ID: Integer; Data: TObject=nil); virtual; ... public ... procedure Register(Component: TComponent); procedure UnRegister(Component: TComponent); ... What you do is use the Register method to register a component for event notifications, and UnRegister to unregister. When a component is registered for event notifications, it will receive such notifications via the Notification method, which you can override to handle the notification. Returning True from the notification method will stop a component from notifying any other subsequent components (even if they are registered for notifications), whereas returning False will allow the notifications to proceed. When you want to notify all registered components of an event, you can use the Notify method. Just be sure to use the cmUser identifier (defined in the WebCore unit as 1000) as the base for your event IDs. That will keep you away from any internal EWB event IDs. Tim Young Elevate Software www.elevatesoft.com |
Wed, Jun 14 2017 4:25 PM | Permanent Link |
Mark Brooks Slikware | Awesome Tim. I'll give that a spin for sure. Thanks.
|
Thu, Jun 15 2017 5:38 AM | Permanent Link |
Matthew Jones | Tim Young [Elevate Software] wrote:
> Everything you need is in the WebCore unit for the TComponent class. I remember now why I chose to roll my own. Yours is great for when you know the components, and very effective. In my situation, part of the problem I had was that the sender didn't have a clue how to find the interested recipient. Typically some sort of parent, but not directly, and complicated to go find. As you know, from my fun with unit ordering. So my version was a central point where you could send a message and not care how many recipients etc there are, and no need to override functions, just provide event handlers. The built-in system could probably work, but the nice thing with Web Builder is you can make these systems and use them as required. Not constrained in any way. -- Matthew Jones |
Mon, Jun 19 2017 1:52 PM | Permanent Link |
Tim Young [Elevate Software] Elevate Software, Inc. timyoung@elevatesoft.com | Matthew,
<< I remember now why I chose to roll my own. Yours is great for when you know the components, and very effective. In my situation, part of the problem I had was that the sender didn't have a clue how to find the interested recipient. >> Just to clarify: the above code does not require the sender to know anything about the recipient other than the fact that the recipient registered to receive notifications. The recipient is responsible for filtering the notifications, based upon their needs. << and no need to override functions, just provide event handlers. >> This can, of course, be easily added to a descendant class, if you need such functionality. Tim Young Elevate Software www.elevatesoft.com |
This web page was last updated on Wednesday, October 9, 2024 at 05:37 AM | Privacy PolicySite Map © 2024 Elevate Software, Inc. All Rights Reserved Questions or comments ? E-mail us at info@elevatesoft.com |