messages rewrite using internal observer system 1

This commit is contained in:
Basile Burg 2014-11-07 14:11:25 +01:00
parent 4ef06c984a
commit afabbb1b45
9 changed files with 293 additions and 61 deletions

View File

@ -5,12 +5,14 @@ unit ce_customtools;
interface interface
uses uses
Classes, SysUtils, process, ce_common, ce_writableComponent; Classes, SysUtils, process, asyncprocess, ce_common, ce_writableComponent,
ce_interfaces, ce_observer;
type type
TCEToolItem = class(TCollectionItem) TCEToolItem = class(TCollectionItem)
private private
fProcess: TAsyncProcess;
fExecutable: string; fExecutable: string;
fWorkingDir: string; fWorkingDir: string;
fShowWin: TShowWindowOptions; fShowWin: TShowWindowOptions;
@ -18,6 +20,7 @@ type
fParameters: TStringList; fParameters: TStringList;
fToolAlias: string; fToolAlias: string;
fShortcut: string; fShortcut: string;
fLogMessager: TCELogMessageSubject;
procedure setParameters(const aValue: TStringList); procedure setParameters(const aValue: TStringList);
published published
property toolAlias: string read fToolAlias write fToolAlias; property toolAlias: string read fToolAlias write fToolAlias;
@ -59,11 +62,14 @@ begin
inherited; inherited;
fToolAlias := format('<tool %d>', [ID]); fToolAlias := format('<tool %d>', [ID]);
fParameters := TStringList.create; fParameters := TStringList.create;
fLogMessager := TCELogMessageSubject.create;
end; end;
destructor TCEToolItem.destroy; destructor TCEToolItem.destroy;
begin begin
fParameters.Free; fParameters.Free;
fLogMessager.Free;
killProcess(fProcess);
inherited; inherited;
end; end;
@ -75,25 +81,22 @@ end;
procedure TCEToolItem.execute; procedure TCEToolItem.execute;
var var
i: Integer; i: Integer;
proc: TProcess;
begin begin
proc := TProcess.Create(nil); killProcess(fProcess);
try fProcess := TAsyncProcess.Create(nil);
proc.Options := fOpts; //
if fExecutable <> '' then fProcess.Options := fOpts;
proc.Executable := CEMainForm.expandSymbolicString(fExecutable); if fExecutable <> '' then
proc.ShowWindow := fShowWin; fProcess.Executable := CEMainForm.expandSymbolicString(fExecutable);
if fWorkingDir <> '' then fProcess.ShowWindow := fShowWin;
proc.CurrentDirectory := CEMainForm.expandSymbolicString(fWorkingDir); if fWorkingDir <> '' then
proc.Parameters.Clear; fProcess.CurrentDirectory := CEMainForm.expandSymbolicString(fWorkingDir);
for i:= 0 to fParameters.Count-1 do fProcess.Parameters.Clear;
if fParameters.Strings[i] <> '' then for i:= 0 to fParameters.Count-1 do
proc.Parameters.AddText(CEMainForm.expandSymbolicString(fParameters.Strings[i])); if fParameters.Strings[i] <> '' then
proc.Options := proc.Options - [poUsePipes, poWaitOnExit]; fProcess.Parameters.AddText(CEMainForm.expandSymbolicString(fParameters.Strings[i]));
proc.Execute; subjLmProcess(fLogMessager, fProcess, nil, amcTool, amkBub);
finally fProcess.Execute;
proc.Free;
end;
end; end;
constructor TCETools.create(aOwner: TComponent); constructor TCETools.create(aOwner: TComponent);

View File

@ -248,7 +248,7 @@ end;
procedure TCEEditorWidget.removeEditor(const aIndex: NativeInt); procedure TCEEditorWidget.removeEditor(const aIndex: NativeInt);
begin begin
CEMainForm.MessageWidget.ClearMessages(mcEditor); //CEMainForm.MessageWidget.ClearMessages(mcEditor);
editor[aIndex].OnChange:= nil; editor[aIndex].OnChange:= nil;
pageControl.Pages[aIndex].Free; pageControl.Pages[aIndex].Free;
end; end;
@ -399,11 +399,11 @@ begin
fKeyChanged := false; fKeyChanged := false;
if fDoc.Lines.Count = 0 then exit; if fDoc.Lines.Count = 0 then exit;
// //
if fProj = nil then //if fProj = nil then
CEMainForm.MessageWidget.ClearMessages(mcEditor) //CEMainForm.MessageWidget.ClearMessages(mcEditor)
else begin //else begin
// if the source is in proj then we want to keep messages to correct mistakes. // if the source is in proj then we want to keep messages to correct mistakes.
end; //end;
lex(fDoc.Lines.Text, tokLst); lex(fDoc.Lines.Text, tokLst);
@ -428,7 +428,7 @@ begin
if md = '' then md := extractFileName(fDoc.fileName); if md = '' then md := extractFileName(fDoc.fileName);
pageControl.ActivePage.Caption := md; pageControl.ActivePage.Caption := md;
CEMainForm.MessageWidget.scrollToBack; //CEMainForm.MessageWidget.scrollToBack;
tokLst.Clear; tokLst.Clear;
errLst.Clear; errLst.Clear;
end; end;

View File

@ -5,7 +5,8 @@ unit ce_interfaces;
interface interface
uses uses
Classes, SysUtils, actnList, menus, ce_synmemo, ce_project, ce_observer; Classes, SysUtils, actnList, process, menus,
ce_synmemo, ce_project, ce_observer;
type type
@ -137,6 +138,30 @@ type
end; end;
/// describes the message kind, when Auto implies that a ICELogMessageObserver guess the kind.
TCEAppMessageKind = (amkAuto, amkBub, amkInf, amkWarn, amkErr);
/// describes the message context. Used by a ICELogMessageObserver to filter the messages.
TCEAppMessageCtxt = (amcApp, amcTool, amcProj, amcEdit);
(**
* An implementer get some log messages.
*)
ICELogMessageObserver = interface
['ICEMessage']
// a TCELogMessageSubject sends a message based on a string.
procedure lmStandard(const aValue: string; aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
// a TCELogMessageSubject sends a message based on a process output.
procedure lmProcess(const aValue: TProcess; aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
end;
(**
* An implementer sends some log messages.
*)
TCELogMessageSubject = class(TCECustomSubject)
protected
function acceptObserver(aObject: TObject): boolean; override;
end;
{ {
subject Primitives: subject Primitives:
@ -147,27 +172,34 @@ type
(** (**
* TCEMultiDocSubject primitives. * TCEMultiDocSubject primitives.
*) *)
procedure subjDocNew(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjDocNew(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjDocClosing(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjDocClosing(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjDocFocused(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjDocFocused(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjDocChanged(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjDocChanged(aSubject: TCEMultiDocSubject; aDoc: TCESynMemo); {$IFDEF RELEASE}inline;{$ENDIF}
(** (**
* TCEProjectSubject primitives. * TCEProjectSubject primitives.
*) *)
procedure subjProjNew(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjProjNew(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjProjClosing(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjProjClosing(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjProjFocused(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjProjFocused(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjProjChanged(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjProjChanged(aSubject: TCEProjectSubject; aProj: TCEProject); {$IFDEF RELEASE}inline;{$ENDIF}
(** (**
* TCESessionOptionsSubject primitives. * TCESessionOptionsSubject primitives.
*) *)
procedure subjSesOptsBeforeSave(aSubject: TCESessionOptionsSubject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjSesOptsBeforeSave(aSubject: TCESessionOptionsSubject); {$IFDEF RELEASE}inline;{$ENDIF}
procedure subjSesOptsDeclareProperties(aSubject: TCESessionOptionsSubject; aFiler: TFiler);{$IFDEF RELEASE}inline;{$ENDIF} procedure subjSesOptsDeclareProperties(aSubject: TCESessionOptionsSubject; aFiler: TFiler);{$IFDEF RELEASE}inline;{$ENDIF}
procedure subjSesOptsAfterLoad(aSubject: TCESessionOptionsSubject); {$IFDEF RELEASE}inline;{$ENDIF} procedure subjSesOptsAfterLoad(aSubject: TCESessionOptionsSubject); {$IFDEF RELEASE}inline;{$ENDIF}
(**
* TCELogMessageSubject primitives.
*)
procedure subjLmStandard(aSubject: TCELogMessageSubject; const aValue: string;
aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
procedure subjLmProcess(aSubject: TCELogMessageSubject; const aValue: TProcess;
aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
implementation implementation
@ -280,7 +312,7 @@ begin
end; end;
{$ENDREGION} {$ENDREGION}
{$REGION TCEEditableShortCutSubject} {$REGION TCEMainMenuSubject}
function TCEMainMenuSubject.acceptObserver(aObject: TObject): boolean; function TCEMainMenuSubject.acceptObserver(aObject: TObject): boolean;
begin begin
exit(aObject is ICEMainMenuProvider); exit(aObject is ICEMainMenuProvider);
@ -292,5 +324,31 @@ function TCEEditableShortCutSubject.acceptObserver(aObject: TObject): boolean;
begin begin
exit(aObject is ICEEditableShortCut); exit(aObject is ICEEditableShortCut);
end; end;
{$ENDREGION}
{$REGION TCELogMessageSubject}
function TCELogMessageSubject.acceptObserver(aObject: TObject): boolean;
begin
exit(aObject is ICELogMessageObserver);
end;
procedure subjLmStandard(aSubject: TCELogMessageSubject; const aValue: string;
aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
var
i: Integer;
begin
with aSubject do for i:= 0 to fObservers.Count-1 do
(fObservers.Items[i] as ICELogMessageObserver).lmStandard(aValue, aData, aCtxt, aKind);
end;
procedure subjLmProcess(aSubject: TCELogMessageSubject; const aValue: TProcess;
aData: Pointer; aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
var
i: Integer;
begin
with aSubject do for i:= 0 to fObservers.Count-1 do
(fObservers.Items[i] as ICELogMessageObserver).lmProcess(aValue, aData, aCtxt, aKind);
end;
{$ENDREGION} {$ENDREGION}
end. end.

View File

@ -197,6 +197,8 @@ type
fRunProc: TAsyncProcess; fRunProc: TAsyncProcess;
fLogMessager: TCELogMessageSubject;
// ICEMultiDocObserver // ICEMultiDocObserver
procedure docNew(const aDoc: TCESynMemo); procedure docNew(const aDoc: TCESynMemo);
procedure docClosing(const aDoc: TCESynMemo); procedure docClosing(const aDoc: TCESynMemo);
@ -280,7 +282,7 @@ type
function expandSymbolicString(const symString: string): string; function expandSymbolicString(const symString: string): string;
// //
property WidgetList: TCEWidgetList read fWidgList; property WidgetList: TCEWidgetList read fWidgList;
property MessageWidget: TCEMessagesWidget read fMesgWidg; //property MessageWidget: TCEMessagesWidget read fMesgWidg;
property LibraryManager: TLibraryManager read fLibMan; property LibraryManager: TLibraryManager read fLibMan;
property CustomTools: TCETools read fTools; property CustomTools: TCETools read fTools;
end; end;
@ -300,6 +302,8 @@ uses
constructor TCEMainForm.create(aOwner: TComponent); constructor TCEMainForm.create(aOwner: TComponent);
begin begin
inherited create(aOwner); inherited create(aOwner);
fLogMessager := TCELogMessageSubject.create;
//
EntitiesConnector.addObserver(self); EntitiesConnector.addObserver(self);
// //
InitMRUs; InitMRUs;
@ -590,7 +594,10 @@ begin
if WindowState = wsMinimized then if WindowState = wsMinimized then
WindowState := wsNormal; WindowState := wsNormal;
for i:= 0 to fWidgList.Count-1 do for i:= 0 to fWidgList.Count-1 do
begin
DockMaster.GetAnchorSite(fWidgList.widget[i]).Show; DockMaster.GetAnchorSite(fWidgList.widget[i]).Show;
DockMaster.GetAnchorSite(fWidgList.widget[i]).WindowState := wsNormal;
end;
if not Visible then exit; if not Visible then exit;
// //
forceDirectory(getDocPath); forceDirectory(getDocPath);
@ -688,9 +695,7 @@ begin
exit; exit;
// //
fname := fRunProc.Executable; fname := fRunProc.Executable;
fRunProc.Terminate(0); killProcess(fRunProc);
fRunProc.Free;
fRunProc := nil;
if fileExists(fname) then if fileExists(fname) then
sysutils.DeleteFile(fname); sysutils.DeleteFile(fname);
end; end;
@ -707,6 +712,7 @@ begin
fProject.Free; fProject.Free;
FreeRunnableProc; FreeRunnableProc;
// //
fLogMessager.Free;
EntitiesConnector.removeObserver(self); EntitiesConnector.removeObserver(self);
inherited; inherited;
end; end;
@ -1622,7 +1628,10 @@ var
begin begin
// TODO-cbugfix: possible loading AV, xml saved after undocking some widgets, xml file abnormal size. // TODO-cbugfix: possible loading AV, xml saved after undocking some widgets, xml file abnormal size.
for i:= 0 to fWidgList.Count-1 do for i:= 0 to fWidgList.Count-1 do
begin
DockMaster.GetAnchorSite(fWidgList.widget[i]).Show; DockMaster.GetAnchorSite(fWidgList.widget[i]).Show;
DockMaster.GetAnchorSite(fWidgList.widget[i]).WindowState := wsNormal;
end;
// //
forceDirectory(extractFilePath(aFilename)); forceDirectory(extractFilePath(aFilename));
xcfg := TXMLConfigStorage.Create(aFilename, false); xcfg := TXMLConfigStorage.Create(aFilename, false);
@ -2012,24 +2021,24 @@ begin
ctxt := opCode and $0F000000; ctxt := opCode and $0F000000;
oper := opCode and $000FFFFF; oper := opCode and $000FFFFF;
{
case ctxt of case ctxt of
CTXT_MSGS: CTXT_MSGS:
case oper of case oper of
DT_ERR: CEMainForm.MessageWidget.addCeErr(PChar(data1)); //DT_ERR: CEMainForm.MessageWidget.addCeErr(PChar(data1));
DT_INF: CEMainForm.MessageWidget.addCeInf(PChar(data1)); //DT_INF: CEMainForm.MessageWidget.addCeInf(PChar(data1));
DT_WARN: CEMainForm.MessageWidget.addCeWarn(PChar(data1)); //DT_WARN: CEMainForm.MessageWidget.addCeWarn(PChar(data1));
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode'); //else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end; end;
CTXT_DLGS: CTXT_DLGS:
case oper of case oper of
DT_ERR: dlgOkError(PChar(data1)); DT_ERR: dlgOkError(PChar(data1));
DT_INF: dlgOkInfo(PChar(data1)); DT_INF: dlgOkInfo(PChar(data1));
DT_WARN: dlgOkInfo(PChar(data1)); DT_WARN: dlgOkInfo(PChar(data1));
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode'); //else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end; end;
else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode'); //else CEMainForm.MessageWidget.addCeWarn('unsupported dispatcher opCode');
end; end;}
end; end;

View File

@ -6,8 +6,8 @@ interface
uses uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls,
lcltype, ce_widget, ActnList, Menus, clipbrd, AnchorDocking, ce_project, lcltype, ce_widget, ActnList, Menus, clipbrd, AnchorDocking, process, asyncprocess,
ce_synmemo, ce_dlangutils, ce_interfaces, ce_observer; ce_common, ce_project, ce_synmemo, ce_dlangutils, ce_interfaces, ce_observer;
type type
@ -21,7 +21,7 @@ type
position: TPoint; position: TPoint;
end; end;
TCEMessagesWidget = class(TCEWidget, ICEMultiDocObserver, ICEProjectObserver) TCEMessagesWidget = class(TCEWidget, ICEMultiDocObserver, ICEProjectObserver, ICELogMessageObserver)
imgList: TImageList; imgList: TImageList;
List: TTreeView; List: TTreeView;
procedure ListDblClick(Sender: TObject); procedure ListDblClick(Sender: TObject);
@ -45,6 +45,9 @@ type
procedure setMaxMessageCount(aValue: Integer); procedure setMaxMessageCount(aValue: Integer);
procedure listDeletion(Sender: TObject; Node: TTreeNode); procedure listDeletion(Sender: TObject; Node: TTreeNode);
function newMessageItemData(aCtxt: TMessageContext): PMessageItemData; function newMessageItemData(aCtxt: TMessageContext): PMessageItemData;
procedure processOutput(Sender: TObject);
procedure processTerminate(Sender: TObject);
procedure logProcessOutput(const aProcess: TProcess);
// //
procedure optset_MaxMessageCount(aReader: TReader); procedure optset_MaxMessageCount(aReader: TReader);
procedure optget_MaxMessageCount(awriter: TWriter); procedure optget_MaxMessageCount(awriter: TWriter);
@ -57,6 +60,7 @@ type
procedure scrollToBack; procedure scrollToBack;
procedure addMessage(const aMsg: string; aCtxt: TMessageContext = mcUnknown); procedure addMessage(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
procedure addMessage(const aMsg: string; const aData: PMessageItemData); procedure addMessage(const aMsg: string; const aData: PMessageItemData);
procedure addCeBub(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
procedure addCeInf(const aMsg: string; aCtxt: TMessageContext = mcUnknown); procedure addCeInf(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
procedure addCeErr(const aMsg: string; aCtxt: TMessageContext = mcUnknown); procedure addCeErr(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
procedure addCeWarn(const aMsg: string; aCtxt: TMessageContext = mcUnknown); procedure addCeWarn(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
@ -77,6 +81,11 @@ type
procedure docFocused(const aDoc: TCESynMemo); procedure docFocused(const aDoc: TCESynMemo);
procedure docChanged(const aDoc: TCESynMemo); procedure docChanged(const aDoc: TCESynMemo);
// //
procedure lmStandard(const aValue: string; aData: Pointer;
aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
procedure lmProcess(const aValue: TProcess; aData: Pointer;
aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
//
procedure ClearAllMessages; procedure ClearAllMessages;
procedure ClearMessages(aCtxt: TMessageContext); procedure ClearMessages(aCtxt: TMessageContext);
end; end;
@ -309,6 +318,58 @@ begin
end; end;
{$ENDREGION} {$ENDREGION}
{$REGION ICELogMessageObserver ---------------------------------------------------}
procedure TCEMessagesWidget.lmStandard(const aValue: string; aData: Pointer;
aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
begin
case aKInd of
amkBub: addCeBub(aValue);
amkInf: addCeInf(aValue);
amkWarn:addCeWarn(aValue);
amkErr: addCeErr(aValue);
end;
end;
procedure TCEMessagesWidget.lmProcess(const aValue: TProcess; aData: Pointer;
aCtxt: TCEAppMessageCtxt; aKind: TCEAppMessageKind);
begin
if not (poUsePipes in aValue.Options) then
exit;
//
if aValue is TAsyncProcess then begin
TAsyncProcess(aValue).OnReadData := @processOutput;
TAsyncProcess(aValue).OnTerminate := @processTerminate;
end else
logProcessOutput(aValue);
end;
procedure TCEMessagesWidget.processOutput(Sender: TObject);
begin
logProcessOutput(TProcess(Sender));
end;
procedure TCEMessagesWidget.processTerminate(Sender: TObject);
begin
logProcessOutput(TProcess(Sender));
end;
procedure TCEMessagesWidget.logProcessOutput(const aProcess: TProcess);
var
lst: TStringList;
str: string;
begin
lst := TStringList.Create;
try
processOutputToStrings(aProcess, lst);
for str in lst do
addCeBub(str);
finally
lst.Free;
end;
end;
{$ENDREGION}
{$REGION Messages --------------------------------------------------------------} {$REGION Messages --------------------------------------------------------------}
procedure TCEMessagesWidget.clearOutOfRangeMessg; procedure TCEMessagesWidget.clearOutOfRangeMessg;
begin begin
@ -395,6 +456,18 @@ begin
end; end;
end; end;
procedure TCEMessagesWidget.addCeBub(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
var
item: TTreeNode;
begin
item := List.Items.Add(nil, 'Coedit message: ' + aMsg);
item.Data := newMessageItemData(aCtxt);
item.ImageIndex := 0;
item.SelectedIndex := 0;
clearOutOfRangeMessg;
scrollToBack;
end;
procedure TCEMessagesWidget.addCeInf(const aMsg: string; aCtxt: TMessageContext = mcUnknown); procedure TCEMessagesWidget.addCeInf(const aMsg: string; aCtxt: TMessageContext = mcUnknown);
var var
item: TTreeNode; item: TTreeNode;

View File

@ -6,7 +6,8 @@ interface
uses uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Menus, ComCtrls, Buttons, lcltype, strutils, ce_widget, ce_common; Menus, ComCtrls, Buttons, lcltype, strutils, ce_widget, ce_common,
ce_interfaces, ce_observer;
type type
TCEMiniExplorerWidget = class(TCEWidget) TCEMiniExplorerWidget = class(TCEWidget)
@ -31,6 +32,7 @@ type
private private
fFavorites: TStringList; fFavorites: TStringList;
fLastFold: string; fLastFold: string;
fLogMessager: TCELogMessageSubject;
procedure lstFavDblClick(Sender: TObject); procedure lstFavDblClick(Sender: TObject);
procedure optset_LastFold(aReader: TReader); procedure optset_LastFold(aReader: TReader);
procedure optget_LastFold(aWriter: TWriter); procedure optget_LastFold(aWriter: TWriter);
@ -69,6 +71,7 @@ uses
constructor TCEMiniExplorerWidget.create(aIwner: TComponent); constructor TCEMiniExplorerWidget.create(aIwner: TComponent);
begin begin
inherited; inherited;
fLogMessager := TCELogMessageSubject.create;
fFavorites := TStringList.Create; fFavorites := TStringList.Create;
fFavorites.onChange := @favStringsChange; fFavorites.onChange := @favStringsChange;
lstFiles.OnDeletion := @lstDeletion; lstFiles.OnDeletion := @lstDeletion;
@ -87,6 +90,7 @@ end;
destructor TCEMiniExplorerWidget.destroy; destructor TCEMiniExplorerWidget.destroy;
begin begin
fLogMessager.Free;
fFavorites.Free; fFavorites.Free;
inherited; inherited;
end; end;
@ -253,8 +257,9 @@ begin
if lstFiles.Selected.Data = nil then exit; if lstFiles.Selected.Data = nil then exit;
fname := PString(lstFiles.Selected.Data)^; fname := PString(lstFiles.Selected.Data)^;
if not fileExists(fname) then exit; if not fileExists(fname) then exit;
if not shellOpen(fname) then CEMainForm.MessageWidget.addCeErr if not shellOpen(fname) then subjLmStandard(fLogMessager,
(format('the shell failed to open "%s"', [shortenPath(fname, 25)])); (format('the shell failed to open "%s"', [shortenPath(fname, 25)])),
nil, amcTool, amkErr);
end; end;
{$ENDREGION} {$ENDREGION}

View File

@ -44,7 +44,8 @@ type
end; end;
(** (**
* Standard implementation of an ICESubject * Standard implementation of an ICESubject.
* Any descendant adds itself to the global EntitiesConnector.
*) *)
TCECustomSubject = class(ICESubject) TCECustomSubject = class(ICESubject)
protected protected

View File

@ -8,8 +8,8 @@ uses
{$IFDEF DEBUG} {$IFDEF DEBUG}
LclProc, LclProc,
{$ENDIF} {$ENDIF}
Classes, SysUtils, ce_common, ce_writableComponent ,ce_dmdwrap, ce_libman, Classes, SysUtils, process, asyncprocess, ce_common, ce_writableComponent,
ce_observer; ce_dmdwrap, ce_libman, ce_observer;
type type
@ -34,6 +34,8 @@ type
fLibMan: TLibraryManager; fLibMan: TLibraryManager;
fChangedCount: NativeInt; fChangedCount: NativeInt;
fProjectSubject: TCECustomSubject; fProjectSubject: TCECustomSubject;
fRunner: TAsyncProcess;
fLogMessager: TCECustomSubject;
procedure doChanged; procedure doChanged;
procedure setLibAliases(const aValue: TStringList); procedure setLibAliases(const aValue: TStringList);
procedure subMemberChanged(sender : TObject); procedure subMemberChanged(sender : TObject);
@ -43,6 +45,7 @@ type
procedure setConfIx(aValue: Integer); procedure setConfIx(aValue: Integer);
function getConfig(const ix: integer): TCompilerConfiguration; function getConfig(const ix: integer): TCompilerConfiguration;
function getCurrConf: TCompilerConfiguration; function getCurrConf: TCompilerConfiguration;
procedure runPrePostProcess(const processInfo: TCompileProcOptions);
protected protected
procedure afterSave; override; procedure afterSave; override;
procedure afterLoad; override; procedure afterLoad; override;
@ -68,6 +71,8 @@ type
function addConfiguration: TCompilerConfiguration; function addConfiguration: TCompilerConfiguration;
procedure getOpts(const aList: TStrings); procedure getOpts(const aList: TStrings);
function outputFilename: string; function outputFilename: string;
procedure runProject;
procedure compileProject;
// //
property libraryManager: TLibraryManager read fLibMan write fLibMan; property libraryManager: TLibraryManager read fLibMan write fLibMan;
property configuration[ix: integer]: TCompilerConfiguration read getConfig; property configuration[ix: integer]: TCompilerConfiguration read getConfig;
@ -79,11 +84,12 @@ type
implementation implementation
uses uses
ce_interfaces, controls, dialogs; ce_interfaces, controls, dialogs, ce_main;
constructor TCEProject.create(aOwner: TComponent); constructor TCEProject.create(aOwner: TComponent);
begin begin
inherited create(aOwner); inherited create(aOwner);
fLogMessager := TCELogMessageSubject.create;
fProjectSubject := TCEProjectSubject.create; fProjectSubject := TCEProjectSubject.create;
// //
fLibAliases := TStringList.Create; fLibAliases := TStringList.Create;
@ -103,6 +109,7 @@ destructor TCEProject.destroy;
begin begin
subjProjClosing(TCEProjectSubject(fProjectSubject), self); subjProjClosing(TCEProjectSubject(fProjectSubject), self);
fProjectSubject.Free; fProjectSubject.Free;
fLogMessager.Free;
// //
fOnChange := nil; fOnChange := nil;
fLibAliases.Free; fLibAliases.Free;
@ -431,6 +438,78 @@ begin
end; end;
end; end;
procedure TCEProject.runPrePostProcess(const processInfo: TCompileProcOptions);
var
process: TProcess;
pname: string;
i, j: integer;
begin
with currentConfiguration do
begin
pname := CEMainForm.expandSymbolicString(preBuildProcess.executable);
if pname <> '``' then
if exeInSysPath(pname) then
begin
process := TProcess.Create(nil);
try
processInfo.setProcess(process);
process.Executable := pname;
j := process.Parameters.Count-1;
for i:= 0 to j do
process.Parameters.AddText(CEMainForm.expandSymbolicString(process.Parameters.Strings[i]));
for i:= 0 to j do
process.Parameters.Delete(0);
if process.CurrentDirectory = '' then
process.CurrentDirectory := extractFilePath(process.Executable);
process.Execute;
if not (poWaitOnExit in process.Options) then
if poUsePipes in process.Options then
subjLmProcess(TCELogMessageSubject(fLogMessager), process, @Self, amcProj, amkBub);
finally
process.Free;
end;
end
else subjLmStandard(TCELogMessageSubject(fLogMessager),
'the pre/post compilation executable does not exist', @Self, amcProj, amkBub);
end;
end;
procedure TCEProject.runProject;
begin
killProcess(fRunner);
fRunner := TAsyncProcess.Create(nil);
end;
procedure TCEProject.compileProject;
var
compilproc: TProcess;
olddir: string;
begin
runPrePostProcess(currentConfiguration.preBuildProcess);
compilproc := TProcess.Create(nil);
getDir(0, olddir);
try
compilproc.Executable := DCompiler;
compilproc.Options := compilproc.Options + [poStderrToOutPut, poUsePipes];
compilproc.ShowWindow := swoHIDE;
getOpts(compilproc.Parameters);
compilproc.Execute;
subjLmProcess(TCELogMessageSubject(fLogMessager), compilproc, @Self, amcProj, amkBub);
if compilproc.ExitStatus <> 0 then
else ;
runPrePostProcess(currentConfiguration.postBuildProcess);
finally
compilproc.Free;
chDir(olddir);
end;
end;
initialization initialization
RegisterClasses([TCEProject]); RegisterClasses([TCEProject]);
end. end.

View File

@ -24,6 +24,7 @@ type
procedure TreeFilterEdit1AfterFilter(Sender: TObject); procedure TreeFilterEdit1AfterFilter(Sender: TObject);
procedure TreeKeyPress(Sender: TObject; var Key: char); procedure TreeKeyPress(Sender: TObject; var Key: char);
private private
fLogMessager: TCELogMessageSubject;
fActRefresh: TAction; fActRefresh: TAction;
fActRefreshOnChange: TAction; fActRefreshOnChange: TAction;
fActRefreshOnFocus: TAction; fActRefreshOnFocus: TAction;
@ -85,6 +86,7 @@ uses ce_main, ce_libman;
{$REGION Standard Comp/Obj------------------------------------------------------} {$REGION Standard Comp/Obj------------------------------------------------------}
constructor TCEStaticExplorerWidget.create(aOwner: TComponent); constructor TCEStaticExplorerWidget.create(aOwner: TComponent);
begin begin
fLogMessager := TCELogMessageSubject.create;
fAutoRefresh := false; fAutoRefresh := false;
fRefreshOnFocus := true; fRefreshOnFocus := true;
fRefreshOnChange := false; fRefreshOnChange := false;
@ -132,6 +134,8 @@ end;
destructor TCEStaticExplorerWidget.destroy; destructor TCEStaticExplorerWidget.destroy;
begin begin
EntitiesConnector.removeObserver(self); EntitiesConnector.removeObserver(self);
//
fLogMessager.Free;
inherited; inherited;
end; end;
{$ENDREGION} {$ENDREGION}
@ -479,7 +483,7 @@ begin
'struct' :ndCat := Tree.Items.AddChildObject(ndStruct, nme, ln); 'struct' :ndCat := Tree.Items.AddChildObject(ndStruct, nme, ln);
'template' :ndCat := Tree.Items.AddChildObject(ndTmp, nme, ln); 'template' :ndCat := Tree.Items.AddChildObject(ndTmp, nme, ln);
'variable' :ndCat := Tree.Items.AddChildObject(ndVar, nme, ln); 'variable' :ndCat := Tree.Items.AddChildObject(ndVar, nme, ln);
else CEMainForm.MessageWidget.addCeWarn('static explorer does not handle this kind: ' + knd); else subjLmStandard(fLogMessager, 'static explorer does not handle this kind: ' + knd, nil, amcApp, amkWarn);
end; end;
if ndCat = nil then if ndCat = nil then