00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPNotificationCenter.j>
00024
00025 @import "CPControl.j"
00026 @import "CPImage.j"
00027 @import "CPShadowView.j"
00028
00029 #include "Platform/Platform.h"
00030 #include "Platform/DOM/CPDOMDisplayServer.h"
00031
00032 #include "CoreGraphics/CGGeometry.h"
00033
00034
00035
00036
00037
00038
00039 CPScaleProportionally = 0;
00040
00041
00042
00043
00044 CPScaleToFit = 1;
00045
00046
00047
00048
00049 CPScaleNone = 2;
00050
00051
00052 var CPImageViewShadowBackgroundColor = nil;
00053
00054 var LEFT_SHADOW_INSET = 3.0,
00055 RIGHT_SHADOW_INSET = 3.0,
00056 TOP_SHADOW_INSET = 3.0,
00057 BOTTOM_SHADOW_INSET = 5.0,
00058 VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET,
00059 HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET;
00060
00067 @implementation CPImageView : CPControl
00068 {
00069 DOMElement _DOMImageElement;
00070
00071 BOOL _hasShadow;
00072 CPView _shadowView;
00073
00074 CGRect _imageRect;
00075 }
00076
00077 - (id)initWithFrame:(CGRect)aFrame
00078 {
00079 self = [super initWithFrame:aFrame];
00080
00081 if (self)
00082 {
00083 #if PLATFORM(DOM)
00084 _DOMImageElement = document.createElement("img");
00085 _DOMImageElement.style.position = "absolute";
00086 _DOMImageElement.style.left = "0px";
00087 _DOMImageElement.style.top = "0px";
00088
00089 CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
00090
00091 _DOMImageElement.style.visibility = "hidden";
00092 #endif
00093 }
00094
00095 return self;
00096 }
00097
00101 - (CPImage)image
00102 {
00103 return [self objectValue];
00104 }
00105
00106 - (void)setImage:(CPImage)anImage
00107 {
00108 [self setObjectValue:anImage];
00109 }
00110
00112 - (void)setObjectValue:(CPImage)anImage
00113 {
00114 var oldImage = [self objectValue];
00115
00116 if (oldImage === anImage)
00117 return;
00118
00119 [super setObjectValue:anImage];
00120
00121 var defaultCenter = [CPNotificationCenter defaultCenter];
00122
00123 if (oldImage)
00124 [defaultCenter removeObserver:self name:CPImageDidLoadNotification object:oldImage];
00125
00126 var newImage = [self objectValue];
00127
00128 #if PLATFORM(DOM)
00129 _DOMImageElement.src = newImage ? [newImage filename] : "";
00130 #endif
00131
00132 var size = [newImage size];
00133
00134 if (size && size.width === -1 && size.height === -1)
00135 {
00136 [defaultCenter addObserver:self selector:@selector(imageDidLoad:) name:CPImageDidLoadNotification object:newImage];
00137
00138 #if PLATFORM(DOM)
00139 _DOMImageElement.width = 0;
00140 _DOMImageElement.height = 0;
00141 #endif
00142
00143 [_shadowView setHidden:YES];
00144 }
00145 else
00146 {
00147 [self hideOrDisplayContents];
00148 [self setNeedsLayout];
00149 [self setNeedsDisplay:YES];
00150 }
00151 }
00152
00153 - (void)imageDidLoad:(CPNotification)aNotification
00154 {
00155 [self hideOrDisplayContents];
00156
00157 [self setNeedsLayout];
00158 [self setNeedsDisplay:YES];
00159 }
00160
00165 - (BOOL)hasShadow
00166 {
00167 return _hasShadow;
00168 }
00169
00174 - (void)setHasShadow:(BOOL)shouldHaveShadow
00175 {
00176 if (_hasShadow == shouldHaveShadow)
00177 return;
00178
00179 _hasShadow = shouldHaveShadow;
00180
00181 if (_hasShadow)
00182 {
00183 _shadowView = [[CPShadowView alloc] initWithFrame:[self bounds]];
00184
00185 [self addSubview:_shadowView];
00186
00187 [self setNeedsLayout];
00188 [self setNeedsDisplay:YES];
00189 }
00190 else
00191 {
00192 [_shadowView removeFromSuperview];
00193
00194 _shadowView = nil;
00195 }
00196
00197 [self hideOrDisplayContents];
00198 }
00199
00205 - (void)setImageScaling:(CPImageScaling)anImageScaling
00206 {
00207 [super setImageScaling:anImageScaling];
00208
00209 #if PLATFORM(DOM)
00210 if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit)
00211 {
00212 CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0);
00213 }
00214 #endif
00215
00216 [self setNeedsLayout];
00217 [self setNeedsDisplay:YES];
00218 }
00219
00223 - (void)hideOrDisplayContents
00224 {
00225 if (![self image])
00226 {
00227 #if PLATFORM(DOM)
00228 _DOMImageElement.style.visibility = "hidden";
00229 #endif
00230 [_shadowView setHidden:YES];
00231 }
00232 else
00233 {
00234 #if PLATFORM(DOM)
00235 _DOMImageElement.style.visibility = "visible";
00236 #endif
00237 [_shadowView setHidden:NO];
00238 }
00239 }
00240
00244 - (CGRect)imageRect
00245 {
00246 return _imageRect;
00247 }
00248
00252 - (void)layoutSubviews
00253 {
00254 if (![self image])
00255 return;
00256
00257 var bounds = [self bounds],
00258 image = [self image],
00259 imageScaling = [self currentValueForThemeAttribute:@"image-scaling"],
00260 x = 0.0,
00261 y = 0.0,
00262 insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0),
00263 insetHeight = (_hasShadow ? VERTICAL_SHADOW_INSET : 0.0),
00264 boundsWidth = _CGRectGetWidth(bounds),
00265 boundsHeight = _CGRectGetHeight(bounds),
00266 width = boundsWidth - insetWidth,
00267 height = boundsHeight - insetHeight;
00268
00269 if (imageScaling === CPScaleToFit)
00270 {
00271 #if PLATFORM(DOM)
00272 _DOMImageElement.width = ROUND(width);
00273 _DOMImageElement.height = ROUND(height);
00274 #endif
00275 }
00276 else
00277 {
00278 var size = [image size];
00279
00280 if (size.width == -1 && size.height == -1)
00281 return;
00282
00283 if (imageScaling === CPScaleProportionally)
00284 {
00285
00286
00287 if (width >= size.width && height >= size.height)
00288 {
00289 width = size.width;
00290 height = size.height;
00291 }
00292 else
00293 {
00294 var imageRatio = size.width / size.height,
00295 viewRatio = width / height;
00296
00297 if (viewRatio > imageRatio)
00298 width = height * imageRatio;
00299 else
00300 height = width / imageRatio;
00301 }
00302
00303 #if PLATFORM(DOM)
00304 _DOMImageElement.width = ROUND(width);
00305 _DOMImageElement.height = ROUND(height);
00306 #endif
00307 }
00308 else
00309 {
00310 width = size.width;
00311 height = size.height;
00312 }
00313
00314 if (imageScaling == CPScaleNone)
00315 {
00316 #if PLATFORM(DOM)
00317 _DOMImageElement.width = ROUND(size.width);
00318 _DOMImageElement.height = ROUND(size.height);
00319 #endif
00320 }
00321
00322 var x = (boundsWidth - width) / 2.0,
00323 y = (boundsHeight - height) / 2.0;
00324
00325 #if PLATFORM(DOM)
00326 CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
00327 #endif
00328 }
00329
00330 _imageRect = _CGRectMake(x, y, width, height);
00331
00332 if (_hasShadow)
00333 [_shadowView setFrame:_CGRectMake(x - LEFT_SHADOW_INSET, y - TOP_SHADOW_INSET, width + insetWidth, height + insetHeight)];
00334 }
00335
00336 - (void)mouseDown:(CPEvent)anEvent
00337 {
00338
00339 [[self nextResponder] mouseDown:anEvent];
00340 }
00341
00342 @end
00343
00344 var CPImageViewImageKey = @"CPImageViewImageKey",
00345 CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
00346 CPImageViewHasShadowKey = @"CPImageViewHasShadowKey";
00347
00348 @implementation CPImageView (CPCoding)
00349
00355 - (id)initWithCoder:(CPCoder)aCoder
00356 {
00357 #if PLATFORM(DOM)
00358 _DOMImageElement = document.createElement("img");
00359 _DOMImageElement.style.position = "absolute";
00360 _DOMImageElement.style.left = "0px";
00361 _DOMImageElement.style.top = "0px";
00362 _DOMImageElement.style.visibility = "hidden";
00363 #endif
00364
00365 self = [super initWithCoder:aCoder];
00366
00367 if (self)
00368 {
00369 #if PLATFORM(DOM)
00370 _DOMElement.appendChild(_DOMImageElement);
00371 #endif
00372
00373 [self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
00374
00375 [self setNeedsLayout];
00376 [self setNeedsDisplay:YES];
00377 }
00378
00379 return self;
00380 }
00381
00387 - (void)encodeWithCoder:(CPCoder)aCoder
00388 {
00389
00390
00391 if (_shadowView)
00392 {
00393 var actualSubviews = _subviews;
00394
00395 _subviews = [_subviews copy];
00396 [_subviews removeObjectIdenticalTo:_shadowView];
00397 }
00398
00399 [super encodeWithCoder:aCoder];
00400
00401 if (_shadowView)
00402 _subviews = actualSubviews;
00403
00404 [aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
00405 }
00406
00407 @end