Add support for popup preferred edge.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@26023 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2008-02-04 14:56:15 +00:00
parent deca87da4a
commit d5e445c620
6 changed files with 223 additions and 164 deletions

View file

@ -1,3 +1,14 @@
2008-02-04 Fred Kiefer <FredKiefer@gmx.de>
* Images/common_3DArrowLeft.tiff,
* Images/common_3DArrowUp.tiff: New files
* Images/GNUmakefile: Install new files.
* Source/NSMenuView.m
(-setWindowFrameForAttachingToRect:...popUpSelectedItem:):
Implement preferred edge handling.
* Source/NSPopUpButtonCell.m: Rewrote handling of preferred edge,
arrow possition and pull down flag.
2008-02-04 Fred Kiefer <FredKiefer@gmx.de>
* Source/GSHorizontalTypesetter.m

View file

@ -34,6 +34,8 @@ imagedir = $(GNUSTEP_LIBRARY)/Images
IMAGE_FILES = \
GNUstep_Images_Copyright \
common_3DArrowUp.tiff \
common_3DArrowLeft.tiff \
common_3DArrowDown.tiff \
common_ArrowDown.tiff \
common_ArrowDownH.tiff \

Binary file not shown.

Binary file not shown.

View file

@ -91,13 +91,13 @@ static NSMapTable *viewInfo = 0;
if (isAppMenu != 0)
{
if (m == [NSApp mainMenu])
{
*isAppMenu = YES;
}
{
*isAppMenu = YES;
}
else
{
*isAppMenu = NO;
}
{
*isAppMenu = NO;
}
}
return [[m menuRepresentation] isHorizontal];
}
@ -123,7 +123,7 @@ _addLeftBorderOffsetToRect(NSRect aRect)
if (viewInfo == 0)
{
viewInfo = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 20);
NSNonOwnedPointerMapValueCallBacks, 20);
}
}
@ -137,7 +137,7 @@ _addLeftBorderOffsetToRect(NSRect aRect)
height = [font boundingRectForFont].size.height;
if (height < 22)
height = 22;
height = 22;
}
return height;
@ -328,7 +328,7 @@ _addLeftBorderOffsetToRect(NSRect aRect)
_cellSize = NSMakeSize (r.size.width * 10., r.size.height + 3.);
if (_cellSize.height < 20)
_cellSize.height = 20;
_cellSize.height = 20;
[self setNeedsSizing: YES];
}
@ -919,7 +919,7 @@ _addLeftBorderOffsetToRect(NSRect aRect)
NSRect theRect;
theRect.origin.y
= _cellSize.height * ([_itemCells count] - index - 1);
= _cellSize.height * ([_itemCells count] - index - 1);
theRect.origin.x = _leftBorderOffset;
theRect.size = _cellSize;
@ -1020,9 +1020,9 @@ _addLeftBorderOffsetToRect(NSRect aRect)
}
- (void) setWindowFrameForAttachingToRect: (NSRect)screenRect
onScreen: (NSScreen*)screen
preferredEdge: (NSRectEdge)edge
popUpSelectedItem: (int)selectedItemIndex
onScreen: (NSScreen*)screen
preferredEdge: (NSRectEdge)edge
popUpSelectedItem: (int)selectedItemIndex
{
NSRect r;
NSRect cellFrame;
@ -1050,37 +1050,48 @@ _addLeftBorderOffsetToRect(NSRect aRect)
float f;
if (_horizontal == NO)
{
f = screenRect.size.height * (items - 1);
screenFrame.size.height += f + _leftBorderOffset;
screenFrame.origin.y -= f;
screenFrame.size.width += _leftBorderOffset;
screenFrame.origin.x -= _leftBorderOffset;
// Compute position for popups, if needed
if (selectedItemIndex != -1)
{
screenFrame.origin.y
+= screenRect.size.height * selectedItemIndex;
}
}
{
f = screenRect.size.height * (items - 1);
screenFrame.size.height += f + _leftBorderOffset;
screenFrame.origin.y -= f;
screenFrame.size.width += _leftBorderOffset;
screenFrame.origin.x -= _leftBorderOffset;
// Compute position for popups, if needed
if (selectedItemIndex != -1)
{
screenFrame.origin.y
+= screenRect.size.height * selectedItemIndex;
}
}
else
{
f = screenRect.size.width * (items - 1);
screenFrame.size.width += f;
// Compute position for popups, if needed
if (selectedItemIndex != -1)
{
screenFrame.origin.x -= screenRect.size.width * selectedItemIndex;
}
}
{
f = screenRect.size.width * (items - 1);
screenFrame.size.width += f;
// Compute position for popups, if needed
if (selectedItemIndex != -1)
{
screenFrame.origin.x -= screenRect.size.width * selectedItemIndex;
}
}
}
// Update position, if needed, using the preferredEdge
if (edge == NSMaxYEdge)
{
screenFrame.origin.y += screenRect.size.height;
}
else if (edge == NSMaxXEdge)
{
screenFrame.origin.x += screenRect.size.width;
}
else if (edge == NSMinXEdge)
{
screenFrame.origin.x -= screenRect.size.width;
}
// Get the frameRect
r = [NSWindow frameRectForContentRect: screenFrame
styleMask: [_window styleMask]];
// Update position,if needed, using the preferredEdge;
// TODO
styleMask: [_window styleMask]];
// Set the window frame
[_window setFrame: r display: NO];

View file

@ -37,10 +37,11 @@
#include "AppKit/NSPopUpButtonCell.h"
#include "AppKit/NSWindow.h"
/* The image to use in a specific popupbutton is
* _pbc_image[_pbcFlags.pullsDown]; that is, _pbc_image[0] if it is a
* popup menu, _pbc_image[1] if it is a pulls down list. */
static NSImage *_pbc_image[2];
/* The image to use in a specific popupbutton depends on type and
* preferred edge; that is, _pbc_image[0] if it is a
* popup menu, _pbc_image[1] if it is a pulls down list pointing down,
* and so on. */
static NSImage *_pbc_image[5];
@implementation NSPopUpButtonCell
+ (void) initialize
@ -50,6 +51,9 @@ static NSImage *_pbc_image[2];
[self setVersion: 2];
ASSIGN(_pbc_image[0], [NSImage imageNamed: @"common_Nibble"]);
ASSIGN(_pbc_image[1], [NSImage imageNamed: @"common_3DArrowDown"]);
ASSIGN(_pbc_image[2], [NSImage imageNamed: @"common_3DArrowRight"]);
ASSIGN(_pbc_image[3], [NSImage imageNamed: @"common_3DArrowUp"]);
ASSIGN(_pbc_image[4], [NSImage imageNamed: @"common_3DArrowLeft"]);
}
}
@ -85,7 +89,7 @@ static NSImage *_pbc_image[2];
* reciever will be a pulldown button.
*/
- (id) initTextCell: (NSString *)stringValue
pullsDown: (BOOL)flag
pullsDown: (BOOL)flag
{
NSMenu *menu;
@ -97,6 +101,8 @@ static NSImage *_pbc_image[2];
[self setPullsDown: flag];
_pbcFlags.usesItemFromMenu = YES;
[self setPreferredEdge: NSMinYEdge];
[self setArrowPosition: NSPopUpArrowAtCenter];
if ([stringValue length] > 0)
{
@ -178,21 +184,13 @@ static NSImage *_pbc_image[2];
NSMenuItem *item = _menuItem;
[self setMenuItem: nil];
_pbcFlags.pullsDown = flag;
[self setAltersStateOfSelectedItem: !flag];
if (flag && !_pbcFlags.pullsDown
&& _pbcFlags.altersStateOfSelectedItem)
{
[[self selectedItem] setState: NSOffState];
}
if (!flag)
{
// pop up
[self setArrowPosition: NSPopUpArrowAtCenter];
[self setPreferredEdge: NSMinYEdge];
}
else
{
// pull down
[self setArrowPosition: NSPopUpArrowAtBottom];
[self setPreferredEdge: NSMaxYEdge];
}
_pbcFlags.pullsDown = flag;
[self setMenuItem: item];
}
@ -309,7 +307,7 @@ static NSImage *_pbc_image[2];
- (void) addItemWithTitle: (NSString *)title
{
[self insertItemWithTitle: title
atIndex: [_menu numberOfItems]];
atIndex: [_menu numberOfItems]];
}
/**
@ -317,8 +315,8 @@ static NSImage *_pbc_image[2];
*/
- (void) addItemsWithTitles: (NSArray *)titles
{
unsigned c = [titles count];
unsigned i;
unsigned c = [titles count];
unsigned i;
for (i = 0; i < c; i++)
{
@ -351,9 +349,9 @@ static NSImage *_pbc_image[2];
index = count;
anItem = [_menu insertItemWithTitle: title
action: NULL
keyEquivalent: @""
atIndex: index];
action: NULL
keyEquivalent: @""
atIndex: index];
/* Disable showing the On/Off/Mixed state. We change the state of
menu items when selected, according to the doc, but we don't want
it to appear on the screen. */
@ -492,7 +490,7 @@ static NSImage *_pbc_image[2];
*/
- (id <NSMenuItem>) lastItem
{
int end = [_menu numberOfItems] - 1;
int end = [_menu numberOfItems] - 1;
if (end < 0)
return nil;
@ -517,11 +515,47 @@ static NSImage *_pbc_image[2];
if ([object respondsToSelector: @selector(intValue)])
{
int i = [object intValue];
[self selectItemAtIndex: i];
}
}
- (NSImage *) _currentArrowImage
{
if (_pbcFlags.pullsDown)
{
if (_pbcFlags.arrowPosition == NSPopUpNoArrow)
{
return nil;
}
if (_pbcFlags.preferredEdge == NSMinYEdge)
{
return _pbc_image[1];
}
else if (_pbcFlags.preferredEdge == NSMaxXEdge)
{
return _pbc_image[2];
}
else if (_pbcFlags.preferredEdge == NSMaxYEdge)
{
return _pbc_image[3];
}
else if (_pbcFlags.preferredEdge == NSMinXEdge)
{
return _pbc_image[4];
}
else
{
return _pbc_image[1];
}
}
else
{
return _pbc_image[0];
}
}
- (void) setImage: (NSImage *)anImage
{
// Do nothing as the image is determined by the current item
@ -534,19 +568,7 @@ static NSImage *_pbc_image[2];
if (_menuItem == item)
return;
if (_pbcFlags.arrowPosition == NSPopUpArrowAtBottom)
{
image = _pbc_image[1];
}
else if (_pbcFlags.arrowPosition == NSPopUpArrowAtCenter)
{
image = _pbc_image[0];
}
else
{
// No image for NSPopUpNoArrow
image = nil;
}
image = [self _currentArrowImage];
if ([_menuItem image] == image)
{
@ -554,7 +576,7 @@ static NSImage *_pbc_image[2];
}
//[super setMenuItem: item];
ASSIGN (_menuItem, item);
ASSIGN(_menuItem, item);
if ([_menuItem image] == nil)
{
@ -570,9 +592,9 @@ static NSImage *_pbc_image[2];
if (_selectedItem != nil)
{
if (_pbcFlags.altersStateOfSelectedItem)
{
[_selectedItem setState: NSOffState];
}
{
[_selectedItem setState: NSOffState];
}
}
_selectedItem = item;
@ -581,13 +603,13 @@ static NSImage *_pbc_image[2];
{
if (_pbcFlags.altersStateOfSelectedItem)
{
[_selectedItem setState: NSOnState];
[_selectedItem setState: NSOnState];
}
}
/* Set the item in the menu */
[[_menu menuRepresentation] setHighlightedItemIndex:
[_menu indexOfItem: _selectedItem]];
[_menu indexOfItem: _selectedItem]];
}
- (void) selectItemAtIndex: (int)index
@ -616,22 +638,22 @@ static NSImage *_pbc_image[2];
if (_pbcFlags.pullsDown)
{
if ([_menu numberOfItems] == 0)
{
anItem = nil;
}
{
anItem = nil;
}
else
{
anItem = [_menu itemAtIndex: 0];
}
{
anItem = [_menu itemAtIndex: 0];
}
}
else
{
anItem = [_menu itemWithTitle: aString];
if (anItem == nil)
{
{
[self addItemWithTitle: aString];
anItem = [_menu itemWithTitle: aString];
}
anItem = [_menu itemWithTitle: aString];
}
}
[self selectItem: anItem];
}
@ -672,14 +694,14 @@ static NSImage *_pbc_image[2];
if (index < 0)
{
// If no item is highighted, display the selected one, if there is one.
index = [self indexOfSelectedItem];
}
// If no item is highighted, display the selected one, if there is one.
index = [self indexOfSelectedItem];
}
else
{
// Selected the highlighted item
[self selectItemAtIndex: index];
}
// Selected the highlighted item
[self selectItemAtIndex: index];
}
}
if ((index >= 0) && ([_menu numberOfItems] > index))
@ -715,9 +737,9 @@ static NSImage *_pbc_image[2];
*/
- (NSArray *) itemTitles
{
unsigned count = [_menu numberOfItems];
id items[count];
unsigned i;
unsigned count = [_menu numberOfItems];
id items[count];
unsigned i;
[[_menu itemArray] getObjects: items];
for (i = 0; i < count; i++)
@ -745,18 +767,18 @@ static NSImage *_pbc_image[2];
* Attach popup
*/
- (void) attachPopUpWithFrame: (NSRect)cellFrame
inView: (NSView *)controlView
inView: (NSView *)controlView
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSWindow *cvWin = [controlView window];
NSMenuView *mr = [_menu menuRepresentation];
int selectedItem;
[nc postNotificationName: NSPopUpButtonCellWillPopUpNotification
object: self];
object: self];
[nc postNotificationName: NSPopUpButtonWillPopUpNotification
object: controlView];
object: controlView];
// Convert to Screen Coordinates
cellFrame = [controlView convertRect: cellFrame toView: nil];
@ -792,7 +814,7 @@ static NSImage *_pbc_image[2];
*/
- (void) dismissPopUp
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver: self
name: NSMenuDidSendActionNotification
@ -816,8 +838,8 @@ static NSImage *_pbc_image[2];
}
- (BOOL) trackMouse: (NSEvent *)theEvent
inRect: (NSRect)cellFrame
ofView: (NSView *)controlView
inRect: (NSRect)cellFrame
ofView: (NSView *)controlView
untilMouseUp: (BOOL)untilMouseUp
{
NSMenuView *mr = [[self menu] menuRepresentation];
@ -836,7 +858,7 @@ static NSImage *_pbc_image[2];
// Attach the popUp
[self attachPopUpWithFrame: cellFrame
inView: controlView];
inView: controlView];
p = [[controlView window] convertBaseToScreen: [theEvent locationInWindow]];
p = [menuWindow convertScreenToBase: p];
@ -844,15 +866,18 @@ static NSImage *_pbc_image[2];
// Process events; we start menu events processing by converting
// this event to the menu window, and sending it there.
e = [NSEvent mouseEventWithType: [theEvent type]
location: p
modifierFlags: [theEvent modifierFlags]
timestamp: [theEvent timestamp]
windowNumber: [menuWindow windowNumber]
context: [theEvent context]
eventNumber: [theEvent eventNumber]
clickCount: [theEvent clickCount]
pressure: [theEvent pressure]];
[NSApp sendEvent: e];
location: p
modifierFlags: [theEvent modifierFlags]
timestamp: [theEvent timestamp]
windowNumber: [menuWindow windowNumber]
context: [theEvent context]
eventNumber: [theEvent eventNumber]
clickCount: [theEvent clickCount]
pressure: [theEvent pressure]];
// Send the event directly to the popup window, as it may not be located
// at the event position.
[mr mouseDown: e];
// End of mouse tracking here -- dismiss popup
// No synchronization needed here
@ -879,7 +904,7 @@ static NSImage *_pbc_image[2];
* This drawing uses the same code that is used to draw cells in the menu.
*/
- (void) drawInteriorWithFrame: (NSRect)cellFrame
inView: (NSView*)controlView
inView: (NSView*)controlView
{
BOOL new = NO;
@ -922,10 +947,16 @@ static NSImage *_pbc_image[2];
NSSize titleSize;
int i, count;
NSString *title;
NSImage *image;
count = [_menu numberOfItems];
imageSize = [_pbc_image[_pbcFlags.pullsDown] size];
image = [self _currentArrowImage];
if (image)
imageSize = [image size];
else
imageSize = NSZeroSize;
s = NSMakeSize(0, imageSize.height);
if (count == 0)
@ -992,9 +1023,9 @@ static NSImage *_pbc_image[2];
// encode the menu, if present.
if (_menu != nil)
{
[aCoder encodeObject: _menu forKey: @"NSMenu"];
}
{
[aCoder encodeObject: _menu forKey: @"NSMenu"];
}
}
else
{
@ -1019,33 +1050,36 @@ static NSImage *_pbc_image[2];
NSMenu *menu;
self = [super initWithCoder: aDecoder];
if (!self)
return nil;
if ([aDecoder allowsKeyedCoding])
{
if ([aDecoder containsValueForKey: @"NSAltersState"])
{
BOOL alters = [aDecoder decodeBoolForKey: @"NSAltersState"];
[self setAltersStateOfSelectedItem: alters];
}
BOOL alters = [aDecoder decodeBoolForKey: @"NSAltersState"];
[self setAltersStateOfSelectedItem: alters];
}
if ([aDecoder containsValueForKey: @"NSUsesItemFromMenu"])
{
BOOL usesItem = [aDecoder decodeBoolForKey: @"NSUsesItemFromMenu"];
[self setUsesItemFromMenu: usesItem];
}
BOOL usesItem = [aDecoder decodeBoolForKey: @"NSUsesItemFromMenu"];
[self setUsesItemFromMenu: usesItem];
}
if ([aDecoder containsValueForKey: @"NSArrowPosition"])
{
NSPopUpArrowPosition position = [aDecoder decodeIntForKey:
@"NSArrowPosition"];
[self setArrowPosition: position];
}
NSPopUpArrowPosition position = [aDecoder decodeIntForKey:
@"NSArrowPosition"];
[self setArrowPosition: position];
}
if ([aDecoder containsValueForKey: @"NSPreferredEdge"])
{
NSRectEdge edge = [aDecoder decodeIntForKey: @"NSPreferredEdge"];
[self setPreferredEdge: edge];
}
NSRectEdge edge = [aDecoder decodeIntForKey: @"NSPreferredEdge"];
[self setPreferredEdge: edge];
}
menu = [aDecoder decodeObjectForKey: @"NSMenu"];
[self setMenu: nil];
@ -1056,14 +1090,14 @@ static NSImage *_pbc_image[2];
int flag;
id<NSMenuItem> selectedItem;
int version = [aDecoder versionForClassName:
@"NSPopUpButtonCell"];
@"NSPopUpButtonCell"];
menu = [aDecoder decodeObject];
/*
FIXME: This same ivar already gets set in NSCell initWithCoder,
but there it is used directly not via a method call. So here we first
unset it and than set it again as our setMenu: method tries to optimize
duplicate calls.
FIXME: This same ivar already gets set in NSCell initWithCoder,
but there it is used directly not via a method call. So here we first
unset it and than set it again as our setMenu: method tries to optimize
duplicate calls.
*/
[self setMenu: nil];
[self setMenu: menu];
@ -1081,25 +1115,26 @@ static NSImage *_pbc_image[2];
if (version < 2)
{
int i;
// Not the stored format did change but the interpretation of it.
// in version 1 most of the ivars were not used, so their values may
// be arbitray. We overwrite them with valid settings.
[self setPullsDown: _pbcFlags.pullsDown];
_pbcFlags.usesItemFromMenu = YES;
for (i = 0; i < [_menu numberOfItems]; i++)
{
id <NSMenuItem> anItem = [menu itemAtIndex: i];
[anItem setOnStateImage: nil];
[anItem setMixedStateImage: nil];
}
[self setEnabled: YES];
}
int i;
// Not the stored format did change but the interpretation of it.
// in version 1 most of the ivars were not used, so their values may
// be arbitray. We overwrite them with valid settings.
[self setPullsDown: _pbcFlags.pullsDown];
_pbcFlags.usesItemFromMenu = YES;
for (i = 0; i < [_menu numberOfItems]; i++)
{
id <NSMenuItem> anItem = [menu itemAtIndex: i];
[anItem setOnStateImage: nil];
[anItem setMixedStateImage: nil];
}
[self setEnabled: YES];
}
[self selectItem: selectedItem];
}
return self;
}