Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  nsMacCursor.mm   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsMacCursor.h"
#include "nsObjCExceptions.h"
#include "nsDebug.h"
#include "nsDirectoryServiceDefs.h"
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsString.h"

/*! @category   nsMacCursor (PrivateMethods)
    @abstract   Private methods internal to the nsMacCursor class.
    @discussion <code>nsMacCursor</code> is effectively an abstract class. It
   does not define complete behaviour in and of itself, the subclasses defined
   in this file provide the useful implementations.
*/
@interface nsMacCursor (PrivateMethods)

/*! @method     getNextCursorFrame
    @abstract   get the index of the next cursor frame to display.
    @discussion Increments and returns the frame counter of an animated cursor.
    @result     The index of the next frame to display in the cursor animation
*/
- (int)getNextCursorFrame;

/*! @method     numFrames
    @abstract   Query the number of frames in this cursor's animation.
    @discussion Returns the number of frames in this cursor's animation. Static
   cursors return 1.
*/
- (int)numFrames;

/*! @method     createTimer
    @abstract   Create a Timer to use to animate the cursor.
    @discussion Creates an instance of <code>NSTimer</code> which is used to
   drive the cursor animation. This method should only be called for cursors
   that are animated.
*/
- (void)createTimer;

/*! @method     destroyTimer
    @abstract   Destroy any timer instance associated with this cursor.
    @discussion Invalidates and releases any <code>NSTimer</code> instance
   associated with this cursor.
 */
- (void)destroyTimer;
/*! @method     destroyTimer
    @abstract   Destroy any timer instance associated with this cursor.
    @discussion Invalidates and releases any <code>NSTimer</code> instance
   associated with this cursor.
*/

/*! @method     advanceAnimatedCursor:
    @abstract   Method called by animation timer to perform animation.
    @discussion Called by an animated cursor's associated timer to advance the
   animation to the next frame. Determines which frame should occur next and
   sets the cursor to that frame.
    @param      aTimer the timer causing the animation
*/
- (void)advanceAnimatedCursor:(NSTimer*)aTimer;

/*! @method     setFrame:
    @abstract   Sets the current cursor, using an index to determine which frame
   in the animation to display.
    @discussion Sets the current cursor. The frame index determines which frame
   is shown if the cursor is animated. Frames and numbered from <code>0</code>
   to <code>-[nsMacCursor numFrames] - 1</code>. A static cursor has a single
   frame, numbered 0.
    @param      aFrameIndex the index indicating which frame from the animation
   to display
*/
- (void)setFrame:(int)aFrameIndex;

@end

/*! @class      nsCocoaCursor
    @abstract   Implementation of <code>nsMacCursor</code> that uses Cocoa
   <code>NSCursor</code> instances.
    @discussion Displays a static or animated cursor, using Cocoa
   <code>NSCursor</code> instances. These can be either built-in
   <code>NSCursor</code> instances, or custom <code>NSCursor</code>s created
   from images. When more than one <code>NSCursor</code> is provided, the cursor
   will use these as animation frames.
*/
@interface nsCocoaCursor : nsMacCursor {
 @private
  NSArray* mFrames;
  NSCursor* mLastSetCocoaCursor;
}

/*! @method     initWithFrames:
    @abstract   Create an animated cursor by specifying the frames to use for
   the animation.
    @discussion Creates a cursor that will animate by cycling through the given
   frames. Each element of the array must be an instance of
   <code>NSCursor</code>
    @param      aCursorFrames an array of <code>NSCursor</code>, representing
   the frames of an animated cursor, in the order they should be played.
    @param      aType the corresponding <code>nsCursor</code> constant
    @result     an instance of <code>nsCocoaCursor</code> that will animate the
   given cursor frames
 */
- (id)initWithFrames:(NSArray*)aCursorFrames type:(nsCursor)aType;

/*! @method     initWithCursor:
    @abstract   Create a cursor by specifying a Cocoa <code>NSCursor</code>.
    @discussion Creates a cursor representing the given Cocoa built-in cursor.
    @param      aCursor the <code>NSCursor</code> to use
    @param      aType the corresponding <code>nsCursor</code> constant
    @result     an instance of <code>nsCocoaCursor</code> representing the given
   <code>NSCursor</code>
*/
- (id)initWithCursor:(NSCursor*)aCursor type:(nsCursor)aType;

/*! @method     initWithImageNamed:hotSpot:
    @abstract   Create a cursor by specifying the name of an image resource to
   use for the cursor and a hotspot.
    @discussion Creates a cursor by loading the named image using the
   <code>+[NSImage imageNamed:]</code> method. <p>The image must be compatible
   with any restrictions laid down by <code>NSCursor</code>. These vary by
   operating system version.</p> <p>The hotspot precisely determines the point
   where the user clicks when using the cursor.</p>
    @param      aCursor the name of the image to use for the cursor
    @param      aPoint the point within the cursor to use as the hotspot
    @param      aType the corresponding <code>nsCursor</code> constant
    @result     an instance of <code>nsCocoaCursor</code> that uses the given
   image and hotspot
*/
- (id)initWithImageNamed:(NSString*)aCursorImage
                 hotSpot:(NSPoint)aPoint
                    type:(nsCursor)aType;

@end

@implementation nsMacCursor

+ (nsMacCursor*)cursorWithCursor:(NSCursor*)aCursor type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return [[[nsCocoaCursor alloc] initWithCursor:aCursor
                                           type:aType] autorelease];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

+ (nsMacCursor*)cursorWithImageNamed:(NSString*)aCursorImage
                             hotSpot:(NSPoint)aPoint
                                type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return [[[nsCocoaCursor alloc] initWithImageNamed:aCursorImage
                                            hotSpot:aPoint
                                               type:aType] autorelease];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

+ (nsMacCursor*)cursorWithFrames:(NSArray*)aCursorFrames type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return [[[nsCocoaCursor alloc] initWithFrames:aCursorFrames
                                           type:aType] autorelease];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

+ (NSCursor*)cocoaCursorWithImageNamed:(NSString*)imageName
                               hotSpot:(NSPoint)aPoint {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  nsCOMPtr<nsIFile> resDir;
  nsAutoCString resPath;
  NSString *pathToImage, *pathToHiDpiImage;
  NSImage *cursorImage, *hiDpiCursorImage;

  nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(resDir));
  if (NS_FAILED(rv)) goto INIT_FAILURE;
  resDir->AppendNative("res"_ns);
  resDir->AppendNative("cursors"_ns);

  rv = resDir->GetNativePath(resPath);
  if (NS_FAILED(rv)) goto INIT_FAILURE;

  pathToImage = [NSString stringWithUTF8String:(const char*)resPath.get()];
  if (!pathToImage) goto INIT_FAILURE;
  pathToImage = [pathToImage stringByAppendingPathComponent:imageName];
  pathToHiDpiImage = [pathToImage stringByAppendingString:@"@2x"];
  // Add same extension to both image paths.
  pathToImage = [pathToImage stringByAppendingPathExtension:@"png"];
  pathToHiDpiImage = [pathToHiDpiImage stringByAppendingPathExtension:@"png"];

  cursorImage =
      [[[NSImage alloc] initWithContentsOfFile:pathToImage] autorelease];
  if (!cursorImage) goto INIT_FAILURE;

  // Note 1: There are a few different ways to get a hidpi image via
  // initWithContentsOfFile. We let the OS handle this here: when the
  // file basename ends in "@2x", it will be displayed at native resolution
  // instead of being pixel-doubled. See bug 784909 comment 7 for alternates
  // ways.
  //
  // Note 2: The OS is picky, and will ignore the hidpi representation
  // unless it is exactly twice the size of the lowdpi image.
  hiDpiCursorImage =
      [[[NSImage alloc] initWithContentsOfFile:pathToHiDpiImage] autorelease];
  if (hiDpiCursorImage) {
    NSImageRep* imageRep = [[hiDpiCursorImage representations] objectAtIndex:0];
    [cursorImage addRepresentation:imageRep];
  }
  return [[[NSCursor alloc] initWithImage:cursorImage
                                  hotSpot:aPoint] autorelease];

INIT_FAILURE:
  NS_WARNING("Problem getting path to cursor image file!");
  [self release];
  return nil;

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

- (BOOL)isSet {
  // implemented by subclasses
  return NO;
}

- (void)set {
  if ([self isAnimated]) {
    [self createTimer];
  }
  // if the cursor isn't animated or the timer creation fails for any reason...
  if (!mTimer) {
    [self setFrame:0];
  }
}

- (void)unset {
  [self destroyTimer];
}

- (BOOL)isAnimated {
  return [self numFrames] > 1;
}

- (int)numFrames {
  // subclasses need to override this to support animation
  return 1;
}

- (int)getNextCursorFrame {
  mFrameCounter = (mFrameCounter + 1) % [self numFrames];
  return mFrameCounter;
}

- (void)createTimer {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  if (!mTimer) {
    mTimer = [[NSTimer
        scheduledTimerWithTimeInterval:0.25
                                target:self
                              selector:@selector(advanceAnimatedCursor:)
                              userInfo:nil
                               repeats:YES] retain];
  }

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

- (void)destroyTimer {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  if (mTimer) {
    [mTimer invalidate];
    [mTimer release];
    mTimer = nil;
  }

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

- (void)advanceAnimatedCursor:(NSTimer*)aTimer {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  if ([aTimer isValid]) {
    [self setFrame:[self getNextCursorFrame]];
  }

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

- (void)setFrame:(int)aFrameIndex {
  // subclasses need to do something useful here
}

- (nsCursor)type {
  return mType;
}

- (void)dealloc {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  [self destroyTimer];
  [super dealloc];

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

@end

@implementation nsCocoaCursor

- (id)initWithFrames:(NSArray*)aCursorFrames type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  self = [super init];
  NSEnumerator* it = [aCursorFrames objectEnumerator];
  NSObject* frame = nil;
  while ((frame = [it nextObject])) {
    NS_ASSERTION([frame isKindOfClass:[NSCursor class]],
                 "Invalid argument: All frames must be of type NSCursor");
  }
  mFrames = [aCursorFrames retain];
  mFrameCounter = 0;
  mType = aType;
  return self;

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

- (id)initWithCursor:(NSCursor*)aCursor type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  NSArray* frame = [NSArray arrayWithObjects:aCursor, nil];
  return [self initWithFrames:frame type:aType];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

- (id)initWithImageNamed:(NSString*)aCursorImage
                 hotSpot:(NSPoint)aPoint
                    type:(nsCursor)aType {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return
      [self initWithCursor:[nsMacCursor cocoaCursorWithImageNamed:aCursorImage
                                                          hotSpot:aPoint]
                      type:aType];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

- (BOOL)isSet {
  return [NSCursor currentCursor] == mLastSetCocoaCursor;
}

- (void)setFrame:(int)aFrameIndex {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  NSCursor* newCursor = [mFrames objectAtIndex:aFrameIndex];
  [newCursor set];
  mLastSetCocoaCursor = newCursor;

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

- (int)numFrames {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return [mFrames count];

  NS_OBJC_END_TRY_BLOCK_RETURN(0);
}

- (NSString*)description {
  NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

  return [mFrames description];

  NS_OBJC_END_TRY_BLOCK_RETURN(nil);
}

- (void)dealloc {
  NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;

  [mFrames release];
  [super dealloc];

  NS_OBJC_END_TRY_IGNORE_BLOCK;
}

@end

[ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge