|
From: <dav...@us...> - 2009-08-16 05:23:25
|
Revision: 828
http://instantobjects.svn.sourceforge.net/instantobjects/revision/?rev=828&view=rev
Author: davidvtaylor
Date: 2009-08-16 05:23:17 +0000 (Sun, 16 Aug 2009)
Log Message:
-----------
Revise IDE menu handling to make menu entries visible to GExperts and IDE menu customization dialogs
- Install custom TAction instances into the IDE ActionList
- Add Ctrl-Shift-B shortcut to DatabaseBuilder menu entry
- Add logic to disable action event handlers when design package is unloaded
Modified Paths:
--------------
trunk/Source/Design/InstantModelExpert.pas
Modified: trunk/Source/Design/InstantModelExpert.pas
===================================================================
--- trunk/Source/Design/InstantModelExpert.pas 2009-08-15 10:38:20 UTC (rev 827)
+++ trunk/Source/Design/InstantModelExpert.pas 2009-08-16 05:23:17 UTC (rev 828)
@@ -24,7 +24,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
- * Nando Dessena, Steven Mitchell, Brian Andersen
+ * Nando Dessena, Steven Mitchell, Brian Andersen, David Taylor
*
* ***** END LICENSE BLOCK ***** *)
@@ -41,7 +41,7 @@
uses
Classes, ToolsAPI, InstantOTA, Menus, ImgList, ExtCtrls, Forms,
InstantDesignResources, InstantModelExplorer, InstantCode,
- InstantConsts;
+ InstantConsts, ActnList;
type
TIOMetaDataCheckState = (mcNeverChecked, mcCheckError, mcCheckCorrect);
@@ -165,10 +165,13 @@
InstantConnectionManager, Dialogs;
const
+ SIOIdeMenuCategory = 'InstantObjects';
SBuilderItemCaption = 'InstantObjects Database &Builder...';
- SBuilderItemName = 'InstantBuilderItem';
+ SBuilderItemName = 'InstantBuilderItem'; // Do not localize
SExplorerItemCaption = 'InstantObjects &Model Explorer';
- SExplorerItemName = 'InstantExplorerItem';
+ SExplorerItemName = 'InstantExplorerItem'; // Do not localize
+ SExplorerItemActionName = 'InstantExplorerItemAction'; // Do not localize
+ SBuilderItemActionName = 'InstantBuilderItemAction'; // Do not localize
SModelCompiler = 'Model Compiler';
SResFileExt = '.mdr';
UpdateInterval = 500;
@@ -186,6 +189,81 @@
InstantCodeReaderIdle := ReaderIdle;
end;
+function FindOrCreateMenuAction(AName, ACaption: string;
+ AEventHandler: TNotifyEvent; AImageIndex : integer = -1;
+ AShortCut: TShortCut = 0): TContainedAction;
+var
+ IdeMainForm: TCustomForm;
+ IdeActionList: TCustomActionList;
+ NTAServices: INTAServices;
+ NewAction: TAction;
+ I: integer;
+begin
+ // Get the IDE's action list
+ NTAServices := BorlandIDEServices as INTAServices;
+ Assert(Assigned(NTAServices));
+ IdeActionList := NTAServices.ActionList;
+ Assert(Assigned(IdeActionList));
+
+ // Search for an existing IDE action
+ Result := nil;
+ for I := 0 to IdeActionList.ActionCount-1 do
+ begin
+ if (not SameText(IdeActionList.Actions[I].Name, AName)) then
+ continue;
+ Result := IdeActionList.Actions[I];
+ // Reconnect/enable the event handler (package reload)
+ Result.OnExecute := AEventHandler;
+ if (Result is TCustomAction) then
+ TCustomAction(Result).Enabled := true;
+ break;
+ end;
+
+ // Create a new action if not found
+ if (not assigned(Result)) then
+ begin
+ // Get the IDE's main form
+ Assert(Assigned(Application));
+ IdeMainForm := Application.FindComponent('AppBuilder') as TCustomForm;
+
+ // Create and initialize the action
+ NewAction := TAction.Create(IdeMainForm);
+ NewAction.ActionList := IdeActionList;
+ NewAction.Name := AName;
+ NewAction.Caption := ACaption;
+ NewAction.Category := SIOIdeMenuCategory;
+ NewAction.ImageIndex := AImageIndex;
+ NewAction.ShortCut := AShortCut;
+ NewAction.OnExecute := AEventHandler;
+ Result := NewAction;
+ end;
+end;
+
+// Searches for an IDE action matching the given name and
+// diables its OnExecute event handlers This avoids an AV
+// if the expert is unloaded (e.g. during a package rebuild)
+procedure DisableMenuAction(AName: string);
+var
+ IdeActionList: TCustomActionList;
+ NTAServices: INTAServices;
+ I: integer;
+begin
+ // Get the IDE's action list
+ NTAServices := BorlandIDEServices as INTAServices;
+ Assert(Assigned(NTAServices));
+ IdeActionList := NTAServices.ActionList;
+ Assert(Assigned(IdeActionList));
+
+ // Search for and diable IDE action
+ for I := 0 to IdeActionList.ActionCount-1 do
+ begin
+ if (not SameText(IdeActionList.Actions[I].Name, AName)) then
+ continue;
+ IdeActionList.Actions[I].OnExecute := nil;
+ break;
+ end;
+end;
+
function FindText(const SubStr, Str: string;
var Pos, Line, Column: Integer): Boolean;
var
@@ -464,13 +542,13 @@
procedure CreateBuilderMenuItem;
begin
FBuilderItem := TReferencedMenuItem.Create(nil, FBuilderItem);
- with FBuilderItem do
- begin
- Name := SBuilderItemName;
- Caption := SBuilderItemCaption;
- Action := Explorer.BuildDatabaseAction;
- ImageIndex := FToolImageOffset + 1;
- end;
+ FBuilderItem.Name := SBuilderItemName;
+ FBuilderItem.Action := FindOrCreateMenuAction(
+ SBuilderItemActionName,
+ SBuilderItemCaption,
+ BuilderItemClick,
+ FToolImageOffset + 1,
+ Menus.ShortCut(Word('B'), [ssCtrl, ssShift]));
end;
var
@@ -496,14 +574,14 @@
if Assigned(Menu) then
begin
FExplorerItem := TMenuItem.Create(nil);
- with FExplorerItem do
- begin
- Name := SExplorerItemName;
- Caption := SExplorerItemCaption;
- ShortCut := Menus.ShortCut(Word('M'), [ssCtrl, ssShift]);
- ImageIndex := FToolImageOffset;
- OnClick := ExplorerItemClick;
- end;
+ FExplorerItem.Name := SExplorerItemName;
+ FExplorerItem.Action := FindOrCreateMenuAction(
+ SExplorerItemActionName,
+ SExplorerItemCaption,
+ ExplorerItemClick,
+ FToolImageOffset,
+ Menus.ShortCut(Word('M'), [ssCtrl, ssShift]));
+
{$IFDEF D9+}
Item := ItemByName(Menu, 'ViewStructureItem');
{$ELSE}
@@ -681,6 +759,8 @@
destructor TInstantModelExpert.Destroy;
begin
+ DisableMenuAction(SBuilderItemActionName);
+ DisableMenuAction(SExplorerItemActionName);
Application.OnIdle := FSaveApplicationIdle;
DetachMenus;
FUpdateTimer.Free;
|