This commit is contained in:
Basile Burg 2014-08-18 09:44:39 +02:00
parent da52e21153
commit 4a43e6200d
25 changed files with 293 additions and 30 deletions

View File

@ -135,7 +135,7 @@
<PackageName Value="LCL"/>
</Item6>
</RequiredPackages>
<Units Count="23">
<Units Count="24">
<Unit0>
<Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/>
@ -281,6 +281,11 @@
<IsPartOfProject Value="True"/>
<UnitName Value="ce_customtools"/>
</Unit22>
<Unit23>
<Filename Value="..\src\ce_observer.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="ce_observer"/>
</Unit23>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -7,7 +7,7 @@ uses
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, Forms, lazcontrols, runtimetypeinfocontrols,
ce_main, ce_dcd;
ce_main, ce_dcd, ce_observer;
{$R *.res}

View File

@ -1,6 +1,6 @@
unit ce_common;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_customtools;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

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

View File

@ -1,5 +1,5 @@
unit ce_dcd;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_dlang;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_dlangutils;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_dmdwrap;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -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);

View File

@ -1,6 +1,6 @@
unit ce_libman;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_libmaneditor;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -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

View File

@ -1,6 +1,6 @@
unit ce_messages;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_miniexplorer;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

189
src/ce_observer.pas Normal file
View File

@ -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.

View File

@ -1,6 +1,6 @@
unit ce_plugin;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_projconf;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_project;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_projinspect;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_search;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_staticexplorer;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

@ -1,6 +1,6 @@
unit ce_synmemo;
{$mode objfpc}{$H+}
{$MODE OBJFPC}{$H+}
interface

View File

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

View File

@ -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.