Implement vertical alignment in wxDataViewCtrl in wxOSX
When using non-default row height, text would be aligned to the top of the row. This is a known limitation of NSTextFieldCell and the solution is to either switch to modern view-based rendering or customize the cell as this commit does. See https://red-sweater.com/blog/148/what-a-difference-a-cell-makes for Daniel Jalkut's description of this solution.
This commit is contained in:
@@ -367,6 +367,16 @@ private:
|
|||||||
-(NSSize) cellSize;
|
-(NSSize) cellSize;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// NSTextFieldCell customized to allow vertical alignment
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
@interface wxTextFieldCell : NSTextFieldCell
|
||||||
|
-(void) setWXAlignment:(int)alignment;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxImageTextCell
|
// wxImageTextCell
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -382,7 +392,7 @@ private:
|
|||||||
// into their reserved space. Smaller or not existing images use the fixed
|
// into their reserved space. Smaller or not existing images use the fixed
|
||||||
// reserved size and are scaled if necessary.
|
// reserved size and are scaled if necessary.
|
||||||
//
|
//
|
||||||
@interface wxImageTextCell : NSTextFieldCell
|
@interface wxImageTextCell : wxTextFieldCell
|
||||||
{
|
{
|
||||||
@private
|
@private
|
||||||
CGFloat xImageShift; // shift for the image in x-direction from border
|
CGFloat xImageShift; // shift for the image in x-direction from border
|
||||||
|
@@ -40,6 +40,9 @@
|
|||||||
|
|
||||||
#define DataViewPboardType @"OutlineViewItem"
|
#define DataViewPboardType @"OutlineViewItem"
|
||||||
|
|
||||||
|
static const int MINIMUM_NATIVE_ROW_HEIGHT = 17;
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Classes used locally in dataview.mm
|
// Classes used locally in dataview.mm
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -1231,7 +1234,7 @@ outlineView:(NSOutlineView*)outlineView
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxImageTextCell
|
// wxImageCell
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@implementation wxImageCell
|
@implementation wxImageCell
|
||||||
|
|
||||||
@@ -1245,6 +1248,84 @@ outlineView:(NSOutlineView*)outlineView
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxTextFieldCell
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
@interface wxTextFieldCell ()
|
||||||
|
{
|
||||||
|
int _wxAlignment;
|
||||||
|
BOOL _adjustRect;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation wxTextFieldCell
|
||||||
|
|
||||||
|
- (void)setWXAlignment:(int)alignment
|
||||||
|
{
|
||||||
|
_wxAlignment = alignment;
|
||||||
|
_adjustRect = (alignment & (wxALIGN_CENTRE_VERTICAL | wxALIGN_BOTTOM)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These three overrides implement vertical alignment of text cells.
|
||||||
|
// The solution is described by Daniel Jalkut at
|
||||||
|
// https://red-sweater.com/blog/148/what-a-difference-a-cell-makes
|
||||||
|
|
||||||
|
- (NSRect)drawingRectForBounds:(NSRect)theRect
|
||||||
|
{
|
||||||
|
// Get the parent's idea of where we should draw
|
||||||
|
NSRect r = [super drawingRectForBounds:theRect];
|
||||||
|
|
||||||
|
if (!_adjustRect)
|
||||||
|
return r;
|
||||||
|
if (theRect.size.height <= MINIMUM_NATIVE_ROW_HEIGHT)
|
||||||
|
return r; // don't mess with default-sized rows as they are centered
|
||||||
|
|
||||||
|
NSSize bestSize = [self cellSizeForBounds:theRect];
|
||||||
|
if (bestSize.height < r.size.height)
|
||||||
|
{
|
||||||
|
if (_wxAlignment & wxALIGN_CENTER_VERTICAL)
|
||||||
|
{
|
||||||
|
r.origin.y += int(r.size.height - bestSize.height) / 2;
|
||||||
|
r.size.height = bestSize.height;
|
||||||
|
}
|
||||||
|
else if (_wxAlignment & wxALIGN_BOTTOM)
|
||||||
|
{
|
||||||
|
r.origin.y += r.size.height - bestSize.height;
|
||||||
|
r.size.height = bestSize.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength
|
||||||
|
{
|
||||||
|
BOOL oldAdjustRect = _adjustRect;
|
||||||
|
if (oldAdjustRect)
|
||||||
|
{
|
||||||
|
aRect = [self drawingRectForBounds:aRect];
|
||||||
|
_adjustRect = NO;
|
||||||
|
}
|
||||||
|
[super selectWithFrame:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
|
||||||
|
_adjustRect = oldAdjustRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent
|
||||||
|
{
|
||||||
|
BOOL oldAdjustRect = _adjustRect;
|
||||||
|
if (oldAdjustRect)
|
||||||
|
{
|
||||||
|
aRect = [self drawingRectForBounds:aRect];
|
||||||
|
_adjustRect = NO;
|
||||||
|
}
|
||||||
|
[super editWithFrame:aRect inView:controlView editor:textObj delegate:anObject event:theEvent];
|
||||||
|
_adjustRect = oldAdjustRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxImageTextCell
|
// wxImageTextCell
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -2441,7 +2522,6 @@ void wxCocoaDataViewControl::SetRowHeight(int height)
|
|||||||
|
|
||||||
int wxCocoaDataViewControl::GetDefaultRowHeight() const
|
int wxCocoaDataViewControl::GetDefaultRowHeight() const
|
||||||
{
|
{
|
||||||
const int MINIMUM_NATIVE_HEIGHT = 17;
|
|
||||||
// Custom setup of NSLayoutManager is necessary to match NSTableView sizing.
|
// Custom setup of NSLayoutManager is necessary to match NSTableView sizing.
|
||||||
// See http://stackoverflow.com/questions/17095927/dynamically-changing-row-height-after-font-size-of-entire-nstableview-nsoutlin
|
// See http://stackoverflow.com/questions/17095927/dynamically-changing-row-height-after-font-size-of-entire-nstableview-nsoutlin
|
||||||
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
|
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
|
||||||
@@ -2449,7 +2529,7 @@ int wxCocoaDataViewControl::GetDefaultRowHeight() const
|
|||||||
[lm setUsesScreenFonts:NO];
|
[lm setUsesScreenFonts:NO];
|
||||||
CGFloat height = [lm defaultLineHeightForFont:GetWXPeer()->GetFont().OSXGetNSFont()];
|
CGFloat height = [lm defaultLineHeightForFont:GetWXPeer()->GetFont().OSXGetNSFont()];
|
||||||
[lm release];
|
[lm release];
|
||||||
return wxMax(MINIMUM_NATIVE_HEIGHT, int(height));
|
return wxMax(MINIMUM_NATIVE_ROW_HEIGHT, int(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCocoaDataViewControl::SetRowHeight(const wxDataViewItem& WXUNUSED(item), unsigned int WXUNUSED(height))
|
void wxCocoaDataViewControl::SetRowHeight(const wxDataViewItem& WXUNUSED(item), unsigned int WXUNUSED(height))
|
||||||
@@ -2653,6 +2733,8 @@ void wxDataViewRenderer::OSXUpdateAlignment()
|
|||||||
int align = GetEffectiveAlignment();
|
int align = GetEffectiveAlignment();
|
||||||
NSCell *cell = GetNativeData()->GetColumnCell();
|
NSCell *cell = GetNativeData()->GetColumnCell();
|
||||||
[cell setAlignment:ConvertToNativeHorizontalTextAlignment(align)];
|
[cell setAlignment:ConvertToNativeHorizontalTextAlignment(align)];
|
||||||
|
if ([cell respondsToSelector:@selector(setWXAlignment:)])
|
||||||
|
[(wxTextFieldCell*)cell setWXAlignment:align];
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
|
void wxDataViewRenderer::SetMode(wxDataViewCellMode mode)
|
||||||
@@ -2829,7 +2911,7 @@ wxDataViewTextRenderer::wxDataViewTextRenderer(const wxString& varianttype,
|
|||||||
NSTextFieldCell* cell;
|
NSTextFieldCell* cell;
|
||||||
|
|
||||||
|
|
||||||
cell = [[NSTextFieldCell alloc] init];
|
cell = [[wxTextFieldCell alloc] init];
|
||||||
[cell setAlignment:ConvertToNativeHorizontalTextAlignment(align)];
|
[cell setAlignment:ConvertToNativeHorizontalTextAlignment(align)];
|
||||||
SetNativeData(new wxDataViewRendererNativeData(cell));
|
SetNativeData(new wxDataViewRendererNativeData(cell));
|
||||||
[cell release];
|
[cell release];
|
||||||
@@ -3050,7 +3132,7 @@ wxDataViewDateRenderer::wxDataViewDateRenderer(const wxString& varianttype,
|
|||||||
dateFormatter = [[NSDateFormatter alloc] init];
|
dateFormatter = [[NSDateFormatter alloc] init];
|
||||||
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
||||||
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
|
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
|
||||||
cell = [[NSTextFieldCell alloc] init];
|
cell = [[wxTextFieldCell alloc] init];
|
||||||
[cell setFormatter:dateFormatter];
|
[cell setFormatter:dateFormatter];
|
||||||
SetNativeData(new wxDataViewRendererNativeData(cell,[NSDate dateWithString:@"2000-12-30 20:00:00 +0000"]));
|
SetNativeData(new wxDataViewRendererNativeData(cell,[NSDate dateWithString:@"2000-12-30 20:00:00 +0000"]));
|
||||||
[cell release];
|
[cell release];
|
||||||
|
Reference in New Issue
Block a user