Better placement of pull down menus. If there is not enough room at

the preferred edge display the menu at the opposite edge.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@31040 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
wlux 2010-07-26 22:13:11 +00:00
parent b623ba6665
commit 52d2e5cf3b
2 changed files with 93 additions and 33 deletions

View file

@ -1,3 +1,9 @@
2010-07-27 Wolfgang Lux <wolfgang.lux@gmail.com>
* Source/NSMenuView.m (-setWindowFrameForAttachingToRect:...):
Better placement of pull down menus. If there is not enough room
at the preferred edge display the menu at the opposite edge.
2010-07-26 Wolfgang Lux <wolfgang.lux@gmail.com> 2010-07-26 Wolfgang Lux <wolfgang.lux@gmail.com>
* Source/NSMenuView.m (-trackWithEvent:): * Source/NSMenuView.m (-trackWithEvent:):

View file

@ -1078,7 +1078,7 @@ static NSMapTable *viewInfo = 0;
{ {
NSRect r; NSRect r;
NSRect cellFrame; NSRect cellFrame;
NSRect screenFrame; NSRect popUpFrame;
int items = [_itemCells count]; int items = [_itemCells count];
BOOL growHeight = YES; BOOL growHeight = YES;
BOOL resizeCell = NO; BOOL resizeCell = NO;
@ -1167,8 +1167,8 @@ static NSMapTable *viewInfo = 0;
/* /*
* Compute the frame * Compute the frame
*/ */
screenFrame.origin = screenRect.origin; popUpFrame.origin = screenRect.origin;
screenFrame.size = cellFrame.size; popUpFrame.size = cellFrame.size;
if (items > 0) if (items > 0)
{ {
float f; float f;
@ -1176,10 +1176,10 @@ static NSMapTable *viewInfo = 0;
if (_horizontal == NO) if (_horizontal == NO)
{ {
f = cellFrame.size.height * (items - 1); f = cellFrame.size.height * (items - 1);
screenFrame.size.height += f + _leftBorderOffset; popUpFrame.size.height += f + _leftBorderOffset;
screenFrame.origin.y -= f; popUpFrame.origin.y -= f;
screenFrame.size.width += _leftBorderOffset; popUpFrame.size.width += _leftBorderOffset;
screenFrame.origin.x -= _leftBorderOffset; popUpFrame.origin.x -= _leftBorderOffset;
// If the menu is a pull down menu the first item, which would // If the menu is a pull down menu the first item, which would
// appear at the top of the menu, holds the title and is omitted // appear at the top of the menu, holds the title and is omitted
@ -1187,22 +1187,22 @@ static NSMapTable *viewInfo = 0;
{ {
if ([[_attachedMenu _owningPopUp] pullsDown]) if ([[_attachedMenu _owningPopUp] pullsDown])
{ {
screenFrame.size.height -= cellFrame.size.height; popUpFrame.size.height -= cellFrame.size.height;
screenFrame.origin.y += cellFrame.size.height; popUpFrame.origin.y += cellFrame.size.height;
} }
} }
// Compute position for popups, if needed // Compute position for popups, if needed
if (selectedItemIndex != -1) if (selectedItemIndex != -1)
{ {
screenFrame.origin.y popUpFrame.origin.y
+= cellFrame.size.height * selectedItemIndex; += cellFrame.size.height * selectedItemIndex;
} }
} }
else else
{ {
f = cellFrame.size.width * (items - 1); f = cellFrame.size.width * (items - 1);
screenFrame.size.width += f; popUpFrame.size.width += f;
// If the menu is a pull down menu the first item holds the // If the menu is a pull down menu the first item holds the
// title and is omitted // title and is omitted
@ -1210,14 +1210,14 @@ static NSMapTable *viewInfo = 0;
{ {
if ([[_attachedMenu _owningPopUp] pullsDown]) if ([[_attachedMenu _owningPopUp] pullsDown])
{ {
screenFrame.size.width -= cellFrame.size.width; popUpFrame.size.width -= cellFrame.size.width;
} }
} }
// Compute position for popups, if needed // Compute position for popups, if needed
if (selectedItemIndex != -1) if (selectedItemIndex != -1)
{ {
screenFrame.origin.x -= cellFrame.size.width * selectedItemIndex; popUpFrame.origin.x -= cellFrame.size.width * selectedItemIndex;
} }
} }
} }
@ -1225,31 +1225,85 @@ static NSMapTable *viewInfo = 0;
// Update position, if needed, using the preferredEdge // Update position, if needed, using the preferredEdge
if (selectedItemIndex == -1) if (selectedItemIndex == -1)
{ {
// FIXME if screen space is tight at the preferred edge attach NSRect screenFrame;
// the menu at the opposite edge
screenFrame.origin.y -= cellFrame.size.height; if (screen == nil)
switch (edge) screen = [NSScreen mainScreen];
screenFrame = [screen frame];
popUpFrame.origin.y -= cellFrame.size.height;
if (edge == NSMinYEdge || edge == NSMaxYEdge)
{ {
default: NSRect minYFrame = popUpFrame;
case NSMinYEdge: NSRect maxYFrame = popUpFrame;
break;
case NSMaxYEdge: // show menu above or below the cell depending on the preferred edge
screenFrame.origin.y += // if the menu would be partially off screen on that edge use the
screenFrame.size.height + screenRect.size.height - _leftBorderOffset; // opposite edge or at least the one where more space is left
break; maxYFrame.origin.y +=
case NSMinXEdge: maxYFrame.size.height + screenRect.size.height - _leftBorderOffset;
screenFrame.origin.y += screenRect.size.height;
screenFrame.origin.x -= screenFrame.size.width; if (edge == NSMinYEdge)
break; {
case NSMaxXEdge: if ((NSMinY(minYFrame) < NSMinY(screenFrame))
screenFrame.origin.y += screenRect.size.height; && ((NSMaxY(maxYFrame) <= NSMaxY(screenFrame))
screenFrame.origin.x += screenRect.size.width + _leftBorderOffset; || (NSMaxY(screenFrame) - NSMaxY(screenRect) >
break; NSMinY(screenRect) - NSMinY(screenFrame))))
{
edge = NSMaxYEdge;
}
}
else
{
if ((NSMaxY(maxYFrame) > NSMaxY(screenFrame))
&& ((NSMinY(minYFrame) >= NSMinY(screenFrame))
|| (NSMaxY(screenFrame) - NSMaxY(screenRect) <
NSMinY(screenRect) - NSMinY(screenFrame))))
{
edge = NSMinYEdge;
}
}
popUpFrame = edge == NSMinYEdge ? minYFrame : maxYFrame;
}
else
{
NSRect minXFrame = popUpFrame;
NSRect maxXFrame = popUpFrame;
minXFrame.origin.y += screenRect.size.height;
minXFrame.origin.x -= minXFrame.size.width;
maxXFrame.origin.y += screenRect.size.height;
maxXFrame.origin.x += screenRect.size.width + _leftBorderOffset;
// show menu on the opposite edge if it does not fit on screen on
// the preferred edge
if (edge == NSMinXEdge)
{
if ((NSMinX(minXFrame) < NSMinX(screenFrame))
&& ((NSMaxX(maxXFrame) <= NSMaxX(screenFrame))
|| (NSMaxX(screenFrame) - NSMaxX(screenRect) >
NSMinX(screenRect) - NSMinX(screenFrame))))
{
edge = NSMaxXEdge;
}
}
else
{
if ((NSMaxX(maxXFrame) > NSMaxX(screenFrame))
&& ((NSMinX(minXFrame) >= NSMinX(screenFrame))
|| (NSMaxX(screenFrame) - NSMaxX(screenRect) <
NSMinX(screenRect) - NSMinX(screenFrame))))
{
edge = NSMinXEdge;
}
}
popUpFrame = edge == NSMinXEdge ? minXFrame : maxXFrame;
} }
} }
// Get the frameRect // Get the frameRect
r = [NSWindow frameRectForContentRect: screenFrame r = [NSWindow frameRectForContentRect: popUpFrame
styleMask: [_window styleMask]]; styleMask: [_window styleMask]];
// Set the window frame // Set the window frame