// ---------------------------------------------------------------------------- // * HitTest // ---------------------------------------------------------------------------- void GuidoCarbonControl::HitTest( EventRef inEvent ) { OSStatus err; // Extract the mouse location Point localClick; err = ::GetEventParameter( inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &localClick); // Is the mouse in the view? Rect localBounds; ::GetControlBounds( GetControlRef(), &localBounds ); // printf( "Hit test (%d %d), bounds: %d, %d, %d, %d \n", where.h, where.v, bounds.left, // bounds.top, bounds.right, bounds.bottom ); ControlPartCode part = kControlNoPart; if( ::PtInRect( localClick, &localBounds )) part = 1; // Send back the value of the hit part err = ::SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, sizeof( ControlPartCode ), &part ); }
// ---------------------------------------------------------------------------- // * GetSize // ---------------------------------------------------------------------------- // Returns the size of the control, that is: the visible portion of the score. void GuidoCarbonControl::GetSize( int * oX, int * oY ) const { Rect bounds = { 0, 0, 0, 0 }; ::GetControlBounds( GetControlRef(), &bounds ); if( oX ) *oX = bounds.right - bounds.left; if( oY ) *oY = bounds.bottom - bounds.top; }
int wxMacDataBrowserListControl::DoListHitTest(const wxPoint& inpoint) const { OSStatus err; // There are few reasons why this is complicated: // 1) There is no native HitTest function for Mac // 2) GetDataBrowserItemPartBounds only works on visible items // 3) We can't do it through GetDataBrowserTableView[Item]RowHeight // because what it returns is basically inaccurate in the context // of the coordinates we want here, but we use this as a guess // for where the first visible item lies wxPoint point = inpoint; // get column property ID (req. for call to itempartbounds) DataBrowserTableViewColumnID colId = 0; err = GetDataBrowserTableViewColumnProperty(GetControlRef(), 0, &colId); wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty")); // OK, first we need to find the first visible item we have - // this will be the "low" for our binary search. There is no real // easy way around this, as we will need to do a SLOW linear search // until we find a visible item, but we can do a cheap calculation // via the row height to speed things up a bit UInt32 scrollx, scrolly; err = GetDataBrowserScrollPosition(GetControlRef(), &scrollx, &scrolly); wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserScrollPosition")); UInt16 height; err = GetDataBrowserTableViewRowHeight(GetControlRef(), &height); wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewRowHeight")); wxListBox *list = wxDynamicCast( GetWXPeer() , wxListBox ); // these indices are 0-based, as usual, so we need to add 1 to them when // passing them to data browser functions which use 1-based indices int low = scrolly / height, high = list->GetCount() - 1; // search for the first visible item (note that the scroll guess above // is the low bounds of where the item might lie so we only use that as a // starting point - we should reach it within 1 or 2 iterations of the loop) while ( low <= high ) { Rect bounds; err = GetDataBrowserItemPartBounds( GetControlRef(), low + 1, colId, kDataBrowserPropertyEnclosingPart, &bounds); // note +1 to translate to Mac ID if ( err == noErr ) break; // errDataBrowserItemNotFound is expected as it simply means that the // item is not currently visible -- but other errors are not wxCHECK_MSG( err == errDataBrowserItemNotFound, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserItemPartBounds") ); low++; } // NOW do a binary search for where the item lies, searching low again if // we hit an item that isn't visible while ( low <= high ) { int mid = (low + high) / 2; Rect bounds; err = GetDataBrowserItemPartBounds( GetControlRef(), mid + 1, colId, kDataBrowserPropertyEnclosingPart, &bounds); //note +1 to trans to mac id wxCHECK_MSG( err == noErr || err == errDataBrowserItemNotFound, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserItemPartBounds") ); if ( err == errDataBrowserItemNotFound ) { // item not visible, attempt to find a visible one // search lower high = mid - 1; } else // visible item, do actual hitttest { // if point is within the bounds, return this item (since we assume // all x coords of items are equal we only test the x coord in // equality) if ((point.x >= bounds.left && point.x <= bounds.right) && (point.y >= bounds.top && point.y <= bounds.bottom) ) { // found! return mid; } if ( point.y < bounds.top ) // index(bounds) greater than key(point) high = mid - 1; else // index(bounds) less than key(point) low = mid + 1; } } return wxNOT_FOUND; }
// ---------------------------------------------------------------------------- // * DoDraw // ---------------------------------------------------------------------------- void GuidoCarbonControl::DoDraw() { const GRHandler guidoRef = GetGuidoGR(); if( guidoRef == 0 ) return; ControlRef theControl = GetControlRef(); if( theControl == 0 ) return; // - Get our local size int localWidth; int localHeight; GetSize( &localWidth, &localHeight ); CGRect deviceRect = ::CGRectMake( 0, 0, localWidth, localHeight ); // VGDevice * device = GetGDevice(); // <- was const int kScrollBarHeight = 15; // - Create the graphic context. It must be initialized with the actual size of the window, // otherwise the y-origin is not calculated properly. WindowRef winRef = ::GetControlOwner( theControl ); GrafPtr port = ::GetWindowPort( winRef ); CGContextRef contextRef = 0; OSStatus status = ::CreateCGContextForPort( port, &contextRef ); if( status != noErr ) return; GSystemOSX system(contextRef, NULL); VGDevice* device = system.CreateDisplayDevice(); device->NotifySize(localWidth, localHeight + kScrollBarHeight ); ::CGContextRelease(contextRef); // because the device now owns the context. // - Draw the background device->BeginDraw(); device->PushPen( VGColor( 0, 0, 0, ALPHA_OPAQUE ), 1 ); device->PushFillColor( VGColor( 255, 255, 255, ALPHA_TRANSPARENT )); device->Rectangle( 0, 0, localWidth, localHeight ); device->PopFillColor(); device->PopPen(); // - Setup the clipping rectangle, to avoid drawing on scrollbars. ::CGContextClipToRect( contextRef, deviceRect ); // - Draw the music score int virtualScrollX = (int)((float)mScrollX * 10 / GetZoom()); int virtualScrollY = (int)((float)mScrollY * 10 / GetZoom()); float virtualVisibleWidth = localWidth * 10 / GetZoom(); float virtualVisibleHeight = localHeight * 10 / GetZoom(); float fullScoreWidth; float fullScoreHeight; GetFullScoreSize( &fullScoreWidth, &fullScoreHeight ); GuidoOnDrawDesc desc; desc.handle = guidoRef; desc.hdc = device; desc.updateRegion.erase = false; desc.updateRegion.left = virtualScrollX; // absolute virtual coordinates clip rect desc.updateRegion.top = virtualScrollY; desc.updateRegion.right = (int)(virtualScrollX + virtualVisibleWidth); desc.updateRegion.bottom = (int)(virtualScrollY + virtualVisibleHeight); desc.scrollx = (int)virtualScrollX; desc.scrolly = (int)virtualScrollY; desc.page = GetPageNum(); desc.sizex = (int)fullScoreWidth; desc.sizey = (int)fullScoreHeight; MClock clock; GuidoOnDraw( &desc ); // debug #if 0 std::cout << "Score : sizex = " << desc.sizex << " ; sizey = " << desc.sizey << std::endl; std::cout << "Guido: time do draw the score: " << clock.Milliseconds() << " ms" << std::endl; // std::cout << "Guido: graphical objects: " << GuidoGRObjectCount() << std::endl; #endif if( GetParam( kDrawSymbolMap ) == 1 ) DrawSymbolMap(); // drawMap (guidoRef, device, GetPageNum()); device->EndDraw(); delete device; }