diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 4ccdf378..28181eca 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -135,7 +135,7 @@ - + @@ -281,6 +281,11 @@ + + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index cd13f0bb..33a3327e 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -7,7 +7,7 @@ uses cthreads, {$ENDIF}{$ENDIF} Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, - ce_main, ce_dcd; + ce_main, ce_dcd, ce_observer; {$R *.res} diff --git a/src/ce_common.pas b/src/ce_common.pas index 26128858..bbbb5d8e 100644 --- a/src/ce_common.pas +++ b/src/ce_common.pas @@ -1,6 +1,6 @@ unit ce_common; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_customtools.pas b/src/ce_customtools.pas index 0549ebd1..6f121eb1 100644 --- a/src/ce_customtools.pas +++ b/src/ce_customtools.pas @@ -1,6 +1,6 @@ unit ce_customtools; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_d2syn.pas b/src/ce_d2syn.pas index e96fb340..9cc6cace 100644 --- a/src/ce_d2syn.pas +++ b/src/ce_d2syn.pas @@ -1,6 +1,6 @@ unit ce_d2syn; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface @@ -465,6 +465,7 @@ end; //TODO-cstring literals: delimited strings. //TODO-ccomments: correct nested comments handling (inc/dec) //TODO-cfeature: something like pascal {$region} : /*folder blabla*/ /*endfolder*/ +//TODO-bugfix: token string, curly brackets pairs must be even. {$BOOLEVAL ON} procedure TSynD2Syn.next; diff --git a/src/ce_dcd.pas b/src/ce_dcd.pas index 49b96548..f896b161 100644 --- a/src/ce_dcd.pas +++ b/src/ce_dcd.pas @@ -1,5 +1,5 @@ unit ce_dcd; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_dlang.pas b/src/ce_dlang.pas index ebad062e..ff66f4f9 100644 --- a/src/ce_dlang.pas +++ b/src/ce_dlang.pas @@ -1,6 +1,6 @@ unit ce_dlang; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_dlangutils.pas b/src/ce_dlangutils.pas index a55d18f6..6537ee45 100644 --- a/src/ce_dlangutils.pas +++ b/src/ce_dlangutils.pas @@ -1,6 +1,6 @@ unit ce_dlangutils; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_dmdwrap.pas b/src/ce_dmdwrap.pas index 61750b29..5805f832 100644 --- a/src/ce_dmdwrap.pas +++ b/src/ce_dmdwrap.pas @@ -1,6 +1,6 @@ unit ce_dmdwrap; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_editor.pas b/src/ce_editor.pas index 05fe4121..8bc6dc0c 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -1,6 +1,6 @@ unit ce_editor; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface @@ -8,8 +8,8 @@ uses Classes, SysUtils, FileUtil, ExtendedNotebook, Forms, Controls, lcltype, Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus, SynEditHighlighterFoldBase, SynMacroRecorder, SynPluginSyncroEdit, SynEdit, - SynHighlighterLFM, SynCompletion, AnchorDocking, ce_widget, ce_d2syn, - ce_synmemo, ce_dlang, ce_project, ce_common, types, ce_dcd; + SynHighlighterLFM, SynCompletion, AnchorDocking, ce_widget, ce_d2syn, ce_widgettypes, + ce_synmemo, ce_dlang, ce_project, ce_common, types, ce_dcd, ce_observer; type @@ -33,6 +33,7 @@ type private fKeyChanged: boolean; fProj: TCEProject; + fMultiDocSubject: TCEMultiDocSubject; // http://bugs.freepascal.org/view.php?id=26329 fSyncEdit: TSynPluginSyncroEdit; @@ -94,10 +95,14 @@ begin finally bmp.Free; end; + // + fMultiDocSubject := TCEMultiDocSubject.create; + EntitiesConnector.addSubject(fMultiDocSubject); end; destructor TCEEditorWidget.destroy; begin + fMultiDocSubject.Free; tokLst.Free; errLst.Free; inherited; @@ -144,6 +149,8 @@ begin beginUpdateByDelay; end; end; + + self.fMultiDocSubject.docFocused(curr); end; procedure TCEEditorWidget.PageControlChange(Sender: TObject); diff --git a/src/ce_libman.pas b/src/ce_libman.pas index d0735b44..cab4aa45 100644 --- a/src/ce_libman.pas +++ b/src/ce_libman.pas @@ -1,6 +1,6 @@ unit ce_libman; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_libmaneditor.pas b/src/ce_libmaneditor.pas index 2d1f3b53..a5b62d2d 100644 --- a/src/ce_libmaneditor.pas +++ b/src/ce_libmaneditor.pas @@ -1,6 +1,6 @@ unit ce_libmaneditor; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_main.pas b/src/ce_main.pas index 2c17c6ca..33eb7aab 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -10,7 +10,8 @@ uses Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls, dynlibs, ce_common, ce_dmdwrap, ce_project, ce_dcd, ce_plugin, ce_synmemo, ce_widget, ce_messages, ce_widgettypes, ce_editor, ce_projinspect, ce_projconf, ce_search, - ce_staticexplorer, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_customtools; + ce_staticexplorer, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_customtools, + ce_observer; type diff --git a/src/ce_messages.pas b/src/ce_messages.pas index e9b760f9..c3d1b009 100644 --- a/src/ce_messages.pas +++ b/src/ce_messages.pas @@ -1,6 +1,6 @@ unit ce_messages; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_miniexplorer.pas b/src/ce_miniexplorer.pas index 8c1e48d4..f4411630 100644 --- a/src/ce_miniexplorer.pas +++ b/src/ce_miniexplorer.pas @@ -1,6 +1,6 @@ unit ce_miniexplorer; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_observer.pas b/src/ce_observer.pas new file mode 100644 index 00000000..f86aedf7 --- /dev/null +++ b/src/ce_observer.pas @@ -0,0 +1,189 @@ +unit ce_observer; + +{$MODE OBJFPC}{$H+} +{$INTERFACES CORBA} + +interface + +uses + Classes, SysUtils, Contnrs; + +type + + (** + * Manages the connections between the observers and their subjects in the whole program. + *) + TCEEntitiesConnector = class + private + fObservers: TObjectList; + fSubjects: TObjectList; + fUpdating: boolean; + procedure updateEntities; + public + constructor create; + destructor destroy; override; + // + procedure beginUpdate; + procedure endUpdate; + procedure addObserver(anObserver: TObject); + procedure addSubject(aSubject: TObject); + procedure removeObserver(anObserver: TObject); + procedure removeSubject(aSubject: TObject); + end; + + (** + * Interface for a Coedit subject. Basically designed to hold a list of observer + *) + ICESubject = interface + // an observer is proposed. anObserver is not necessarly compatible. + procedure addObserver(anObserver: TObject); + // anObserver must be removed. + procedure removeObserver(anObserver: TObject); + // optionally implemented to trigger all the methods of the observer interface. + procedure updateObservers; + end; + + (** + * Standard implementation of an ICESubject + *) + TCECustomSubject = class(ICESubject) + protected + fObservers: TObjectList; + // test for a specific interface when adding an observer. + function acceptObserver(aObject: TObject): boolean; virtual; + public + constructor create; + destructor destroy; override; + // + procedure addObserver(anObserver: TObject); + procedure removeObserver(anObserver: TObject); + procedure updateObservers; virtual; + end; + + ICEObserver = interface + //function subjectType: ICESubject; + end; + +var + EntitiesConnector: TCEEntitiesConnector = nil; + +implementation + +{$REGION TCEEntitiesConnector --------------------------------------------------} +constructor TCEEntitiesConnector.create; +begin + fObservers := TObjectList.create(false); + fSubjects := TObjectList.create(false); +end; + +destructor TCEEntitiesConnector.destroy; +begin + fObservers.Free; + fSubjects.Free; + inherited; +end; + +procedure TCEEntitiesConnector.updateEntities; +var + i,j: Integer; +begin + fUpdating := false; + for i := 0 to fSubjects.Count-1 do + begin + if (fSubjects[i] as ICESubject) = nil then + continue; + for j := 0 to fObservers.Count-1 do + begin + if (fSubjects[i] as ICEObserver) <> nil then + if fSubjects[i] <> fObservers[j] then + (fSubjects[i] as ICESubject).addObserver(fObservers[j]); + end; + end; +end; + +procedure TCEEntitiesConnector.beginUpdate; +begin + fUpdating := true; +end; + +procedure TCEEntitiesConnector.endUpdate; +begin + updateEntities; +end; + +procedure TCEEntitiesConnector.addObserver(anObserver: TObject); +begin + if (anObserver as ICEObserver) = nil then + exit; + if fObservers.IndexOf(anObserver) <> -1 then + exit; + fUpdating := true; + fObservers.Add(anObserver); +end; + +procedure TCEEntitiesConnector.addSubject(aSubject: TObject); +begin + if (aSubject as ICESubject) = nil then + exit; + if fSubjects.IndexOf(aSubject) <> -1 then + exit; + fUpdating := true; + fSubjects.Add(aSubject); +end; + +procedure TCEEntitiesConnector.removeObserver(anObserver: TObject); +begin + fUpdating := true; + fObservers.Remove(anObserver); +end; + +procedure TCEEntitiesConnector.removeSubject(aSubject: TObject); +begin + fUpdating := true; + fSubjects.Remove(aSubject); +end; +{$ENDREGION} + +{$REGION TCECustomSubject --------------------------------------------------} +constructor TCECustomSubject.create; +begin + fObservers := TObjectList.create(false); +end; + +destructor TCECustomSubject.destroy; +begin + fObservers.Free; + Inherited; +end; + +function TCECustomSubject.acceptObserver(aObject: TObject): boolean; +begin + exit(false); +end; + +procedure TCECustomSubject.addObserver(anObserver: TObject); +begin + if not acceptObserver(anObserver) then + exit; + if fObservers.IndexOf(anObserver) <> -1 then + exit; + fObservers.Add(anObserver); +end; + +procedure TCECustomSubject.removeObserver(anObserver: TObject); +begin + fObservers.Remove(anObserver); +end; + +procedure TCECustomSubject.updateObservers; +begin +end; +{$ENDREGION} + +initialization + EntitiesConnector := TCEEntitiesConnector.create; +finalization + EntitiesConnector.Free; + EntitiesConnector := nil; +end. + diff --git a/src/ce_plugin.pas b/src/ce_plugin.pas index ac4ca5c3..c1026a0f 100644 --- a/src/ce_plugin.pas +++ b/src/ce_plugin.pas @@ -1,6 +1,6 @@ unit ce_plugin; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_projconf.pas b/src/ce_projconf.pas index 8ea8c4c6..4bf1175c 100644 --- a/src/ce_projconf.pas +++ b/src/ce_projconf.pas @@ -1,6 +1,6 @@ unit ce_projconf; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_project.pas b/src/ce_project.pas index ca7f7842..454ce24f 100644 --- a/src/ce_project.pas +++ b/src/ce_project.pas @@ -1,6 +1,6 @@ unit ce_project; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_projinspect.pas b/src/ce_projinspect.pas index b782038f..ba9c6b01 100644 --- a/src/ce_projinspect.pas +++ b/src/ce_projinspect.pas @@ -1,6 +1,6 @@ unit ce_projinspect; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_search.pas b/src/ce_search.pas index 01548557..a2f2b163 100644 --- a/src/ce_search.pas +++ b/src/ce_search.pas @@ -1,6 +1,6 @@ unit ce_search; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_staticexplorer.pas b/src/ce_staticexplorer.pas index c8405ab4..636f5e43 100644 --- a/src/ce_staticexplorer.pas +++ b/src/ce_staticexplorer.pas @@ -1,6 +1,6 @@ unit ce_staticexplorer; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index fbfd9467..7c61af18 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -1,6 +1,6 @@ unit ce_synmemo; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface diff --git a/src/ce_widget.pas b/src/ce_widget.pas index 7c0ee29c..427e08ea 100644 --- a/src/ce_widget.pas +++ b/src/ce_widget.pas @@ -1,6 +1,6 @@ unit ce_widget; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} interface @@ -15,7 +15,7 @@ type * Base type for an UI module. *) PTCEWidget = ^TCEWidget; - TCEWidget = class(TForm, ICEContextualActions, ICEProjectMonitor, ICEMultiDocMonitor, ICEWidgetPersist) + TCEWidget = class(TForm, ICEContextualActions, ICEProjectMonitor, ICEMultiDocObserver, ICEWidgetPersist) Content: TPanel; Back: TPanel; contextMenu: TPopupMenu; @@ -203,7 +203,7 @@ begin end; {$ENDREGION} -{$REGION ICEMultiDocMonitor ----------------------------------------------------} +{$REGION ICEMultiDocObserver ----------------------------------------------------} procedure TCEWidget.docNew(const aDoc: TCESynMemo); begin end; diff --git a/src/ce_widgettypes.pas b/src/ce_widgettypes.pas index 65b4b441..7a30dc36 100644 --- a/src/ce_widgettypes.pas +++ b/src/ce_widgettypes.pas @@ -1,11 +1,12 @@ unit ce_widgettypes; -{$mode objfpc}{$H+} +{$MODE OBJFPC}{$H+} +{$INTERFACES CORBA} interface uses - Classes, SysUtils, actnList, ce_synmemo, ce_project; + Classes, SysUtils, actnList, menus, ce_synmemo, ce_project, ce_observer; type @@ -37,7 +38,7 @@ type (** * An implementer is informed about the current file(s). *) - ICEMultiDocMonitor = interface + ICEMultiDocObserver = interface(ICEObserver) // the new document aDoc has been created (empty, runnable, project source, ...). procedure docNew(const aDoc: TCESynMemo); // aDoc is the document being edited. @@ -48,6 +49,19 @@ type procedure docClose(const aDoc: TCESynMemo); end; + (** + * An implementer informs some ICEMultiDocObserver about the current file(s) + *) + TCEMultiDocSubject = class(TCECustomSubject, ICEMultiDocObserver) + protected + function acceptObserver(aObject: TObject): boolean; override; + public + procedure docNew(const aDoc: TCESynMemo); + procedure docFocused(const aDoc: TCESynMemo); + procedure docChanged(const aDoc: TCESynMemo); + procedure docClose(const aDoc: TCESynMemo); + end; + (** * An implementer is informed about the current project(s). *) @@ -66,5 +80,51 @@ type procedure projFocused(const aProject: TCEProject); // rename: projSelected or projActivated end; + (** + * An implementer can add a mainmenu entry. + *) + ICEMainMenuProvider = interface(ICEObserver) + // item must contain the full items tree to be added + procedure menuDeclare(out item: TMenuItem); + end; + implementation + +function TCEMultiDocSubject.acceptObserver(aObject: TObject): boolean; +begin + result := (aObject as ICEMultiDocObserver) <> nil; +end; + +procedure TCEMultiDocSubject.docNew(const aDoc: TCESynMemo); +var + i: Integer; +begin + for i:= 0 to fObservers.Count-1 do + (fObservers.Items[i] as ICEMultiDocObserver).docNew(aDoc); +end; + +procedure TCEMultiDocSubject.docFocused(const aDoc: TCESynMemo); +var + i: Integer; +begin + for i:= 0 to fObservers.Count-1 do + (fObservers.Items[i] as ICEMultiDocObserver).docFocused(aDoc); +end; + +procedure TCEMultiDocSubject.docChanged(const aDoc: TCESynMemo); +var + i: Integer; +begin + for i:= 0 to fObservers.Count-1 do + (fObservers.Items[i] as ICEMultiDocObserver).docChanged(aDoc); +end; + +procedure TCEMultiDocSubject.docClose(const aDoc: TCESynMemo); +var + i: Integer; +begin + for i:= 0 to fObservers.Count-1 do + (fObservers.Items[i] as ICEMultiDocObserver).docClose(aDoc); +end; + end.