IDEIntf: fixed showing separators

git-svn-id: trunk@52921 -
This commit is contained in:
mattias 2016-09-06 09:47:09 +00:00
parent 38dcdbe7cb
commit b00a384cdc
3 changed files with 136 additions and 57 deletions

View File

@ -126,7 +126,6 @@ type
const AMethod: TMethod);
protected
procedure MenuItemClick(Sender: TObject); override;
procedure SetMenuItem(const AValue: TMenuItem); override;
procedure SetChildrenAsSubMenu(const AValue: boolean); virtual;
procedure SetVisible(const AValue: Boolean); override;
procedure SetSubMenuImages(const AValue: TCustomImageList); virtual;
@ -1017,6 +1016,7 @@ begin
if TopSeparator<>nil then
FreeTopSeparator;
FTopSeparator:=MenuItemClass.Create(nil);
TopSeparator.Caption:='-';
TopSeparator.AddHandlerOnDestroy(@OnSeparatorDestroy);
ParentMenuItem.Insert(aMenuIndex,TopSeparator);
end;
@ -1039,6 +1039,7 @@ begin
if BottomSeparator<>nil then
FreeBottomSeparator;
FBottomSeparator:=MenuItemClass.Create(nil);
BottomSeparator.Caption:='-';
BottomSeparator.AddHandlerOnDestroy(@OnSeparatorDestroy);
ParentMenuItem.Insert(aMenuIndex,BottomSeparator);
end;
@ -1082,8 +1083,12 @@ var
// structure has changed
if Item.MenuItem<>nil then
Item.ClearMenuItems;
if (Item.MenuItem=nil) and aVisible and Item.VisibleActive then
//debugln([' UpdateSection Item=',Item.Name,' RealVisible=',Item.RealVisible,' Item.VisibleActive=',Item.VisibleActive]);
if (Item.MenuItem=nil) and aVisible and Item.VisibleActive then begin
Item.CreateMenuItem;
if Item is TIDEMenuSection then
TIDEMenuSection(Item).UpdateContainer;
end;
if Item.MenuItem<>nil then begin
if Item.MenuItem.Parent=nil then
ParentMenuItem.Insert(aMenuIndex,Item.MenuItem);
@ -1099,8 +1104,11 @@ begin
if Section<>nil then Section.UpdateContainer;
exit;
end;
if MenuItem=nil then exit;
if imssClearing in FStates then exit;
if MenuItem=nil then exit;
{$IFDEF VerboseMenuIntf}
debugln(['TIDEMenuSection.UpdateContainer "',Name,'" Count=',Count]);
{$ENDIF}
ParentMenuItem:=MenuItem;
aMenuIndex:=0;
UpdateSection(Self);
@ -1129,27 +1137,44 @@ begin
end;
procedure TIDEMenuSection.UpdateVisibleCommandCount(Add: integer);
var
PendingContainer: TIDEMenuSection;
procedure Update(aSection: TIDEMenuSection);
begin
aSection:=aSection.GetContainerSection;
if PendingContainer=aSection then exit;
if PendingContainer<>nil then
PendingContainer.UpdateContainer;
PendingContainer:=aSection;
end;
var
aSection: TIDEMenuSection;
WasVisibleActive: Boolean;
begin
aSection:=Self;
PendingContainer:=GetContainerSection; // always update the current container
while aSection<>nil do begin
WasVisibleActive:=VisibleActive;
WasVisibleActive:=aSection.VisibleActive;
inc(aSection.FVisibleCommandCount,Add);
if aSection.FVisibleCommandCount<0 then
RaiseGDBException('');
if (WasVisibleActive<>aSection.VisibleActive) or (aSection=Self) then begin
if (WasVisibleActive<>aSection.VisibleActive) then begin
{$IFDEF VerboseMenuIntf}
debugln(['TIDEMenuSection.UpdateVisibleCommandCount "',Name,'" Section="',aSection.Name,'" WasVis=',WasVisibleActive,' NowVis=',aSection.VisibleActive,' MI.Vis=',(aSection.MenuItem<>nil) and aSection.MenuItem.Visible]);
{$ENDIF}
if aSection.MenuItem<>nil then
aSection.RealizeVisible;
aSection.UpdateContainer;
Update(aSection);
if aSection.ChildrenAsSubMenu and (aSection.Section<>nil) then
Update(aSection.Section);
end;
if not aSection.Visible then break;
aSection:=aSection.Section;
end;
if PendingContainer<>nil then
PendingContainer.UpdateContainer;
end;
procedure TIDEMenuSection.NotifySubSectionOnShow(Sender: TObject;
@ -1232,6 +1257,9 @@ var
begin
AnItem.Section:=nil;
AnItem.Name:=CreateUniqueName(AnItem.Name);
{$IFDEF VerboseMenuIntf}
debugln(['TIDEMenuSection.Insert Self="',Name,'" Item="',AnItem.Name,'" AnItem.VisibleActive=',AnItem.VisibleActive]);
{$ENDIF}
FItems.Insert(Index,AnItem);
UpdateAllChildrenIndex(Index);
AnItem.FSection:=Self;
@ -1241,10 +1269,9 @@ begin
AddedVisibleCommands:=AnItem.VisibleCommandCount;
// update this and parents TMenuItems
UpdateVisibleCommandCount(AddedVisibleCommands);
// connect child TMenuItems
UpdateSubMenus;
{$IFDEF VerboseMenuIntf}
debugln(['TIDEMenuSection.Insert AAA3 Self="',Name,'" Item="',AnItem.Name,'" VisibleActive=',VisibleActive,' VisibleCommandCount=',VisibleCommandCount,' MenuItem=',DbgSName(MenuItem)]);
ConsistencyCheck;
{$ENDIF}
end;
@ -1337,17 +1364,15 @@ var
Sibling: TIDEMenuItem;
begin
Result:=false;
if MenuItem=nil then exit;
if ChildrenAsSubMenu then exit;
if Section=nil then exit;
if not VisibleActive then exit;
// this is a logical section with visible MenuItems
if Section<>nil then begin
// search for a MenuItem in front
for i:=SectionIndex-1 downto 0 do begin
Sibling:=Section[i];
if Sibling.VisibleActive then
exit(true); // there is a visible sibling above -> yes, need TopSeparator
end;
// search for a MenuItem in front
for i:=SectionIndex-1 downto 0 do begin
Sibling:=Section[i];
if Sibling.VisibleActive then
exit(true); // there is a visible sibling above -> yes, need TopSeparator
end;
end;
@ -1357,22 +1382,20 @@ var
Sibling: TIDEMenuItem;
begin
Result:=false;
if MenuItem=nil then exit;
if ChildrenAsSubMenu then exit;
if Section=nil then exit;
if not VisibleActive then exit;
// this is a logical section with visible MenuItems
if Section<>nil then begin
for i:=SectionIndex+1 to Section.Count-1 do begin
Sibling:=Section[i];
if Sibling.VisibleActive then begin
// there is a visible sibling below
if Sibling is TIDEMenuSection then begin
if not TIDEMenuSection(Sibling).ChildrenAsSubMenu then
exit(false); // the below sibling is a logical section with a TopSeparator -> no need for BottomSeparator
end;
// -> yes, need BottomSeparator
exit(true);
for i:=SectionIndex+1 to Section.Count-1 do begin
Sibling:=Section[i];
if Sibling.VisibleActive then begin
// there is a visible sibling below
if Sibling is TIDEMenuSection then begin
if not TIDEMenuSection(Sibling).ChildrenAsSubMenu then
exit(false); // the below sibling is a logical section with a TopSeparator -> no need for BottomSeparator
end;
// -> yes, need BottomSeparator
exit(true);
end;
end;
end;
@ -1561,8 +1584,12 @@ var
i: Integer;
Item: TIDEMenuItem;
RealVisibleCommandCount: Integer;
CanHaveMenuItem: Boolean;
begin
inherited ConsistencyCheck;
CanHaveMenuItem:=RealVisible and (GetRoot.MenuItem<>nil);
RealVisibleCommandCount:=0;
for i:=0 to Count-1 do begin
Item:=Items[i];
@ -1580,7 +1607,7 @@ begin
RaiseError('VisibleCommandCount='+dbgs(VisibleCommandCount)+' Real='+dbgs(RealVisibleCommandCount));
if NeedTopSeparator then begin
if TopSeparator=nil then
if (TopSeparator=nil) and CanHaveMenuItem then
RaiseError('');
end else begin
if TopSeparator<>nil then
@ -1588,16 +1615,21 @@ begin
end;
if NeedBottomSeparator then begin
if BottomSeparator=nil then
if (BottomSeparator=nil) and CanHaveMenuItem then
RaiseError('');
end else begin
if BottomSeparator<>nil then
RaiseError('');
end;
if ChildrenAsSubMenu and (MenuItem<>nil) then begin
i:=0;
CheckContainerMenuItems(Self,i);
if ChildrenAsSubMenu then begin
if MenuItem<>nil then begin
i:=0;
CheckContainerMenuItems(Self,i);
end else begin
if VisibleActive and CanHaveMenuItem then
RaiseError('');
end;
end;
end;
@ -1634,19 +1666,6 @@ begin
NotifySubSectionOnShow(Sender);
end;
procedure TIDEMenuSection.SetMenuItem(const AValue: TMenuItem);
begin
if MenuItem=AValue then exit;
inherited SetMenuItem(AValue);
{$IFDEF VerboseMenuIntf}
debugln('TIDEMenuSection.SetMenuItem Name="',Name,'"');
{$ENDIF}
if (MenuItem<>nil) and VisibleActive then begin
UpdateContainer;
UpdateSubMenus;
end;
end;
procedure TIDEMenuSection.SetChildrenAsSubMenu(const AValue: boolean);
begin
if FChildrenAsSubMenu=AValue then exit;
@ -1659,7 +1678,6 @@ begin
Section.UpdateContainer;
if ChildrenAsSubMenu then
UpdateContainer;
UpdateSubMenus;
end;
procedure TIDEMenuSection.SetVisible(const AValue: Boolean);

View File

@ -925,7 +925,6 @@ procedure TMainIDEBase.CreateMenuSeparatorSection(
const AName: String);
begin
Section:=RegisterIDEMenuSection(ParentSection,AName);
Section.ChildrenAsSubMenu := false;
end;
procedure TMainIDEBase.CreateMenuSubSection(ParentSection: TIDEMenuSection;

View File

@ -129,6 +129,7 @@ end;
procedure TTestMenuIntf.TestPopupMenuLogicalSections;
var
Section1, Section2: TIDEMenuSection;
Item1, Item2: TIDEMenuCommand;
begin
FPopupMenuRoot.MenuItem:=Dialog.TestPopupMenuIntf1.Items;
PopupMenuRoot.ConsistencyCheck;
@ -136,14 +137,14 @@ begin
Section1:=RegisterIDEMenuSection(PopupMenuRoot,'Section1');
AssertEquals('Section1.ChildrenAsSubMenu',false,Section1.ChildrenAsSubMenu);
PopupMenuRoot.ConsistencyCheck;
RegisterIDEMenuCommand(Section1,'Item1','Item1');
Item1:=RegisterIDEMenuCommand(Section1,'Item1','Item1');
PopupMenuRoot.ConsistencyCheck;
Section2:=RegisterIDEMenuSection(PopupMenuRoot,'Section2');
AssertEquals('Section2.ChildrenAsSubMenu',false,Section2.ChildrenAsSubMenu);
PopupMenuRoot.ConsistencyCheck;
PopupMenuRoot.ConsistencyCheck;
RegisterIDEMenuCommand(Section2,'Item2','Item2');
Item2:=RegisterIDEMenuCommand(Section2,'Item2','Item2');
PopupMenuRoot.ConsistencyCheck;
AssertEquals('Section1.Section=PopupMenuRoot',true,Section1.Section=PopupMenuRoot);
@ -156,21 +157,60 @@ begin
AssertEquals('Section2.VisibleCommandCount',1,Section2.VisibleCommandCount);
AssertEquals('Section1.VisibleActive',true,Section1.VisibleActive);
AssertEquals('Section2.VisibleActive',true,Section2.VisibleActive);
AssertEquals('Section1.NeedTopSeparator',false,Section1.NeedTopSeparator);
AssertEquals('Section1.NeedBottomSeparator',false,Section1.NeedBottomSeparator);
AssertEquals('Section2.NeedTopSeparator',true,Section2.NeedTopSeparator);
AssertEquals('has Section2.TopSeparator',true,Section2.TopSeparator<>nil);
AssertEquals('Section2.NeedBottomSeparator',false,Section2.NeedBottomSeparator);
AssertEquals('Section1.TopSeparator',false,Section1.TopSeparator<>nil);
AssertEquals('Section1.MenuItem',false,Section1.MenuItem<>nil);
AssertEquals('Section1.BottomSeparator',false,Section1.BottomSeparator<>nil);
AssertEquals('Item1.MenuItem',true,Item1.MenuItem<>nil);
AssertEquals('Section2.TopSeparator',true,Section2.TopSeparator<>nil);
AssertEquals('Section2.MenuItem',false,Section2.MenuItem<>nil);
AssertEquals('Section2.BottomSeparator',false,Section2.BottomSeparator<>nil);
AssertEquals('Item2.MenuItem',true,Item2.MenuItem<>nil);
AssertEquals('PopupMenuRoot.MenuItem.Count',3,PopupMenuRoot.MenuItem.Count);
AssertEquals('Item1.MenuItem=PopupMenuRoot.MenuItem[0]',true,Item1.MenuItem=PopupMenuRoot.MenuItem[0]);
AssertEquals('Section2.TopSeparator=PopupMenuRoot.MenuItem[1]',true,Section2.TopSeparator=PopupMenuRoot.MenuItem[1]);
AssertEquals('Item2.MenuItem=PopupMenuRoot.MenuItem[2]',true,Item2.MenuItem=PopupMenuRoot.MenuItem[2]);
end;
procedure TTestMenuIntf.TestPopupMenuSubMenu;
var
Section1: TIDEMenuSection;
Item1: TIDEMenuCommand;
begin
FPopupMenuRoot.MenuItem:=Dialog.TestPopupMenuIntf1.Items;
PopupMenuRoot.ConsistencyCheck;
Section1:=RegisterIDESubMenu(PopupMenuRoot,'Section1','Section1');
AssertEquals('Section1.ChildrenAsSubMenu',true,Section1.ChildrenAsSubMenu);
AssertEquals('Section1.Section=PopupMenuRoot',true,Section1.Section=PopupMenuRoot);
AssertEquals('Section1.SectionIndex',0,Section1.SectionIndex);
AssertEquals('Section1.Visible',true,Section1.Visible);
PopupMenuRoot.ConsistencyCheck;
RegisterIDEMenuCommand(Section1,'Item1','Item1');
Item1:=RegisterIDEMenuCommand(Section1,'Item1','Item1');
AssertEquals('Item1.Visible',true,Item1.Visible);
PopupMenuRoot.ConsistencyCheck;
AssertEquals('Section1.Count',1,Section1.Count);
AssertEquals('Section1[0]=Item1',true,Section1[0]=Item1);
AssertEquals('Section1.VisibleCommandCount',1,Section1.VisibleCommandCount);
AssertEquals('Section1.VisibleActive',true,Section1.VisibleActive);
AssertEquals('Section1.NeedTopSeparator',false,Section1.NeedTopSeparator);
AssertEquals('Section1.NeedBottomSeparator',false,Section1.NeedBottomSeparator);
AssertEquals('Section1.TopSeparator',false,Section1.TopSeparator<>nil);
AssertEquals('Section1.MenuItem',true,Section1.MenuItem<>nil);
AssertEquals('Section1.BottomSeparator',false,Section1.BottomSeparator<>nil);
AssertEquals('Item1.MenuItem',true,Item1.MenuItem<>nil);
AssertEquals('PopupMenuRoot.MenuItem.Count',1,PopupMenuRoot.MenuItem.Count);
AssertEquals('Section1.MenuItem=PopupMenuRoot.MenuItem[0]',true,Section1.MenuItem=PopupMenuRoot.MenuItem[0]);
AssertEquals('Section1.MenuItem.Count',1,Section1.MenuItem.Count);
AssertEquals('Item1.MenuItem=Section1.MenuItem[0]',true,Item1.MenuItem=Section1.MenuItem[0]);
end;
procedure TTestMenuIntf.TestPopupMenuVisible;
@ -203,29 +243,46 @@ begin
AssertEquals('LogSection2.VisibleActive',true,LogSection2.VisibleActive);
AssertEquals('LogSection2.VisibleCommandCount',2,LogSection2.VisibleCommandCount);
AssertEquals('LogSection1.TopSeparator',false,LogSection1.TopSeparator<>nil);
AssertEquals('LogSection1.BottomSeparator',true,LogSection1.BottomSeparator<>nil);
AssertEquals('LogSection2.TopSeparator',true,LogSection2.TopSeparator<>nil);
AssertEquals('LogSection2.BottomSeparator',false,LogSection2.BottomSeparator<>nil);
// hide Item1 -> auto hides LogSection1
Item1.Visible:=false;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection1.VisibleActive',false,LogSection1.VisibleActive);
AssertEquals('LogSection1.VisibleCommandCount',0,LogSection1.VisibleCommandCount);
AssertEquals('LogSection1.TopSeparator',false,LogSection1.TopSeparator<>nil);
AssertEquals('LogSection1.BottomSeparator',false,LogSection1.BottomSeparator<>nil);
// show Item1 -> auto shows LogSection1
Item1.Visible:=true;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection1.VisibleActive',true,LogSection1.VisibleActive);
AssertEquals('LogSection1.VisibleCommandCount',1,LogSection1.VisibleCommandCount);
AssertEquals('LogSection1.TopSeparator',false,LogSection1.TopSeparator<>nil);
AssertEquals('LogSection1.BottomSeparator',true,LogSection1.BottomSeparator<>nil);
// hide Item2 -> auto hides SubMenu2
Item2.Visible:=false;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('SubMenu2.VisibleActive',false,SubMenu2.VisibleActive);
AssertEquals('SubMenu2.VisibleCommandCount',0,SubMenu2.VisibleCommandCount);
AssertEquals('LogSection1.TopSeparator',false,LogSection1.TopSeparator<>nil);
AssertEquals('LogSection1.BottomSeparator',false,LogSection1.BottomSeparator<>nil);
AssertEquals('LogSection2.TopSeparator',true,LogSection2.TopSeparator<>nil);
AssertEquals('LogSection2.BottomSeparator',false,LogSection2.BottomSeparator<>nil);
// show Item2 -> auto shows SubMenu2
Item2.Visible:=true;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('SubMenu2.VisibleActive',true,SubMenu2.VisibleActive);
AssertEquals('SubMenu2.VisibleCommandCount',1,SubMenu2.VisibleCommandCount);
AssertEquals('LogSection1.TopSeparator',false,LogSection1.TopSeparator<>nil);
AssertEquals('LogSection1.BottomSeparator',true,LogSection1.BottomSeparator<>nil);
AssertEquals('LogSection2.TopSeparator',true,LogSection2.TopSeparator<>nil);
AssertEquals('LogSection2.BottomSeparator',false,LogSection2.BottomSeparator<>nil);
// hide Item3, Item4 still visible
Item3.Visible:=false;
@ -238,12 +295,17 @@ begin
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection2.VisibleActive',false,LogSection2.VisibleActive);
AssertEquals('LogSection2.VisibleCommandCount',0,LogSection2.VisibleCommandCount);
AssertEquals('LogSection1.BottomSeparator',true,LogSection1.BottomSeparator<>nil);
AssertEquals('LogSection2.TopSeparator',false,LogSection2.TopSeparator<>nil);
AssertEquals('LogSection2.BottomSeparator',false,LogSection2.BottomSeparator<>nil);
// show Item3 -> auto shows LogSection2
Item3.Visible:=true;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection2.VisibleActive',true,LogSection2.VisibleActive);
AssertEquals('LogSection2.VisibleCommandCount',1,LogSection2.VisibleCommandCount);
AssertEquals('LogSection2.TopSeparator',true,LogSection2.TopSeparator<>nil);
AssertEquals('LogSection2.BottomSeparator',false,LogSection2.BottomSeparator<>nil);
end;
procedure TTestMenuIntf.TestPopupMenuClearHiddenSection;
@ -264,14 +326,14 @@ begin
Item2:=RegisterIDEMenuCommand(SubSection2,'Item2','Item2');
PopupMenuRoot.ConsistencyCheck;
writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection START');
//writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection START');
AssertEquals('LogSection1.VisibleActive',true,LogSection1.VisibleActive);
AssertEquals('LogSection1.VisibleCommandCount',2,LogSection1.VisibleCommandCount);
AssertEquals('SubSection2.VisibleActive',true,SubSection2.VisibleActive);
AssertEquals('SubSection2.VisibleCommandCount',1,SubSection2.VisibleCommandCount);
// hide SubSection2 -> LogSection1 looses one command
writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection hide SubSection2 -> LogSection1 looses one command');
//writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection hide SubSection2 -> LogSection1 looses one command');
SubSection2.Visible:=false;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection1.VisibleActive',true,LogSection1.VisibleActive);
@ -280,7 +342,7 @@ begin
AssertEquals('SubSection2.VisibleCommandCount',1,SubSection2.VisibleCommandCount);
// hide Item2 -> no effect on LogSection1
writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection hide Item2 -> no effect on LogSection1');
//writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection hide Item2 -> no effect on LogSection1');
Item2.Visible:=false;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection1.VisibleActive',true,LogSection1.VisibleActive);
@ -289,7 +351,7 @@ begin
AssertEquals('SubSection2.VisibleCommandCount',0,SubSection2.VisibleCommandCount);
// show Item2 -> no effect on LogSection1
writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection show Item2 -> no effect on LogSection1');
//writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection show Item2 -> no effect on LogSection1');
Item2.Visible:=true;
PopupMenuRoot.ConsistencyCheck;
AssertEquals('LogSection1.VisibleActive',true,LogSection1.VisibleActive);
@ -298,7 +360,7 @@ begin
AssertEquals('SubSection2.VisibleCommandCount',1,SubSection2.VisibleCommandCount);
// clear SubSection2 -> no effect on LogSection1
writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection clear SubSection2 -> no effect on LogSection1');
//writeln('TTestMenuIntf.TestPopupMenuClearHiddenSection clear SubSection2 -> no effect on LogSection1');
SubSection2.Clear;
Item2:=nil;
PopupMenuRoot.ConsistencyCheck;