Home | History | Annotate | Download | only in cocoa
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/cocoa/table_row_nsimage_cache.h"
      6 
      7 #include "base/logging.h"
      8 #include "skia/ext/skia_utils_mac.h"
      9 #include "third_party/skia/include/core/SkBitmap.h"
     10 
     11 TableRowNSImageCache::TableRowNSImageCache(Table* model)
     12     : model_(model),
     13       icon_images_([[NSPointerArray alloc] initWithOptions:
     14           NSPointerFunctionsStrongMemory |
     15           NSPointerFunctionsObjectPersonality]) {
     16   int count = model_->RowCount();
     17   [icon_images_ setCount:count];
     18 }
     19 
     20 TableRowNSImageCache::~TableRowNSImageCache() {}
     21 
     22 void TableRowNSImageCache::OnModelChanged() {
     23   int count = model_->RowCount();
     24   [icon_images_ setCount:0];
     25   [icon_images_ setCount:count];
     26 }
     27 
     28 void TableRowNSImageCache::OnItemsChanged(int start, int length) {
     29   DCHECK_LE(start + length, static_cast<int>([icon_images_ count]));
     30   for (int i = start; i < (start + length); ++i) {
     31     [icon_images_ replacePointerAtIndex:i withPointer:NULL];
     32   }
     33   DCHECK_EQ(model_->RowCount(),
     34             static_cast<int>([icon_images_ count]));
     35 }
     36 
     37 void TableRowNSImageCache::OnItemsAdded(int start, int length) {
     38   DCHECK_LE(start, static_cast<int>([icon_images_ count]));
     39 
     40   // -[NSPointerArray insertPointer:atIndex:] throws if index == count.
     41   // Instead expand the array with NULLs.
     42   if (start == static_cast<int>([icon_images_ count])) {
     43     [icon_images_ setCount:start + length];
     44   } else {
     45     for (int i = 0; i < length; ++i) {
     46       [icon_images_ insertPointer:NULL atIndex:start];  // Values slide up.
     47     }
     48   }
     49   DCHECK_EQ(model_->RowCount(),
     50             static_cast<int>([icon_images_ count]));
     51 }
     52 
     53 void TableRowNSImageCache::OnItemsRemoved(int start, int length) {
     54   DCHECK_LE(start + length, static_cast<int>([icon_images_ count]));
     55   for (int i = 0; i < length; ++i) {
     56     [icon_images_ removePointerAtIndex:start];  // Values slide down.
     57   }
     58   DCHECK_EQ(model_->RowCount(),
     59             static_cast<int>([icon_images_ count]));
     60 }
     61 
     62 NSImage* TableRowNSImageCache::GetImageForRow(int row) {
     63   DCHECK_EQ(model_->RowCount(),
     64             static_cast<int>([icon_images_ count]));
     65   DCHECK_GE(row, 0);
     66   DCHECK_LT(row, static_cast<int>([icon_images_ count]));
     67   NSImage* image = static_cast<NSImage*>([icon_images_ pointerAtIndex:row]);
     68   if (!image) {
     69     const SkBitmap bitmap_icon =
     70         model_->GetIcon(row);
     71     // This means GetIcon() will get called until it returns a non-empty bitmap.
     72     // Empty bitmaps are intentionally not cached.
     73     if (!bitmap_icon.isNull()) {
     74       image = gfx::SkBitmapToNSImage(bitmap_icon);
     75       DCHECK(image);
     76       [icon_images_ replacePointerAtIndex:row withPointer:image];
     77     }
     78   }
     79   return image;
     80 }
     81 
     82