mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 20:01:11 +00:00
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:
parent
6123e28d45
commit
464f76e2be
5 changed files with 170 additions and 112 deletions
33
ChangeLog
33
ChangeLog
|
@ -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
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
id _items_link;
|
||||
BOOL _keepAttachedMenus;
|
||||
int _oldHighlightedItemIndex;
|
||||
int _leftBorderOffset;
|
||||
}
|
||||
|
||||
+ (float)menuBarHeight;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue