// Author:
// Modified by:
// Created: 2009-01-31
-// RCS-ID: $Id: dataview.mm$
// Copyright:
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/utils.h"
#endif
-#include "wx/osx/cocoa/dataview.h"
#include "wx/osx/private.h"
+#include "wx/osx/cocoa/dataview.h"
#include "wx/renderer.h"
+#include "wx/stopwatch.h"
+#include "wx/dcgraph.h"
// ============================================================================
// Constants used locally
{
}
+ // Get the identifier we use for the specified column. This should be used
+ // for finding columns from identifier only, to initialize the identifier
+ // of a new column use initWithColumnPointer below instead.
+ +(NSString*) identifierForColumnPointer:(const wxDataViewColumn*)column;
+
+ // Initialize the column with the given pointer to the associated
+ // wxDataViewColumn. This pointer can later be retrieved using
+ // getColumnPointer.
+ -(id) initWithColumnPointer:(const wxDataViewColumn*)column;
+
+ // Retrieve the associated column.
+ -(wxDataViewColumn*) getColumnPointer;
+
-(id) dataCellForRow:(NSInteger)row;
@end
@implementation wxDVCNSTableColumn
++(NSString*) identifierForColumnPointer:(const wxDataViewColumn*)column
+{
+ // Starting from OS X 10.7 the column identifier must be an NSString and
+ // not just some arbitrary object, so we serialize the pointer into the
+ // string. Notice the use of NSInteger which is big enough to store a
+ // pointer in both 32 and 64 bit builds.
+ return [NSString stringWithFormat:@"%lu", reinterpret_cast<NSUInteger>(column)];
+}
+
+-(id) initWithColumnPointer:(const wxDataViewColumn*)column
+{
+ [self initWithIdentifier: [wxDVCNSTableColumn identifierForColumnPointer:column]];
+ return self;
+}
+
+-(wxDataViewColumn*) getColumnPointer
+{
+ // The case to NSString is needed for OS X < 10.7.
+ return reinterpret_cast<wxDataViewColumn*>(
+ [static_cast<NSString*>([self identifier]) integerValue]);
+}
+
-(id) dataCellForRow:(NSInteger)row
{
// what we want to do here is to simply return nil for the cells which
// or progress cells in the columns using the corresponding types even for
// the container rows which is wrong
- // half of the problem is just finding the objects we need from the column
- // pointer which is itself stashed inside wxPointerObject which we use as
- // our identifier
- const wxDataViewColumn * const
- dvCol = static_cast<wxDataViewColumn *>(
- [(wxPointerObject *)[self identifier] pointer]
- );
+ const wxDataViewColumn * const dvCol = [self getColumnPointer];
const wxDataViewCtrl * const dvc = dvCol->GetOwner();
const wxCocoaDataViewControl * const
NSInteger result = NSOrderedSame;
for ( NSUInteger i = 0; i < count && result == NSOrderedSame; ++i )
{
- // constant definition for abbreviational purposes:
wxSortDescriptorObject* const
sortDescriptor = (wxSortDescriptorObject*)
[sortDescriptors objectAtIndex:i];
wxCHECK_MSG( renderer, NULL, "column should have a renderer" );
wxDVCNSTableColumn * const nativeColumn(
- [[wxDVCNSTableColumn alloc] initWithIdentifier:
- [[[wxPointerObject alloc] initWithPointer:
- const_cast<wxDataViewColumn*>(column)]
- autorelease]]
+ [[wxDVCNSTableColumn alloc] initWithColumnPointer: column]
);
// setting the size related parameters:
- const int width = column->GetWidthVariable();
+ int resizingMask;
if (column->IsResizeable())
{
- [nativeColumn setResizingMask:NSTableColumnUserResizingMask];
+ resizingMask = NSTableColumnUserResizingMask;
[nativeColumn setMinWidth:column->GetMinWidth()];
[nativeColumn setMaxWidth:column->GetMaxWidth()];
}
- else
+ else // column is not resizable [by user]
{
- [nativeColumn setResizingMask:NSTableColumnNoResizing];
- [nativeColumn setMinWidth:width];
- [nativeColumn setMaxWidth:width];
+ // if the control doesn't show a header, make the columns resize
+ // automatically, this is particularly important for the single column
+ // controls (such as wxDataViewTreeCtrl) as their unique column should
+ // always take up all the available splace
+ resizingMask = column->GetOwner()->HasFlag(wxDV_NO_HEADER)
+ ? NSTableColumnAutoresizingMask
+ : NSTableColumnNoResizing;
}
- [nativeColumn setWidth:width];
+ [nativeColumn setResizingMask:resizingMask];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
// setting the visibility:
acceptDrop:(id<NSDraggingInfo>)info
item:(id)item childIndex:(NSInteger)index
{
+ wxUnusedVar(outlineView);
+ wxUnusedVar(index);
+
NSArray* supportedTypes(
[NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil]
);
wxCHECK_MSG( dvc->GetModel(), false,
"Pointer to model not set correctly." );
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_DROP, dvc->GetId());
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_DROP, dvc->GetId());
event.SetEventObject(dvc);
event.SetItem(wxDataViewItemFromItem(item));
event.SetModel(dvc->GetModel());
- BOOL dragSuccessful;
+ BOOL dragSuccessful = false;
if ( [bestType compare:DataViewPboardType] == NSOrderedSame )
{
NSArray* dataArray((NSArray*)
::CFRelease(osxData);
delete dataObjects;
}
+ return dragSuccessful;
}
-(id) outlineView:(NSOutlineView*)outlineView
child:(NSInteger)index
ofItem:(id)item
{
+ wxUnusedVar(outlineView);
+
if ((item == currentParentItem) &&
(index < ((NSInteger) [self getChildCount])))
return [self getChild:index];
-(BOOL) outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item
{
+ wxUnusedVar(outlineView);
+
wxCHECK_MSG( model, 0, "Valid model in data source does not exist." );
return model->IsContainer(wxDataViewItemFromItem(item));
}
-(NSInteger) outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(id)item
{
+ wxUnusedVar(outlineView);
+
NSInteger noOfChildren;
wxDataViewItemArray dataViewChildren;
objectValueForTableColumn:(NSTableColumn*)tableColumn
byItem:(id)item
{
+ wxUnusedVar(outlineView);
+
wxCHECK_MSG( model, nil, "Valid model in data source does not exist." );
- wxDataViewColumn* col(static_cast<wxDataViewColumn*>([[tableColumn identifier] pointer]));
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
const unsigned colIdx = col->GetModelColumn();
wxDataViewItem dataViewItem(wxDataViewItemFromItem(item));
forTableColumn:(NSTableColumn*)tableColumn
byItem:(id)item
{
- wxDataViewColumn* col(static_cast<wxDataViewColumn*>([[tableColumn identifier] pointer]));
+ wxUnusedVar(outlineView);
+
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
col->GetRenderer()->
OSXOnCellChanged(object, wxDataViewItemFromItem(item), col->GetModelColumn());
}
-(void) outlineView:(NSOutlineView*)outlineView sortDescriptorsDidChange:(NSArray*)oldDescriptors
-// Warning: the new sort descriptors are guaranteed to be only of type NSSortDescriptor! Therefore, the
-// sort descriptors for the data source have to be converted.
{
+ wxUnusedVar(oldDescriptors);
+
+ // Warning: the new sort descriptors are guaranteed to be only of type
+ // NSSortDescriptor! Therefore, the sort descriptors for the data source
+ // have to be converted.
NSArray* newDescriptors;
NSMutableArray* wxSortDescriptors;
wxSortDescriptors = [NSMutableArray arrayWithCapacity:noOfDescriptors];
for (NSUInteger i=0; i<noOfDescriptors; ++i)
{
- // constant definition for abbreviational purposes:
NSSortDescriptor* const newDescriptor = [newDescriptors objectAtIndex:i];
[wxSortDescriptors addObject:[[[wxSortDescriptorObject alloc] initWithModelPtr:model
sortingColumnPtr:dvc->GetColumn([[newDescriptor key] intValue])
ascending:[newDescriptor ascending]] autorelease]];
}
- [[outlineView dataSource] setSortDescriptors:wxSortDescriptors];
+ [(wxCocoaOutlineDataSource*)[outlineView dataSource] setSortDescriptors:wxSortDescriptors];
- // send first the event to wxWidgets that the sorting has changed so that the program can do special actions before
- // the sorting actually starts:
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED,dvc->GetId()); // variable defintion
+ // send first the event to wxWidgets that the sorting has changed so that
+ // the program can do special actions before the sorting actually starts:
+ wxDataViewEvent event(wxEVT_DATAVIEW_COLUMN_SORTED,dvc->GetId()); // variable definition
event.SetEventObject(dvc);
if (noOfDescriptors > 0)
{
- // constant definition for abbreviational purposes:
wxDataViewColumn* const col = [[wxSortDescriptors objectAtIndex:0] columnPtr];
event.SetColumn(dvc->GetColumnPosition(col));
-(NSDragOperation) outlineView:(NSOutlineView*)outlineView validateDrop:(id<NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{
+ wxUnusedVar(outlineView);
+ wxUnusedVar(index);
+
NSArray* supportedTypes([NSArray arrayWithObjects:DataViewPboardType,NSStringPboardType,nil]);
NSPasteboard* pasteboard([info draggingPasteboard]);
if (bestType == nil)
return NSDragOperationNone;
- NSDragOperation dragOperation;
+ NSDragOperation dragOperation = NSDragOperationNone;
wxDataViewCtrl* const dvc(implementation->GetDataViewCtrl());
wxCHECK_MSG(dvc, false, "Pointer to data view control not set correctly.");
wxCHECK_MSG(dvc->GetModel(), false, "Pointer to model not set correctly.");
wxDataViewEvent
- event(wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE,dvc->GetId());
+ event(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE,dvc->GetId());
event.SetEventObject(dvc);
event.SetItem(wxDataViewItemFromItem(item));
}
else
{
- CFDataRef osxData; // needed to convert internally used UTF-16 representation to a UTF-8 representation
+ // needed to convert internally used UTF-16 representation to a UTF-8
+ // representation
+ CFDataRef osxData;
wxDataObjectComposite* dataObjects (new wxDataObjectComposite());
wxTextDataObject* textDataObject(new wxTextDataObject());
}
-(BOOL) outlineView:(NSOutlineView*)outlineView writeItems:(NSArray*)writeItems toPasteboard:(NSPasteboard*)pasteboard
-// the pasteboard will be filled up with an array containing the data as returned by the events (including the data type)
-// and a concatenation of text (string) data; the text data will only be put onto the pasteboard if for all items a
-// string representation exists
{
+ wxUnusedVar(outlineView);
+
+ // the pasteboard will be filled up with an array containing the data as
+ // returned by the events (including the data type) and a concatenation of
+ // text (string) data; the text data will only be put onto the pasteboard
+ // if for all items a string representation exists
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
wxDataViewItemArray dataViewItems;
if ([writeItems count] > 0)
{
bool dataStringAvailable(true); // a flag indicating if for all items a data string is available
- NSMutableArray* dataArray = [[NSMutableArray arrayWithCapacity:[writeItems count]] retain]; // data of all items
+ NSMutableArray* dataArray = [NSMutableArray arrayWithCapacity:[writeItems count]]; // data of all items
wxString dataString; // contains the string data of all items
- // send a begin drag event for all selected items and proceed with dragging unless the event is vetoed:
+ // send a begin drag event for all selected items and proceed with
+ // dragging unless the event is vetoed:
wxDataViewEvent
- event(wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG,dvc->GetId());
+ event(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG,dvc->GetId());
event.SetEventObject(dvc);
event.SetModel(dvc->GetModel());
// check if event has not been vetoed:
if (dvc->HandleWindowEvent(event) && event.IsAllowed() && (event.GetDataObject()->GetFormatCount() > 0))
{
- // constant definition for abbreviational purposes:
size_t const noOfFormats = event.GetDataObject()->GetFormatCount();
- // variable definition and initialization:
wxDataFormat* dataFormats(new wxDataFormat[noOfFormats]);
event.GetDataObject()->GetAllFormats(dataFormats,wxDataObject::Get);
size_t const dataSize = event.GetDataObject()->GetDataSize(idDataFormat);
size_t const dataBufferSize = sizeof(wxDataFormatId)+dataSize;
// variable definitions (used in all case statements):
- wxMemoryBuffer dataBuffer(dataBufferSize);
+ // give additional headroom for trailing NULL
+ wxMemoryBuffer dataBuffer(dataBufferSize+4);
dataBuffer.AppendData(&idDataFormat,sizeof(wxDataFormatId));
switch (idDataFormat)
{
case wxDF_TEXT:
- if (!itemStringAvailable) // otherwise wxDF_UNICODETEXT already filled up the string; and the UNICODE representation has priority
+ // otherwise wxDF_UNICODETEXT already filled up
+ // the string; and the UNICODE representation has
+ // priority
+ if (!itemStringAvailable)
{
event.GetDataObject()->GetDataHere(wxDF_TEXT,dataBuffer.GetAppendBuf(dataSize));
dataBuffer.UngetAppendBuf(dataSize);
break;
default:
wxFAIL_MSG("Data object has invalid or unsupported data format");
- [dataArray release];
return NO;
}
}
delete[] dataFormats;
delete itemObject;
if (dataStringAvailable)
+ {
if (itemStringAvailable)
{
if (itemCounter > 0)
}
else
dataStringAvailable = false;
+ }
}
else
{
- [dataArray release];
delete itemObject;
return NO; // dragging was vetoed or no data available
}
@implementation wxCustomCell
+#if 0 // starting implementation for custom cell clicks
+
+- (id)init
+{
+ self = [super init];
+ [self setAction:@selector(clickedAction)];
+ [self setTarget:self];
+ return self;
+}
+
+- (void) clickedAction: (id) sender
+{
+ wxUnusedVar(sender);
+}
+
+#endif
+
-(NSSize) cellSize
{
wxCustomRendererObject * const
wxDataViewCustomRenderer * const renderer = obj->customRenderer;
- wxDC * const dc = renderer->GetDC();
- renderer->WXCallRender(wxFromNSRect(controlView, cellFrame), dc, 0);
- renderer->SetDC(NULL);
+ // if this method is called everything is already setup correctly,
+ CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
+ CGContextSaveGState( context );
+
+ if ( ![controlView isFlipped] )
+ {
+ CGContextTranslateCTM( context, 0, [controlView bounds].size.height );
+ CGContextScaleCTM( context, 1, -1 );
+ }
+
+ wxGCDC dc;
+ wxGraphicsContext* gc = wxGraphicsContext::CreateFromNative(context);
+ dc.SetGraphicsContext(gc);
+
+ int state = 0;
+ if ( [self isHighlighted] )
+ state |= wxDATAVIEW_CELL_SELECTED;
+
+ renderer->WXCallRender(wxFromNSRect(controlView, cellFrame), &dc, state);
+
+ CGContextRestoreGState( context );
}
-(NSRect) imageRectForBounds:(NSRect)cellFrame
{
CGFloat const cellSpace = cellFrame.size.width-[self cellSize].width;
- if (cellSpace <= 0) // if the cell's frame is smaller than its contents (at least in x-direction) make sure that the image is visible:
+ // if the cell's frame is smaller than its contents (at least
+ // in x-direction) make sure that the image is visible:
+ if (cellSpace <= 0)
NSDivideRect(cellFrame,imageFrame,textFrame,xImageShift+imageSize.width+spaceImageText,NSMinXEdge);
else // otherwise center the image and text in the cell's frame
NSDivideRect(cellFrame,imageFrame,textFrame,xImageShift+imageSize.width+spaceImageText+0.5*cellSpace,NSMinXEdge);
{
CGFloat const cellSpace = cellFrame.size.width-[self cellSize].width;
- if (cellSpace <= 0) // if the cell's frame is smaller than its contents (at least in x-direction) make sure that the image is visible:
+ // if the cell's frame is smaller than its contents (at least
+ // in x-direction) make sure that the image is visible:
+ if (cellSpace <= 0)
NSDivideRect(cellFrame,imageFrame,textFrame,xImageShift+imageSize.width+spaceImageText,NSMinXEdge);
else // otherwise right align the image and text in the cell's frame
NSDivideRect(cellFrame,imageFrame,textFrame,xImageShift+imageSize.width+spaceImageText+cellSpace,NSMinXEdge);
[self determineCellParts:cellFrame imagePart:&imageFrame textPart:&textFrame];
// draw the image part by ourselves;
- // check if the cell has to draw its own background (checking is done by the parameter of the textfield's cell):
+ // check if the cell has to draw its own background (checking is done by
+ // the parameter of the textfield's cell):
if ([self drawsBackground])
{
[[self backgroundColor] set];
}
if (image != nil)
{
- // the image is slightly shifted (xImageShift) and has a fixed size but the image's frame might be larger and starts
- // currently on the left side of the cell's frame; therefore, the origin and the image's frame size have to be adjusted:
+ // the image is slightly shifted (xImageShift) and has a fixed size
+ // but the image's frame might be larger and starts currently on the
+ // left side of the cell's frame; therefore, the origin and the
+ // image's frame size have to be adjusted:
if (imageFrame.size.width >= xImageShift+imageSize.width+spaceImageText)
{
imageFrame.origin.x += imageFrame.size.width-imageSize.width-spaceImageText;
imageFrame.size.height = imageSize.height;
imageFrame.origin.y += ceil(0.5*(cellFrame.size.height-imageFrame.size.height));
- // according to the documentation the coordinate system should be flipped for NSTableViews (y-coordinate goes from top to bottom);
- // to draw an image correctly the coordinate system has to be transformed to a bottom-top coordinate system, otherwise the image's
+ // according to the documentation the coordinate system should be
+ // flipped for NSTableViews (y-coordinate goes from top to bottom); to
+ // draw an image correctly the coordinate system has to be transformed
+ // to a bottom-top coordinate system, otherwise the image's
// content is flipped:
NSAffineTransform* coordinateTransform([NSAffineTransform transform]);
}
[image drawInRect:imageFrame fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; // suggested method to draw the image
// instead of compositeToPoint:operation:
- // take back previous transformation (if the view is not flipped the coordinate transformation matrix contains the identity matrix
- // and the next two operations do not change the content's transformation matrix):
+ // take back previous transformation (if the view is not flipped the
+ // coordinate transformation matrix contains the identity matrix and
+ // the next two operations do not change the content's transformation
+ // matrix):
[coordinateTransform invert];
[coordinateTransform concat];
}
// let the textfield cell draw the text part:
- if (textFrame.size.width > [self cellTextSize].width) // for unknown reasons the alignment of the text cell is ignored; therefore change the size so that
- textFrame.size.width = [self cellTextSize].width; // alignment does not influence the visualization anymore
+ if (textFrame.size.width > [self cellTextSize].width)
+ {
+ // for unknown reasons the alignment of the text cell is ignored;
+ // therefore change the size so that alignment does not influence the
+ // visualization anymore
+ textFrame.size.width = [self cellTextSize].width;
+ }
[super drawWithFrame:textFrame inView:controlView];
}
if (imageFrame.size.height > imageSize.height)
imageFrame.size.height = imageSize.height;
imageFrame.origin.y += ceil(0.5*(cellFrame.size.height-imageFrame.size.height));
- // If the point is in the image rect, then it is a content hit (see documentation for hitTestForEvent:inRect:ofView):
+ // If the point is in the image rect, then it is a content hit (see
+ // documentation for hitTestForEvent:inRect:ofView):
if (NSMouseInRect(point, imageFrame, [controlView isFlipped]))
return NSCellHitContentArea;
}
// if the image was not hit let's try the text part:
- if (textFrame.size.width > [self cellTextSize].width) // for unknown reasons the alignment of the text cell is ignored; therefore change the size so that
- textFrame.size.width = [self cellTextSize].width; // alignment does not influence the visualization anymore
+ if (textFrame.size.width > [self cellTextSize].width)
+ {
+ // for unknown reasons the alignment of the text cell is ignored;
+ // therefore change the size so that alignment does not influence the
+ // visualization anymore
+ textFrame.size.width = [self cellTextSize].width;
+ }
+
return [super hitTestForEvent:event inRect:textFrame ofView:controlView];
}
#endif
// actions
//
-(void) actionDoubleClick:(id)sender
-// actually the documentation (NSTableView 2007-10-31) for doubleAction: and setDoubleAction: seems to be wrong as this action message is always sent
-// whether the cell is editable or not
{
+ wxUnusedVar(sender);
+
+ // actually the documentation (NSTableView 2007-10-31) for doubleAction:
+ // and setDoubleAction: seems to be wrong as this action message is always
+ // sent whether the cell is editable or not
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED,dvc->GetId()); // variable definition
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_ACTIVATED,dvc->GetId());
event.SetEventObject(dvc);
// contextual menus
//
-(NSMenu*) menuForEvent:(NSEvent*)theEvent
-// this method does not do any special menu event handling but only sends an event message; therefore, the user
-// has full control if a context menu should be shown or not
{
+ wxUnusedVar(theEvent);
+
+ // this method does not do any special menu event handling but only sends
+ // an event message; therefore, the user has full control if a context
+ // menu should be shown or not
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU,dvc->GetId());
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,dvc->GetId());
wxDataViewItemArray selectedItems;
event.SetEventObject(dvc);
event.SetModel(dvc->GetModel());
// get the item information;
- // theoretically more than one ID can be returned but the event can only handle one item, therefore only the first
- // item of the array is returned:
+ // theoretically more than one ID can be returned but the event can only
+ // handle one item, therefore only the first item of the array is
+ // returned:
if (dvc->GetSelections(selectedItems) > 0)
event.SetItem(selectedItems[0]);
dvc->GetEventHandler()->ProcessEvent(event);
//
// delegate methods
//
--(void) outlineView:(NSOutlineView*)outlineView mouseDownInHeaderOfTableColumn:(NSTableColumn*)tableColumn
+-(void) outlineView:(NSOutlineView*)outlineView didClickTableColumn:(NSTableColumn*)tableColumn
{
- wxDataViewColumn* const col(static_cast<wxDataViewColumn*>([[tableColumn identifier] pointer]));
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
wxDataViewEvent
- event(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK,dvc->GetId());
+ event(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK,dvc->GetId());
// first, send an event that the user clicked into a column's header:
dvc->HandleWindowEvent(event);
// now, check if the click may have had an influence on sorting, too;
- // the sorting setup has to be done only if the clicked table column is sortable and has not been used for
- // sorting before the click; if the column is already responsible for sorting the native control changes
- // the sorting direction automatically and informs the data source via outlineView:sortDescriptorsDidChange:
+ // the sorting setup has to be done only if the clicked table column is
+ // sortable and has not been used for sorting before the click; if the
+ // column is already responsible for sorting the native control changes
+ // the sorting direction automatically and informs the data source via
+ // outlineView:sortDescriptorsDidChange:
if (col->IsSortable() && ([tableColumn sortDescriptorPrototype] == nil))
{
- // remove the sort order from the previously sorted column table (it can also be that
- // no sorted column table exists):
+ // remove the sort order from the previously sorted column table (it
+ // can also be that no sorted column table exists):
UInt32 const noOfColumns = [outlineView numberOfColumns];
for (UInt32 i=0; i<noOfColumns; ++i)
NSArray* sortDescriptors;
NSSortDescriptor* sortDescriptor;
- sortDescriptor = [[NSSortDescriptor alloc] initWithKey:[NSString stringWithFormat:@"%d",[outlineView columnWithIdentifier:[tableColumn identifier]]]
+ sortDescriptor = [[NSSortDescriptor alloc] initWithKey:[NSString stringWithFormat:@"%ld",(long)[outlineView columnWithIdentifier:[tableColumn identifier]]]
ascending:YES];
sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[tableColumn setSortDescriptorPrototype:sortDescriptor];
-(BOOL) outlineView:(NSOutlineView*)outlineView shouldCollapseItem:(id)item
{
+ wxUnusedVar(outlineView);
+
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,dvc->GetId()); // variable definition
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_COLLAPSING,dvc->GetId());
event.SetEventObject(dvc);
-(BOOL) outlineView:(NSOutlineView*)outlineView shouldExpandItem:(id)item
{
+ wxUnusedVar(outlineView);
+
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,dvc->GetId()); // variable definition
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EXPANDING,dvc->GetId());
event.SetEventObject(dvc);
-(BOOL) outlineView:(NSOutlineView*)outlineView shouldSelectTableColumn:(NSTableColumn*)tableColumn
{
+ wxUnusedVar(tableColumn);
+ wxUnusedVar(outlineView);
+
return NO;
}
forTableColumn:(NSTableColumn*)tableColumn
item:(id)item
{
+ wxUnusedVar(outlineView);
+
wxDataViewCtrl * const dvc = implementation->GetDataViewCtrl();
wxDataViewModel * const model = dvc->GetModel();
- wxDataViewColumn * const
- dvCol(static_cast<wxDataViewColumn*>(
- [[tableColumn identifier] pointer]
- )
- );
+ wxDataViewColumn* const
+ dvCol([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
const unsigned colIdx = dvCol->GetModelColumn();
wxDataViewItem dvItem(wxDataViewItemFromItem(item));
model->GetAttr(dvItem, colIdx, attr);
renderer->OSXApplyAttr(attr);
+ // set the state (enabled/disabled) of the item
+ renderer->OSXApplyEnabled(model->IsEnabled(dvItem, colIdx));
+
// and finally do draw it
renderer->MacRender();
}
{
int const newColumnPosition = [[[notification userInfo] objectForKey:@"NSNewColumn"] intValue];
- wxDataViewColumn* const col(static_cast<wxDataViewColumn*>([[[[self tableColumns] objectAtIndex:newColumnPosition] identifier] pointer]));
+ NSTableColumn*
+ tableColumn = [[self tableColumns] objectAtIndex:newColumnPosition];
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED,dvc->GetId());
+ wxDataViewEvent event(wxEVT_DATAVIEW_COLUMN_REORDERED,dvc->GetId());
event.SetEventObject(dvc);
{
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,dvc->GetId());
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_COLLAPSED,dvc->GetId());
event.SetEventObject(dvc);
{
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,dvc->GetId());
+ wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EXPANDED,dvc->GetId());
event.SetEventObject(dvc);
-(void) outlineViewSelectionDidChange:(NSNotification*)notification
{
- wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
+ wxUnusedVar(notification);
- wxDataViewEvent event(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED,dvc->GetId()); // variable definition
+ wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
+ wxDataViewEvent event(wxEVT_DATAVIEW_SELECTION_CHANGED,dvc->GetId());
event.SetEventObject(dvc);
- event.SetModel (dvc->GetModel());
+ event.SetModel(dvc->GetModel());
+ event.SetItem(dvc->GetSelection());
dvc->GetEventHandler()->ProcessEvent(event);
}
-(void) textDidBeginEditing:(NSNotification*)notification
-// this notification is only sent if the user started modifying the cell (not when the user clicked into the cell
-// and the cell's editor is called!)
{
- // call method of superclass (otherwise editing does not work correctly - the outline data source class is not
- // informed about a change of data):
+ // this notification is only sent if the user started modifying the cell
+ // (not when the user clicked into the cell and the cell's editor is
+ // called!)
+
+ // call method of superclass (otherwise editing does not work correctly -
+ // the outline data source class is not informed about a change of data):
[super textDidBeginEditing:notification];
// remember the column being edited, it will be used in textDidEndEditing:
currentlyEditedColumn = [self editedColumn];
currentlyEditedRow = [self editedRow];
- wxDataViewColumn* const col =
- static_cast<wxDataViewColumn*>(
- [[[[self tableColumns] objectAtIndex:currentlyEditedColumn] identifier] pointer]);
+ NSTableColumn*
+ tableColumn = [[self tableColumns] objectAtIndex:currentlyEditedColumn];
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
// now, send the event:
wxDataViewEvent
- event(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED,dvc->GetId()); // variable definition
+ event(wxEVT_DATAVIEW_ITEM_EDITING_STARTED,dvc->GetId());
event.SetEventObject(dvc);
event.SetItem(
-(void) textDidEndEditing:(NSNotification*)notification
{
- // call method of superclass (otherwise editing does not work correctly - the outline data source class is not
- // informed about a change of data):
+ // call method of superclass (otherwise editing does not work correctly -
+ // the outline data source class is not informed about a change of data):
[super textDidEndEditing:notification];
- // under OSX an event indicating the end of an editing session can be sent even if no event indicating a start of an
- // editing session has been sent (see Documentation for NSControl controlTextDidEndEditing:); this is not expected by a user
- // of the wxWidgets library and therefore an wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE event is only sent if a corresponding
- // wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED has been sent before; to check if a wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED
- // has been sent the last edited column/row are valid:
+ // under OSX an event indicating the end of an editing session can be sent
+ // even if no event indicating a start of an editing session has been sent
+ // (see Documentation for NSControl controlTextDidEndEditing:); this is
+ // not expected by a user of the wxWidgets library and therefore an
+ // wxEVT_DATAVIEW_ITEM_EDITING_DONE event is only sent if a
+ // corresponding wxEVT_DATAVIEW_ITEM_EDITING_STARTED has been sent
+ // before; to check if a wxEVT_DATAVIEW_ITEM_EDITING_STARTED has
+ // been sent the last edited column/row are valid:
if ( currentlyEditedColumn != -1 && currentlyEditedRow != -1 )
{
- wxDataViewColumn* const col =
- static_cast<wxDataViewColumn*>(
- [[[[self tableColumns] objectAtIndex:currentlyEditedColumn] identifier] pointer]);
+ NSTableColumn*
+ tableColumn = [[self tableColumns] objectAtIndex:currentlyEditedColumn];
+ wxDataViewColumn* const
+ col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
// send event to wxWidgets:
wxDataViewEvent
- event(wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE,dvc->GetId()); // variable definition
+ event(wxEVT_DATAVIEW_ITEM_EDITING_DONE,dvc->GetId());
event.SetEventObject(dvc);
event.SetItem(
[scrollview setAutohidesScrollers:YES];
[scrollview setDocumentView:m_OutlineView];
+ // we cannot call InstallHandler(m_OutlineView) here, because we are handling
+ // our action:s ourselves, only associate the view with this impl
+ Associate(m_OutlineView,this);
// initialize the native control itself too
InitOutlineView(style);
}
[m_OutlineView setOutlineTableColumn:nil]; // due to a bug this does not work
[m_OutlineView removeTableColumn:columnPtr->GetNativeData()->GetNativeColumnPtr()]; // due to a confirmed bug #6555162 the deletion does not work for
// outline table columns (... and there is no workaround)
- return (([m_OutlineView columnWithIdentifier:[[[wxPointerObject alloc] initWithPointer:columnPtr] autorelease]]) == -1);
+ return (([m_OutlineView columnWithIdentifier:[wxDVCNSTableColumn identifierForColumnPointer:columnPtr]]) == -1);
}
void wxCocoaDataViewControl::DoSetExpanderColumn(const wxDataViewColumn *columnPtr)
wxDataViewColumn* wxCocoaDataViewControl::GetColumn(unsigned int pos) const
{
- return static_cast<wxDataViewColumn*>([[[[m_OutlineView tableColumns] objectAtIndex:pos] identifier] pointer]);
+ NSTableColumn* tableColumn = [[m_OutlineView tableColumns] objectAtIndex:pos];
+ return [static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer];
}
int wxCocoaDataViewControl::GetColumnPosition(const wxDataViewColumn *columnPtr) const
{
- return [m_OutlineView columnWithIdentifier:[[[wxPointerObject alloc] initWithPointer:const_cast<wxDataViewColumn*>(columnPtr)] autorelease]];
+ return [m_OutlineView columnWithIdentifier:[wxDVCNSTableColumn identifierForColumnPointer:columnPtr]];
}
bool wxCocoaDataViewControl::InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr)
[m_OutlineView addTableColumn:nativeColumn];
if (pos != static_cast<unsigned int>([m_OutlineView numberOfColumns]-1))
[m_OutlineView moveColumn:[m_OutlineView numberOfColumns]-1 toColumn:pos];
+
+ // set columns width now that it can be computed even for autosized columns:
+ columnPtr->SetWidth(columnPtr->GetWidthVariable());
+
// done:
return true;
}
+void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos)
+{
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+ const int count = GetCount();
+ NSTableColumn *column = GetColumn(pos)->GetNativeData()->GetNativeColumnPtr();
+
+ class MaxWidthCalculator
+ {
+ public:
+ MaxWidthCalculator(wxCocoaOutlineView *view,
+ NSTableColumn *column, unsigned columnIndex)
+ : m_width(0),
+ m_view(view),
+ m_column(columnIndex),
+ m_indent(0)
+ {
+ // account for indentation in the column with expander
+ if ( column == [m_view outlineTableColumn] )
+ m_indent = [m_view indentationPerLevel];
+ }
+
+ void UpdateWithWidth(int width)
+ {
+ m_width = wxMax(m_width, width);
+ }
+
+ void UpdateWithRow(int row)
+ {
+ NSCell *cell = [m_view preparedCellAtColumn:m_column row:row];
+ unsigned cellWidth = [cell cellSize].width + 1/*round the float up*/;
+
+ if ( m_indent )
+ cellWidth += m_indent * ([m_view levelForRow:row] + 1);
+
+ m_width = wxMax(m_width, cellWidth);
+ }
+
+ int GetMaxWidth() const { return m_width; }
+
+ private:
+ int m_width;
+ wxCocoaOutlineView *m_view;
+ unsigned m_column;
+ int m_indent;
+ };
+
+ MaxWidthCalculator calculator(m_OutlineView, column, pos);
+
+ if ( [column headerCell] )
+ {
+ calculator.UpdateWithWidth([[column headerCell] cellSize].width + 1/*round the float up*/);
+ }
+
+ // The code below deserves some explanation. For very large controls, we
+ // simply can't afford to calculate sizes for all items, it takes too
+ // long. So the best we can do is to check the first and the last N/2
+ // items in the control for some sufficiently large N and calculate best
+ // sizes from that. That can result in the calculated best width being too
+ // small for some outliers, but it's better to get slightly imperfect
+ // result than to wait several seconds after every update. To avoid highly
+ // visible miscalculations, we also include all currently visible items
+ // no matter what. Finally, the value of N is determined dynamically by
+ // measuring how much time we spent on the determining item widths so far.
+
+#if wxUSE_STOPWATCH
+ int top_part_end = count;
+ static const long CALC_TIMEOUT = 20/*ms*/;
+ // don't call wxStopWatch::Time() too often
+ static const unsigned CALC_CHECK_FREQ = 100;
+ wxStopWatch timer;
+#else
+ // use some hard-coded limit, that's the best we can do without timer
+ int top_part_end = wxMin(500, count);
+#endif // wxUSE_STOPWATCH/!wxUSE_STOPWATCH
+
+ int row = 0;
+
+ for ( row = 0; row < top_part_end; row++ )
+ {
+#if wxUSE_STOPWATCH
+ if ( row % CALC_CHECK_FREQ == CALC_CHECK_FREQ-1 &&
+ timer.Time() > CALC_TIMEOUT )
+ break;
+#endif // wxUSE_STOPWATCH
+ calculator.UpdateWithRow(row);
+ }
+
+ // row is the first unmeasured item now; that's our value of N/2
+
+ if ( row < count )
+ {
+ top_part_end = row;
+
+ // add bottom N/2 items now:
+ const int bottom_part_start = wxMax(row, count - row);
+ for ( row = bottom_part_start; row < count; row++ )
+ calculator.UpdateWithRow(row);
+
+ // finally, include currently visible items in the calculation:
+ const NSRange visible = [m_OutlineView rowsInRect:[m_OutlineView visibleRect]];
+ const int first_visible = wxMax(visible.location, top_part_end);
+ const int last_visible = wxMin(first_visible + visible.length, bottom_part_start);
+
+ for ( row = first_visible; row < last_visible; row++ )
+ calculator.UpdateWithRow(row);
+
+ wxLogTrace("dataview",
+ "determined best size from %d top, %d bottom plus %d more visible items out of %d total",
+ top_part_end,
+ count - bottom_part_start,
+ wxMax(0, last_visible - first_visible),
+ count);
+ }
+
+ [column setWidth:calculator.GetMaxWidth()];
+#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+}
+
//
// item related methods (inherited from wxDataViewWidgetImpl)
//
bool wxCocoaDataViewControl::Reload()
{
[m_DataSource clearBuffers];
+ [m_OutlineView reloadData];
[m_OutlineView scrollColumnToVisible:0];
[m_OutlineView scrollRowToVisible:0];
- [m_OutlineView reloadData];
return true;
}
bool wxCocoaDataViewControl::Update(const wxDataViewColumn *columnPtr)
{
+ wxUnusedVar(columnPtr);
+
return false;
}
//
// selection related methods (inherited from wxDataViewWidgetImpl)
//
+
+wxDataViewItem wxCocoaDataViewControl::GetCurrentItem() const
+{
+ return wxDataViewItem([[m_OutlineView itemAtRow:[m_OutlineView selectedRow]] pointer]);
+}
+
+wxDataViewColumn *wxCocoaDataViewControl::GetCurrentColumn() const
+{
+ int col = [m_OutlineView selectedColumn];
+ if ( col == -1 )
+ return NULL;
+ return GetColumn(col);
+}
+
+void wxCocoaDataViewControl::SetCurrentItem(const wxDataViewItem& item)
+{
+ // We can't have unselected current item in a NSTableView, as the
+ // documentation of its deselectRow method explains, the control will
+ // automatically change the current item to the closest still selected item
+ // if the current item is deselected. So we have no choice but to select
+ // the item in the same time as making it current.
+ Select(item);
+}
+
+int wxCocoaDataViewControl::GetSelectedItemsCount() const
+{
+ return [m_OutlineView numberOfSelectedRows];
+}
+
int wxCocoaDataViewControl::GetSelections(wxDataViewItemArray& sel) const
{
NSIndexSet* selectedRowIndexes([m_OutlineView selectedRowIndexes]);
{
if (item.IsOk())
[m_OutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:[m_OutlineView rowForItem:[m_DataSource getDataViewItemFromBuffer:item]]]
- byExtendingSelection:NO];
+ byExtendingSelection:GetDataViewCtrl()->HasFlag(wxDV_MULTIPLE) ? YES : NO];
}
void wxCocoaDataViewControl::SelectAll()
for (UInt32 i=0; i<noOfColumns; ++i)
if ([[columns objectAtIndex:i] sortDescriptorPrototype] != nil)
- return static_cast<wxDataViewColumn*>([[[columns objectAtIndex:i] identifier] pointer]);
+ return GetColumn(i);
return NULL;
}
[m_OutlineView reloadData];
}
+void wxCocoaDataViewControl::StartEditor( const wxDataViewItem & item, unsigned int column )
+{
+ [m_OutlineView editColumn:column row:[m_OutlineView rowForItem:[m_DataSource getDataViewItemFromBuffer:item]] withEvent:nil select:YES];
+}
+
//
// other methods (inherited from wxDataViewWidgetImpl)
//
indexRow = [m_OutlineView rowAtPoint: nativePoint];
if ((indexColumn >= 0) && (indexRow >= 0))
{
- columnPtr = static_cast<wxDataViewColumn*>([[[[m_OutlineView tableColumns] objectAtIndex:indexColumn] identifier] pointer]);
+ columnPtr = GetColumn(indexColumn);
item = wxDataViewItem([[m_OutlineView itemAtRow:indexRow] pointer]);
}
else
const wxDataViewItem& item,
unsigned col)
{
- // TODO: we probably should get rid of this code entirely and make this
- // function pure virtual, but currently we still have some native
- // renderers (wxDataViewChoiceRenderer) which don't override it and
- // there is also wxDataViewCustomRenderer for which it's not obvious
- // how it should be implemented so keep this "auto-deduction" of
- // variant type from NSObject for now
+ // TODO: This code should really be removed and this function be made pure
+ // virtual. We just need to decide what to do with custom renderers
+ // (i.e. wxDataViewCustomRenderer), currently OS X "in place" editing
+ // which doesn't really create an editor control is not compatible
+ // with the in place editing under other platforms.
wxVariant value;
if ( [object isKindOfClass:[NSString class]] )
}
const wxColour& c = attr.GetColour();
- colText = [NSColor colorWithDeviceRed:c.Red() / 255.
+ colText = [NSColor colorWithCalibratedRed:c.Red() / 255.
green:c.Green() / 255.
blue:c.Blue() / 255.
alpha:c.Alpha() / 255.];
[(id)cell setTextColor:colText];
}
+void wxDataViewRenderer::OSXApplyEnabled(bool enabled)
+{
+ [GetNativeData()->GetItemCell() setEnabled:enabled];
+}
+
IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
// ---------------------------------------------------------
[cell release];
}
+// This method returns 'true' if
+// - the passed bitmap is valid and it could be assigned to the native data
+// browser;
+// - the passed bitmap is invalid (or is not initialized); this case
+// simulates a non-existing bitmap.
+// In all other cases the method returns 'false'.
bool wxDataViewBitmapRenderer::MacRender()
- // This method returns 'true' if
- // - the passed bitmap is valid and it could be assigned to the native data browser;
- // - the passed bitmap is invalid (or is not initialized); this case simulates a non-existing bitmap.
- // In all other cases the method returns 'false'.
{
wxCHECK_MSG(GetValue().GetType() == GetVariantType(),false,wxString("Bitmap renderer cannot render value; value type: ") << GetValue().GetType());
cell = [[NSPopUpButtonCell alloc] init];
[cell setControlSize:NSMiniControlSize];
- [cell setFont:[[NSFont fontWithName:[[cell font] fontName] size:[NSFont systemFontSizeForControlSize:NSMiniControlSize]] autorelease]];
+ [cell setFont:[NSFont fontWithName:[[cell font] fontName] size:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]];
for (size_t i=0; i<choices.GetCount(); ++i)
- [cell addItemWithTitle:[[wxCFStringRef(choices[i]).AsNSString() retain] autorelease]];
+ [cell addItemWithTitle:wxCFStringRef(choices[i]).AsNSString()];
SetNativeData(new wxDataViewRendererNativeData(cell));
[cell release];
}
+void
+wxDataViewChoiceRenderer::OSXOnCellChanged(NSObject *value,
+ const wxDataViewItem& item,
+ unsigned col)
+{
+ // At least under OS X 10.7 we get the index of the item selected and not
+ // its string.
+ wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+ model->ChangeValue(GetChoice(ObjectToLong(value)), item, col);
+}
+
bool wxDataViewChoiceRenderer::MacRender()
{
if (GetValue().GetType() == GetVariantType())
if (GetValue().GetDateTime().IsValid())
{
// -- find best fitting style to show the date --
- // as the style should be identical for all cells a reference date instead of the actual cell's date
- // value is used for all cells; this reference date is stored in the renderer's native data section
- // for speed purposes; otherwise, the reference date's string has to be recalculated for each item that
- // may become timewise long if a lot of rows using dates exist;
- // the algorithm has the preference to display as much information as possible in the first instance;
- // but as this is often impossible due to space restrictions the style is shortened per loop; finally,
- // if the shortest time and date format does not fit into the cell the time part is dropped;
- // remark: the time part itself is not modified per iteration loop and only uses the short style,
- // means that only the hours and minutes are being shown
- [GetNativeData()->GetItemCell() setObjectValue:GetNativeData()->GetObject()]; // GetObject() returns a date for testing the size of a date object
+ // as the style should be identical for all cells a reference date
+ // instead of the actual cell's date value is used for all cells;
+ // this reference date is stored in the renderer's native data
+ // section for speed purposes; otherwise, the reference date's
+ // string has to be recalculated for each item that may become
+ // timewise long if a lot of rows using dates exist; the algorithm
+ // has the preference to display as much information as possible
+ // in the first instance; but as this is often impossible due to
+ // space restrictions the style is shortened per loop; finally, if
+ // the shortest time and date format does not fit into the cell
+ // the time part is dropped; remark: the time part itself is not
+ // modified per iteration loop and only uses the short style,
+ // means that only the hours and minutes are being shown
+
+ // GetObject() returns a date for testing the size of a date object
+ [GetNativeData()->GetItemCell() setObjectValue:GetNativeData()->GetObject()];
[[GetNativeData()->GetItemCell() formatter] setTimeStyle:NSDateFormatterShortStyle];
for (int dateFormatterStyle=4; dateFormatterStyle>0; --dateFormatterStyle)
{
[[GetNativeData()->GetItemCell() formatter] setDateStyle:(NSDateFormatterStyle)dateFormatterStyle];
if (dateFormatterStyle == 1)
{
- // if the shortest style for displaying the date and time is too long to be fully visible remove the time part of the date:
+ // if the shortest style for displaying the date and time
+ // is too long to be fully visible remove the time part of
+ // the date:
if ([GetNativeData()->GetItemCell() cellSize].width > [GetNativeData()->GetColumnPtr() width])
[[GetNativeData()->GetItemCell() formatter] setTimeStyle:NSDateFormatterNoStyle];
- break; // basically not necessary as the loop would end anyway but let's save the last comparison
+ {
+ // basically not necessary as the loop would end anyway
+ // but let's save the last comparison
+ break;
+ }
}
else if ([GetNativeData()->GetItemCell() cellSize].width <= [GetNativeData()->GetColumnPtr() width])
break;
}
- // set data (the style is set by the previous loop);
- // on OSX the date has to be specified with respect to UTC; in wxWidgets the date is always entered in the local timezone; so, we have to do a conversion
- // from the local to UTC timezone when adding the seconds to 1970-01-01 UTC:
+ // set data (the style is set by the previous loop); on OSX the
+ // date has to be specified with respect to UTC; in wxWidgets the
+ // date is always entered in the local timezone; so, we have to do
+ // a conversion from the local to UTC timezone when adding the
+ // seconds to 1970-01-01 UTC:
[GetNativeData()->GetItemCell() setObjectValue:[NSDate dateWithTimeIntervalSince1970:GetValue().GetDateTime().ToUTC().Subtract(wxDateTime(1,wxDateTime::Jan,1970)).GetSeconds().ToDouble()]];
}
return true;
iconText << GetValue();
if (iconText.GetIcon().IsOk())
[cell setImage:[[wxBitmap(iconText.GetIcon()).GetNSImage() retain] autorelease]];
+ else
+ [cell setImage:nil];
[cell setStringValue:[[wxCFStringRef(iconText.GetText()).AsNSString() retain] autorelease]];
return true;
}
int align)
: wxDataViewRenderer(varianttype,mode,align)
{
+ wxUnusedVar(label);
+
NSLevelIndicatorCell* cell;
cell = [[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle];
m_title(title)
{
InitCommon(width, align, flags);
- if (renderer && (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
+ if (renderer && !renderer->IsCustomRenderer() &&
+ (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
renderer->SetAlignment(align);
}
m_NativeDataPtr(new wxDataViewColumnNativeData())
{
InitCommon(width, align, flags);
- if (renderer && (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
+ if (renderer && !renderer->IsCustomRenderer() &&
+ (renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
renderer->SetAlignment(align);
}
{
m_alignment = align;
[[m_NativeDataPtr->GetNativeColumnPtr() headerCell] setAlignment:ConvertToNativeHorizontalTextAlignment(align)];
- if (m_renderer && (m_renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
+ if (m_renderer && !m_renderer->IsCustomRenderer() &&
+ (m_renderer->GetAlignment() == wxDVR_DEFAULT_ALIGNMENT))
m_renderer->SetAlignment(align);
}
void wxDataViewColumn::SetBitmap(const wxBitmap& bitmap)
{
- // bitmaps and titles cannot exist at the same time - if the bitmap is set the title is removed:
+ // bitmaps and titles cannot exist at the same time - if the bitmap is set
+ // the title is removed:
m_title = wxEmptyString;
wxDataViewColumnBase::SetBitmap(bitmap);
[[m_NativeDataPtr->GetNativeColumnPtr() headerCell] setImage:[[bitmap.GetNSImage() retain] autorelease]];
void wxDataViewColumn::SetReorderable(bool reorderable)
{
+ wxUnusedVar(reorderable);
+}
+
+void wxDataViewColumn::SetHidden(bool hidden)
+{
+ // How to set flag here?
+
+ [m_NativeDataPtr->GetNativeColumnPtr() setHidden:hidden];
+}
+
+bool wxDataViewColumn::IsHidden() const
+{
+ return [m_NativeDataPtr->GetNativeColumnPtr() isHidden];
}
-void wxDataViewColumn::SetResizeable(bool resizeable)
+void wxDataViewColumn::SetResizeable(bool resizable)
{
- wxDataViewColumnBase::SetResizeable(resizeable);
- if (resizeable)
+ wxDataViewColumnBase::SetResizeable(resizable);
+ if (resizable)
[m_NativeDataPtr->GetNativeColumnPtr() setResizingMask:NSTableColumnUserResizingMask];
else
[m_NativeDataPtr->GetNativeColumnPtr() setResizingMask:NSTableColumnNoResizing];
void wxDataViewColumn::SetSortable(bool sortable)
{
- wxDataViewColumnBase::SetSortable(sortable);
+ // wxDataViewColumnBase::SetSortable(sortable);
+ // Avoid endless recursion and just set the flag here
+ if (sortable)
+ m_flags |= wxDATAVIEW_COL_SORTABLE;
+ else
+ m_flags &= ~wxDATAVIEW_COL_SORTABLE;
}
void wxDataViewColumn::SetSortOrder(bool ascending)
void wxDataViewColumn::SetTitle(const wxString& title)
{
- // bitmaps and titles cannot exist at the same time - if the title is set the bitmap is removed:
+ // bitmaps and titles cannot exist at the same time - if the title is set
+ // the bitmap is removed:
wxDataViewColumnBase::SetBitmap(wxBitmap());
m_title = title;
[[m_NativeDataPtr->GetNativeColumnPtr() headerCell] setStringValue:[[wxCFStringRef(title).AsNSString() retain] autorelease]];
void wxDataViewColumn::SetWidth(int width)
{
- [m_NativeDataPtr->GetNativeColumnPtr() setWidth:width];
m_width = width;
-}
-void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
-{
- // see wxGTK native wxDataViewColumn implementation
- wxFAIL_MSG("not implemented");
+ switch ( width )
+ {
+ case wxCOL_WIDTH_AUTOSIZE:
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+ if ( GetOwner() )
+ {
+ wxCocoaDataViewControl *peer = static_cast<wxCocoaDataViewControl*>(GetOwner()->GetPeer());
+ peer->FitColumnWidthToContent(GetOwner()->GetColumnPosition(this));
+ break;
+ }
+#endif
+ // fall through if unsupported (OSX < 10.5) or not yet settable
+
+ case wxCOL_WIDTH_DEFAULT:
+ width = wxDVC_DEFAULT_WIDTH;
+ // fall through
+
+ default:
+ [m_NativeDataPtr->GetNativeColumnPtr() setWidth:width];
+ break;
+ }
}
void wxDataViewColumn::SetNativeData(wxDataViewColumnNativeData* newNativeDataPtr)