Apply patch from Eric Wasylishen, add live resize and

live moving for table columns if GSUseGhostResize is
set to NO.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@28376 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicolas Roard 2009-06-30 00:40:57 +00:00
parent a145faad11
commit 4905a0de91
2 changed files with 202 additions and 203 deletions

View file

@ -1,3 +1,9 @@
2009-06-30 Nicolas Roard <nicolas@roard.com>
* Source/NSTableHeaderView.m: Apply patch from Eric
Wasylishen <ewasylishen@gmail.com>, add live resize and
live moving for table columns if GSUseGhostResize is
set to NO.
2009-06-28 23:46-EDT Gregory John Casamento <greg.casamento@gmail.com>
* Source/NSTextView.m (-initWithCoder:): Retain the text

View file

@ -32,6 +32,7 @@
#include <Foundation/NSArray.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSRunLoop.h>
#include <Foundation/NSUserDefaults.h>
#include "AppKit/NSTableHeaderCell.h"
#include "AppKit/NSTableHeaderView.h"
#include "AppKit/NSTableColumn.h"
@ -270,6 +271,13 @@
}
}
/**
* In -mouseDown we intercept the mouse event to handle the
* colum resize and rearrangement. Resizing or moving columns
* will do a live resize/move of the columns by default. Users can revert to
* a "ghost" resize/move indicator by doing:
* defaults write NSGlobalDomain GSUseGhostResize YES
*/
- (void) mouseDown: (NSEvent*)event
{
NSPoint location = [event locationInWindow];
@ -342,184 +350,145 @@
{
/* Width of the highlighted area. */
const float divWidth = 4;
/* Dragging limits */
float minCoord;
float maxCoord;
float minAbsCoord;
float maxAbsCoord;
float minVisCoord;
float maxVisCoord;
NSRect tvRect;
NSPoint unconverted;
NSArray *columns;
/* Coordinates of visible part of table */
float minVisCoord = NSMinX([self visibleRect]);
float maxVisCoord = NSMaxX([self visibleRect]);
NSPoint unconverted = [event locationInWindow];
NSArray *columns = [_tableView tableColumns];
/* Column on the left of resizing bound */
NSTableColumn *column;
NSRect rectLow = [self headerRectOfColumn: _resizedColumn];
/* Old highlighted rect, used to avoid useless redrawing */
NSRect oldRect = NSZeroRect;
/* Current highlighted rect */
NSRect r;
NSTableColumn *column = [columns objectAtIndex: _resizedColumn];
const float columnMinX = NSMinX([self headerRectOfColumn: _resizedColumn]);
const float columnMinWidth = [column minWidth];
const float columnMaxWidth = [column maxWidth];
float newColumnWidth;
float newColumnMaxX;
NSRect oldHighlightRect;
NSRect highlightRect = [self visibleRect];
highlightRect.size.width = divWidth;
/* Mouse position */
float p;
float q;
BOOL outside = NO;
/* YES if some highlighting was done and needs to be undone */
BOOL lit = NO;
/* YES if some dragging was actually done - to avoid
retiling/redrawing the table if no dragging is done */
BOOL dragged = NO;
NSEvent *e;
NSDate *farAway = [NSDate distantFuture];
unsigned int eventMask = NSLeftMouseUpMask | NSLeftMouseDraggedMask
| NSPeriodicMask;
/* Determine dragging limits, constrained to visible rect */
rect = [self visibleRect];
minVisCoord = MAX (NSMinX (rectLow), NSMinX (rect)) + divWidth;
maxVisCoord = NSMaxX (rect) - divWidth;
BOOL liveResize = ![[NSUserDefaults standardUserDefaults] boolForKey: @"GSUseGhostResize"];
/* Then constrain to minimum and maximum column width if any */
columns = [_tableView tableColumns];
/* Column at the left */
column = [columns objectAtIndex: _resizedColumn];
if ([column isResizable] == NO)
{
_resizedColumn = -1;
return;
}
/* We use p as a temporary variable for a while */
minAbsCoord = NSMinX (rectLow) + [column minWidth];
maxAbsCoord = NSMinX (rectLow) + [column maxWidth];
minCoord = MAX (minAbsCoord, minVisCoord);
maxCoord = MIN (maxAbsCoord, maxVisCoord);
/* Do we need to check that we already fit into this area ?
We should */
[self lockFocus];
if (!liveResize)
{
oldHighlightRect = NSZeroRect;
[self lockFocus];
[[NSColor lightGrayColor] set];
}
[[NSRunLoop currentRunLoop] limitDateForMode: NSEventTrackingRunLoopMode];
[[NSColor lightGrayColor] set];
r.size.width = divWidth;
r.size.height = NSHeight (rect);
r.origin.y = NSMinY (rect);
[NSEvent startPeriodicEventsAfterDelay: 0.05 withPeriod: 0.05];
e = [NSApp nextEventMatchingMask: eventMask
untilDate: farAway
untilDate: [NSDate distantFuture]
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
/* Safety assignment to make sure p is never left
unitialized - should make no difference with current code
but anyway */
p = NSMaxX (rectLow);
while ([e type] != NSLeftMouseUp)
{
if ([e type] != NSPeriodic)
{
dragged = YES;
unconverted = [e locationInWindow];
p = [self convertPoint: unconverted fromView: nil].x;
q = p;
if (p > maxVisCoord || p < minVisCoord)
{
outside = YES;
}
else
{
outside = NO;
}
if (p < minCoord)
{
p = minCoord;
}
else if (p > maxCoord)
{
p = maxCoord;
}
r.origin.x = p - (divWidth / 2.);
if (!outside && NSEqualRects(r, oldRect) == NO)
{
if (lit == YES)
{
NSHighlightRect (oldRect);
}
NSHighlightRect (r);
[_window flushWindow];
lit = YES;
oldRect = r;
}
}
else
p = [self convertPoint: unconverted fromView: nil].x;
minVisCoord = NSMinX([self visibleRect]);
maxVisCoord = NSMaxX([self visibleRect]);
/* newColumnWidth is always positive, since we always resize
the column to the left of the mouse pointer */
newColumnWidth = (p - columnMinX);
newColumnWidth = MAX(MIN(newColumnWidth, columnMaxWidth), columnMinWidth);
newColumnMaxX = columnMinX + newColumnWidth;
if (liveResize && [column width] != newColumnWidth)
{
if (outside)
[_tableView _userResizedTableColumn: _resizedColumn
width: newColumnWidth];
}
else if (!liveResize)
{
highlightRect.origin.x = newColumnMaxX;
/* Only draw the divider if it is not the same as the currently
drawn one, and lies within the header view area */
if (!NSEqualRects(oldHighlightRect,highlightRect) &&
highlightRect.origin.x > [self visibleRect].origin.x &&
highlightRect.origin.x + divWidth < [self visibleRect].origin.x + [self visibleRect].size.width)
{
q = [self convertPoint: unconverted
fromView: nil].x;
if (lit)
{
NSHighlightRect (oldRect);
[_window flushWindow];
lit = NO;
NSHighlightRect(oldHighlightRect);
}
tvRect = [_tableView visibleRect];
if (q > maxVisCoord)
{
if (q > maxAbsCoord + 5)
q = maxAbsCoord + 5;
tvRect.origin.x += (q - maxVisCoord)/2;
}
else if (q < minVisCoord)
{
if (q < minAbsCoord - 5)
q = minAbsCoord - 5;
tvRect.origin.x += (q - minVisCoord)/2;
}
else // TODO remove this condition
{
NSLog(@"not outside !");
}
[_tableView scrollPoint: tvRect.origin];
rect = [self visibleRect];
minVisCoord = NSMinX (rect) + divWidth;
maxVisCoord = NSMaxX (rect) - divWidth;
minCoord = MAX (minAbsCoord, minVisCoord);
maxCoord = MIN (maxAbsCoord, maxVisCoord);
NSHighlightRect(highlightRect);
[_window flushWindow];
lit = YES;
oldHighlightRect = highlightRect;
}
}
/* Scroll the tableview, if needed, so the user's desired new
column edge position lies at the edge of the visible part of
the table */
if ((p > maxVisCoord && newColumnMaxX > maxVisCoord)
|| (p < minVisCoord && newColumnMaxX < minVisCoord))
{
NSRect tvRect = [_tableView visibleRect];
if (!liveResize && lit)
{
NSHighlightRect(oldHighlightRect);
lit = NO;
[_window flushWindow];
}
if (p > maxVisCoord) /* resizing to the right */
tvRect.origin.x = newColumnMaxX - tvRect.size.width;
else /* resizing to the left */
tvRect.origin.x = newColumnMaxX;
[_tableView scrollPoint: tvRect.origin];
}
e = [NSApp nextEventMatchingMask: eventMask
untilDate: farAway
untilDate: [NSDate distantFuture]
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
}
[NSEvent stopPeriodicEvents];
if (outside)
{
p = [self convertPoint: [e locationInWindow] fromView: nil].x;
if (p > maxAbsCoord)
p = maxAbsCoord;
else if (p < minAbsCoord)
p = minAbsCoord;
}
if (lit == YES)
{
NSHighlightRect(oldRect);
[_window flushWindow];
}
[self unlockFocus];
/* The following tiles the table. We use a private method
which avoids tiling the table twice. */
if (dragged == YES)
if (!liveResize)
{
[_tableView _userResizedTableColumn: _resizedColumn
width: (p - NSMinX (rectLow))];
if (lit)
{
NSHighlightRect(oldHighlightRect);
[_window flushWindow];
}
[self unlockFocus];
/* The following tiles the table. We use a private method
which avoids tiling the table twice. */
if ([column width] != newColumnWidth)
{
[_tableView _userResizedTableColumn: _resizedColumn
width: newColumnWidth];
}
}
/* Clean up */
@ -575,7 +544,8 @@
NSRect highlightRect = NSZeroRect, oldRect = NSZeroRect;
BOOL outside = NO;
BOOL lit = NO;
BOOL liveResize = ![[NSUserDefaults standardUserDefaults] boolForKey: @"GSUseGhostResize"];
BOOL mouseDragged = NO;
float p;
NSPoint unconverted;
@ -599,8 +569,11 @@
highlightRect.size.height = NSHeight (visibleRect);
highlightRect.origin.y = NSMinY (visibleRect);
[self lockFocus];
[[NSColor lightGrayColor] set];
if (!liveResize)
{
[self lockFocus];
[[NSColor lightGrayColor] set];
}
[NSEvent startPeriodicEventsAfterDelay: 0.05
withPeriod: 0.05];
e = [NSApp nextEventMatchingMask: eventMask
@ -638,76 +611,93 @@
while (p < (_cO[i] + _cO[i-1]) / 2)
i--;
}
if (i != columnIndex
&& i != columnIndex + 1)
{
j = i;
highlightRect.size.height = NSHeight (visibleRect);
highlightRect.origin.y = NSMinY (visibleRect);
highlightRect.size.width = 7;
if (i == numberOfColumns)
if (!liveResize)
{
if (i != columnIndex
&& i != columnIndex + 1)
{
highlightRect.origin.x = _cO[i] - 3;
}
else if (i == 0)
{
highlightRect.origin.x = _cO[i] - 3;
j = i;
highlightRect.size.height = NSHeight (visibleRect);
highlightRect.origin.y = NSMinY (visibleRect);
highlightRect.size.width = 7;
if (i == numberOfColumns)
{
highlightRect.origin.x = _cO[i] - 3;
}
else if (i == 0)
{
highlightRect.origin.x = _cO[i] - 3;
}
else
{
highlightRect.origin.x = _cO[i] - 3;
}
if (!NSEqualRects(highlightRect, oldRect))
{
if (lit)
NSHighlightRect(oldRect);
NSHighlightRect(highlightRect);
[_window flushWindow];
}
else if (!lit)
{
NSHighlightRect(highlightRect);
[_window flushWindow];
}
oldRect = highlightRect;
lit = YES;
}
else
{
highlightRect.origin.x = _cO[i] - 3;
i = columnIndex;
highlightRect.size.height = NSHeight (visibleRect);
highlightRect.origin.y = NSMinY (visibleRect);
highlightRect.origin.x = _cO[columnIndex];
highlightRect.size.width =
_cO[columnIndex + 1] - _cO[columnIndex];
if (!NSEqualRects(highlightRect, oldRect))
{
if (lit)
NSHighlightRect(oldRect);
// NSHighlightRect(highlightRect);
[_window flushWindow];
}
else if (!lit)
{
// NSHighlightRect(highlightRect);
// [_window flushWindow];
}
// oldRect = highlightRect;
oldRect = NSZeroRect;
lit = NO; //lit = YES;
}
if (!NSEqualRects(highlightRect, oldRect))
{
if (lit)
NSHighlightRect(oldRect);
NSHighlightRect(highlightRect);
[_window flushWindow];
}
else if (!lit)
{
NSHighlightRect(highlightRect);
[_window flushWindow];
}
oldRect = highlightRect;
lit = YES;
}
else
{
i = columnIndex;
highlightRect.size.height = NSHeight (visibleRect);
highlightRect.origin.y = NSMinY (visibleRect);
highlightRect.origin.x = _cO[columnIndex];
highlightRect.size.width =
_cO[columnIndex + 1] - _cO[columnIndex];
if (!NSEqualRects(highlightRect, oldRect))
{
if (lit)
NSHighlightRect(oldRect);
// NSHighlightRect(highlightRect);
[_window flushWindow];
}
else if (!lit)
{
// NSHighlightRect(highlightRect);
// [_window flushWindow];
}
// oldRect = highlightRect;
oldRect = NSZeroRect;
lit = NO; //lit = YES;
}
}
else if (liveResize)
{
if (i > columnIndex)
i--;
if (i != columnIndex)
{
[_tableView moveColumn: columnIndex
toColumn: i];
}
columnIndex = i;
}
}
break;
case NSPeriodic:
if (outside == YES)
{
if (lit)
if (!liveResize)
{
NSHighlightRect(oldRect);
[_window flushWindow];
lit = NO;
oldRect = NSZeroRect;
if (lit)
{
NSHighlightRect(oldRect);
[_window flushWindow];
lit = NO;
oldRect = NSZeroRect;
}
}
p = [self convertPoint: unconverted
fromView: nil].x;
@ -744,17 +734,20 @@
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
}
if (lit)
if (!liveResize)
{
NSHighlightRect(highlightRect);
[_window flushWindow];
lit = NO;
if (lit)
{
NSHighlightRect(highlightRect);
[_window flushWindow];
lit = NO;
}
[self unlockFocus];
}
[NSEvent stopPeriodicEvents];
[self unlockFocus];
[NSEvent stopPeriodicEvents];
if (mouseDragged == NO)
{
[_tableView _selectColumn: columnIndex