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 CPScaleProportionally = 0;
00035 CPScaleToFit = 1;
00036 CPScaleNone = 2;
00037
00038 var CPImageViewShadowBackgroundColor = nil;
00039
00040 var LEFT_SHADOW_INSET = 3.0,
00041 RIGHT_SHADOW_INSET = 3.0,
00042 TOP_SHADOW_INSET = 3.0,
00043 BOTTOM_SHADOW_INSET = 5.0,
00044 VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET,
00045 HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET;
00046
00053 @implementation CPImageView : CPControl
00054 {
00055 DOMElement _DOMImageElement;
00056
00057 BOOL _hasShadow;
00058 CPView _shadowView;
00059
00060 BOOL _isEditable;
00061
00062 CGRect _imageRect;
00063 }
00064
00065 - (id)initWithFrame:(CGRect)aFrame
00066 {
00067 self = [super initWithFrame:aFrame];
00068
00069 if (self)
00070 {
00071 #if PLATFORM(DOM)
00072 _DOMImageElement = document.createElement("img");
00073 _DOMImageElement.style.position = "absolute";
00074 _DOMImageElement.style.left = "0px";
00075 _DOMImageElement.style.top = "0px";
00076
00077 if ([CPPlatform supportsDragAndDrop])
00078 {
00079 _DOMImageElement.setAttribute("draggable", "true");
00080 _DOMImageElement.style["-khtml-user-drag"] = "element";
00081 }
00082
00083 CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement);
00084
00085 _DOMImageElement.style.visibility = "hidden";
00086 #endif
00087 }
00088
00089 return self;
00090 }
00091
00095 - (CPImage)image
00096 {
00097 return [self objectValue];
00098 }
00099
00100 - (void)setImage:(CPImage)anImage
00101 {
00102 [self setObjectValue:anImage];
00103 }
00104
00106 - (void)setObjectValue:(CPImage)anImage
00107 {
00108 var oldImage = [self objectValue];
00109
00110 if (oldImage === anImage)
00111 return;
00112
00113 [super setObjectValue:anImage];
00114
00115 var defaultCenter = [CPNotificationCenter defaultCenter];
00116
00117 if (oldImage)
00118 [defaultCenter removeObserver:self name:CPImageDidLoadNotification object:oldImage];
00119
00120 var newImage = [self objectValue];
00121
00122 #if PLATFORM(DOM)
00123 _DOMImageElement.src = newImage ? [newImage filename] : "";
00124 #endif
00125
00126 var size = [newImage size];
00127
00128 if (size && size.width === -1 && size.height === -1)
00129 {
00130 [defaultCenter addObserver:self selector:@selector(imageDidLoad:) name:CPImageDidLoadNotification object:newImage];
00131
00132 #if PLATFORM(DOM)
00133 _DOMImageElement.width = 0;
00134 _DOMImageElement.height = 0;
00135 #endif
00136
00137 [_shadowView setHidden:YES];
00138 }
00139 else
00140 {
00141 [self hideOrDisplayContents];
00142 [self setNeedsLayout];
00143 [self setNeedsDisplay:YES];
00144 }
00145 }
00146
00147 - (void)imageDidLoad:(CPNotification)aNotification
00148 {
00149 [self hideOrDisplayContents];
00150
00151 [self setNeedsLayout];
00152 [self setNeedsDisplay:YES];
00153 }
00154
00159 - (BOOL)hasShadow
00160 {
00161 return _hasShadow;
00162 }
00163
00168 - (void)setHasShadow:(BOOL)shouldHaveShadow
00169 {
00170 if (_hasShadow == shouldHaveShadow)
00171 return;
00172
00173 _hasShadow = shouldHaveShadow;
00174
00175 if (_hasShadow)
00176 {
00177 _shadowView = [[CPShadowView alloc] initWithFrame:[self bounds]];
00178
00179 [self addSubview:_shadowView];
00180
00181 [self setNeedsLayout];
00182 [self setNeedsDisplay:YES];
00183 }
00184 else
00185 {
00186 [_shadowView removeFromSuperview];
00187
00188 _shadowView = nil;
00189 }
00190
00191 [self hideOrDisplayContents];
00192 }
00193
00199 - (void)setImageScaling:(CPImageScaling)anImageScaling
00200 {
00201 [super setImageScaling:anImageScaling];
00202
00203 #if PLATFORM(DOM)
00204 if ([self currentValueForThemeAttribute:@"image-scaling"] === CPScaleToFit)
00205 {
00206 CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0);
00207 }
00208 #endif
00209
00210 [self setNeedsLayout];
00211 [self setNeedsDisplay:YES];
00212 }
00213
00214 - (unsigned)imageScaling
00215 {
00216 return [self currentValueForThemeAttribute:@"image-scaling"];
00217 }
00218
00222 - (void)hideOrDisplayContents
00223 {
00224 if (![self image])
00225 {
00226 #if PLATFORM(DOM)
00227 _DOMImageElement.style.visibility = "hidden";
00228 #endif
00229 [_shadowView setHidden:YES];
00230 }
00231 else
00232 {
00233 #if PLATFORM(DOM)
00234 _DOMImageElement.style.visibility = "visible";
00235 #endif
00236 [_shadowView setHidden:NO];
00237 }
00238 }
00239
00243 - (CGRect)imageRect
00244 {
00245 return _imageRect;
00246 }
00247
00251 - (void)layoutSubviews
00252 {
00253 if (![self image])
00254 return;
00255
00256 var bounds = [self bounds],
00257 image = [self image],
00258 imageScaling = [self currentValueForThemeAttribute:@"image-scaling"],
00259 x = 0.0,
00260 y = 0.0,
00261 insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0),
00262 insetHeight = (_hasShadow ? VERTICAL_SHADOW_INSET : 0.0),
00263 boundsWidth = _CGRectGetWidth(bounds),
00264 boundsHeight = _CGRectGetHeight(bounds),
00265 width = boundsWidth - insetWidth,
00266 height = boundsHeight - insetHeight;
00267
00268 if (imageScaling === CPScaleToFit)
00269 {
00270 #if PLATFORM(DOM)
00271 _DOMImageElement.width = ROUND(width);
00272 _DOMImageElement.height = ROUND(height);
00273 #endif
00274 }
00275 else
00276 {
00277 var size = [image size];
00278
00279 if (size.width == -1 && size.height == -1)
00280 return;
00281
00282 if (imageScaling === CPScaleProportionally)
00283 {
00284
00285
00286 if (width >= size.width && height >= size.height)
00287 {
00288 width = size.width;
00289 height = size.height;
00290 }
00291 else
00292 {
00293 var imageRatio = size.width / size.height,
00294 viewRatio = width / height;
00295
00296 if (viewRatio > imageRatio)
00297 width = height * imageRatio;
00298 else
00299 height = width / imageRatio;
00300 }
00301
00302 #if PLATFORM(DOM)
00303 _DOMImageElement.width = ROUND(width);
00304 _DOMImageElement.height = ROUND(height);
00305 #endif
00306 }
00307 else
00308 {
00309 width = size.width;
00310 height = size.height;
00311 }
00312
00313 if (imageScaling == CPScaleNone)
00314 {
00315 #if PLATFORM(DOM)
00316 _DOMImageElement.width = ROUND(size.width);
00317 _DOMImageElement.height = ROUND(size.height);
00318 #endif
00319 }
00320
00321 var x = (boundsWidth - width) / 2.0,
00322 y = (boundsHeight - height) / 2.0;
00323
00324 #if PLATFORM(DOM)
00325 CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y);
00326 #endif
00327 }
00328
00329 _imageRect = _CGRectMake(x, y, width, height);
00330
00331 if (_hasShadow)
00332 [_shadowView setFrame:_CGRectMake(x - LEFT_SHADOW_INSET, y - TOP_SHADOW_INSET, width + insetWidth, height + insetHeight)];
00333 }
00334
00335 - (void)mouseDown:(CPEvent)anEvent
00336 {
00337
00338 [[self nextResponder] mouseDown:anEvent];
00339 }
00340
00341 - (void)setEditable:(BOOL)shouldBeEditable
00342 {
00343 if (_isEditable === shouldBeEditable)
00344 return;
00345
00346 _isEditable = shouldBeEditable;
00347
00348 if (_isEditable)
00349 [self registerForDraggedTypes:[CPImagesPboardType]];
00350
00351 else
00352 {
00353 var draggedTypes = [self registeredDraggedTypes];
00354
00355 [self unregisterDraggedTypes];
00356
00357 [draggedTypes removeObjectIdenticalTo:CPImagesPboardType];
00358
00359 [self registerForDraggedTypes:draggedTypes];
00360 }
00361 }
00362
00363 - (BOOL)isEditable
00364 {
00365 return _isEditable;
00366 }
00367
00368 - (void)performDragOperation:(CPDraggingInfo)aSender
00369 {
00370 var images = [CPKeyedUnarchiver unarchiveObjectWithData:[[aSender draggingPasteboard] dataForType:CPImagesPboardType]];
00371
00372 if ([images count])
00373 [self setImage:images[0]];
00374 }
00375
00376 @end
00377
00378 var CPImageViewImageKey = @"CPImageViewImageKey",
00379 CPImageViewImageScalingKey = @"CPImageViewImageScalingKey",
00380 CPImageViewHasShadowKey = @"CPImageViewHasShadowKey",
00381 CPImageViewIsEditableKey = @"CPImageViewIsEditableKey";
00382
00383 @implementation CPImageView (CPCoding)
00384
00390 - (id)initWithCoder:(CPCoder)aCoder
00391 {
00392 #if PLATFORM(DOM)
00393 _DOMImageElement = document.createElement("img");
00394 _DOMImageElement.style.position = "absolute";
00395 _DOMImageElement.style.left = "0px";
00396 _DOMImageElement.style.top = "0px";
00397 _DOMImageElement.style.visibility = "hidden";
00398 if ([CPPlatform supportsDragAndDrop])
00399 {
00400 _DOMImageElement.setAttribute("draggable", "true");
00401 _DOMImageElement.style["-khtml-user-drag"] = "element";
00402 }
00403 #endif
00404
00405 self = [super initWithCoder:aCoder];
00406
00407 if (self)
00408 {
00409 #if PLATFORM(DOM)
00410 _DOMElement.appendChild(_DOMImageElement);
00411 #endif
00412
00413 [self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]];
00414
00415 if ([aCoder decodeBoolForKey:CPImageViewIsEditableKey] || NO)
00416 [self setEditable:YES];
00417
00418 [self setNeedsLayout];
00419 [self setNeedsDisplay:YES];
00420 }
00421
00422 return self;
00423 }
00424
00430 - (void)encodeWithCoder:(CPCoder)aCoder
00431 {
00432
00433
00434 if (_shadowView)
00435 {
00436 var actualSubviews = _subviews;
00437
00438 _subviews = [_subviews copy];
00439 [_subviews removeObjectIdenticalTo:_shadowView];
00440 }
00441
00442 [super encodeWithCoder:aCoder];
00443
00444 if (_shadowView)
00445 _subviews = actualSubviews;
00446
00447 [aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey];
00448
00449 if (_isEditable)
00450 [aCoder encodeBool:_isEditable forKey:CPImageViewIsEditableKey];
00451 }
00452
00453 @end