Improvements for popupbuttons.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@12946 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Michael Silva 2002-03-01 23:25:06 +00:00
parent 6123e28d45
commit 464f76e2be
5 changed files with 170 additions and 112 deletions

View file

@ -1,3 +1,36 @@
2002-03-01 Michael Hanni <mhanni@yahoo.com>
First cut at improving NSPopUpButton/Cell.
* Source/NSMenuItemCell.m
([drawBorderAndBackgroundWithFrame:inView:]): Remove special
popupbutton case.
([drawInteriorWithFrame:inView:]): ditto.
* Headers/NSMenuView.h: added _leftBorderOffset int.
* Source/NSMenuView.m: added static function
_addLeftBorderOffsetToRect()
([initWithFrame:]): init left offset value to 1 (default for a
menu.)
([sizeToFit]): change left offset value to 0 if we are a
popup. Use this value to set the correct frame size. Before when
the menuview was sizeToFit'ed the menuWindow was resized by an
additional pixel when we were a popupbutton.
([innerRect]): use left offset value to return the correct rect.
([rectOfItemAtIndex:]): ditto.
([indexOfItemAtPoint:]): use _addLeftBorderOffsetToRect() to
correct the rect we use to calculate the event area for a
menuItemCell in a normal menu.
([setNeedsDisplayForItemAtIndex:]): ditto.
([drawRect:]): Modified to not draw a border line on the left side
if we are a popup.
* Source/NSPopUpButtonCell.m: added some comments for further
fixes.
([drawWithFrame:inView:]): removed all the code in favor of
having the NSMenuItemCell of the selected item draw the
popupbuttoncell.
([drawInteriorWithFrame:inView:]): removed everything but the
responder status code (this is still a FIXME).
2002-03-01 Pierre-Yves Rivaille <pyrivail@ens-lyon.fr>
* Source/NSBundleAdditions.m

View file

@ -64,6 +64,7 @@
id _items_link;
BOOL _keepAttachedMenus;
int _oldHighlightedItemIndex;
int _leftBorderOffset;
}
+ (float)menuBarHeight;

View file

@ -371,11 +371,6 @@ static NSImage *arrowImageH = nil;
[controlView lockFocus];
if (_mcell_belongs_to_popupbutton)
{
cellFrame.origin.x--;
}
if (_cell.is_highlighted && (_highlightsByMask & NSPushInCellMask))
{
NSDrawGrayBezel(cellFrame, NSZeroRect);
@ -576,16 +571,7 @@ static NSImage *arrowImageH = nil;
// Set cell's background color
[_backgroundColor set];
if (_mcell_belongs_to_popupbutton)
{
cellFrame.origin.x--;
NSRectFill(cellFrame);
cellFrame.origin.x++;
}
else
{
NSRectFill(cellFrame);
}
NSRectFill(cellFrame);
/*
* Determine the image and the title that will be

View file

@ -36,6 +36,22 @@
@implementation NSMenuView
static NSRect
_addLeftBorderOffsetToRect(NSRect aRect, BOOL isHorizontal)
{
if (isHorizontal == NO)
{
aRect.origin.x--;
aRect.size.width++;
}
else
{
aRect.origin.y--;
aRect.size.height++;
}
return aRect;
}
/*
* Class methods.
*/
@ -80,6 +96,12 @@
_highlightedItemIndex = -1;
_horizontalEdgePad = 4.;
/* Set the necessary offset for the menuView. That is, how many pixels
* do we need for our left side border line. For regular menus this
* equals 1, for popups it is 0.
*/
_leftBorderOffset = 1;
// Create an array to store our menu item cells.
_itemCells = [NSMutableArray new];
@ -396,6 +418,17 @@
float neededStateImageWidth = 0.0;
float accumulatedOffset = 0.0;
/* Set the necessary offset for the menuView. That is, how many pixels
* do we need for our left side border line. For regular menus this
* equals 1, for popups it is 0.
*
* Why here? I could not think of a better place. I figure that everyone
* should sizeToFit their popup/menu before using it so we should get
* this set properly fairly early.
*/
if ([_menu _ownedByPopUp])
_leftBorderOffset = 0;
// TODO: Optimize this loop.
for (i = 0; i < howMany; i++)
{
@ -472,13 +505,13 @@
if (_horizontal == NO)
{
[self setFrameSize: NSMakeSize(_cellSize.width + 1,
[self setFrameSize: NSMakeSize(_cellSize.width + _leftBorderOffset,
(howMany * _cellSize.height))];
}
else
{
[self setFrameSize: NSMakeSize((howMany * _cellSize.width),
_cellSize.height + 1)];
_cellSize.height + _leftBorderOffset)];
}
_needsSizing = NO;
@ -536,13 +569,13 @@
{
if (_horizontal == NO)
{
return NSMakeRect(_bounds.origin.x + 1, _bounds.origin.y,
_bounds.size.width - 1, _bounds.size.height);
return NSMakeRect(_bounds.origin.x + _leftBorderOffset, _bounds.origin.y,
_bounds.size.width - _leftBorderOffset, _bounds.size.height);
}
else
{
return NSMakeRect(_bounds.origin.x, _bounds.origin.y + 1,
_bounds.size.width, _bounds.size.height - 1);
return NSMakeRect(_bounds.origin.x, _bounds.origin.y + _leftBorderOffset,
_bounds.size.width, _bounds.size.height - _leftBorderOffset);
}
}
@ -554,19 +587,29 @@
{
[self sizeToFit];
}
/* When we are a normal menu we fiddle with the origin so that the item
* rect is shifted 1 pixel over so we do not draw on the heavy line at
* origin.x = 0. However, for popups we don't want this modification of
* our rect so our _leftBorderOffset = 0 (set in sizeToFit).
*/
if (_horizontal == NO)
{
theRect.origin.y = _bounds.size.height - (_cellSize.height * (index + 1));
theRect.origin.x = 1;
theRect.origin.x = _leftBorderOffset;
}
else
{
theRect.origin.x = _bounds.size.width - (_cellSize.width * (index + 1));
theRect.origin.y = 1;
theRect.origin.y = _leftBorderOffset;
}
theRect.size = _cellSize;
/* NOTE: This returns the correct NSRect for drawing cells, but nothing
* else (unless we are a popup). This rect will have to be modified for
* event calculation, etc..
*/
return theRect;
}
@ -579,17 +622,13 @@
{
NSRect aRect = [self rectOfItemAtIndex: i];
// Add the border to the rectangle
if (_horizontal == NO)
{
aRect.origin.x--;
aRect.size.width++;
}
else
{
aRect.origin.y--;
aRect.size.height++;
}
/* We need to modify the rect to take into account the modifications
* to origin made by [-rectOfItemAtIndex:] in order to return an
* item clicked at the left hand margin. However, for a popup this
* calculation is unnecessary since we have no extra margin.
*/
if (![_menu _ownedByPopUp])
aRect = _addLeftBorderOffsetToRect(aRect, _horizontal);
if (NSMouseInRect(point, aRect, NO))
return i;
@ -600,18 +639,17 @@
- (void) setNeedsDisplayForItemAtIndex: (int)index
{
NSRect aRect = [self rectOfItemAtIndex: index];
NSRect aRect;
if (_horizontal == NO)
{
aRect.origin.x--;
aRect.size.width++;
}
else
{
aRect.origin.y--;
aRect.size.height++;
}
aRect = [self rectOfItemAtIndex: index];
/* We need to modify the rect to take into account the modifications
* to origin made by [-rectOfItemAtIndex:] in order to return an
* item clicked at the left hand margin. However, for a popup this
* calculation is unnecessary since we have no extra margin.
*/
if (![_menu _ownedByPopUp])
aRect = _addLeftBorderOffsetToRect(aRect, _horizontal);
[self setNeedsDisplayInRect: aRect];
}
@ -733,24 +771,29 @@
int i;
int howMany = [_itemCells count];
NSGraphicsContext *ctxt = GSCurrentContext();
/* For popupButtons we do not want this dark line. */
// Draw a dark gray line at the left of the menu item cells.
DPSgsave(ctxt);
DPSsetlinewidth(ctxt, 1);
DPSsetgray(ctxt, NSDarkGray);
if (_horizontal == NO)
if (![_menu _ownedByPopUp])
{
DPSmoveto(ctxt, NSMinX(_bounds), NSMinY(_bounds));
DPSrlineto(ctxt, 0, _bounds.size.height);
NSGraphicsContext *ctxt = GSCurrentContext();
// Draw a dark gray line at the left of the menu item cells.
DPSgsave(ctxt);
DPSsetlinewidth(ctxt, 1);
DPSsetgray(ctxt, NSDarkGray);
if (_horizontal == NO)
{
DPSmoveto(ctxt, NSMinX(_bounds), NSMinY(_bounds));
DPSrlineto(ctxt, 0, _bounds.size.height);
}
else
{
DPSmoveto(ctxt, NSMinX(_bounds), NSMaxY(_bounds));
DPSrlineto(ctxt, _bounds.size.width, 0);
}
DPSstroke(ctxt);
DPSgrestore(ctxt);
}
else
{
DPSmoveto(ctxt, NSMinX(_bounds), NSMaxY(_bounds));
DPSrlineto(ctxt, _bounds.size.width, 0);
}
DPSstroke(ctxt);
DPSgrestore(ctxt);
// Draw the menu cells.
for (i = 0; i < howMany; i++)

View file

@ -485,67 +485,58 @@ static NSImage *_pbc_image[2];
* What would be nice and natural is to make this drawing using the same code
* that is used to draw cells in the menu.
* This looks like a mess to do in this framework.
*
* Well, here is an attempt to make this work.
*/
- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
{
NSMenuItemCell *aCell;
// Save last view drawn to
if (_control_view != controlView)
_control_view = controlView;
// Transparent buttons never draw
if (_buttoncell_is_transparent)
return;
// Do nothing if cell's frame rect is zero
if (NSIsEmptyRect(cellFrame))
return;
// Do nothing if the window is deferred
if ([[controlView window] gState] == 0)
return;
/* Get the NSMenuItemCell of the selected item */
aCell = [[_menu menuRepresentation] menuItemCellForItemAtIndex: [self indexOfSelectedItem]];
/* Turn off highlighting so the NSPopUpButton looks right */
[aCell setHighlighted: NO];
[aCell drawWithFrame: cellFrame inView: controlView];
/* Draw our own interior so we pick up our dotted frame */
[self drawInteriorWithFrame: cellFrame inView: controlView];
/* Rehighlight item for consistency */
[aCell setHighlighted: YES];
}
/* FIXME: This needs to be removed in favor of allowing the cell to draw
* our NSDottedRect.
*/
- (void) drawInteriorWithFrame: (NSRect)cellFrame
inView: (NSView*)view
{
NSSize size;
NSPoint position;
NSImage *anImage;
// Save last view drawn to
if (_control_view != view)
_control_view = view;
// Transparent buttons never draw
if (_buttoncell_is_transparent)
return;
[view lockFocus];
// [super drawWithFrame: cellFrame inView: view];
cellFrame = [self drawingRectForBounds: cellFrame];
if (_cell.is_bordered || _cell.is_bezeled)
{
cellFrame.origin.x += 3;
cellFrame.size.width -= 6;
cellFrame.origin.y += 1;
cellFrame.size.height -= 2;
}
// Skip 5 points from left side
// cellFrame.origin.x += 5;
// cellFrame.size.width -= 5;
cellFrame.origin.x += 2;
cellFrame.size.width -= 2;
[self _drawText: [self titleOfSelectedItem] inFrame: cellFrame];
cellFrame.origin.x -= 4;
cellFrame.size.width += 4;
anImage = _pbc_image[_pbcFlags.pullsDown];
/* NB: If we are drawing here, then the control can't be selected */
[anImage setBackgroundColor: [NSColor controlBackgroundColor]];
size = [anImage size];
position.x = cellFrame.origin.x + cellFrame.size.width - size.width;
position.y = MAX(NSMidY(cellFrame) - (size.height/2.), 0.);
/*
* Images are always drawn with their bottom-left corner at the origin
* so we must adjust the position to take account of a flipped view.
*/
if ([view isFlipped])
position.y += size.height;
[anImage compositeToPoint: position operation: NSCompositeCopy];
if (_cell.is_bordered || _cell.is_bezeled)
{
cellFrame.origin.x -= 1;
cellFrame.size.width += 2;
}
cellFrame.origin.y -= 1;
cellFrame.size.height += 2;
cellFrame.size.width += 2;
if (_cell.shows_first_responder
&& [[view window] firstResponder] == view)
NSDottedFrameRect(cellFrame);
@ -553,6 +544,10 @@ static NSImage *_pbc_image[2];
[view unlockFocus];
}
/* FIXME: this method needs to be rewritten to be something like
* NSMenuView's sizeToFit. That way if you call [NSPopUpButton sizeToFit];
* you will get the absolutely correct cellSize.
*/
- (NSSize) cellSize
{
NSSize s;