From e3831ac40433d9050b681f4e5e961ca2cf191bab Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Sat, 26 Dec 2015 12:08:25 +0100 Subject: [PATCH] observers, use generic type to validate --- src/ce_interfaces.pas | 78 ++++++++----------------------------------- src/ce_observer.pas | 10 ++++-- src/ce_synmemo.pas | 2 +- 3 files changed, 22 insertions(+), 68 deletions(-) diff --git a/src/ce_interfaces.pas b/src/ce_interfaces.pas index fdd48bed..2cab7868 100644 --- a/src/ce_interfaces.pas +++ b/src/ce_interfaces.pas @@ -22,7 +22,7 @@ type * Each project format has its own dedicated editors. * A few common properties allow some generic operations whatever is the format. *) - ICECommonProject = interface + ICECommonProject = interface(ISubjectType) ['ICECommonProject'] // general properties ------------------------------------------------------ @@ -90,7 +90,7 @@ type (** * An implementer declares some actions on demand. *) - ICEContextualActions = interface + ICEContextualActions = interface(ISubjectType) ['ICEContextualActions'] // declares a context name for the actions function contextName: string; @@ -105,7 +105,7 @@ type (** * An implementer is informed about the current file(s). *) - ICEMultiDocObserver = interface + ICEMultiDocObserver = interface(ISubjectType) ['ICEMultiDocObserver'] // aDoc has been created (empty, runnable, project source, ...). procedure docNew(aDoc: TCESynMemo); @@ -119,17 +119,14 @@ type (** * An implementer informs some ICEMultiDocObserver about the current file(s) *) - TCEMultiDocSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEMultiDocSubject = specialize TCECustomSubject; (** * An implementer is informed about the current project(s). *) - ICEProjectObserver = interface + ICEProjectObserver = interface(ISubjectType) ['ICEProjectObserver'] // aProject has been created/opened procedure projNew(aProject: ICECommonProject); @@ -145,17 +142,14 @@ type (** * An implementer informs some ICEProjectObserver about the current project(s) *) - TCEProjectSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEProjectSubject = specialize TCECustomSubject; (** * An implementer can add a main menu entry. *) - ICEMainMenuProvider = interface + ICEMainMenuProvider = interface(ISubjectType) ['ICEMainMenuProvider'] // item is a new mainMenu entry. item must be filled with the sub-items to be added. procedure menuDeclare(item: TMenuItem); @@ -165,10 +159,7 @@ type (** * An implementer collects and updates its observers menus. *) - TCEMainMenuSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEMainMenuSubject = specialize TCECustomSubject; @@ -176,7 +167,7 @@ type * An implementer declares some actions which have their own main menu entry and * whose shortcuts are automatically handled *) - ICEActionProvider = interface + ICEActionProvider = interface(ISubjectType) ['ICEActionProvider'] // the action handler will clear the references to the actions collected previously and start collecting if result. function actHandlerWantRecollect: boolean; @@ -190,17 +181,14 @@ type (** * An implementer handles its observers actions. *) - TCEActionProviderSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEActionProviderSubject = specialize TCECustomSubject; (** * An implementer can expose some customizable shortcuts to be edited in a dedicated widget. *) - ICEEditableShortCut = interface + ICEEditableShortCut = interface(ISubjectType) ['ICEEditableShortCut'] // a TCEEditableShortCutSubject will start to collect shortcuts if result function scedWantFirst: boolean; @@ -212,10 +200,7 @@ type (** * An implementer manages its observers shortcuts. *) - TCEEditableShortCutSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEEditableShortCutSubject = specialize TCECustomSubject; @@ -227,7 +212,7 @@ type (** * An implementer can expose some options to be edited in a dedicated widget. *) - ICEEditableOptions = interface + ICEEditableOptions = interface(ISubjectType) ['ICEEditableOptions'] // the widget wants the category. function optionedWantCategory(): string; @@ -243,10 +228,7 @@ type (** * An implementer displays its observers editable options. *) - TCEEditableOptionsSubject = class(TCECustomSubject) - protected - function acceptObserver(aObject: TObject): boolean; override; - end; + TCEEditableOptionsSubject = specialize TCECustomSubject; @@ -377,11 +359,6 @@ type implementation {$REGION TCEMultiDocSubject ----------------------------------------------------} -function TCEMultiDocSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEMultiDocObserver); -end; - procedure subjDocNew(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); var i: Integer; @@ -416,11 +393,6 @@ end; {$ENDREGION} {$REGION TCEProjectSubject -----------------------------------------------------} -function TCEProjectSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEProjectObserver); -end; - procedure subjProjNew(aSubject: TCEProjectSubject; aProj: ICECommonProject); var i: Integer; @@ -462,28 +434,6 @@ begin end; {$ENDREGION} -{$REGION Misc subjects ---------------------------------------------------------} -function TCEMainMenuSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEMainMenuProvider); -end; - -function TCEEditableShortCutSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEEditableShortCut); -end; - -function TCEEditableOptionsSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEEditableOptions); -end; - -function TCEActionProviderSubject.acceptObserver(aObject: TObject): boolean; -begin - exit(aObject is ICEActionProvider); -end; -{$ENDREGION} - {$REGION ICESingleService getters ----------------------------------------------} function getMessageDisplay(var obj: ICEMessagesDisplay): ICEMessagesDisplay; begin diff --git a/src/ce_observer.pas b/src/ce_observer.pas index bdf5a1db..12757266 100644 --- a/src/ce_observer.pas +++ b/src/ce_observer.pas @@ -68,15 +68,19 @@ type procedure updateObservers; end; + // Base type for an interface that contains the methods of a subject. + ISubjectType = interface + end; + (** * Standard implementation of an ICESubject. * Any descendant adds itself to the global EntitiesConnector. *) - TCECustomSubject = class(ICESubject) + generic TCECustomSubject = class(ICESubject) protected fObservers: TObjectList; // test for a specific interface when adding an observer. - function acceptObserver(aObject: TObject): boolean; virtual; + function acceptObserver(aObject: TObject): boolean; function getObserversCount: Integer; function getObserver(index: Integer): TObject; public @@ -242,7 +246,7 @@ end; function TCECustomSubject.acceptObserver(aObject: TObject): boolean; begin - exit(False); + exit(aObject is T); end; function TCECustomSubject.getObserversCount: Integer; diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index d2ede24d..1c4b8825 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -106,7 +106,7 @@ type fFocusForInput: boolean; fIdentifier: string; fTempFileName: string; - fMultiDocSubject: TCECustomSubject; + fMultiDocSubject: TObject; fDefaultFontSize: Integer; fPositions: TCESynMemoPositions; fMousePos: TPoint;