mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 10:20:58 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4877 72102866-910b-0410-8b05-ffd578937521
901 lines
20 KiB
Objective-C
901 lines
20 KiB
Objective-C
/*
|
|
NSMenuView.m
|
|
|
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
Author: Michael Hanni <mhanni@sprintmail.com>
|
|
Date: 1999
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, write to the Free Software Foundation,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <AppKit/NSApplication.h>
|
|
#include <AppKit/NSEvent.h>
|
|
#include <AppKit/NSMenuView.h>
|
|
#include <AppKit/NSWindow.h>
|
|
#include <AppKit/PSOperators.h>
|
|
|
|
static float GSMenuBarHeight = 25.0; // a guess.
|
|
|
|
// These private methods are used in NSPopUpButton. For NSPB we need to be
|
|
// able to init with a frame, but have a very custom cell size.
|
|
|
|
@implementation NSMenuView
|
|
|
|
// Class methods.
|
|
|
|
+ (float)menuBarHeight
|
|
{
|
|
return GSMenuBarHeight;
|
|
}
|
|
|
|
- (BOOL)acceptsFirstMouse: (NSEvent *)theEvent
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
// Init methods.
|
|
|
|
- (id)init
|
|
{
|
|
return [self initWithFrame: NSZeroRect];
|
|
}
|
|
|
|
- (id)initWithFrame: (NSRect)aFrame
|
|
{
|
|
cellSize = NSMakeSize(110,20);
|
|
menuv_highlightedItemIndex = -1;
|
|
|
|
return [super initWithFrame: aFrame];
|
|
}
|
|
|
|
- (id)initWithFrame: (NSRect)aFrame
|
|
cellSize: (NSSize)aSize
|
|
{
|
|
[self initWithFrame:aFrame];
|
|
|
|
cellSize = aSize;
|
|
|
|
return self;
|
|
}
|
|
|
|
// Our menu.
|
|
|
|
- (void)setMenu: (NSMenu *)menu
|
|
{
|
|
ASSIGN(menuv_menu, menu);
|
|
menuv_items_link = [menuv_menu itemArray];
|
|
}
|
|
|
|
- (NSMenu *)menu
|
|
{
|
|
return menuv_menu;
|
|
}
|
|
|
|
- (void)setHorizontal: (BOOL)flag
|
|
{
|
|
menuv_horizontal = flag;
|
|
}
|
|
|
|
- (BOOL)isHorizontal
|
|
{
|
|
return menuv_horizontal;
|
|
}
|
|
|
|
- (void)setFont: (NSFont *)font
|
|
{
|
|
ASSIGN(menuv_font, font);
|
|
}
|
|
|
|
- (NSFont *)font
|
|
{
|
|
return menuv_font;
|
|
}
|
|
|
|
/*
|
|
* - (void)setHighlightedItemIndex: (int)index
|
|
*
|
|
* MacOS-X defines this function as the central way of switching to a new
|
|
* highlighted item. The index value is == to the item you want
|
|
* highlighted. When used this method unhighlights the last item (if
|
|
* applicable) and selects the new item. If index == -1 highlighting is
|
|
* turned off.
|
|
*
|
|
* NOTES (Michael Hanni):
|
|
*
|
|
* I modified this method for GNUstep to take submenus into account. This
|
|
* way we get maximum performance while still using a method outside the
|
|
* loop.
|
|
*
|
|
*/
|
|
|
|
- (void)setHighlightedItemIndex: (int)index
|
|
{
|
|
id anItem;
|
|
|
|
[self lockFocus];
|
|
|
|
if (index == -1)
|
|
{
|
|
if (menuv_highlightedItemIndex != -1)
|
|
{
|
|
NSRect aRect = [self rectOfItemAtIndex: menuv_highlightedItemIndex];
|
|
|
|
anItem = [menuv_items_link objectAtIndex: menuv_highlightedItemIndex];
|
|
|
|
[anItem highlight: NO
|
|
withFrame: aRect
|
|
inView: self];
|
|
|
|
[self setNeedsDisplayInRect: aRect];
|
|
|
|
[window flushWindow];
|
|
|
|
if ([anItem hasSubmenu]
|
|
&& ![[anItem target] isTornOff])
|
|
[[anItem target] close];
|
|
else if ([anItem hasSubmenu]
|
|
&& [[anItem target] isTornOff])
|
|
[[anItem target] closeTransient];
|
|
|
|
[anItem setState: 0];
|
|
menuv_highlightedItemIndex = -1;
|
|
}
|
|
}
|
|
else if (index >= 0)
|
|
{
|
|
if ( menuv_highlightedItemIndex != -1)
|
|
{
|
|
NSRect aRect = [self rectOfItemAtIndex: menuv_highlightedItemIndex];
|
|
|
|
anItem = [menuv_items_link objectAtIndex: menuv_highlightedItemIndex];
|
|
|
|
[anItem highlight: NO
|
|
withFrame: aRect
|
|
inView: self];
|
|
|
|
[self setNeedsDisplayInRect: aRect];
|
|
|
|
[window flushWindow];
|
|
|
|
if ([anItem hasSubmenu]
|
|
&& ![[anItem target] isTornOff])
|
|
[[anItem target] close];
|
|
else if ([anItem hasSubmenu]
|
|
&& [[anItem target] isTornOff])
|
|
[[anItem target] closeTransient];
|
|
|
|
[anItem setState: 0];
|
|
}
|
|
|
|
if (index != menuv_highlightedItemIndex)
|
|
{
|
|
anItem = [menuv_items_link objectAtIndex: index];
|
|
|
|
if ([anItem isEnabled])
|
|
{
|
|
NSRect aRect = [self rectOfItemAtIndex: index];
|
|
|
|
[anItem highlight: YES
|
|
withFrame: aRect
|
|
inView: self];
|
|
[self setNeedsDisplayInRect: aRect];
|
|
|
|
[window flushWindow];
|
|
|
|
if ([anItem hasSubmenu]
|
|
&& ![[anItem target] isTornOff])
|
|
[[anItem target] display];
|
|
else if ([anItem hasSubmenu]
|
|
&& [[anItem target] isTornOff])
|
|
[[anItem target] displayTransient];
|
|
|
|
[anItem setState: 1];
|
|
}
|
|
|
|
// set ivar to new index
|
|
menuv_highlightedItemIndex = index;
|
|
}
|
|
else if (menuv_highlightedItemIndex == index)
|
|
{
|
|
menuv_highlightedItemIndex = -1;
|
|
}
|
|
}
|
|
|
|
[self unlockFocus];
|
|
}
|
|
|
|
- (int)highlightedItemIndex
|
|
{
|
|
return menuv_highlightedItemIndex;
|
|
}
|
|
|
|
- (void)setMenuItemCell: (NSMenuItemCell *)cell
|
|
forItemAtIndex: (int)index
|
|
{
|
|
// [menuv_items insertObject: cell atIndex: index];
|
|
|
|
// resize the cell
|
|
[cell setNeedsSizing: YES];
|
|
|
|
// resize menuview
|
|
[self setNeedsSizing: YES];
|
|
}
|
|
|
|
- (NSMenuItemCell *)menuItemCellForItemAtIndex: (int)index
|
|
{
|
|
return [menuv_items_link objectAtIndex: index];
|
|
}
|
|
|
|
- (NSMenuView *)attachedMenuView
|
|
{
|
|
return [[menuv_menu attachedMenu] menuView];
|
|
}
|
|
|
|
- (NSMenu *)attachedMenu
|
|
{
|
|
return [menuv_menu attachedMenu];
|
|
}
|
|
|
|
- (BOOL)isAttached
|
|
{
|
|
return [menuv_menu isAttached];
|
|
}
|
|
|
|
- (BOOL)isTornOff
|
|
{
|
|
return [menuv_menu isTornOff];
|
|
}
|
|
|
|
- (void)setHorizontalEdgePadding: (float)pad
|
|
{
|
|
menuv_hEdgePad = pad;
|
|
}
|
|
|
|
- (float)horizontalEdgePadding
|
|
{
|
|
return menuv_hEdgePad;
|
|
}
|
|
|
|
- (void)itemChanged: (NSNotification *)notification
|
|
{
|
|
}
|
|
|
|
- (void)itemAdded: (NSNotification *)notification
|
|
{
|
|
}
|
|
|
|
- (void)itemRemoved: (NSNotification *)notification
|
|
{
|
|
}
|
|
|
|
// Submenus.
|
|
|
|
- (void)detachSubmenu
|
|
{
|
|
}
|
|
|
|
- (void)attachSubmenuForItemAtIndex: (int)index
|
|
{
|
|
// create rect to display submenu in.
|
|
|
|
// order window with submenu in it to front.
|
|
}
|
|
|
|
- (void)update
|
|
{
|
|
// [menuv_menu update];
|
|
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
}
|
|
|
|
- (void)setNeedsSizing: (BOOL)flag
|
|
{
|
|
menuv_needsSizing = flag;
|
|
}
|
|
|
|
- (BOOL)needsSizing
|
|
{
|
|
return menuv_needsSizing;
|
|
}
|
|
|
|
- (void)sizeToFit
|
|
{
|
|
int i;
|
|
int howMany = [menuv_items_link count];
|
|
int howHigh = (howMany * cellSize.height);
|
|
float neededWidth = 0;
|
|
|
|
for (i=0;i<howMany;i++)
|
|
{
|
|
float aWidth;
|
|
|
|
NSMenuItemCell *anItem = [menuv_items_link objectAtIndex: i];
|
|
aWidth = [anItem titleWidth];
|
|
|
|
if (aWidth > neededWidth)
|
|
neededWidth = aWidth;
|
|
}
|
|
|
|
if (![menuv_menu _isBeholdenToPopUpButton])
|
|
cellSize.width = 7 + neededWidth + 7 + 7 + 5;
|
|
|
|
// if ([window contentView] == self)
|
|
// [window setContentSize: NSMakeSize(cellSize.width,howHigh)];
|
|
// else
|
|
// [self setFrame: NSMakeRect(0,0,cellSize.width,howHigh)];
|
|
[self setFrameSize: NSMakeSize(cellSize.width,howHigh)];
|
|
}
|
|
|
|
- (void)sizeToFitForPopUpButton
|
|
{
|
|
int howHigh = ([menuv_items_link count] * cellSize.height);
|
|
|
|
if ([window contentView] == self)
|
|
[window setContentSize: NSMakeSize(cellSize.width,howHigh)];
|
|
else
|
|
[self setFrame: NSMakeRect(0,0,cellSize.width,howHigh)];
|
|
}
|
|
|
|
- (float)stateImageOffset
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_stateImageOffset;
|
|
}
|
|
|
|
- (float)stateImageWidth
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_stateImageWidth;
|
|
}
|
|
|
|
- (float)imageAndTitleOffset
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_imageAndTitleOffset;
|
|
}
|
|
|
|
- (float)imageAndTitleWidth
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_imageAndTitleWidth;
|
|
}
|
|
|
|
- (float)keyEquivalentOffset
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_keyEqOffset;
|
|
}
|
|
|
|
- (float)keyEquivalentWidth
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
return menuv_keyEqWidth;
|
|
}
|
|
|
|
- (NSRect)innerRect
|
|
{
|
|
return bounds;
|
|
|
|
// this could change if we drew menuitemcells as
|
|
// plain rects with no bezel like in macOSX. Talk to Michael Hanni if
|
|
// you would like to see this configurable.
|
|
}
|
|
|
|
- (NSRect)rectOfItemAtIndex: (int)index
|
|
{
|
|
NSRect theRect;
|
|
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
if (index == 0)
|
|
theRect.origin.y = frame.size.height - cellSize.height;
|
|
else
|
|
theRect.origin.y = frame.size.height - (cellSize.height * (index + 1));
|
|
theRect.origin.x = 0;
|
|
theRect.size = cellSize;
|
|
|
|
return theRect;
|
|
}
|
|
|
|
- (int)indexOfItemAtPoint: (NSPoint)point
|
|
{
|
|
// The MacOSX API says that this method calls - rectOfItemAtIndex for
|
|
// *every* cell to figure this out. Well, instead we will just do some
|
|
// simple math. (NOTE: if we get horizontal methods we will have to do
|
|
// this. Very much like NSTabView.
|
|
NSRect aRect = [self rectOfItemAtIndex: 0];
|
|
|
|
// this will need some finnessing but should be close.
|
|
return (frame.size.height - point.y) / aRect.size.height;
|
|
}
|
|
|
|
- (void)setNeedsDisplayForItemAtIndex: (int)index
|
|
{
|
|
[[menuv_items_link objectAtIndex: index] setNeedsDisplay: YES];
|
|
}
|
|
|
|
- (NSPoint)locationForSubmenu: (NSMenu *)aSubmenu
|
|
{
|
|
if (menuv_needsSizing)
|
|
[self sizeToFit];
|
|
|
|
// find aSubmenu's parent
|
|
|
|
// position aSubmenu's window to be adjacent to its parent.
|
|
|
|
// return new origin of window.
|
|
return NSZeroPoint;
|
|
}
|
|
|
|
- (void)resizeWindowWithMaxHeight: (float)maxHeight
|
|
{
|
|
// set the menuview's window to max height in order to keep on screen?
|
|
}
|
|
|
|
- (void)setWindowFrameForAttachingToRect: (NSRect)screenRect
|
|
onScreen: (NSScreen *)screen
|
|
preferredEdge: (NSRectEdge)edge
|
|
popUpSelectedItem: (int)selectedItemIndex
|
|
{
|
|
// huh.
|
|
}
|
|
|
|
// Drawing.
|
|
|
|
- (void)drawRect: (NSRect)rect
|
|
{
|
|
int i;
|
|
NSRect aRect = frame;
|
|
int howMany = [menuv_items_link count];
|
|
|
|
// This code currently doesn't take intercell spacing into account. I'll
|
|
// need to fix that.
|
|
|
|
aRect.origin.y = cellSize.height * (howMany - 1);
|
|
aRect.size = cellSize;
|
|
|
|
for (i=0;i<howMany;i++)
|
|
{
|
|
id aCell = [menuv_items_link objectAtIndex: i];
|
|
|
|
[aCell drawWithFrame: aRect inView: self];
|
|
aRect.origin.y -= cellSize.height;
|
|
}
|
|
}
|
|
|
|
// Event.
|
|
|
|
- (void)performActionWithHighlightingForItemAtIndex: (int)index
|
|
{
|
|
// for use with key equivalents.
|
|
}
|
|
|
|
- (BOOL)trackWithEvent: (NSEvent *)event
|
|
{
|
|
NSPoint lastLocation = [event locationInWindow];
|
|
float height = frame.size.height;
|
|
int index;
|
|
int lastIndex = 0;
|
|
unsigned eventMask = NSLeftMouseUpMask | NSLeftMouseDownMask
|
|
| NSRightMouseUpMask | NSRightMouseDraggedMask
|
|
| NSLeftMouseDraggedMask;
|
|
BOOL done = NO;
|
|
NSApplication *theApp = [NSApplication sharedApplication];
|
|
NSDate *theDistantFuture = [NSDate distantFuture];
|
|
int theCount = [menuv_items_link count];
|
|
id selectedCell;
|
|
|
|
// These 3 BOOLs are misnomers. I'll rename them later. -Michael. FIXME.
|
|
|
|
BOOL weWereOut = NO;
|
|
BOOL weLeftMenu = NO;
|
|
BOOL weRightMenu = NO;
|
|
|
|
// Get our mouse location, regardless of where it may be it the event
|
|
// stream.
|
|
|
|
lastLocation = [window mouseLocationOutsideOfEventStream];
|
|
|
|
index = (height - lastLocation.y) / cellSize.height;
|
|
|
|
if (index >= 0 && index < theCount)
|
|
{
|
|
if (menuv_highlightedItemIndex > -1)
|
|
{
|
|
BOOL finished = NO;
|
|
NSMenu *aMenu = menuv_menu;
|
|
|
|
while (!finished)
|
|
{ // "forward"cursive menu find.
|
|
if ([aMenu attachedMenu])
|
|
{
|
|
aMenu = [aMenu attachedMenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
}
|
|
|
|
finished = NO;
|
|
|
|
while (!finished)
|
|
{ // Recursive menu close & deselect.
|
|
if ([aMenu supermenu] && aMenu != menuv_menu)
|
|
{
|
|
[[aMenu menuView] setHighlightedItemIndex: -1];
|
|
aMenu = [aMenu supermenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
|
|
// [window flushWindow];
|
|
}
|
|
}
|
|
|
|
[self setHighlightedItemIndex: index];
|
|
|
|
lastIndex = index;
|
|
}
|
|
|
|
while (!done)
|
|
{
|
|
event = [theApp nextEventMatchingMask: eventMask
|
|
untilDate: theDistantFuture
|
|
inMode: NSEventTrackingRunLoopMode
|
|
dequeue: YES];
|
|
|
|
switch ([event type])
|
|
{
|
|
case NSRightMouseUp:
|
|
case NSLeftMouseUp:
|
|
// [self setHighlightedItemIndex:-1];
|
|
/* right mouse up or left mouse up means we're done */
|
|
done = YES;
|
|
break;
|
|
case NSRightMouseDragged:
|
|
case NSLeftMouseDragged:
|
|
lastLocation = [window mouseLocationOutsideOfEventStream];
|
|
lastLocation = [self convertPoint: lastLocation fromView: nil];
|
|
|
|
#if 0
|
|
NSLog (@"location = (%f, %f, %f)", lastLocation.x, [window
|
|
frame].origin.x, [window frame].size.width);
|
|
NSLog (@"location = %f (%f, %f)", lastLocation.y, [window
|
|
frame].origin.y, [window frame].size.height);
|
|
#endif
|
|
|
|
/* If the location of the mouse is inside the window on the
|
|
x-axis. */
|
|
|
|
if (lastLocation.x > 0
|
|
&& lastLocation.x < [window frame].size.width)
|
|
{
|
|
|
|
/* Get the index from some simple math. */
|
|
|
|
index = (height - lastLocation.y) / cellSize.height;
|
|
#if 0
|
|
NSLog (@"location = (%f, %f)",
|
|
lastLocation.x, lastLocation.y);
|
|
NSLog (@"index = %d\n", index);
|
|
#endif
|
|
/* If the index generated above is valid, use it. */
|
|
|
|
if (index >= 0 && index < theCount)
|
|
{
|
|
if (index != lastIndex)
|
|
{
|
|
[self setHighlightedItemIndex: index];
|
|
lastIndex = index;
|
|
}
|
|
else
|
|
{
|
|
if (weWereOut)
|
|
{
|
|
[self setHighlightedItemIndex: index];
|
|
lastIndex = index;
|
|
weWereOut = NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we leave the bottom or top deselect menu items in
|
|
the current view. This should check to see if the
|
|
current item, if any, has an open submenu. */
|
|
|
|
if (lastLocation.y > [window frame].size.height
|
|
|| lastLocation.y < 0)
|
|
{
|
|
weWereOut = YES;
|
|
[self setHighlightedItemIndex: -1];
|
|
}
|
|
|
|
}
|
|
|
|
/* If the location of the mouse is greater than the width of
|
|
the current window we need to see if we should display a
|
|
submenu. */
|
|
|
|
else if (lastLocation.x > [window frame].size.width)
|
|
{
|
|
NSRect aRect = [self rectOfItemAtIndex: lastIndex];
|
|
if (lastLocation.y > aRect.origin.y
|
|
&& lastLocation.y < aRect.origin.y + aRect.size.height
|
|
&& [[menuv_items_link objectAtIndex: lastIndex]
|
|
hasSubmenu])
|
|
{
|
|
weLeftMenu = YES;
|
|
done = YES;
|
|
}
|
|
else
|
|
{
|
|
if (![[menuv_items_link objectAtIndex: lastIndex] hasSubmenu])
|
|
{
|
|
[self setHighlightedItemIndex: -1];
|
|
lastIndex = index;
|
|
weWereOut = YES;
|
|
[window flushWindow];
|
|
}
|
|
else
|
|
{
|
|
weLeftMenu = YES;
|
|
done = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If the mouse location is less than 0 we moved to the left,
|
|
perhaps into a supermenu? */
|
|
|
|
else if (lastLocation.x < 0)
|
|
{
|
|
if ([menuv_menu supermenu])
|
|
{
|
|
weRightMenu = YES;
|
|
done = YES;
|
|
}
|
|
else
|
|
{
|
|
[self setHighlightedItemIndex: -1];
|
|
lastIndex = index;
|
|
weWereOut = YES;
|
|
[window flushWindow];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXME, Michael. This might be needed... or not?
|
|
/* FIXME this code is just plain nasty.
|
|
NSLog(@"This is the final else... its evil\n");
|
|
if (lastIndex >= 0 && lastIndex < theCount)
|
|
{
|
|
[self setHighlightedItemIndex: -1];
|
|
lastIndex = index;
|
|
weWereOut = YES;
|
|
[window flushWindow];
|
|
}
|
|
*/
|
|
}
|
|
[window flushWindow];
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If we didn't move out of the window to the left or right, and if we
|
|
didn't move beyond the bounds of the menu (?) and if we have a selected
|
|
cell do the following */
|
|
|
|
if (!weLeftMenu && !weRightMenu && !weWereOut
|
|
&& menuv_highlightedItemIndex != -1)
|
|
{
|
|
if (![[menuv_items_link objectAtIndex: menuv_highlightedItemIndex]
|
|
hasSubmenu])
|
|
{
|
|
BOOL finished = NO;
|
|
NSMenu *aMenu = menuv_menu;
|
|
|
|
if (index >= 0 && index < theCount)
|
|
selectedCell = [menuv_items_link objectAtIndex: index];
|
|
else
|
|
selectedCell = nil;
|
|
|
|
[self setHighlightedItemIndex: -1];
|
|
|
|
[menuv_menu performActionForItem:
|
|
[menuv_items_link objectAtIndex: lastIndex]];
|
|
|
|
if (![menuv_menu _isBeholdenToPopUpButton])
|
|
{
|
|
while (!finished)
|
|
{ // "forward"cursive menu find.
|
|
if ([aMenu attachedMenu])
|
|
{
|
|
aMenu = [aMenu attachedMenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
}
|
|
|
|
finished = NO;
|
|
|
|
while (!finished)
|
|
{ // Recursive menu close & deselect.
|
|
if ([aMenu supermenu])
|
|
{
|
|
[[[aMenu supermenu] menuView] setHighlightedItemIndex: -1];
|
|
aMenu = [aMenu supermenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[menuv_menu close];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOL finished = NO;
|
|
NSMenu *aMenu = menuv_menu;
|
|
|
|
if (index >= 0 && index < theCount)
|
|
selectedCell = [menuv_items_link objectAtIndex: index];
|
|
else
|
|
selectedCell = nil;
|
|
|
|
if (![[selectedCell target] isTornOff])
|
|
return;
|
|
|
|
[self setHighlightedItemIndex: -1];
|
|
|
|
/* If we are a menu */
|
|
|
|
if (![menuv_menu _isBeholdenToPopUpButton])
|
|
{
|
|
while (!finished)
|
|
{ // "forward"cursive menu find.
|
|
if ([aMenu attachedMenu])
|
|
{
|
|
aMenu = [aMenu attachedMenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
}
|
|
|
|
finished = NO;
|
|
|
|
while (!finished)
|
|
{ // Recursive menu close & deselect.
|
|
if ([aMenu supermenu])
|
|
{
|
|
[[aMenu menuView] setHighlightedItemIndex: -1];
|
|
aMenu = [aMenu supermenu];
|
|
}
|
|
else
|
|
finished = YES;
|
|
|
|
[window flushWindow];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[menuv_menu close];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/* If the mouse is released and there is no highlighted cell */
|
|
|
|
else if (menuv_highlightedItemIndex == -1
|
|
&& [menuv_menu _isBeholdenToPopUpButton])
|
|
{
|
|
[menuv_menu close];
|
|
}
|
|
|
|
/* We went to the left of the current NSMenuView. BOOL is a misnomer. */
|
|
|
|
else if (weRightMenu)
|
|
{
|
|
NSPoint cP = [window convertBaseToScreen: lastLocation];
|
|
|
|
[self setHighlightedItemIndex: -1];
|
|
|
|
if ([menuv_menu supermenu] && ![menuv_menu isTornOff])
|
|
{
|
|
[self mouseUp:
|
|
[NSEvent mouseEventWithType: NSLeftMouseUp
|
|
location: cP
|
|
modifierFlags: [event modifierFlags]
|
|
timestamp: [event timestamp]
|
|
windowNumber: [window windowNumber]
|
|
context: [event context]
|
|
eventNumber: [event eventNumber]
|
|
clickCount: [event clickCount]
|
|
pressure: [event pressure]]];
|
|
|
|
[[[menuv_menu supermenu] menuView] mouseDown:
|
|
[NSEvent mouseEventWithType: NSLeftMouseDragged
|
|
location: cP
|
|
modifierFlags: [event modifierFlags]
|
|
timestamp: [event timestamp]
|
|
windowNumber: [[[[menuv_menu supermenu] menuView] window] windowNumber]
|
|
context: [event context]
|
|
eventNumber: [event eventNumber]
|
|
clickCount: [event clickCount]
|
|
pressure: [event pressure]]];
|
|
}
|
|
}
|
|
|
|
/* We went to the right of the current NSMenuView. BOOL is a misnomer. */
|
|
|
|
else if (weLeftMenu)
|
|
{ /* The weLeftMenu case */
|
|
NSPoint cP = [window convertBaseToScreen: lastLocation];
|
|
|
|
selectedCell = [menuv_items_link objectAtIndex: lastIndex];
|
|
if ([selectedCell hasSubmenu])
|
|
{
|
|
[self mouseUp:
|
|
[NSEvent mouseEventWithType: NSLeftMouseUp
|
|
location: cP
|
|
modifierFlags: [event modifierFlags]
|
|
timestamp: [event timestamp]
|
|
windowNumber: [window windowNumber]
|
|
context: [event context]
|
|
eventNumber: [event eventNumber]
|
|
clickCount: [event clickCount]
|
|
pressure: [event pressure]]];
|
|
|
|
[[[selectedCell target] menuView] mouseDown:
|
|
[NSEvent mouseEventWithType: NSLeftMouseDragged
|
|
location: cP
|
|
modifierFlags: [event modifierFlags]
|
|
timestamp: [event timestamp]
|
|
windowNumber: [[[[selectedCell target] menuView] window] windowNumber]
|
|
context: [event context]
|
|
eventNumber: [event eventNumber]
|
|
clickCount: [event clickCount]
|
|
pressure: [event pressure]]];
|
|
}
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)mouseDown: (NSEvent *)theEvent
|
|
{
|
|
[self trackWithEvent: theEvent];
|
|
}
|
|
@end
|