- // return the system-sized icon if we've got one
- if( sysIcon ) return *sysIcon;
- // return the first icon, if we have one
- return max > 0 ? m_icons[0] : wxNullIcon;
+ // Iterate over all icons searching for the exact match or the closest icon
+ // for FALLBACK_NEAREST_LARGER.
+ wxIcon iconBest;
+ int bestDiff = 0;
+ bool bestIsLarger = false;
+ bool bestIsSystem = false;
+
+ const size_t count = GetIconCount();
+
+ const wxIconArray& iconArray = M_ICONBUNDLEDATA->m_icons;
+ for ( size_t i = 0; i < count; i++ )
+ {
+ const wxIcon& icon = iconArray[i];
+ if ( !icon.IsOk() )
+ continue;
+ wxCoord sx = icon.GetWidth(),
+ sy = icon.GetHeight();
+
+ // Exact match ends search immediately in any case.
+ if ( sx == sizeX && sy == sizeY )
+ {
+ iconBest = icon;
+ break;
+ }
+
+ if ( flags & FALLBACK_SYSTEM )
+ {
+ if ( sx == sysX && sy == sysY )
+ {
+ iconBest = icon;
+ bestIsSystem = true;
+ continue;
+ }
+ }
+
+ if ( !bestIsSystem && (flags & FALLBACK_NEAREST_LARGER) )
+ {
+ bool iconLarger = (sx >= sizeX) && (sy >= sizeY);
+ int iconDiff = abs(sx - sizeX) + abs(sy - sizeY);
+
+ // Use current icon as candidate for the best icon, if either:
+ // - we have no candidate yet
+ // - we have no candidate larger than desired size and current icon is
+ // - current icon is closer to desired size than candidate
+ if ( !iconBest.IsOk() ||
+ (!bestIsLarger && iconLarger) ||
+ (iconLarger && (iconDiff < bestDiff)) )
+ {
+ iconBest = icon;
+ bestIsLarger = iconLarger;
+ bestDiff = iconDiff;
+ continue;
+ }
+ }
+ }
+
+#if defined( __WXMAC__ ) && wxOSX_USE_CARBON
+ if (!iconBest.IsOk())
+ return wxNullIcon;
+
+ return wxIcon(iconBest.GetHICON(), size);
+#else
+ return iconBest;
+#endif