ImageEditor.st
author Patrik Svestka <patrik.svestka@gmail.com>
Wed, 14 Nov 2018 12:07:51 +0100
branchjv
changeset 3630 5e718e0a754e
parent 3370 c88532134a2b
child 3374 2cb3e68941a8
permissions -rw-r--r--
Issue #239: Fix all Smalltak/X source files to be in unicode (UTF8 without BOM) and prefixed by "{ Encoding: utf8 }" when any unicode character is present

- All source *.st files are now Unicode UTF8 without BOM
Files are in two groups (fileOut works this way in Smalltalk/X):
- containing a unicode character have "{ Encoding: utf8 }" at the header
- ASCII only are without the header
     1 "
     2  COPYRIGHT (c) 1997-1998 by eXept Software AG
     3               All Rights Reserved
     4 
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice. This software may not
     8  be provided or otherwise made available to, or used by, any
     9  other person. No title to or ownership of the software is
    10  hereby transferred.
    11 "
    12 "{ Package: 'stx:libtool2' }"
    13 
    14 "{ NameSpace: Smalltalk }"
    15 
    16 ResourceSpecEditor subclass:#ImageEditor
    17 	instanceVariableNames:'imageEditView colorMapMode editMode mouseKeyColorMode
    18 		selectedColorIndex postOpenAction imageSeqNr drawingColormap
    19 		lastShiftUsedWrap lastGrabbedScreenArea
    20 		allowedToChangeImageDimensionAndDepth'
    21 	classVariableNames:'LastDirectory LastSizeString MaskClipboard LastColormapMode
    22 		DefaultRelativeSizes LastURL'
    23 	poolDictionaries:''
    24 	category:'Interface-UIPainter'
    25 !
    26 
    27 !ImageEditor class methodsFor:'documentation'!
    28 
    29 copyright
    30 "
    31  COPYRIGHT (c) 1997-1998 by eXept Software AG
    32               All Rights Reserved
    33 
    34  This software is furnished under a license and may be used
    35  only in accordance with the terms of that license and with the
    36  inclusion of the above copyright notice. This software may not
    37  be provided or otherwise made available to, or used by, any
    38  other person. No title to or ownership of the software is
    39  hereby transferred.
    40 "
    41 !
    42 
    43 documentation
    44 "
    45     Image Editor allows you to create, design, modify or just inspect images.
    46 
    47     [start with:]
    48         ImageEditor open
    49         ImageEditor openOnClass:Icon andSelector:#startIcon
    50 
    51     [see also:]
    52         ImageEditView Image
    53 
    54     [author:]
    55         Thomas Zwick, eXept Software AG
    56         Claus Gittinger, eXept Software AG
    57 "
    58 ! !
    59 
    60 !ImageEditor class methodsFor:'instance creation'!
    61 
    62 openLoadingImageWith:aBlock modal:modalBoolean
    63     "opens an Image Editor on anImage"
    64 
    65     |editor|
    66 
    67     editor := self new.
    68     editor allButOpen.
    69     aBlock value:editor.
    70     modalBoolean ifTrue:[
    71         editor openWindowModal.
    72     ] ifFalse:[
    73         editor openWindow.
    74     ].
    75     ^ editor
    76 !
    77 
    78 openModalOnClass: aClass andSelector: aSelector
    79     "opens a modal Image Editor on aClass and aSelector.
    80      Returns the real name of the edited resource method (in case, user changed it)."
    81 
    82     |imageEditor imageEditView className resourceClass resourceSelector| 
    83 
    84     imageEditor := self new.
    85 
    86     aClass isClass  ifTrue: [className := aClass name].
    87     aClass isString ifTrue: [className := aClass].      
    88     aClass isNil    ifTrue: [className := ''].      
    89 
    90     imageEditor postOpenAction: [
    91             imageEditView := imageEditor imageEditView. 
    92             imageEditor loadFromOrPrepareForClass: aClass andSelector: aSelector
    93         ].
    94     imageEditor openModal.
    95 
    96     resourceClass := imageEditView resourceClass.
    97     resourceSelector := imageEditView resourceSelector.
    98 
    99     (resourceClass isNil or:[resourceSelector isNil]) ifTrue:[^ nil].
   100     ^ Array with:resourceClass with:resourceSelector
   101 
   102     "
   103      self openModalOnClass: self andSelector: #leftMouseKeyIcon
   104     "
   105 !
   106 
   107 openModalOnFile:aFileName
   108     "opens an Image Editor on aFileName"
   109 
   110     self openLoadingImageWith:[:editor | 
   111         editor loadFromFile:aFileName.
   112     ] modal:true.
   113 
   114     "
   115      self openModalOnFile: '../../goodies/bitmaps/gifImages/back.gif'
   116     "
   117 !
   118 
   119 openModalOnImage:anImage
   120     "opens a modal Image Editor on an image.
   121      Returns the modified image or nil if unsaved/unchanged"
   122 
   123     |imageEditor imageEditView newImage| 
   124 
   125     imageEditor := self new.
   126     imageEditor allowedToChangeImageDimensionAndDepth:false.
   127     imageEditor postOpenAction: [
   128             imageEditView := imageEditor imageEditView. 
   129             imageEditor loadFromImage: anImage
   130         ].
   131     imageEditor openModal.
   132 
   133     newImage := imageEditor savedImage.
   134     ^ newImage
   135 !
   136 
   137 openOnClass:aClass andSelector:aSelector
   138     "opens an Image Editor on aClass and aSelector"
   139 
   140     self openLoadingImageWith:[:editor | 
   141         editor loadFromClass:aClass theNonMetaclass andSelector:aSelector.
   142     ] modal:false.
   143 
   144     "
   145      self openOnClass:self andSelector:#leftMouseKeyIcon
   146      self openOnClass:self andSelector:nil
   147     "
   148 
   149     "Modified: / 16.3.1999 / 21:33:49 / cg"
   150 !
   151 
   152 openOnFile:aFileName
   153     "opens an Image Editor on aFileName"
   154 
   155     self openLoadingImageWith:[:editor | 
   156         editor loadFromFile:aFileName.
   157     ] modal:false.
   158 
   159     "
   160      self openOnFile: '../../goodies/bitmaps/gifImages/back.gif'
   161     "
   162 
   163     "Modified: / 16.3.1999 / 21:33:25 / cg"
   164 !
   165 
   166 openOnImage:anImage
   167     "opens an Image Editor on anImage"
   168 
   169     self openLoadingImageWith:[:editor | 
   170         editor loadFromImage: anImage.
   171     ] modal:false
   172 
   173     "
   174      self openOnImage: Icon startIcon
   175     "
   176 
   177     "Modified: / 11.3.1999 / 16:18:33 / cg"
   178 ! !
   179 
   180 !ImageEditor class methodsFor:'accessing'!
   181 
   182 listOfColorMaps
   183     "returns the list of default color maps for a new image"
   184 
   185     |colorMap|
   186 
   187     (colorMap := OrderedCollection new)
   188         add: Color black;
   189         add: Color white;
   190         add: Color red;
   191         add: Color green;
   192         add: Color blue;
   193         add: Color cyan;
   194         add: Color yellow;
   195         add: Color magenta;
   196         add: (Color redByte: 127 greenByte:   0 blueByte:   0);
   197         add: (Color redByte:   0 greenByte: 127 blueByte:   0);
   198         add: (Color redByte:   0 greenByte:   0 blueByte: 127);
   199         add: (Color redByte:   0 greenByte: 127 blueByte: 127);
   200         add: (Color redByte: 127 greenByte: 127 blueByte:   0);
   201         add: (Color redByte: 127 greenByte:   0 blueByte: 127);
   202         add: (Color redByte: 127 greenByte: 127 blueByte: 127);
   203         add: (Color redByte: 170 greenByte: 170 blueByte: 170).
   204 
   205     0 to: 5 do: [:r|                                                    
   206         0 to: 5 do: [:g|
   207             0 to: 5 do: [:b|
   208                 colorMap add: (Color redByte: (r*255//5) ceiling greenByte: (g*255//5) ceiling blueByte: (b*255//5) ceiling)
   209             ]
   210         ]
   211     ].
   212 
   213     1 to: 25 do: [:g|                             
   214         colorMap add: (Color redByte: (g*255//26) ceiling greenByte: (g*255//26) ceiling blueByte: (g*255//26) ceiling)
   215     ].
   216 
   217     ^ Dictionary new
   218         at: #depth32 put:(FixedPalette redShift:16 redMask:16rFF greenShift:8 greenMask:16rFF blueShift:0 blueMask:16rFF);
   219         at: #depth24 put:(FixedPalette redShift:16 redMask:16rFF greenShift:8 greenMask:16rFF blueShift:0 blueMask:16rFF);
   220         at: #masked24 put:(FixedPalette redShift:16 redMask:16rFF greenShift:8 greenMask:16rFF blueShift:0 blueMask:16rFF);
   221         at: #depth16 put:(FixedPalette redShift:11 redMask:16r1F greenShift:5 greenMask:16r3F blueShift:0 blueMask:16r1F);
   222         at: #masked16 put:(FixedPalette redShift:11 redMask:16r1F greenShift:5 greenMask:16r3F blueShift:0 blueMask:16r1F);
   223         at: #depth8  put: colorMap;
   224         at: #masked8 put: colorMap;
   225         at: #depth4  put: (colorMap copyFrom: 1 to: 16);
   226         at: #masked4 put: (colorMap copyFrom: 1 to: 16);
   227         at: #depth2  put: (colorMap copyFrom: 1 to: 4);
   228         at: #masked2 put: (colorMap copyFrom: 1 to: 4);
   229         at: #depth1  put: (colorMap copyFrom: 1 to: 2);
   230         at: #masked1 put: (colorMap copyFrom: 1 to: 2);
   231         yourself
   232 !
   233 
   234 listOfDefaultSizes
   235     "returns the list of default sizes for a new image"
   236 
   237     ^ #('8x8' '16x16' '22x22' '32x32' '48x48' '64x64')
   238 
   239     "Modified: / 31.7.1998 / 01:57:34 / cg"
   240 !
   241 
   242 namesOfColorMaps
   243     ^ Dictionary new
   244         at: #depth32 put: '32-plane (rgba)';
   245         at: #depth24 put: '24-plane';
   246         at: #masked24 put: '24-plane + mask';
   247         at: #depth16 put: '16-plane';
   248         at: #masked16 put: '16-plane + mask';
   249         at: #depth8  put: ' 8-plane';
   250         at: #masked8 put: ' 8-plane + mask';
   251         at: #depth4  put: ' 4-plane';
   252         at: #masked4 put: ' 4-plane + mask';
   253         at: #depth2  put: ' 2-plane';
   254         at: #masked2 put: ' 2-plane + mask';
   255         at: #depth1  put: ' 1-plane';
   256         at: #masked1 put: ' 1-plane + mask' ;
   257         yourself
   258 ! !
   259 
   260 !ImageEditor class methodsFor:'help specs'!
   261 
   262 flyByHelpSpec
   263     <resource: #help>
   264 
   265     ^super flyByHelpSpec addPairsFrom:(self localHelpTexts)
   266 
   267     "Modified: / 19-01-2012 / 13:29:48 / cg"
   268 !
   269 
   270 helpSpec
   271     "This resource specification was automatically generated
   272      by the UIHelpTool of ST/X."
   273 
   274     "Do not manually edit this!! If it is corrupted,
   275      the UIHelpTool may not be able to read the specification."
   276 
   277     "
   278      UIHelpTool openOnClass:ImageEditor    
   279     "
   280 
   281     <resource: #help>
   282 
   283     ^ super helpSpec addPairsFrom:(self localHelpTexts)
   284 
   285     "Modified: / 19-01-2012 / 13:29:42 / cg"
   286 !
   287 
   288 localHelpTexts
   289     "This resource specification was automatically generated
   290      by the UIHelpTool of ST/X."
   291 
   292     "Do not manually edit this!! If it is corrupted,
   293      the UIHelpTool may not be able to read the specification."
   294 
   295     "
   296      UIHelpTool openOnClass:ImageEditor    
   297     "
   298 
   299     <resource: #help>
   300 
   301     ^ #(
   302 
   303 #xdrawModeBox
   304 'Rectangle'
   305 
   306 #xdrawModeCopy
   307 'Copy'
   308 
   309 #xdrawModeFill
   310 'Flood-fill'
   311 
   312 #xdrawModeFilledBox
   313 'Filled rectangle'
   314 
   315 #xdrawModePaste
   316 'Paste'
   317 
   318 #xdrawModePasteUnder
   319 'Paste under'
   320 
   321 #xdrawModePasteWithMask
   322 'Paste with Mask'
   323 
   324 #xdrawModePoint
   325 'Point'
   326 
   327 #xfileGrabImage
   328 'Pick from screen'
   329 
   330 #xfileLoadFromClass
   331 'Load from method...'
   332 
   333 #xfileLoadFromFile
   334 'Load from file...'
   335 
   336 #xfileNewImage
   337 'New image'
   338 
   339 #filePrint
   340 'Print'
   341 
   342 #xfileSaveAs
   343 'Save to file...'
   344 
   345 #xfileSaveMaskAs
   346 'Save mask to file...'
   347 
   348 #xfileSaveMethod
   349 'Save as method'
   350 
   351 #xfileSaveMethodAs
   352 'Save as Method...'
   353 
   354 #nextImageInSequence
   355 'Go to the next image in the animated gif image sequence.'
   356 
   357 #previousImageInSequence
   358 'Go to the previous image in the animated gif image sequence.'
   359 
   360 #colorMap
   361 'ColorMap functions'
   362 
   363 #colorMap1
   364 'Convert to depth-1 image'
   365 
   366 #colorMap1M
   367 'Convert to depth-1 image plus mask'
   368 
   369 #colorMap2
   370 'Convert to depth-2 image'
   371 
   372 #colorMap24
   373 'Convert to depth-24 image (rgb)'
   374 
   375 #colorMap2M
   376 'Convert to depth-2 image plus mask'
   377 
   378 #colorMap32
   379 'Convert to depth-32 image (rgba)'
   380 
   381 #colorMap4
   382 'Convert to depth-4 image'
   383 
   384 #colorMap4M
   385 'Convert to depth-4 image plus mask'
   386 
   387 #colorMap8
   388 'Convert to depth-8 image'
   389 
   390 #colorMap8M
   391 'Convert to depth-8 image plus mask'
   392 
   393 #colorMapTable
   394 'Shows a list of used colors of the image'
   395 
   396 #compressColormap
   397 'Remove unneeded entries from the colorMap'
   398 
   399 #cropAll
   400 'Find and remove all borders'
   401 
   402 #cropBottom
   403 'Find and remove bottom border'
   404 
   405 #cropLeft
   406 'Find and remove left border'
   407 
   408 #cropManual
   409 'Specify border(s) to remove.'
   410 
   411 #cropRight
   412 'Find and remove right border'
   413 
   414 #cropTop
   415 'Find and remove top border'
   416 
   417 #drawModeBox
   418 'Rectangle Drawing Mode'
   419 
   420 #drawModeCircle
   421 'Circle Drawing Mode'
   422 
   423 #drawModeCopy
   424 'Area Copy Mode'
   425 
   426 #drawModeFill
   427 'Flood Fill Mode'
   428 
   429 #drawModeFilledBox
   430 'Filled Rectangle Drawing Mode'
   431 
   432 #drawModePaste
   433 'Paste Mode'
   434 
   435 #drawModePasteUnder
   436 'Paste-Under Mode'
   437 
   438 #drawModePasteWithMask
   439 'Paste-with-Mask Mode'
   440 
   441 #drawModePoint
   442 'Point Drawing Mode'
   443 
   444 #drawModeSpecial
   445 'Special operations (select rectangle, then choose operation)'
   446 
   447 #drawModeSpray
   448 'Spray Drawing Mode'
   449 
   450 #editFlipHorizontal
   451 'Flip the image horizontally'
   452 
   453 #editFlipVertical
   454 'Flip the image vertically'
   455 
   456 #editMagnifyImage
   457 'Magnify the image'
   458 
   459 #editNegate
   460 'Invert the images colors'
   461 
   462 #editResize
   463 'Resize the image (preserving the old image)'
   464 
   465 #editRotate
   466 'Rotate the image'
   467 
   468 #fileGrabImageFromScreen
   469 'Pick an image from the screen (specify area)'
   470 
   471 #fileGrabImageFromWindow
   472 'Pick an image from a window on the screen (click on window)'
   473 
   474 #fileLoadFromClass
   475 'Select and load an image from a resource method'
   476 
   477 #fileLoadFromFile
   478 'Select and load an image from a file'
   479 
   480 #fileLoadFromURL
   481 'Load an image from the net, given its URL'
   482 
   483 #fileNewImage
   484 'Create a new image'
   485 
   486 #fileNewImageFromClipboard
   487 'Create a new image and initialize it from the clipboard'
   488 
   489 #fileNewMaskFromClipboard
   490 'Paste the image in the clipboard as a mask. Must be a depth-1 image'
   491 
   492 #filePrint
   493 'Print the image on a postscript printer'
   494 
   495 #fileSave
   496 'Save the image'
   497 
   498 #fileSaveAs
   499 'Save the image to a file'
   500 
   501 #fileSaveButtonImageAs
   502 'Save an image of a button with the image to a file (for html use)'
   503 
   504 #fileSaveMaskAs
   505 'Save the mask of the image to a file'
   506 
   507 #fileSaveMethod
   508 'Save the image as resource method in the current class and selector'
   509 
   510 #fileSaveMethodAs
   511 'Save the image as resource method in a class'
   512 
   513 #magnificationNumber
   514 'Shows the current magnification'
   515 
   516 #magnifyImageDown
   517 'Decrease magnification'
   518 
   519 #magnifyImageUp
   520 'Increase magnification'
   521 
   522 #mouseKeyColorMode
   523 'Toggle between left and right mouse button color'
   524 
   525 #previewView
   526 'Shows a preview of the image'
   527 
   528 #settingsGridMagnification
   529 'Change the grid magnification of the edit view'
   530 
   531 )
   532 
   533     "Created: / 19-01-2012 / 13:29:31 / cg"
   534 ! !
   535 
   536 !ImageEditor class methodsFor:'image specs'!
   537 
   538 circleIcon
   539     <resource: #image>
   540     "This resource specification was automatically generated
   541      by the ImageEditor of ST/X."
   542     "Do not manually edit this!! If it is corrupted,
   543      the ImageEditor may not be able to read the specification."
   544     "
   545      self circleIcon inspect
   546      ImageEditor openOnClass:self andSelector:#circleIcon
   547      Icon flushCachedIcons"
   548     
   549     ^ Icon constantNamed:'ImageEditor class circleIcon'
   550         ifAbsentPut:[
   551             (Depth1Image new)
   552                 width:14;
   553                 height:14;
   554                 photometric:(#palette);
   555                 bitsPerSample:(#( 1 ));
   556                 samplesPerPixel:(1);
   557                 bits:(ByteArray 
   558                             fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@C@@@@@@@@@@@@@@@a');
   559                 colorMapFromArray:#[ 0 0 0 255 0 0 ];
   560                 mask:((ImageMask new)
   561                             width:14;
   562                             height:14;
   563                             bits:(ByteArray 
   564                                         fromPackedString:'@@@@@@N@CF@PDA@PH@  BB@HDA@PD@1 @8@@@@@a');
   565                             yourself);
   566                 yourself
   567         ]
   568 !
   569 
   570 copyIcon
   571     <resource: #image>
   572     "This resource specification was automatically generated
   573      by the ImageEditor of ST/X."
   574     "Do not manually edit this!! If it is corrupted,
   575      the ImageEditor may not be able to read the specification."
   576     "
   577      self copyIcon inspect
   578      ImageEditor openOnClass:self andSelector:#copyIcon
   579      Icon flushCachedIcons"
   580     
   581     ^ Icon constantNamed:'ImageEditor class copyIcon'
   582         ifAbsentPut:[
   583             (Depth2Image new)
   584                 width:14;
   585                 height:14;
   586                 photometric:(#palette);
   587                 bitsPerSample:(#( 2 ));
   588                 samplesPerPixel:(1);
   589                 bits:(ByteArray 
   590                             fromPackedString:'@@@@@@@@@@@** @@J)UUTB*Z*)@*&**PJ)**$B*Z*)@*&**PJ)**$@@Z*)@@F**P@AUUT@@@@@@b');
   591                 colorMapFromArray:#[ 0 0 0 0 0 128 255 255 255 ];
   592                 mask:((ImageMask new)
   593                             width:14;
   594                             height:14;
   595                             bits:(ByteArray 
   596                                         fromPackedString:'@@C? O>@??3??O?<??3??O?<??3??@_<A?0@@@@a');
   597                             yourself);
   598                 yourself
   599         ]
   600 !
   601 
   602 defaultIcon
   603     <resource: #programImage>
   604 
   605     ^ ToolbarIconLibrary startImageEditorIcon
   606 !
   607 
   608 fillGradientRectIcon
   609     <resource: #image>
   610     "This resource specification was automatically generated
   611      by the ImageEditor of ST/X."
   612     "Do not manually edit this!! If it is corrupted,
   613      the ImageEditor may not be able to read the specification."
   614     "
   615      self fillGradientRectIcon inspect
   616      ImageEditor openOnClass:self andSelector:#fillGradientRectIcon
   617      Icon flushCachedIcons"
   618     
   619     ^ Icon constantNamed:'ImageEditor class fillGradientRectIcon'
   620         ifAbsentPut:[
   621             (Depth4Image new)
   622                 width:14;
   623                 height:14;
   624                 photometric:(#palette);
   625                 bitsPerSample:(#[ 4 ]);
   626                 samplesPerPixel:(1);
   627                 bits:(ByteArray 
   628                             fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ADQDQDQ@@@QDQDQDP@@BH"H"H"@@@"H"H"H @@L3L3L3L@@CL3L3L3@@@QDQDQDP@@DQDQDQD@@@@@@@@@
   629 @@@@@@@@@@@b');
   630                 colorMapFromArray:#[ 0 0 0 255 0 0 127 0 0 191 0 0 63 0 0 ];
   631                 mask:((ImageMask new)
   632                             width:14;
   633                             height:14;
   634                             bits:(ByteArray 
   635                                         fromPackedString:'@@@@@C?0O?@?<C?0O?@?<C?0O?@?<C?0@@@@@@@a');
   636                             yourself);
   637                 yourself
   638         ]
   639 !
   640 
   641 fillHorizontalGradientRectIcon
   642     <resource: #image>
   643     "This resource specification was automatically generated
   644      by the ImageEditor of ST/X."
   645     "Do not manually edit this!! If it is corrupted,
   646      the ImageEditor may not be able to read the specification."
   647     "
   648      self fillHorizontalGradientRectIcon inspect
   649      ImageEditor openOnClass:self andSelector:#fillHorizontalGradientRectIcon
   650      Icon flushCachedIcons"
   651     
   652     ^ Icon constantNamed:'ImageEditor class fillHorizontalGradientRectIcon'
   653         ifAbsentPut:[
   654             (Depth4Image new)
   655                 width:14;
   656                 height:14;
   657                 photometric:(#palette);
   658                 bitsPerSample:(#[ 4 ]);
   659                 samplesPerPixel:(1);
   660                 bits:(ByteArray 
   661                             fromPackedString:'@@@@@@@@@@@@@@@@@@@@@DP"L1D@@@ADH#LQ@@@@QBH3DP@@@DP"L1D@@@ADH#LQ@@@@QBH3DP@@@DP"L1D@@@ADH#LQ@@@@QBH3DP@@@DP"L1D@@@@@@@@@
   662 @@@@@@@@@@@b');
   663                 colorMapFromArray:#[ 0 0 0 255 0 0 127 0 0 191 0 0 63 0 0 ];
   664                 mask:((ImageMask new)
   665                             width:14;
   666                             height:14;
   667                             bits:(ByteArray 
   668                                         fromPackedString:'@@@@@C?0O?@?<C?0O?@?<C?0O?@?<C?0@@@@@@@a');
   669                             yourself);
   670                 yourself
   671         ]
   672 !
   673 
   674 fillIcon
   675     <resource: #image>
   676     "This resource specification was automatically generated
   677      by the ImageEditor of ST/X."
   678     "Do not manually edit this!! If it is corrupted,
   679      the ImageEditor may not be able to read the specification."
   680     "
   681      self fillIcon inspect
   682      ImageEditor openOnClass:self andSelector:#fillIcon
   683      Icon flushCachedIcons"
   684     
   685     ^ Icon constantNamed:'ImageEditor class fillIcon'
   686         ifAbsentPut:[
   687             (Depth2Image new)
   688                 width:14;
   689                 height:14;
   690                 photometric:(#palette);
   691                 bitsPerSample:(#( 2 ));
   692                 samplesPerPixel:(1);
   693                 bits:(ByteArray 
   694                             fromPackedString:'@@@@@@@@@@@@@ @@@@*H@@D*(@@DUUP@EAUU@AAEU@@@@U@@DDA@@@@@@@@PP@@@@@@@@@@@@@@b');
   695                 colorMapFromArray:#[ 0 0 0 255 0 0 255 255 255 ];
   696                 mask:((ImageMask new)
   697                             width:14;
   698                             height:14;
   699                             bits:(ByteArray 
   700                                         fromPackedString:'C @Q@BN@I<@?8C?0[?!!G<@O P\@@ D@@@@@@@@@a');
   701                             yourself);
   702                 yourself
   703         ]
   704 !
   705 
   706 fillRectIcon
   707     <resource: #image>
   708     "This resource specification was automatically generated
   709      by the ImageEditor of ST/X."
   710     "Do not manually edit this!! If it is corrupted,
   711      the ImageEditor may not be able to read the specification."
   712     "
   713      self fillRectIcon inspect
   714      ImageEditor openOnClass:self andSelector:#fillRectIcon
   715      Icon flushCachedIcons"
   716     
   717     ^ Icon constantNamed:'ImageEditor class fillRectIcon'
   718         ifAbsentPut:[
   719             (Depth1Image new)
   720                 width:14;
   721                 height:14;
   722                 photometric:(#palette);
   723                 bitsPerSample:(#( 1 ));
   724                 samplesPerPixel:(1);
   725                 bits:(ByteArray 
   726                             fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@@D@@@@a');
   727                 colorMapFromArray:#[ 0 0 0 255 0 0 ];
   728                 mask:((ImageMask new)
   729                             width:14;
   730                             height:14;
   731                             bits:(ByteArray 
   732                                         fromPackedString:'@@@@@C?0O?@?<C?0O?@?<C?0O?@?<C?0@@@@@@@a');
   733                             yourself);
   734                 yourself
   735         ]
   736 !
   737 
   738 fillVerticalGradientRectIcon
   739     <resource: #image>
   740     "This resource specification was automatically generated
   741      by the ImageEditor of ST/X."
   742     "Do not manually edit this!! If it is corrupted,
   743      the ImageEditor may not be able to read the specification."
   744     "
   745      self fillGradientRectIcon inspect
   746      ImageEditor openOnClass:self andSelector:#fillGradientRectIcon
   747      Icon flushCachedIcons"
   748     
   749     ^ Icon constantNamed:'ImageEditor class fillGradientRectIcon'
   750         ifAbsentPut:[
   751             (Depth4Image new)
   752                 width:14;
   753                 height:14;
   754                 photometric:(#palette);
   755                 bitsPerSample:(#[ 4 ]);
   756                 samplesPerPixel:(1);
   757                 bits:(ByteArray 
   758                             fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ADQDQDQ@@@QDQDQDP@@BH"H"H"@@@"H"H"H @@L3L3L3L@@CL3L3L3@@@QDQDQDP@@DQDQDQD@@@@@@@@@
   759 @@@@@@@@@@@b');
   760                 colorMapFromArray:#[ 0 0 0 255 0 0 127 0 0 191 0 0 63 0 0 ];
   761                 mask:((ImageMask new)
   762                             width:14;
   763                             height:14;
   764                             bits:(ByteArray 
   765                                         fromPackedString:'@@@@@C?0O?@?<C?0O?@?<C?0O?@?<C?0@@@@@@@a');
   766                             yourself);
   767                 yourself
   768         ]
   769 
   770     "Created: / 19-01-2012 / 13:44:51 / cg"
   771 !
   772 
   773 flipHorizontalIcon
   774     <resource: #image>
   775     "This resource specification was automatically generated
   776      by the ImageEditor of ST/X."
   777     "Do not manually edit this!! If it is corrupted,
   778      the ImageEditor may not be able to read the specification."
   779     "
   780      self flipHorizontalIcon inspect
   781      ImageEditor openOnClass:self andSelector:#flipHorizontalIcon
   782      Icon flushCachedIcons"
   783     
   784     ^ Icon constantNamed:'ImageEditor class flipHorizontalIcon'
   785         ifAbsentPut:[
   786             (Depth1Image new)
   787                 width:14;
   788                 height:14;
   789                 photometric:(#palette);
   790                 bitsPerSample:(#( 1 ));
   791                 samplesPerPixel:(1);
   792                 bits:(ByteArray 
   793                             fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a');
   794                 colorMapFromArray:#[ 0 0 0 ];
   795                 mask:((ImageMask new)
   796                             width:14;
   797                             height:14;
   798                             bits:(ByteArray 
   799                                         fromPackedString:'@@@A@C?8HP )JC$8_?1??C$8JR !!BC?8@P@@@@@a');
   800                             yourself);
   801                 yourself
   802         ]
   803 !
   804 
   805 flipVerticalIcon
   806     <resource: #image>
   807     "This resource specification was automatically generated
   808      by the ImageEditor of ST/X."
   809     "Do not manually edit this!! If it is corrupted,
   810      the ImageEditor may not be able to read the specification."
   811     "
   812      self flipVerticalIcon inspect
   813      ImageEditor openOnClass:self andSelector:#flipVerticalIcon
   814      Icon flushCachedIcons"
   815     
   816     ^ Icon constantNamed:'ImageEditor class flipVerticalIcon'
   817         ifAbsentPut:[
   818             (Depth1Image new)
   819                 width:14;
   820                 height:14;
   821                 photometric:(#palette);
   822                 bitsPerSample:(#( 1 ));
   823                 samplesPerPixel:(1);
   824                 bits:(ByteArray 
   825                             fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@a');
   826                 colorMapFromArray:#[ 0 0 0 ];
   827                 mask:((ImageMask new)
   828                             width:14;
   829                             height:14;
   830                             bits:(ByteArray 
   831                                         fromPackedString:'@@@C@C?0I9@/4BLPH1A?>BLPH1@/4B^PO?@C@@@a');
   832                             yourself);
   833                 yourself
   834         ]
   835 !
   836 
   837 leftMouseKeyIcon
   838     <resource: #image>
   839     "This resource specification was automatically generated
   840      by the ImageEditor of ST/X."
   841     "Do not manually edit this!! If it is corrupted,
   842      the ImageEditor may not be able to read the specification."
   843     "
   844      self leftMouseKeyIcon inspect
   845      ImageEditor openOnClass:self andSelector:#leftMouseKeyIcon
   846      Icon flushCachedIcons"
   847     
   848     ^ Icon constantNamed:'ImageEditor class leftMouseKeyIcon'
   849         ifAbsentPut:[
   850             (Depth2Image new)
   851                 width:16;
   852                 height:16;
   853                 photometric:(#palette);
   854                 bitsPerSample:(#( 2 ));
   855                 samplesPerPixel:(1);
   856                 bits:(ByteArray 
   857                             fromPackedString:'@@@@@@@@@@@@@@@@@EJJ@@AR" @@T((@@@@@@@B** @@**(@@J**@@B** @@**(@@J**@@@**@@@@@@@@@@@@@@a');
   858                 colorMapFromArray:#[ 0 0 0 255 0 0 255 255 255 ];
   859                 mask:((ImageMask new)
   860                             width:16;
   861                             height:16;
   862                             bits:(ByteArray 
   863                                         fromPackedString:'@@@@@@?0G? _>A?8G? _>A?8G? _>A?8G? O<@_ @@@b');
   864                             yourself);
   865                 yourself
   866         ]
   867 !
   868 
   869 pasteIcon
   870     <resource: #image>
   871     "This resource specification was automatically generated
   872      by the ImageEditor of ST/X."
   873     "Do not manually edit this!! If it is corrupted,
   874      the ImageEditor may not be able to read the specification."
   875     "
   876      self pasteIcon inspect
   877      ImageEditor openOnClass:self andSelector:#pasteIcon
   878      Icon flushCachedIcons"
   879     
   880     ^ Icon constantNamed:'ImageEditor class pasteIcon'
   881         ifAbsentPut:[
   882             (Depth4Image new)
   883                 width:14;
   884                 height:14;
   885                 photometric:(#palette);
   886                 bitsPerSample:(#( 4 ));
   887                 samplesPerPixel:(1);
   888                 bits:(ByteArray 
   889                             fromPackedString:'@@@@@@@@@@@@AU@@@@@CHE@E@2@@@ QDQD@0@@L@@@@@H@@BL#H2L#@@@QDQDQL @@D3L@@@@@@AL3A&Y&X@@SL0Y A&@@D3LF@@A @AL3A&@FX@@QDPY&Y&
   890 @@@@@@@@@@@b');
   891                 colorMapFromArray:#[ 0 0 0 0 0 128 128 128 0 128 128 128 212 208 200 255 255 0 255 255 255 ];
   892                 mask:((ImageMask new)
   893                             width:14;
   894                             height:14;
   895                             bits:(ByteArray 
   896                                         fromPackedString:'C0A?8O?0??C?<O?0??C?>O?8??#?>O?8_? G>@@a');
   897                             yourself);
   898                 yourself
   899         ]
   900 !
   901 
   902 pasteUnderIcon
   903     <resource: #image>
   904     "This resource specification was automatically generated
   905      by the ImageEditor of ST/X."
   906     "Do not manually edit this!! If it is corrupted,
   907      the ImageEditor may not be able to read the specification."
   908     "
   909      self pasteUnderIcon inspect
   910      ImageEditor openOnClass:self andSelector:#pasteUnderIcon
   911      Icon flushCachedIcons"
   912     
   913     ^ Icon constantNamed:'ImageEditor class pasteUnderIcon'
   914         ifAbsentPut:[
   915             (Depth4Image new)
   916                 width:14;
   917                 height:14;
   918                 photometric:(#palette);
   919                 bitsPerSample:(#( 4 ));
   920                 samplesPerPixel:(1);
   921                 bits:(ByteArray 
   922                             fromPackedString:'@@@@@@@@@@@@AU@@@@@CHE@E@2@@@ QDQD@0@@L@@@@@H@@BL#H2L#@@@QDQDQL @@D3L3LP@@@AL3L3E&X@@SL3L0A&@@D3L3@@A @AL3L3@FX@@QDQDQY&
   923 @@@@@@@@@@@b');
   924                 colorMapFromArray:#[ 0 0 0 0 0 128 128 128 0 128 128 128 212 208 200 255 255 0 255 255 255 ];
   925                 mask:((ImageMask new)
   926                             width:14;
   927                             height:14;
   928                             bits:(ByteArray 
   929                                         fromPackedString:'C0A?8O?0??C?<O?0??C?>O?8??#?>O?8_? G>@@a');
   930                             yourself);
   931                 yourself
   932         ]
   933 !
   934 
   935 pasteWithMaskIcon
   936     <resource: #image>
   937     "This resource specification was automatically generated
   938      by the ImageEditor of ST/X."
   939     "Do not manually edit this!! If it is corrupted,
   940      the ImageEditor may not be able to read the specification."
   941     "
   942      self pasteWithMaskIcon inspect
   943      ImageEditor openOnClass:self andSelector:#pasteWithMaskIcon
   944      Icon flushCachedIcons"
   945     
   946     ^ Icon constantNamed:'ImageEditor class pasteWithMaskIcon'
   947         ifAbsentPut:[
   948             (Depth4Image new)
   949                 width:14;
   950                 height:14;
   951                 photometric:(#palette);
   952                 bitsPerSample:(#( 4 ));
   953                 samplesPerPixel:(1);
   954                 bits:(ByteArray 
   955                             fromPackedString:'@@@@@@@@@@@@AU@@@@@CHE@E@2@@@ QDQD@0@@L@@@@@H@@BL#H2L#@@@QDQDQL @@D3L@@@@@@AL3@3M&X@@SL0L3A&@@D3LCL0A @AL3@3LFX@@QDPY&Y&
   956 @@@@@@@@@@@b');
   957                 colorMapFromArray:#[ 0 0 0 0 0 128 128 128 0 128 128 128 212 208 200 255 255 0 255 255 255 ];
   958                 mask:((ImageMask new)
   959                             width:14;
   960                             height:14;
   961                             bits:(ByteArray 
   962                                         fromPackedString:'C0A?8O?0??C?<O?0??C?>O?8??#?>O?8_? G>@@a');
   963                             yourself);
   964                 yourself
   965         ]
   966 !
   967 
   968 pointIcon
   969     <resource: #image>
   970     "This resource specification was automatically generated
   971      by the ImageEditor of ST/X."
   972     "Do not manually edit this!! If it is corrupted,
   973      the ImageEditor may not be able to read the specification."
   974     "
   975      self pointIcon inspect
   976      ImageEditor openOnClass:self andSelector:#pointIcon
   977      Icon flushCachedIcons"
   978     
   979     ^ Icon constantNamed:'ImageEditor class pointIcon'
   980         ifAbsentPut:[
   981             (Depth1Image new)
   982                 width:14;
   983                 height:14;
   984                 photometric:(#palette);
   985                 bitsPerSample:(#( 1 ));
   986                 samplesPerPixel:(1);
   987                 bits:(ByteArray 
   988                             fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@C@@@@@@@@@@@@@@@a');
   989                 colorMapFromArray:#[ 0 0 0 255 255 255 ];
   990                 mask:((ImageMask new)
   991                             width:14;
   992                             height:14;
   993                             bits:(ByteArray 
   994                                         fromPackedString:'@@@@@@@0@G@@8@G@@8@G@@8@G@@X@@@@@@@@@@@a');
   995                             yourself);
   996                 yourself
   997         ]
   998 !
   999 
  1000 rectIcon
  1001     <resource: #image>
  1002     "This resource specification was automatically generated
  1003      by the ImageEditor of ST/X."
  1004     "Do not manually edit this!! If it is corrupted,
  1005      the ImageEditor may not be able to read the specification."
  1006     "
  1007      self rectIcon inspect
  1008      ImageEditor openOnClass:self andSelector:#rectIcon
  1009      Icon flushCachedIcons"
  1010     
  1011     ^ Icon constantNamed:'ImageEditor class rectIcon'
  1012         ifAbsentPut:[
  1013             (Depth1Image new)
  1014                 width:14;
  1015                 height:14;
  1016                 photometric:(#palette);
  1017                 bitsPerSample:(#( 1 ));
  1018                 samplesPerPixel:(1);
  1019                 bits:(ByteArray 
  1020                             fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@C@@@@@@@@@@@@@@@a');
  1021                 colorMapFromArray:#[ 0 0 0 255 0 0 ];
  1022                 mask:((ImageMask new)
  1023                             width:14;
  1024                             height:14;
  1025                             bits:(ByteArray 
  1026                                         fromPackedString:'@@@@@C?0HA@ DB@PHA@ DB@PHA@ DC?0@@@@@@@a');
  1027                             yourself);
  1028                 yourself
  1029         ]
  1030 !
  1031 
  1032 rightMouseKeyIcon
  1033     <resource: #image>
  1034     "This resource specification was automatically generated
  1035      by the ImageEditor of ST/X."
  1036     "Do not manually edit this!! If it is corrupted,
  1037      the ImageEditor may not be able to read the specification."
  1038     "
  1039      self rightMouseKeyIcon inspect
  1040      ImageEditor openOnClass:self andSelector:#rightMouseKeyIcon
  1041      Icon flushCachedIcons"
  1042     
  1043     ^ Icon constantNamed:'ImageEditor class rightMouseKeyIcon'
  1044         ifAbsentPut:[
  1045             (Depth2Image new)
  1046                 width:16;
  1047                 height:16;
  1048                 photometric:(#palette);
  1049                 bitsPerSample:(#( 2 ));
  1050                 samplesPerPixel:(1);
  1051                 bits:(ByteArray 
  1052                             fromPackedString:'@@@@@@@@@@@@@@@@@JJE@@B"!!P@@((T@@@@@@@B** @@**(@@J**@@B** @@**(@@J**@@@**@@@@@@@@@@@@@@a');
  1053                 colorMapFromArray:#[ 0 0 0 255 0 0 255 255 255 ];
  1054                 mask:((ImageMask new)
  1055                             width:16;
  1056                             height:16;
  1057                             bits:(ByteArray 
  1058                                         fromPackedString:'@@@@@@?0G? _>A?8G? _>A?8G? _>A?8G? O<@_ @@@b');
  1059                             yourself);
  1060                 yourself
  1061         ]
  1062 !
  1063 
  1064 smoothIcon
  1065     "This resource specification was automatically generated
  1066      by the ImageEditor of ST/X."
  1067 
  1068     "Do not manually edit this!! If it is corrupted,
  1069      the ImageEditor may not be able to read the specification."
  1070 
  1071     "
  1072      self smoothIcon inspect
  1073      ImageEditor openOnClass:self andSelector:#smoothIcon
  1074      Icon flushCachedIcons
  1075     "
  1076 
  1077     <resource: #image>
  1078 
  1079     ^Icon
  1080         constantNamed:'ImageEditor smoothIcon'
  1081         ifAbsentPut:[(Depth4Image new) width:14; height:14; bits:(ByteArray fromPackedString:'@@@@@@@@@@@RH@@@H!!@@HRD@@RD @BHQ@@DRH@@ADP@ADP@@@@@QD@@@@@@@DQ@@@@@@@ADP@@@@@QD@@QD@@BHQ@@DRH@@!!HP@AHR@@D"@@@BHP@@@@@@@@
  1082 @@@@@@@@@@@b') ; colorMapFromArray:#[127 126 127 255 0 0 255 255 255]; mask:((ImageMask new) width:14; height:14; bits:(ByteArray fromPackedString:'_?1<_G1<_G1??D_DQ<QG1G?<_G1<_G1<_?0@@@@a') ; yourself); yourself]
  1083 !
  1084 
  1085 specialCircleIcon
  1086     <resource: #image>
  1087     "This resource specification was automatically generated
  1088      by the ImageEditor of ST/X."
  1089     "Do not manually edit this!! If it is corrupted,
  1090      the ImageEditor may not be able to read the specification."
  1091     "
  1092      self specialCircleIcon inspect
  1093      ImageEditor openOnClass:self andSelector:#specialCircleIcon
  1094      Icon flushCachedIcons"
  1095     
  1096     ^ Icon constantNamed:'ImageEditor class specialCircleIcon'
  1097         ifAbsentPut:[
  1098             (Depth1Image new)
  1099                 width:14;
  1100                 height:14;
  1101                 photometric:(#palette);
  1102                 bitsPerSample:(#( 1 ));
  1103                 samplesPerPixel:(1);
  1104                 bits:(ByteArray 
  1105                             fromPackedString:'@@L@@@!!BDB@ D4@HP@!!@BD@HHA@PHP!!@@@@@@@@a');
  1106                 colorMapFromArray:#[ 0 0 0 255 0 0 ];
  1107                 mask:((ImageMask new)
  1108                             width:14;
  1109                             height:14;
  1110                             bits:(ByteArray 
  1111                                         fromPackedString:'@@@@@@-@D2@''$D^HQ8!!G"DLHH1@PH@-@@0@@@@@a');
  1112                             yourself);
  1113                 yourself
  1114         ]
  1115 !
  1116 
  1117 specialIcon
  1118     <resource: #image>
  1119     "This resource specification was automatically generated
  1120      by the ImageEditor of ST/X."
  1121     "Do not manually edit this!! If it is corrupted,
  1122      the ImageEditor may not be able to read the specification."
  1123     "
  1124      self specialIcon inspect
  1125      ImageEditor openOnClass:self andSelector:#specialIcon
  1126      Icon flushCachedIcons"
  1127     
  1128     ^ Icon constantNamed:'ImageEditor class specialIcon'
  1129         ifAbsentPut:[
  1130             (Depth1Image new)
  1131                 width:14;
  1132                 height:14;
  1133                 photometric:(#palette);
  1134                 bitsPerSample:(#( 1 ));
  1135                 samplesPerPixel:(1);
  1136                 bits:(ByteArray 
  1137                             fromPackedString:'@@L@@G!!:P@!!@B4@HP@!!@BD@HP@!!@BW!!8@@@@@@@a');
  1138                 colorMapFromArray:#[ 0 0 0 255 0 0 ];
  1139                 mask:((ImageMask new)
  1140                             width:14;
  1141                             height:14;
  1142                             bits:(ByteArray 
  1143                                         fromPackedString:'@@@@@G-8P0!!G"D^HQ8!!G"DLHP0!!@BG-8@0@@@@@a');
  1144                             yourself);
  1145                 yourself
  1146         ]
  1147 !
  1148 
  1149 sprayIcon
  1150     "This resource specification was automatically generated
  1151      by the ImageEditor of ST/X."
  1152 
  1153     "Do not manually edit this!! If it is corrupted,
  1154      the ImageEditor may not be able to read the specification."
  1155 
  1156     "
  1157      self sprayIcon inspect
  1158      ImageEditor openOnClass:self andSelector:#sprayIcon
  1159      Icon flushCachedIcons
  1160     "
  1161 
  1162     <resource: #image>
  1163 
  1164     ^Icon
  1165         constantNamed:'ImageEditor sprayIcon'
  1166         ifAbsentPut:[(Depth4Image new) width:14; height:14; bits:(ByteArray fromPackedString:'@@@@@@@@@@@@@@@@@@@@@@@@@@@P@@@@@@DA@P@@@@@PDA@@@@@@@PDA@@@@@@@PD@@@@"H@@PD@@@H"@@@@@@@ADP@@@@@@@QD@@@@@@@DQ@@@@@@@ADP@@
  1167 @@@@@@@@@@@b') ; colorMapFromArray:#[0 0 0 255 0 0 255 255 255]; mask:((ImageMask new) width:14; height:14; bits:(ByteArray fromPackedString:'@@@@@@@HA%PF*@ITA2 O%@>@C8@O @>@C8@O @@a') ; yourself); yourself]
  1168 ! !
  1169 
  1170 !ImageEditor class methodsFor:'interface specs'!
  1171 
  1172 changeHLSDialogSpec
  1173     "This resource specification was automatically generated
  1174      by the UIPainter of ST/X."
  1175 
  1176     "Do not manually edit this!! If it is corrupted,
  1177      the UIPainter may not be able to read the specification."
  1178 
  1179     "
  1180      UIPainter new openOnClass:ImageEditor andSelector:#changeHLSDialogSpec
  1181      ImageEditor new openInterface:#changeHLSDialogSpec
  1182     "
  1183 
  1184     <resource: #canvas>
  1185 
  1186     ^ 
  1187      #(FullSpec
  1188         name: changeHLSDialogSpec
  1189         window: 
  1190        (WindowSpec
  1191           label: 'HLS Edit Dialog'
  1192           name: 'HLS Edit Dialog'
  1193           min: (Point 10 10)
  1194           bounds: (Rectangle 0 0 312 258)
  1195         )
  1196         component: 
  1197        (SpecCollection
  1198           collection: (
  1199            (LabelSpec
  1200               label: 'Hue-Shift:'
  1201               name: 'HueLabel'
  1202               layout: (LayoutFrame 20 0 21 0 120 0 43 0)
  1203               translateLabel: true
  1204               adjust: right
  1205             )
  1206            (InputFieldSpec
  1207               name: 'HueShiftEntryField'
  1208               layout: (LayoutFrame 123 0 21 0 166 0 43 0)
  1209               tabable: true
  1210               model: hueShiftAmount
  1211               type: numberInRange
  1212               minValue: 0
  1213               maxValue: 360
  1214               acceptChannel: acceptChannel
  1215               acceptOnPointerLeave: false
  1216             )
  1217            (ThumbWheelSpec
  1218               name: 'HueWheel'
  1219               layout: (LayoutFrame 180 0 22 0 297 0 42 0)
  1220               model: hueShiftAmount
  1221               orientation: horizontal
  1222               step: 1
  1223               endlessRotation: true
  1224             )
  1225            (LabelSpec
  1226               label: 'Light Factor:'
  1227               name: 'LightLabel'
  1228               layout: (LayoutFrame 18 0 50 0 120 0 72 0)
  1229               translateLabel: true
  1230               adjust: right
  1231             )
  1232            (InputFieldSpec
  1233               name: 'LightEntryField'
  1234               layout: (LayoutFrame 123 0 50 0 166 0 72 0)
  1235               tabable: true
  1236               model: lightAmount
  1237               type: numberInRange
  1238               minValue: 0
  1239               maxValue: 1000
  1240               acceptChannel: acceptChannel
  1241               acceptOnPointerLeave: false
  1242             )
  1243            (ThumbWheelSpec
  1244               name: 'LightWheel'
  1245               layout: (LayoutFrame 180 0 51 0 297 0 71 0)
  1246               model: lightAmount
  1247               orientation: horizontal
  1248               stop: 1000
  1249               step: 1
  1250             )
  1251            (LabelSpec
  1252               label: 'Saturation Factor:'
  1253               name: 'SaturationLabel'
  1254               layout: (LayoutFrame 9 0 79 0 120 0 101 0)
  1255               translateLabel: true
  1256               adjust: right
  1257             )
  1258            (InputFieldSpec
  1259               name: 'SaturationEntryField'
  1260               layout: (LayoutFrame 123 0 79 0 166 0 101 0)
  1261               tabable: true
  1262               model: saturationAmount
  1263               type: numberInRange
  1264               minValue: 0
  1265               maxValue: 1000
  1266               acceptChannel: acceptChannel
  1267               acceptOnPointerLeave: false
  1268             )
  1269            (ThumbWheelSpec
  1270               name: 'SaturationWheel'
  1271               layout: (LayoutFrame 180 0 80 0 297 0 100 0)
  1272               model: saturationAmount
  1273               orientation: horizontal
  1274               stop: 1000
  1275               step: 1
  1276             )
  1277            (LabelSpec
  1278               label: 'Color Shift'
  1279               name: 'Label2'
  1280               layout: (LayoutFrame 5 0 110 0 -15 0.5 132 0)
  1281               translateLabel: true
  1282             )
  1283            (LabelSpec
  1284               name: 'HueColorLabel'
  1285               layout: (LayoutFrame 18 0.0 133 0 -41 0.5 217 0)
  1286               level: -1
  1287               backgroundChannel: hlsColor
  1288               translateLabel: true
  1289             )
  1290            (LabelSpec
  1291               label: 'Preview'
  1292               name: 'Label3'
  1293               layout: (LayoutFrame 5 0.5 110 0 -5 1 132 0)
  1294               translateLabel: true
  1295             )
  1296            (LabelSpec
  1297               name: 'PreviewLabel'
  1298               layout: (LayoutFrame 36 0.5 133 0 -23 1.0 217 0)
  1299               level: -1
  1300               translateLabel: true
  1301               labelChannel: previewImageHolder
  1302             )
  1303            (HorizontalPanelViewSpec
  1304               name: 'HorizontalPanel1'
  1305               layout: (LayoutFrame 0 0.0 -30 1 0 1.0 0 1)
  1306               horizontalLayout: fitSpace
  1307               verticalLayout: center
  1308               horizontalSpace: 3
  1309               verticalSpace: 3
  1310               reverseOrderIfOKAtLeft: true
  1311               component: 
  1312              (SpecCollection
  1313                 collection: (
  1314                  (ActionButtonSpec
  1315                     label: 'Cancel'
  1316                     name: 'Button1'
  1317                     translateLabel: true
  1318                     tabable: true
  1319                     model: cancel
  1320                     extent: (Point 151 22)
  1321                   )
  1322                  (ActionButtonSpec
  1323                     label: 'OK'
  1324                     name: 'Button2'
  1325                     translateLabel: true
  1326                     tabable: true
  1327                     model: accept
  1328                     extent: (Point 152 22)
  1329                   )
  1330                  )
  1331                
  1332               )
  1333             )
  1334            )
  1335          
  1336         )
  1337       )
  1338 !
  1339 
  1340 cropDialogSpec
  1341     "This resource specification was automatically generated
  1342      by the UIPainter of ST/X."
  1343 
  1344     "Do not manually edit this!! If it is corrupted,
  1345      the UIPainter may not be able to read the specification."
  1346 
  1347     "
  1348      UIPainter new openOnClass:ImageEditor andSelector:#cropDialogSpec
  1349      ImageEditor new openInterface:#cropDialogSpec
  1350     "
  1351 
  1352     <resource: #canvas>
  1353 
  1354     ^ 
  1355      #(FullSpec
  1356         name: cropDialogSpec
  1357         window: 
  1358        (WindowSpec
  1359           label: 'Crop Border(s)'
  1360           name: 'Crop Border(s)'
  1361           min: (Point 10 10)
  1362           bounds: (Rectangle 14 46 259 229)
  1363         )
  1364         component: 
  1365        (SpecCollection
  1366           collection: (
  1367            (LabelSpec
  1368               label: 'Left:'
  1369               name: 'GropLeftLabel'
  1370               layout: (LayoutFrame 14 0 21 0 90 0 43 0)
  1371               translateLabel: true
  1372               adjust: right
  1373             )
  1374            (InputFieldSpec
  1375               name: 'GropLeftEntryField'
  1376               layout: (LayoutFrame 95 0 21 0 132 0 43 0)
  1377               tabable: true
  1378               model: left
  1379               type: number
  1380               acceptChannel: acceptChannel
  1381               acceptOnPointerLeave: false
  1382             )
  1383            (ActionButtonSpec
  1384               label: 'Now'
  1385               name: 'GropLeftNowButton'
  1386               layout: (LayoutFrame 148 0 21 0 221 0 43 0)
  1387               translateLabel: true
  1388               tabable: true
  1389               model: gropLeftNow
  1390               autoRepeat: true
  1391             )
  1392            (LabelSpec
  1393               label: 'Right:'
  1394               name: 'GropRightLabel'
  1395               layout: (LayoutFrame 14 0 51 0 90 0 73 0)
  1396               translateLabel: true
  1397               adjust: right
  1398             )
  1399            (InputFieldSpec
  1400               name: 'GropRightEntryField'
  1401               layout: (LayoutFrame 95 0 51 0 132 0 73 0)
  1402               tabable: true
  1403               model: right
  1404               type: number
  1405               acceptChannel: acceptChannel
  1406               acceptOnPointerLeave: false
  1407             )
  1408            (ActionButtonSpec
  1409               label: 'Now'
  1410               name: 'GropRightButton'
  1411               layout: (LayoutFrame 148 0 51 0 221 0 73 0)
  1412               translateLabel: true
  1413               tabable: true
  1414               model: gropRightNow
  1415               autoRepeat: true
  1416             )
  1417            (LabelSpec
  1418               label: 'Top:'
  1419               name: 'GropTopLabel'
  1420               layout: (LayoutFrame 14 0 81 0 90 0 103 0)
  1421               translateLabel: true
  1422               adjust: right
  1423             )
  1424            (InputFieldSpec
  1425               name: 'GropTopEntryField'
  1426               layout: (LayoutFrame 95 0 81 0 132 0 103 0)
  1427               tabable: true
  1428               model: top
  1429               type: number
  1430               acceptChannel: acceptChannel
  1431               acceptOnPointerLeave: false
  1432             )
  1433            (ActionButtonSpec
  1434               label: 'Now'
  1435               name: 'GropTopButton'
  1436               layout: (LayoutFrame 148 0 81 0 221 0 103 0)
  1437               translateLabel: true
  1438               tabable: true
  1439               model: gropTopNow
  1440               autoRepeat: true
  1441             )
  1442            (LabelSpec
  1443               label: 'Bottom:'
  1444               name: 'GropBottomLabel'
  1445               layout: (LayoutFrame 14 0 111 0 90 0 133 0)
  1446               translateLabel: true
  1447               adjust: right
  1448             )
  1449            (InputFieldSpec
  1450               name: 'GropBottomEntryField'
  1451               layout: (LayoutFrame 95 0 111 0 132 0 133 0)
  1452               tabable: true
  1453               model: bottom
  1454               type: number
  1455               acceptChannel: acceptChannel
  1456               acceptOnPointerLeave: false
  1457             )
  1458            (ActionButtonSpec
  1459               label: 'Now'
  1460               name: 'GropBottomButton'
  1461               layout: (LayoutFrame 148 0 111 0 221 0 133 0)
  1462               translateLabel: true
  1463               tabable: true
  1464               model: gropBottomNow
  1465               autoRepeat: true
  1466             )
  1467            (HorizontalPanelViewSpec
  1468               name: 'HorizontalPanel1'
  1469               layout: (LayoutFrame 0 0.0 -30 1 0 1.0 0 1)
  1470               horizontalLayout: fitSpace
  1471               verticalLayout: center
  1472               horizontalSpace: 3
  1473               verticalSpace: 3
  1474               reverseOrderIfOKAtLeft: true
  1475               component: 
  1476              (SpecCollection
  1477                 collection: (
  1478                  (ActionButtonSpec
  1479                     label: 'Cancel'
  1480                     name: 'Button1'
  1481                     translateLabel: true
  1482                     tabable: true
  1483                     model: cancel
  1484                     extent: (Point 77 22)
  1485                   )
  1486                  (ActionButtonSpec
  1487                     label: 'Apply'
  1488                     name: 'Button3'
  1489                     translateLabel: true
  1490                     tabable: true
  1491                     model: applyAction
  1492                     extent: (Point 78 22)
  1493                   )
  1494                  (ActionButtonSpec
  1495                     label: 'OK'
  1496                     name: 'Button2'
  1497                     translateLabel: true
  1498                     tabable: true
  1499                     model: accept
  1500                     extent: (Point 78 22)
  1501                   )
  1502                  )
  1503                
  1504               )
  1505             )
  1506            )
  1507          
  1508         )
  1509       )
  1510 !
  1511 
  1512 dialogSpecForNewImage
  1513     "This resource specification was automatically generated
  1514      by the UIPainter of ST/X."
  1515 
  1516     "Do not manually edit this!! If it is corrupted,
  1517      the UIPainter may not be able to read the specification."
  1518 
  1519     "
  1520      UIPainter new openOnClass:ImageEditor andSelector:#dialogSpecForNewImage
  1521      ImageEditor new openInterface:#dialogSpecForNewImage
  1522     "
  1523 
  1524     <resource: #canvas>
  1525 
  1526     ^ 
  1527      #(FullSpec
  1528         name: dialogSpecForNewImage
  1529         window: 
  1530        (WindowSpec
  1531           label: 'New Image'
  1532           name: 'New Image'
  1533           min: (Point 10 10)
  1534           bounds: (Rectangle 0 0 301 119)
  1535         )
  1536         component: 
  1537        (SpecCollection
  1538           collection: (
  1539            (ViewSpec
  1540               name: 'View'
  1541               layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -35 1.0)
  1542               level: 1
  1543               component: 
  1544              (SpecCollection
  1545                 collection: (
  1546                  (FramedBoxSpec
  1547                     label: 'Size'
  1548                     name: 'framedBox1'
  1549                     layout: (LayoutFrame 1 0.0 7 0.0 0 0.4 76 0)
  1550                     style: (FontDescription helvetica medium roman 12)
  1551                     labelPosition: topLeft
  1552                     translateLabel: true
  1553                     component: 
  1554                    (SpecCollection
  1555                       collection: (
  1556                        (ComboBoxSpec
  1557                           name: 'defaultSizesComboBox'
  1558                           layout: (LayoutFrame 0 0.0 10 0.0 0 1 35 0.0)
  1559                           model: selectionOfSize
  1560                           type: string
  1561                           acceptOnPointerLeave: false
  1562                           comboList: listOfDefaultSizes
  1563                           isFilenameBox: false
  1564                         )
  1565                        )
  1566                      
  1567                     )
  1568                   )
  1569                  (FramedBoxSpec
  1570                     label: 'Color Map'
  1571                     name: 'framedBox2'
  1572                     layout: (LayoutFrame 0 0.4 7 0.0 -1 1.0 76 0)
  1573                     style: (FontDescription helvetica medium roman 12)
  1574                     labelPosition: topLeft
  1575                     translateLabel: true
  1576                     component: 
  1577                    (SpecCollection
  1578                       collection: (
  1579                        (ComboListSpec
  1580                           name: 'colorMapComboBox'
  1581                           layout: (LayoutFrame 0 0.0 10 0.0 0 1 35 0.0)
  1582                           model: selectionOfColorMap
  1583                           comboList: listOfColorMaps
  1584                           useIndex: false
  1585                           hidePullDownMenuButton: false
  1586                         )
  1587                        )
  1588                      
  1589                     )
  1590                   )
  1591                  )
  1592                
  1593               )
  1594             )
  1595            (UISubSpecification
  1596               name: 'windowSpecForCommitWithoutChannels'
  1597               layout: (LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
  1598               minorKey: windowSpecForCommitWithoutChannels
  1599             )
  1600            )
  1601          
  1602         )
  1603       )
  1604 !
  1605 
  1606 shiftDialogSpec
  1607     "This resource specification was automatically generated
  1608      by the UIPainter of ST/X."
  1609 
  1610     "Do not manually edit this!! If it is corrupted,
  1611      the UIPainter may not be able to read the specification."
  1612 
  1613     "
  1614      UIPainter new openOnClass:ImageEditor andSelector:#shiftDialogSpec
  1615      ImageEditor new openInterface:#shiftDialogSpec
  1616     "
  1617 
  1618     <resource: #canvas>
  1619 
  1620     ^ 
  1621      #(FullSpec
  1622         name: shiftDialogSpec
  1623         window: 
  1624        (WindowSpec
  1625           label: 'Shift'
  1626           name: 'Shift'
  1627           min: (Point 10 10)
  1628           bounds: (Rectangle 14 46 259 229)
  1629         )
  1630         component: 
  1631        (SpecCollection
  1632           collection: (
  1633            (LabelSpec
  1634               label: 'Amount:'
  1635               name: 'AmountLabel'
  1636               layout: (LayoutFrame 14 0 21 0 90 0 43 0)
  1637               translateLabel: true
  1638               adjust: right
  1639             )
  1640            (InputFieldSpec
  1641               name: 'AmountEntryField'
  1642               layout: (LayoutFrame 95 0 21 0 139 0 43 0)
  1643               tabable: true
  1644               model: shiftAmount
  1645               type: number
  1646               acceptChannel: acceptChannel
  1647               acceptOnPointerLeave: false
  1648             )
  1649            (HorizontalPanelViewSpec
  1650               name: 'HorizontalPanel1'
  1651               layout: (LayoutFrame 0 0.0 -30 1 0 1.0 0 1)
  1652               horizontalLayout: fitSpace
  1653               verticalLayout: center
  1654               horizontalSpace: 3
  1655               verticalSpace: 3
  1656               reverseOrderIfOKAtLeft: true
  1657               component: 
  1658              (SpecCollection
  1659                 collection: (
  1660                  (ActionButtonSpec
  1661                     label: 'Cancel'
  1662                     name: 'Button1'
  1663                     translateLabel: true
  1664                     tabable: true
  1665                     model: cancel
  1666                     extent: (Point 118 22)
  1667                   )
  1668                  (ActionButtonSpec
  1669                     label: 'OK'
  1670                     name: 'Button2'
  1671                     translateLabel: true
  1672                     tabable: true
  1673                     model: accept
  1674                     extent: (Point 118 22)
  1675                   )
  1676                  )
  1677                
  1678               )
  1679             )
  1680            (ArrowButtonSpec
  1681               name: 'upArrowButton'
  1682               layout: (LayoutFrame 105 0 63 0 127 0 85 0)
  1683               model: shiftUpNow
  1684               isTriggerOnDown: true
  1685               autoRepeat: true
  1686               actionValue: ''
  1687               direction: up
  1688             )
  1689            (ArrowButtonSpec
  1690               name: 'leftArrowButton'
  1691               layout: (LayoutFrame 84 0 86 0 106 0 108 0)
  1692               model: shiftLeftNow
  1693               isTriggerOnDown: true
  1694               autoRepeat: true
  1695               actionValue: ''
  1696               direction: left
  1697             )
  1698            (ArrowButtonSpec
  1699               name: 'rightArrowButton'
  1700               layout: (LayoutFrame 126 0 86 0 148 0 108 0)
  1701               model: shiftRightNow
  1702               isTriggerOnDown: true
  1703               autoRepeat: true
  1704               actionValue: ''
  1705               direction: right
  1706             )
  1707            (ArrowButtonSpec
  1708               name: 'downArrowButton'
  1709               layout: (LayoutFrame 105 0 107 0 127 0 129 0)
  1710               model: shiftDownNow
  1711               isTriggerOnDown: true
  1712               autoRepeat: true
  1713               actionValue: ''
  1714               direction: down
  1715             )
  1716            (CheckBoxSpec
  1717               label: 'Wrap'
  1718               name: 'CheckBox1'
  1719               layout: (LayoutFrame 153 0 22 0 289 0 44 0)
  1720               model: wrap
  1721               translateLabel: true
  1722             )
  1723            )
  1724          
  1725         )
  1726       )
  1727 !
  1728 
  1729 uncropDialogSpec
  1730     "This resource specification was automatically generated
  1731      by the UIPainter of ST/X."
  1732 
  1733     "Do not manually edit this!! If it is corrupted,
  1734      the UIPainter may not be able to read the specification."
  1735 
  1736     "
  1737      UIPainter new openOnClass:ImageEditor andSelector:#uncropDialogSpec
  1738      ImageEditor new openInterface:#uncropDialogSpec
  1739     "
  1740 
  1741     <resource: #canvas>
  1742 
  1743     ^ 
  1744      #(FullSpec
  1745         name: uncropDialogSpec
  1746         window: 
  1747        (WindowSpec
  1748           label: 'Add Border(s)'
  1749           name: 'Add Border(s)'
  1750           min: (Point 10 10)
  1751           max: (Point 800 478)
  1752           bounds: (Rectangle 0 0 261 228)
  1753         )
  1754         component: 
  1755        (SpecCollection
  1756           collection: (
  1757            (LabelSpec
  1758               label: 'Left:'
  1759               name: 'Label1'
  1760               layout: (LayoutFrame 14 0 21 0 90 0 43 0)
  1761               translateLabel: true
  1762               adjust: right
  1763             )
  1764            (InputFieldSpec
  1765               name: 'EntryField1'
  1766               layout: (LayoutFrame 95 0 21 0 132 0 43 0)
  1767               model: left
  1768               type: number
  1769               acceptOnPointerLeave: false
  1770             )
  1771            (LabelSpec
  1772               label: 'Right:'
  1773               name: 'Label2'
  1774               layout: (LayoutFrame 14 0 51 0 90 0 73 0)
  1775               translateLabel: true
  1776               adjust: right
  1777             )
  1778            (InputFieldSpec
  1779               name: 'EntryField2'
  1780               layout: (LayoutFrame 95 0 51 0 132 0 73 0)
  1781               model: right
  1782               type: number
  1783               acceptOnPointerLeave: false
  1784             )
  1785            (LabelSpec
  1786               label: 'Top:'
  1787               name: 'Label3'
  1788               layout: (LayoutFrame 14 0 81 0 90 0 103 0)
  1789               translateLabel: true
  1790               adjust: right
  1791             )
  1792            (InputFieldSpec
  1793               name: 'EntryField3'
  1794               layout: (LayoutFrame 95 0 81 0 132 0 103 0)
  1795               model: top
  1796               type: number
  1797               acceptOnPointerLeave: false
  1798             )
  1799            (LabelSpec
  1800               label: 'Bottom:'
  1801               name: 'Label4'
  1802               layout: (LayoutFrame 14 0 111 0 90 0 133 0)
  1803               translateLabel: true
  1804               adjust: right
  1805             )
  1806            (InputFieldSpec
  1807               name: 'EntryField4'
  1808               layout: (LayoutFrame 95 0 111 0 132 0 133 0)
  1809               model: bottom
  1810               type: number
  1811               acceptOnPointerLeave: false
  1812             )
  1813            (HorizontalPanelViewSpec
  1814               name: 'HorizontalPanel1'
  1815               layout: (LayoutFrame 0 0.0 -30 1 0 1.0 0 1)
  1816               horizontalLayout: fitSpace
  1817               verticalLayout: center
  1818               horizontalSpace: 3
  1819               verticalSpace: 3
  1820               reverseOrderIfOKAtLeft: true
  1821               component: 
  1822              (SpecCollection
  1823                 collection: (
  1824                  (ActionButtonSpec
  1825                     label: 'Cancel'
  1826                     name: 'Button1'
  1827                     translateLabel: true
  1828                     model: cancel
  1829                     extent: (Point 118 22)
  1830                   )
  1831                  (ActionButtonSpec
  1832                     label: 'OK'
  1833                     name: 'Button2'
  1834                     translateLabel: true
  1835                     model: accept
  1836                     extent: (Point 118 22)
  1837                   )
  1838                  )
  1839                
  1840               )
  1841             )
  1842            )
  1843          
  1844         )
  1845       )
  1846 !
  1847 
  1848 windowSpec
  1849     "This resource specification was automatically generated
  1850      by the UIPainter of ST/X."
  1851 
  1852     "Do not manually edit this!! If it is corrupted,
  1853      the UIPainter may not be able to read the specification."
  1854 
  1855     "
  1856      UIPainter new openOnClass:ImageEditor andSelector:#windowSpec
  1857      ImageEditor new openInterface:#windowSpec
  1858      ImageEditor open
  1859     "
  1860 
  1861     <resource: #canvas>
  1862 
  1863     ^ 
  1864     #(FullSpec
  1865        name: windowSpec
  1866        window: 
  1867       (WindowSpec
  1868          label: 'Image Editor'
  1869          name: 'Image Editor'
  1870          min: (Point 400 320)
  1871          bounds: (Rectangle 0 0 450 350)
  1872          menu: menu
  1873          icon: defaultIcon
  1874        )
  1875        component: 
  1876       (SpecCollection
  1877          collection: (
  1878           (MenuPanelSpec
  1879              name: 'menuToolbarView'
  1880              layout: (LayoutFrame 0 0.0 0 0 0 1.0 32 0)
  1881              style: (FontDescription helvetica medium roman 10)
  1882              menu: menuToolbar
  1883              showSeparatingLines: true
  1884            )
  1885           (VariableHorizontalPanelSpec
  1886              name: 'mainPanel'
  1887              layout: (LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
  1888              snapMode: both
  1889              barLevel: 0
  1890              component: 
  1891             (SpecCollection
  1892                collection: (
  1893                 (ViewSpec
  1894                    name: 'leftView'
  1895                    level: 1
  1896                    component: 
  1897                   (SpecCollection
  1898                      collection: (
  1899                       (VariableVerticalPanelSpec
  1900                          name: 'verticalPanel'
  1901                          layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
  1902                          level: 0
  1903                          snapMode: both
  1904                          component: 
  1905                         (SpecCollection
  1906                            collection: (
  1907                             (ViewSpec
  1908                                name: 'View1'
  1909                                component: 
  1910                               (SpecCollection
  1911                                  collection: (
  1912                                   (MenuPanelSpec
  1913                                      name: 'MouseButtonColorToolBar'
  1914                                      layout: (LayoutFrame 0 0.0 0 0 0 1.0 24 0)
  1915                                      level: 0
  1916                                      menu: menuMouseButtonColors
  1917                                    )
  1918                                   (DataSetSpec
  1919                                      name: 'colorDataSetView'
  1920                                      layout: (LayoutFrame 0 0.0 26 0.0 0 1.0 0 1.0)
  1921                                      activeHelpKey: colorMapTable
  1922                                      style: (FontDescription helvetica medium roman 10)
  1923                                      model: selectedColors
  1924                                      menu: colorMapMenu
  1925                                      hasHorizontalScrollBar: true
  1926                                      hasVerticalScrollBar: true
  1927                                      miniScrollerHorizontal: true
  1928                                      miniScrollerVertical: true
  1929                                      dataList: listOfColors
  1930                                      has3Dseparators: true
  1931                                      doubleClickSelector: doubleClickOnColor:
  1932                                      columnHolder: colorTableColumns
  1933                                      multipleSelectOk: true
  1934                                      verticalSpacing: 1
  1935                                      columnAdaptor: colorColumnAdaptor
  1936                                    )
  1937                                   )
  1938                                 
  1939                                )
  1940                              )
  1941                             (ArbitraryComponentSpec
  1942                                name: 'imagePreView'
  1943                                activeHelpKey: previewView
  1944                                menu: previewMenu
  1945                                hasHorizontalScrollBar: true
  1946                                hasVerticalScrollBar: true
  1947                                miniScrollerHorizontal: false
  1948                                miniScrollerVertical: false
  1949                                hasBorder: false
  1950                                component: ImageView
  1951                              )
  1952                             )
  1953                           
  1954                          )
  1955                          handles: (Any 0.5 1.0)
  1956                        )
  1957                       )
  1958                     
  1959                    )
  1960                  )
  1961                 (ViewSpec
  1962                    name: 'rightView'
  1963                    component: 
  1964                   (SpecCollection
  1965                      collection: (
  1966                       (MenuPanelSpec
  1967                          name: 'ToolBar1'
  1968                          layout: (LayoutFrame 0 0 0 0.0 28 0 0 1.0)
  1969                          level: 1
  1970                          menu: toolsMenuToolbar
  1971                          verticalLayout: true
  1972                          centerItems: true
  1973                          textDefault: true
  1974                        )
  1975                       (ViewSpec
  1976                          name: 'editingView'
  1977                          layout: (LayoutFrame 28 0.0 0 0.0 0 1.0 0 1.0)
  1978                          level: 1
  1979                          component: 
  1980                         (SpecCollection
  1981                            collection: (
  1982                             (ArbitraryComponentSpec
  1983                                name: 'imageEditView'
  1984                                layout: (LayoutFrame 2 0.0 2 0.0 -2 1.0 -24 1.0)
  1985                                hasHorizontalScrollBar: true
  1986                                hasVerticalScrollBar: true
  1987                                hasBorder: false
  1988                                component: ImageEditView
  1989                              )
  1990                             (LabelSpec
  1991                                name: 'coordLabel'
  1992                                layout: (LayoutFrame 2 0.0 -22 1 -83 1.0 0 1.0)
  1993                                level: -1
  1994                                translateLabel: true
  1995                                labelChannel: imageInfoHolder
  1996                                resizeForLabel: false
  1997                                adjust: left
  1998                              )
  1999                             (ArrowButtonSpec
  2000                                name: 'magnifyDownButton'
  2001                                layout: (LayoutFrame -80 1 -22 1 -58 1 0 1)
  2002                                activeHelpKey: magnifyImageDown
  2003                                translateLabel: true
  2004                                model: doMagnifyDown
  2005                                enableChannel: imageIsLoadedHolder
  2006                                isTriggerOnDown: true
  2007                                direction: left
  2008                              )
  2009                             (ArrowButtonSpec
  2010                                name: 'magnifyUpButton'
  2011                                layout: (LayoutFrame -24 1 -22 1 -2 1 0 1)
  2012                                activeHelpKey: magnifyImageUp
  2013                                translateLabel: true
  2014                                model: doMagnifyUp
  2015                                enableChannel: imageIsLoadedHolder
  2016                                isTriggerOnDown: true
  2017                                direction: right
  2018                              )
  2019                             (InputFieldSpec
  2020                                name: 'magnificationInputField'
  2021                                layout: (LayoutFrame -57 1 -22 1 -26 1 0 1)
  2022                                activeHelpKey: magnificationNumber
  2023                                enableChannel: imageIsLoadedHolder
  2024                                model: magnificationHolder
  2025                                type: numberInRange
  2026                                acceptOnReturn: true
  2027                                acceptOnTab: true
  2028                                numChars: 2
  2029                                minValue: 1
  2030                                maxValue: 99
  2031                                acceptOnPointerLeave: true
  2032                              )
  2033                             )
  2034                           
  2035                          )
  2036                        )
  2037                       )
  2038                     
  2039                    )
  2040                  )
  2041                 )
  2042               
  2043              )
  2044              handles: (Any 0.28888900000000006 1.0)
  2045            )
  2046           (UISubSpecification
  2047              name: 'infoBarSubSpec'
  2048              layout: (LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
  2049              majorKey: ToolApplicationModel
  2050              minorKey: windowSpecForInfoBar
  2051            )
  2052           )
  2053         
  2054        )
  2055      )
  2056 ! !
  2057 
  2058 !ImageEditor class methodsFor:'menu specs'!
  2059 
  2060 colorMapMenu
  2061     "This resource specification was automatically generated
  2062      by the MenuEditor of ST/X."
  2063 
  2064     "Do not manually edit this!! If it is corrupted,
  2065      the MenuEditor may not be able to read the specification."
  2066 
  2067     "
  2068      MenuEditor new openOnClass:ImageEditor andSelector:#colorMapMenu
  2069      (Menu new fromLiteralArrayEncoding:(ImageEditor colorMapMenu)) startUp
  2070     "
  2071 
  2072     <resource: #menu>
  2073 
  2074     ^ 
  2075      #(Menu
  2076         (
  2077          (MenuItem
  2078             enabled: hasColormapHolder
  2079             label: 'Add Color'
  2080             itemValue: addColorToColormap
  2081             translateLabel: true
  2082           )
  2083          (MenuItem
  2084             enabled: hasColormapHolder
  2085             label: 'Pick and Add Color...'
  2086             itemValue: pickAndAddColorToColormap
  2087             translateLabel: true
  2088           )
  2089          (MenuItem
  2090             label: '-'
  2091           )
  2092          (MenuItem
  2093             enabled: hasColormapAndSingleColorSelected
  2094             label: 'Cut Color'
  2095             itemValue: cutColorFromColormap
  2096             translateLabel: true
  2097             isVisible: false
  2098           )
  2099          (MenuItem
  2100             enabled: hasSingleColorSelectedHolder
  2101             label: 'Copy Color'
  2102             itemValue: copyColorFromColormap
  2103             translateLabel: true
  2104             shortcutKey: Copy
  2105           )
  2106          (MenuItem
  2107             enabled: hasColormapAndSingleColorSelected
  2108             label: 'Pick and Paste Color...'
  2109             itemValue: pickAndPasteColor
  2110             translateLabel: true
  2111           )
  2112          (MenuItem
  2113             label: 'Paste Color'
  2114             itemValue: pasteColorIntoColormap
  2115             translateLabel: true
  2116             shortcutKey: Paste
  2117           )
  2118          (MenuItem
  2119             label: '-'
  2120           )
  2121          (MenuItem
  2122             enabled: hasColormapAndSingleColorSelected
  2123             label: 'Edit Color...'
  2124             itemValue: editSelectedColor
  2125             translateLabel: true
  2126           )
  2127          (MenuItem
  2128             enabled: hasColormapAndColorSelected
  2129             label: 'Brighter'
  2130             itemValue: makeSelectedColorBrighter
  2131             translateLabel: true
  2132           )
  2133          (MenuItem
  2134             enabled: hasColormapAndColorSelected
  2135             label: 'Darker'
  2136             itemValue: makeSelectedColorDarker
  2137             translateLabel: true
  2138           )
  2139          (MenuItem
  2140             enabled: hasColormapAndColorSelected
  2141             label: 'Make Gray'
  2142             itemValue: makeSelectedColorGray
  2143             translateLabel: true
  2144           )
  2145          (MenuItem
  2146             enabled: hasColormapAndColorSelected
  2147             label: 'Color Shift'
  2148             itemValue: makeSelectedColorShifted
  2149             translateLabel: true
  2150           )
  2151          (MenuItem
  2152             label: '-'
  2153           )
  2154          (MenuItem
  2155             enabled: hasSingleColorSelectedHolder
  2156             label: 'Inspect Color'
  2157             itemValue: inspectColor
  2158             translateLabel: true
  2159           )
  2160          (MenuItem
  2161             enabled: hasColormapHolder
  2162             label: 'Inspect Colormap'
  2163             itemValue: inspectColormap
  2164             translateLabel: true
  2165           )
  2166          )
  2167         nil
  2168         nil
  2169       )
  2170 !
  2171 
  2172 menu
  2173     "This resource specification was automatically generated
  2174      by the MenuEditor of ST/X."
  2175 
  2176     "Do not manually edit this!! If it is corrupted,
  2177      the MenuEditor may not be able to read the specification."
  2178 
  2179     "
  2180      MenuEditor new openOnClass:ImageEditor andSelector:#menu
  2181      (Menu new fromLiteralArrayEncoding:(ImageEditor menu)) startUp
  2182     "
  2183 
  2184     <resource: #menu>
  2185 
  2186     ^ 
  2187      #(Menu
  2188         (
  2189          (MenuItem
  2190             label: '&File'
  2191             translateLabel: true
  2192             submenuChannel: menuFile
  2193             "/ keepLinkedMenu: true
  2194           )
  2195          (MenuItem
  2196             label: 'Edit'
  2197             translateLabel: true
  2198             submenuChannel: menuEdit
  2199             "/ keepLinkedMenu: true
  2200           )
  2201          (MenuItem
  2202             label: 'Mode'
  2203             translateLabel: true
  2204             submenuChannel: modeMenu
  2205           )
  2206          (MenuItem
  2207             label: 'Colors'
  2208             translateLabel: true
  2209             submenuChannel: menuColors
  2210           )
  2211          (MenuItem
  2212             label: 'Settings'
  2213             translateLabel: true
  2214             submenuChannel: menuSettings
  2215           )
  2216          (MenuItem
  2217             label: 'History'
  2218             translateLabel: true
  2219             isVisible: isStandAlone
  2220             submenuChannel: menuHistory
  2221           )
  2222          (MenuItem
  2223             label: 'MENU_Help'
  2224             translateLabel: true
  2225             startGroup: conditionalRight
  2226             submenuChannel: menuHelp
  2227           )
  2228          )
  2229         nil
  2230         nil
  2231       )
  2232 !
  2233 
  2234 menuColors
  2235     "This resource specification was automatically generated
  2236      by the MenuEditor of ST/X."
  2237 
  2238     "Do not manually edit this!! If it is corrupted,
  2239      the MenuEditor may not be able to read the specification."
  2240 
  2241     "
  2242      MenuEditor new openOnClass:ImageEditor andSelector:#menuColors
  2243      (Menu new fromLiteralArrayEncoding:(ImageEditor menuColors)) startUp
  2244     "
  2245 
  2246     <resource: #menu>
  2247 
  2248     ^ 
  2249      #(Menu
  2250         (
  2251          (MenuItem
  2252             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2253             label: 'Depth'
  2254             translateLabel: true
  2255             submenu: 
  2256            (Menu
  2257               (
  2258                (MenuItem
  2259                   activeHelpKey: colorMap1
  2260                   label: '1-Plane'
  2261                   itemValue: colorMapMode:
  2262                   translateLabel: true
  2263                   argument: depth1
  2264                   choice: colorMapMode
  2265                   choiceValue: depth1
  2266                 )
  2267                (MenuItem
  2268                   activeHelpKey: colorMap1M
  2269                   label: '1-Plane + Mask'
  2270                   itemValue: colorMapMode:
  2271                   translateLabel: true
  2272                   argument: masked1
  2273                   choice: colorMapMode
  2274                   choiceValue: masked1
  2275                 )
  2276                (MenuItem
  2277                   label: '-'
  2278                 )
  2279                (MenuItem
  2280                   activeHelpKey: colorMap2
  2281                   label: '2-Plane'
  2282                   itemValue: colorMapMode:
  2283                   translateLabel: true
  2284                   argument: depth2
  2285                   choice: colorMapMode
  2286                   choiceValue: depth2
  2287                 )
  2288                (MenuItem
  2289                   activeHelpKey: colorMap2M
  2290                   label: '2-Plane + Mask'
  2291                   itemValue: colorMapMode:
  2292                   translateLabel: true
  2293                   argument: masked2
  2294                   choice: colorMapMode
  2295                   choiceValue: masked2
  2296                 )
  2297                (MenuItem
  2298                   label: '-'
  2299                 )
  2300                (MenuItem
  2301                   activeHelpKey: colorMap4
  2302                   label: '4-Plane'
  2303                   itemValue: colorMapMode:
  2304                   translateLabel: true
  2305                   argument: depth4
  2306                   choice: colorMapMode
  2307                   choiceValue: depth4
  2308                 )
  2309                (MenuItem
  2310                   activeHelpKey: colorMap4M
  2311                   label: '4-Plane + Mask'
  2312                   itemValue: colorMapMode:
  2313                   translateLabel: true
  2314                   argument: masked4
  2315                   choice: colorMapMode
  2316                   choiceValue: masked4
  2317                 )
  2318                (MenuItem
  2319                   label: '-'
  2320                 )
  2321                (MenuItem
  2322                   activeHelpKey: colorMap8
  2323                   label: '8-Plane'
  2324                   itemValue: colorMapMode:
  2325                   translateLabel: true
  2326                   argument: depth8
  2327                   choice: colorMapMode
  2328                   choiceValue: depth8
  2329                 )
  2330                (MenuItem
  2331                   activeHelpKey: colorMap8M
  2332                   label: '8-Plane + Mask'
  2333                   itemValue: colorMapMode:
  2334                   translateLabel: true
  2335                   argument: masked8
  2336                   choice: colorMapMode
  2337                   choiceValue: masked8
  2338                 )
  2339                (MenuItem
  2340                   label: '-'
  2341                 )
  2342                (MenuItem
  2343                   activeHelpKey: colorMap16
  2344                   label: '16-Plane'
  2345                   itemValue: colorMapMode:
  2346                   translateLabel: true
  2347                   argument: depth16
  2348                   choice: colorMapMode
  2349                   choiceValue: depth16
  2350                 )
  2351                (MenuItem
  2352                   activeHelpKey: colorMap16M
  2353                   label: '16-Plane + Mask'
  2354                   itemValue: colorMapMode:
  2355                   translateLabel: true
  2356                   argument: masked16
  2357                   choice: colorMapMode
  2358                   choiceValue: masked16
  2359                 )
  2360                (MenuItem
  2361                   label: '-'
  2362                 )
  2363                (MenuItem
  2364                   activeHelpKey: colorMap24
  2365                   label: '24-Plane'
  2366                   itemValue: colorMapMode:
  2367                   translateLabel: true
  2368                   argument: depth24
  2369                   choice: colorMapMode
  2370                   choiceValue: depth24
  2371                 )
  2372                (MenuItem
  2373                   activeHelpKey: colorMap24M
  2374                   label: '24-Plane + Mask'
  2375                   itemValue: colorMapMode:
  2376                   translateLabel: true
  2377                   argument: masked24
  2378                   choice: colorMapMode
  2379                   choiceValue: masked24
  2380                 )
  2381                (MenuItem
  2382                   label: '-'
  2383                 )
  2384                (MenuItem
  2385                   activeHelpKey: colorMap32
  2386                   label: '32-Plane (rgba)'
  2387                   itemValue: colorMapMode:
  2388                   translateLabel: true
  2389                   argument: depth32
  2390                   choice: colorMapMode
  2391                   choiceValue: depth32
  2392                 )
  2393                )
  2394               nil
  2395               nil
  2396             )
  2397           )
  2398          (MenuItem
  2399             enabled: imageIsLoadedHolder
  2400             label: 'ColorMap'
  2401             translateLabel: true
  2402             submenu: 
  2403            (Menu
  2404               (
  2405                (MenuItem
  2406                   activeHelpKey: compressColormap
  2407                   enabled: hasColormapHolder
  2408                   label: 'Compress Colormap'
  2409                   itemValue: #'menu_compressColorMap'
  2410                   translateLabel: true
  2411                 )
  2412                (MenuItem
  2413                   enabled: hasColormapHolder
  2414                   label: 'Sort Colormap'
  2415                   itemValue: #'menu_sortColorMap'
  2416                   translateLabel: true
  2417                 )
  2418                (MenuItem
  2419                   label: 'Reduce Number of Colors by Rounding...'
  2420                   itemValue: reduceNumberOfColors2
  2421                   translateLabel: true
  2422                 )
  2423                (MenuItem
  2424                   label: 'Reduce Number of Colors by Masking Bits...'
  2425                   itemValue: reduceNumberOfColors
  2426                   translateLabel: true
  2427                 )
  2428                (MenuItem
  2429                   label: 'Dither to Depth...'
  2430                   itemValue: ditherToDepth
  2431                   translateLabel: true
  2432                 )
  2433                (MenuItem
  2434                   label: '-'
  2435                 )
  2436                (MenuItem
  2437                   enabled: imageIsLoadedHolder
  2438                   label: 'Brighten'
  2439                   itemValue: doBrightenImage
  2440                   translateLabel: true
  2441                 )
  2442                (MenuItem
  2443                   enabled: imageIsLoadedHolder
  2444                   label: 'Darken'
  2445                   itemValue: doDarkenImage
  2446                   translateLabel: true
  2447                 )
  2448                (MenuItem
  2449                   enabled: imageIsLoadedHolder
  2450                   label: 'Invert'
  2451                   itemValue: doNegativeImage
  2452                   translateLabel: true
  2453                 )
  2454                )
  2455               nil
  2456               nil
  2457             )
  2458           )
  2459          (MenuItem
  2460             enabled: imageIsLoadedHolder
  2461             label: 'Process'
  2462             translateLabel: true
  2463             submenu: 
  2464            (Menu
  2465               (
  2466                (MenuItem
  2467                   label: 'Make GrayScale'
  2468                   itemValue: makeGrayScaleImage
  2469                   translateLabel: true
  2470                 )
  2471                (MenuItem
  2472                   enabled: allowedToChangeImageDimensionAndDepth
  2473                   label: 'Make dithered 8Bit Palette'
  2474                   itemValue: makeDitheredPaletteImage
  2475                   translateLabel: true
  2476                   isVisible: false
  2477                 )
  2478                (MenuItem
  2479                   label: 'Make Inverse'
  2480                   itemValue: makeInverse
  2481                   translateLabel: true
  2482                 )
  2483                (MenuItem
  2484                   label: '-'
  2485                 )
  2486                (MenuItem
  2487                   label: 'Make Slightly Brighter'
  2488                   itemValue: makeSlightlyBrighter
  2489                   translateLabel: true
  2490                 )
  2491                (MenuItem
  2492                   label: 'Make Slightly Darker'
  2493                   itemValue: makeSlightlyDarker
  2494                   translateLabel: true
  2495                 )
  2496                (MenuItem
  2497                   label: '-'
  2498                 )
  2499                (MenuItem
  2500                   label: 'Make Brighter'
  2501                   itemValue: makeBrighter
  2502                   translateLabel: true
  2503                 )
  2504                (MenuItem
  2505                   label: 'Make Darker'
  2506                   itemValue: makeDarker
  2507                   translateLabel: true
  2508                 )
  2509                (MenuItem
  2510                   label: '-'
  2511                 )
  2512                (MenuItem
  2513                   label: 'Change HLS...'
  2514                   itemValue: changeHLS
  2515                   translateLabel: true
  2516                 )
  2517                (MenuItem
  2518                   label: 'Colorize...'
  2519                   itemValue: colorize
  2520                   translateLabel: true
  2521                 )
  2522                )
  2523               nil
  2524               nil
  2525             )
  2526           )
  2527          (MenuItem
  2528             enabled: imageIsLoadedHolder
  2529             label: 'Mask'
  2530             translateLabel: true
  2531             submenu: 
  2532            (Menu
  2533               (
  2534                (MenuItem
  2535                   activeHelpKey: copyMask
  2536                   enabled: hasMask
  2537                   label: 'Copy Mask'
  2538                   itemValue: #'menu_copyMask'
  2539                   translateLabel: true
  2540                 )
  2541                (MenuItem
  2542                   activeHelpKey: pasteMask
  2543                   enabled: hasMask
  2544                   label: 'Paste Mask'
  2545                   itemValue: #'menu_pasteMask'
  2546                   translateLabel: true
  2547                 )
  2548                (MenuItem
  2549                   enabled: hasMask
  2550                   label: 'Clear Masked Pixels'
  2551                   itemValue: #'menu_clearMaskedPixels'
  2552                   translateLabel: true
  2553                 )
  2554                (MenuItem
  2555                   enabled: hasMask
  2556                   label: 'Clear Colormap Entry for Masked Pixels'
  2557                   itemValue: #'menu_clearColormapEntry0AndMaskedPixels'
  2558                   translateLabel: true
  2559                 )
  2560                )
  2561               nil
  2562               nil
  2563             )
  2564           )
  2565          )
  2566         nil
  2567         nil
  2568       )
  2569 !
  2570 
  2571 menuEdit
  2572     "This resource specification was automatically generated
  2573      by the MenuEditor of ST/X."
  2574 
  2575     "Do not manually edit this!! If it is corrupted,
  2576      the MenuEditor may not be able to read the specification."
  2577 
  2578     "
  2579      MenuEditor new openOnClass:ImageEditor andSelector:#menuEdit
  2580      (Menu new fromLiteralArrayEncoding:(ImageEditor menuEdit)) startUp
  2581     "
  2582 
  2583     <resource: #menu>
  2584 
  2585     ^ 
  2586      #(Menu
  2587         (
  2588          (MenuItem
  2589             activeHelpKey: editUndo
  2590             enabled: canUndoHolder
  2591             label: 'Undo'
  2592             itemValue: doUndo
  2593             translateLabel: true
  2594           )
  2595          (MenuItem
  2596             label: '-'
  2597           )
  2598          (MenuItem
  2599             enabled: imageIsLoadedHolder
  2600             label: 'Copy to Clipboard'
  2601             itemValue: doCopyImageToClipboard
  2602             translateLabel: true
  2603           )
  2604          (MenuItem
  2605             label: '-'
  2606           )
  2607          (MenuItem
  2608             activeHelpKey: editResize
  2609             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2610             label: 'Resize...'
  2611             itemValue: doResizeImage
  2612             translateLabel: true
  2613           )
  2614          (MenuItem
  2615             activeHelpKey: editMagnifyImage
  2616             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2617             label: 'Magnify...'
  2618             itemValue: doMagnifyImage
  2619             translateLabel: true
  2620           )
  2621          (MenuItem
  2622             activeHelpKey: editMagnifyImage
  2623             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2624             label: 'Magnify By...'
  2625             itemValue: doMagnifyImageBy
  2626             translateLabel: true
  2627           )
  2628          (MenuItem
  2629             activeHelpKey: editRotate
  2630             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2631             label: 'Rotate...'
  2632             itemValue: doRotateImage
  2633             translateLabel: true
  2634           )
  2635          (MenuItem
  2636             activeHelpKey: edit3DProjection
  2637             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2638             label: '3D Projection...'
  2639             itemValue: do3DProjection
  2640             translateLabel: true
  2641           )
  2642          (MenuItem
  2643             enabled: imageIsLoadedHolder
  2644             label: 'Flip'
  2645             translateLabel: true
  2646             submenu: 
  2647            (Menu
  2648               (
  2649                (MenuItem
  2650                   activeHelpKey: editFlipVertical
  2651                   enabled: imageIsLoadedHolder
  2652                   label: 'Flip - Vertical'
  2653                   itemValue: doFlipVertical
  2654                   translateLabel: true
  2655                   labelImage: (ResourceRetriever ImageEditor flipVerticalIcon 'Flip - Vertical')
  2656                 )
  2657                (MenuItem
  2658                   activeHelpKey: editFlipHorizontal
  2659                   enabled: imageIsLoadedHolder
  2660                   label: 'Flip - Horizontal'
  2661                   itemValue: doFlipHorizontal
  2662                   translateLabel: true
  2663                   labelImage: (ResourceRetriever ImageEditor flipHorizontalIcon 'Flip - Horizontal')
  2664                 )
  2665                )
  2666               nil
  2667               nil
  2668             )
  2669           )
  2670          (MenuItem
  2671             label: '-'
  2672           )
  2673          (MenuItem
  2674             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2675             label: 'Crop'
  2676             translateLabel: true
  2677             submenu: 
  2678            (Menu
  2679               (
  2680                (MenuItem
  2681                   activeHelpKey: cropManual
  2682                   label: 'Manual...'
  2683                   itemValue: doCropManual
  2684                   translateLabel: true
  2685                 )
  2686                (MenuItem
  2687                   label: '-'
  2688                 )
  2689                (MenuItem
  2690                   activeHelpKey: cropAll
  2691                   label: 'All'
  2692                   itemValue: doCropAll
  2693                   translateLabel: true
  2694                 )
  2695                (MenuItem
  2696                   label: '-'
  2697                 )
  2698                (MenuItem
  2699                   activeHelpKey: cropLeft
  2700                   label: 'Left'
  2701                   itemValue: doCropLeft
  2702                   translateLabel: true
  2703                 )
  2704                (MenuItem
  2705                   activeHelpKey: cropRight
  2706                   label: 'Right'
  2707                   itemValue: doCropRight
  2708                   translateLabel: true
  2709                 )
  2710                (MenuItem
  2711                   activeHelpKey: cropTop
  2712                   label: 'Top'
  2713                   itemValue: doCropTop
  2714                   translateLabel: true
  2715                 )
  2716                (MenuItem
  2717                   activeHelpKey: cropBottom
  2718                   label: 'Bottom'
  2719                   itemValue: doCropBottom
  2720                   translateLabel: true
  2721                 )
  2722                )
  2723               nil
  2724               nil
  2725             )
  2726           )
  2727          (MenuItem
  2728             activeHelpKey: uncropManual
  2729             enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  2730             label: 'Uncrop (Add Border)...'
  2731             itemValue: doUnCropManual
  2732             translateLabel: true
  2733           )
  2734          (MenuItem
  2735             activeHelpKey: shiftManual
  2736             enabled: imageIsLoadedHolder
  2737             label: 'Shift...'
  2738             itemValue: doShiftManual
  2739             translateLabel: true
  2740           )
  2741          (MenuItem
  2742             label: '-'
  2743           )
  2744          (MenuItem
  2745             activeHelpKey: fileEditMask
  2746             enabled: imageIsLoadedHolder
  2747             label: 'Edit Mask'
  2748             itemValue: doEditMask
  2749             translateLabel: true
  2750           )
  2751          (MenuItem
  2752             enabled: imageIsLoadedHolder
  2753             label: 'Text...'
  2754             itemValue: doInsertTextFromUser
  2755             translateLabel: true
  2756           )
  2757          (MenuItem
  2758             label: '-'
  2759           )
  2760          (MenuItem
  2761             label: 'Animation Sequence'
  2762             translateLabel: true
  2763             submenu: 
  2764            (Menu
  2765               (
  2766                (MenuItem
  2767                   enabled: imageHasNextImageHolder
  2768                   label: 'Next in Sequence'
  2769                   itemValue: nextImageInSequence
  2770                   translateLabel: true
  2771                 )
  2772                (MenuItem
  2773                   enabled: imageHasPreviousImageHolder
  2774                   label: 'Previous in Sequence'
  2775                   itemValue: previousImageInSequence
  2776                   translateLabel: true
  2777                 )
  2778                (MenuItem
  2779                   label: '-'
  2780                 )
  2781                (MenuItem
  2782                   enabled: imageHasImageSequenceHolder
  2783                   label: 'Edit each from Sequence'
  2784                   itemValue: editEachImageFromSequence
  2785                   translateLabel: true
  2786                 )
  2787                )
  2788               nil
  2789               nil
  2790             )
  2791           )
  2792          )
  2793         nil
  2794         nil
  2795       )
  2796 !
  2797 
  2798 menuFile
  2799     "This resource specification was automatically generated
  2800      by the MenuEditor of ST/X."
  2801 
  2802     "Do not manually edit this!! If it is corrupted,
  2803      the MenuEditor may not be able to read the specification."
  2804 
  2805 
  2806     "
  2807      MenuEditor new openOnClass:ImageEditor andSelector:#menuFile
  2808      (Menu new fromLiteralArrayEncoding:(ImageEditor menuFile)) startUp
  2809     "
  2810 
  2811     <resource: #menu>
  2812 
  2813     ^ 
  2814      #(Menu
  2815         (
  2816          (MenuItem
  2817             activeHelpKey: fileNewImageEditor
  2818             label: 'New ImageEditor'
  2819             itemValue: doNewImageEditor
  2820           )
  2821          (MenuItem
  2822             label: '-'
  2823           )
  2824          (MenuItem
  2825             activeHelpKey: fileNewImage
  2826             label: 'New...'
  2827             itemValue: doNewImage
  2828           )
  2829          (MenuItem
  2830             activeHelpKey: fileNewImageFromClipboard
  2831             label: 'New from ClipBoard'
  2832             itemValue: doNewImageFromClipboard
  2833           )
  2834          (MenuItem
  2835             activeHelpKey: fileNewMaskFromClipboard
  2836             label: 'Mask from ClipBoard'
  2837             itemValue: doNewMaskFromClipboard
  2838           )
  2839          (MenuItem
  2840             label: '-'
  2841           )
  2842          (MenuItem
  2843             activeHelpKey: fileLoadFromClass
  2844             label: 'Load...'
  2845             itemValue: doLoadFromClass
  2846           )
  2847          (MenuItem
  2848             activeHelpKey: fileLoadFromFile
  2849             label: 'Load from File...'
  2850             itemValue: doLoadFromFile
  2851           )
  2852          (MenuItem
  2853             activeHelpKey: fileLoadFromURL
  2854             label: 'Load from URL...'
  2855             itemValue: doLoadFromURL
  2856           )
  2857          (MenuItem
  2858             label: 'Grab'
  2859             submenu: 
  2860            (Menu
  2861               (
  2862                (MenuItem
  2863                   activeHelpKey: fileGrabImageFromScreen
  2864                   label: 'Grab from Screen Area...'
  2865                   itemValue: grabScreenImage
  2866                 )
  2867                (MenuItem
  2868                   activeHelpKey: fileGrabImageFromScreen
  2869                   enabled: hasLastGrabScreenArea
  2870                   label: 'Grab again from same Screen Area'
  2871                   itemValue: grabScreenImageFromLastArea
  2872                 )
  2873                (MenuItem
  2874                   label: '-'
  2875                 )
  2876                (MenuItem
  2877                   activeHelpKey: fileGrabImageFromWindow
  2878                   label: 'Grab from Window...'
  2879                   itemValue: grabWindowImage
  2880                 )
  2881                )
  2882               nil
  2883               nil
  2884             )
  2885           )
  2886          (MenuItem
  2887             label: '-'
  2888           )
  2889          (MenuItem
  2890             activeHelpKey: fileSaveMethod
  2891             enabled: imageIsLoadedAndClassDefined
  2892             label: 'Save'
  2893             itemValue: doSaveMethod
  2894           )
  2895          (MenuItem
  2896             activeHelpKey: fileSaveMethodAs
  2897             enabled: imageIsLoadedHolder
  2898             label: 'Save As...'
  2899             itemValue: doSaveMethodAs
  2900           )
  2901          (MenuItem
  2902             activeHelpKey: fileSaveAs
  2903             enabled: imageIsLoadedHolder
  2904             label: 'Save to File...'
  2905             itemValue: doSaveImageFileAs
  2906           )
  2907          (MenuItem
  2908             activeHelpKey: fileSaveMaskAs
  2909             enabled: imageIsLoadedHolder
  2910             label: 'Save Mask to File...'
  2911             itemValue: doSaveImageMaskFileAs
  2912           )
  2913          (MenuItem
  2914             activeHelpKey: fileSaveButtonImageAs
  2915             enabled: imageIsLoadedHolder
  2916             label: 'Save as Button to File...'
  2917             itemValue: doSaveButtonImageToFileAs
  2918           )
  2919          (MenuItem
  2920             label: '-'
  2921           )
  2922          (MenuItem
  2923             activeHelpKey: filePrint
  2924             enabled: imageIsLoadedHolder
  2925             label: 'Print'
  2926             itemValue: doPrint
  2927           )
  2928          (MenuItem
  2929             label: '-'
  2930             isVisible: isStandAlone
  2931           )
  2932          (MenuItem
  2933             activeHelpKey: fileBrowseClass
  2934             enabled: hasClassDefinedHolder
  2935             label: 'Browse Class'
  2936             itemValue: doBrowseClass
  2937             isVisible: isStandAlone
  2938           )
  2939          (MenuItem
  2940             enabled: imageIsLoadedHolder
  2941             label: 'Inspect Image'
  2942             itemValue: doInspectImage
  2943             isVisible: isStandAlone
  2944           )
  2945          (MenuItem
  2946             activeHelpKey: fileShowStoreString
  2947             enabled: imageIsLoadedHolder
  2948             label: 'Show storeString'
  2949             itemValue: doShowStoreString
  2950           )
  2951          (MenuItem
  2952             activeHelpKey: fileShowStoreString
  2953             enabled: imageIsLoadedHolder
  2954             label: 'Show Pixel Array Literal String'
  2955             itemValue: doShowPixelArrayLiteralString
  2956           )
  2957          (MenuItem
  2958             label: '-'
  2959             isVisible: isStandAlone
  2960           )
  2961          (MenuItem
  2962             activeHelpKey: fileExit
  2963             label: 'Exit'
  2964             itemValue: closeRequest
  2965             isVisible: isStandAlone
  2966           )
  2967          )
  2968         nil
  2969         nil
  2970       )
  2971 !
  2972 
  2973 menuMouseButtonColors
  2974     "This resource specification was automatically generated
  2975      by the MenuEditor of ST/X."
  2976 
  2977     "Do not manually edit this!! If it is corrupted,
  2978      the MenuEditor may not be able to read the specification."
  2979 
  2980     "
  2981      MenuEditor new openOnClass:ImageEditor andSelector:#menuMouseButtonColors
  2982      (Menu new fromLiteralArrayEncoding:(ImageEditor menuMouseButtonColors)) startUp
  2983     "
  2984 
  2985     <resource: #menu>
  2986 
  2987     ^
  2988      
  2989        #(#Menu
  2990           
  2991            #(
  2992              #(#MenuItem
  2993                 #label: 'Left Mouse Button'
  2994                 #nameKey: #leftMouseKeyButton
  2995                 #activeHelpKey: #mouseKeyColorMode
  2996                 #enabled: #imageIsLoadedHolder
  2997                 #labelImage: #(#ResourceRetriever nil #leftMouseKeyIcon)
  2998                 #choice: #mouseKeyColorMode
  2999                 #choiceValue: 1
  3000             )
  3001              #(#MenuItem
  3002                 #label: 'Right Mouse Button'
  3003                 #nameKey: #rightMouseKeyButton
  3004                 #activeHelpKey: #mouseKeyColorMode
  3005                 #enabled: #imageIsLoadedHolder
  3006                 #labelImage: #(#ResourceRetriever nil #rightMouseKeyIcon)
  3007                 #choice: #mouseKeyColorMode
  3008                 #choiceValue: 2
  3009             )
  3010           ) nil
  3011           nil
  3012       )
  3013 
  3014     "Modified: / 04-07-2010 / 10:17:37 / cg"
  3015 !
  3016 
  3017 menuSettings
  3018     "This resource specification was automatically generated
  3019      by the MenuEditor of ST/X."
  3020 
  3021     "Do not manually edit this!! If it is corrupted,
  3022      the MenuEditor may not be able to read the specification."
  3023 
  3024 
  3025     "
  3026      MenuEditor new openOnClass:ImageEditor andSelector:#menuSettings
  3027      (Menu new fromLiteralArrayEncoding:(ImageEditor menuSettings)) startUp
  3028     "
  3029 
  3030     <resource: #menu>
  3031 
  3032     ^ 
  3033      #(Menu
  3034         (
  3035          (MenuItem
  3036             activeHelpKey: settingsGridMagnification
  3037             label: 'Grid Magnification Limit...'
  3038             itemValue: doChangeGridMagnification
  3039             translateLabel: true
  3040           )
  3041          (MenuItem
  3042             label: 'Pen'
  3043             translateLabel: true
  3044             submenu: 
  3045            (Menu
  3046               (
  3047                (MenuItem
  3048                   label: '1'
  3049                   translateLabel: true
  3050                   choice: penWidthHolder
  3051                   choiceValue: 1
  3052                 )
  3053                (MenuItem
  3054                   label: '5'
  3055                   translateLabel: true
  3056                   choice: penWidthHolder
  3057                   choiceValue: 5
  3058                 )
  3059                (MenuItem
  3060                   label: '10'
  3061                   translateLabel: true
  3062                   choice: penWidthHolder
  3063                   choiceValue: 10
  3064                 )
  3065                )
  3066               nil
  3067               nil
  3068             )
  3069           )
  3070          (MenuItem
  3071             label: 'Spray'
  3072             translateLabel: true
  3073             submenu: 
  3074            (Menu
  3075               (
  3076                (MenuItem
  3077                   label: '4'
  3078                   translateLabel: true
  3079                   choice: spraySpotHolder
  3080                   choiceValue: 4
  3081                 )
  3082                (MenuItem
  3083                   label: '8'
  3084                   translateLabel: true
  3085                   choice: spraySpotHolder
  3086                   choiceValue: 8
  3087                 )
  3088                (MenuItem
  3089                   label: '16'
  3090                   translateLabel: true
  3091                   choice: spraySpotHolder
  3092                   choiceValue: 16
  3093                 )
  3094                (MenuItem
  3095                   label: '32'
  3096                   translateLabel: true
  3097                   choice: spraySpotHolder
  3098                   choiceValue: 32
  3099                 )
  3100                )
  3101               nil
  3102               nil
  3103             )
  3104           )
  3105          )
  3106         nil
  3107         nil
  3108       )
  3109 !
  3110 
  3111 menuToolbar
  3112     "This resource specification was automatically generated
  3113      by the MenuEditor of ST/X."
  3114 
  3115     "Do not manually edit this!! If it is corrupted,
  3116      the MenuEditor may not be able to read the specification."
  3117 
  3118 
  3119     "
  3120      MenuEditor new openOnClass:ImageEditor andSelector:#menuToolbar
  3121      (Menu new fromLiteralArrayEncoding:(ImageEditor menuToolbar)) startUp
  3122     "
  3123 
  3124     <resource: #menu>
  3125 
  3126     ^ 
  3127      #(Menu
  3128         (
  3129          (MenuItem
  3130             activeHelpKey: fileNewImage
  3131             label: 'newImage'
  3132             itemValue: doNewImage
  3133             translateLabel: true
  3134             isButton: true
  3135             labelImage: (ResourceRetriever ToolbarIconLibrary newImageIcon)
  3136           )
  3137          (MenuItem
  3138             activeHelpKey: fileGrabImageFromScreen
  3139             label: 'grabScreenImage'
  3140             itemValue: grabScreenImage
  3141             translateLabel: true
  3142             isButton: true
  3143             labelImage: (ResourceRetriever ToolbarIconLibrary snapshot24x24Icon)
  3144           )
  3145          (MenuItem
  3146             label: '-'
  3147           )
  3148          (MenuItem
  3149             activeHelpKey: fileLoadFromClass
  3150             label: 'loadFromClass'
  3151             itemValue: doLoadFromClass
  3152             translateLabel: true
  3153             isButton: true
  3154             isVisible: isStandAlone
  3155             submenuChannel: menuHistory
  3156             labelImage: (ResourceRetriever XPToolbarIconLibrary loadImageFromMethodIcon)
  3157             keepLinkedMenu: true
  3158           )
  3159          (MenuItem
  3160             activeHelpKey: fileSaveMethodAs
  3161             enabled: imageIsLoadedHolder
  3162             label: 'fileSaveMethodAs'
  3163             itemValue: doSaveMethodAs
  3164             translateLabel: true
  3165             isButton: true
  3166             isVisible: isStandAlone
  3167             labelImage: (ResourceRetriever XPToolbarIconLibrary saveImageAsMethodAsIcon)
  3168           )
  3169          (MenuItem
  3170             activeHelpKey: fileSaveMethod
  3171             enabled: imageIsLoadedHolder
  3172             label: 'saveAsMethod'
  3173             itemValue: doSaveMethod
  3174             translateLabel: true
  3175             isButton: true
  3176             isVisible: isNotStandAlone
  3177             labelImage: (ResourceRetriever ToolbarIconLibrary saveImageAsMethodIcon)
  3178           )
  3179          (MenuItem
  3180             label: '-'
  3181           )
  3182          (MenuItem
  3183             activeHelpKey: fileLoadFromFile
  3184             label: 'loadFromFile'
  3185             itemValue: doLoadFromFile
  3186             translateLabel: true
  3187             isButton: true
  3188             labelImage: (ResourceRetriever ToolbarIconLibrary loadImageFromFileIcon)
  3189           )
  3190          (MenuItem
  3191             activeHelpKey: fileSaveAs
  3192             enabled: imageIsLoadedHolder
  3193             label: 'saveAsFile'
  3194             itemValue: doSaveImageFileAs
  3195             translateLabel: true
  3196             isButton: true
  3197             labelImage: (ResourceRetriever ToolbarIconLibrary saveImageToFileAsIcon)
  3198           )
  3199          (MenuItem
  3200             label: '-'
  3201           )
  3202          (MenuItem
  3203             activeHelpKey: editUndo
  3204             enabled: canUndoHolder
  3205             label: 'Undo'
  3206             itemValue: doUndo
  3207             translateLabel: true
  3208             isButton: true
  3209             labelImage: (ResourceRetriever ToolbarIconLibrary undoIcon)
  3210           )
  3211          (MenuItem
  3212             label: '-'
  3213             isVisible: imageHasImageSequenceHolder
  3214           )
  3215          (MenuItem
  3216             activeHelpKey: previousImageInSequence
  3217             enabled: imageHasPreviousImageHolder
  3218             label: 'Previous Image'
  3219             itemValue: previousImageInSequence
  3220             translateLabel: true
  3221             isVisible: imageHasImageSequenceHolder
  3222             labelImage: (ResourceRetriever ToolbarIconLibrary leftArrow24x24Icon)
  3223           )
  3224          (MenuItem
  3225             activeHelpKey: nextImageInSequence
  3226             enabled: imageHasNextImageHolder
  3227             label: 'Next Image'
  3228             itemValue: nextImageInSequence
  3229             translateLabel: true
  3230             isVisible: imageHasImageSequenceHolder
  3231             labelImage: (ResourceRetriever ToolbarIconLibrary rightArrow24x24Icon)
  3232           )
  3233          )
  3234         nil
  3235         nil
  3236       )
  3237 !
  3238 
  3239 modeMenu
  3240     "This resource specification was automatically generated
  3241      by the MenuEditor of ST/X."
  3242 
  3243     "Do not manually edit this!! If it is corrupted,
  3244      the MenuEditor may not be able to read the specification."
  3245 
  3246     "
  3247      MenuEditor new openOnClass:ImageEditor andSelector:#modeMenu
  3248      (Menu new fromLiteralArrayEncoding:(ImageEditor modeMenu)) startUp
  3249     "
  3250 
  3251     <resource: #menu>
  3252 
  3253     ^ 
  3254      #(Menu
  3255         (
  3256          (MenuItem
  3257             activeHelpKey: drawModePoint
  3258             enabled: imageIsLoadedHolder
  3259             label: 'Point'
  3260             translateLabel: true
  3261             labelImage: (ResourceRetriever ImageEditor pointIcon 'Point')
  3262             choice: editMode
  3263             choiceValue: point
  3264           )
  3265          (MenuItem
  3266             activeHelpKey: drawModePoint
  3267             enabled: imageIsLoadedHolder
  3268             label: 'Spray'
  3269             translateLabel: true
  3270             labelImage: (ResourceRetriever ImageEditor sprayIcon 'Spray')
  3271             choice: editMode
  3272             choiceValue: spray
  3273           )
  3274          (MenuItem
  3275             activeHelpKey: drawModeSmooth
  3276             enabled: imageIsLoadedHolder
  3277             label: 'Smooth'
  3278             translateLabel: true
  3279             labelImage: (ResourceRetriever ImageEditor smoothIcon 'Smooth')
  3280             choice: editMode
  3281             choiceValue: smooth
  3282           )
  3283          (MenuItem
  3284             activeHelpKey: drawModeBox
  3285             enabled: imageIsLoadedHolder
  3286             label: 'Rect'
  3287             translateLabel: true
  3288             labelImage: (ResourceRetriever ImageEditor rectIcon 'Rect')
  3289             choice: editMode
  3290             choiceValue: box
  3291           )
  3292          (MenuItem
  3293             activeHelpKey: drawModeFilledBox
  3294             enabled: imageIsLoadedHolder
  3295             label: 'Filled Rectangle'
  3296             translateLabel: true
  3297             labelImage: (ResourceRetriever ImageEditor fillRectIcon 'Filled Rectangle')
  3298             choice: editMode
  3299             choiceValue: filledBox
  3300           )
  3301          (MenuItem
  3302             activeHelpKey: drawModeBox
  3303             enabled: imageIsLoadedHolder
  3304             label: 'Circle'
  3305             translateLabel: true
  3306             labelImage: (ResourceRetriever ImageEditor circleIcon 'Circle')
  3307             choice: editMode
  3308             choiceValue: circle
  3309           )
  3310          (MenuItem
  3311             activeHelpKey: drawModeFill
  3312             enabled: imageIsLoadedHolder
  3313             label: 'Fill'
  3314             translateLabel: true
  3315             labelImage: (ResourceRetriever ImageEditor fillIcon 'Fill')
  3316             choice: editMode
  3317             choiceValue: fill
  3318           )
  3319          (MenuItem
  3320             activeHelpKey: drawModeCopy
  3321             enabled: imageIsLoadedHolder
  3322             label: 'Copy'
  3323             translateLabel: true
  3324             labelImage: (ResourceRetriever ImageEditor copyIcon 'Copy')
  3325             choice: editMode
  3326             choiceValue: copy
  3327           )
  3328          (MenuItem
  3329             activeHelpKey: drawModePaste
  3330             enabled: imageIsLoadedHolder
  3331             label: 'Paste'
  3332             translateLabel: true
  3333             labelImage: (ResourceRetriever ImageEditor pasteIcon 'Paste')
  3334             choice: editMode
  3335             choiceValue: paste
  3336           )
  3337          (MenuItem
  3338             activeHelpKey: drawModePasteUnder
  3339             enabled: imageIsLoadedHolder
  3340             label: 'Paste Under'
  3341             translateLabel: true
  3342             labelImage: (ResourceRetriever ImageEditor pasteUnderIcon 'Paste Under')
  3343             choice: editMode
  3344             choiceValue: pasteUnder
  3345           )
  3346          (MenuItem
  3347             activeHelpKey: drawModePasteWithMask
  3348             enabled: imageIsLoadedHolder
  3349             label: 'Paste with Mask'
  3350             translateLabel: true
  3351             labelImage: (ResourceRetriever ImageEditor pasteWithMaskIcon 'Paste with Mask')
  3352             choice: editMode
  3353             choiceValue: pasteWithMask
  3354           )
  3355          (MenuItem
  3356             activeHelpKey: drawModeSpecial
  3357             enabled: imageIsLoadedHolder
  3358             label: 'Special'
  3359             translateLabel: true
  3360             labelImage: (ResourceRetriever ImageEditor specialIcon 'Special')
  3361             choice: editMode
  3362             choiceValue: specialOperation
  3363           )
  3364          )
  3365         nil
  3366         nil
  3367       )
  3368 
  3369     "Modified: / 04-07-2010 / 10:18:08 / cg"
  3370 !
  3371 
  3372 previewMenu
  3373     "This resource specification was automatically generated
  3374      by the MenuEditor of ST/X."
  3375 
  3376     "Do not manually edit this!! If it is corrupted,
  3377      the MenuEditor may not be able to read the specification."
  3378 
  3379     "
  3380      MenuEditor new openOnClass:ImageEditor andSelector:#previewMenu
  3381      (Menu new fromLiteralArrayEncoding:(ImageEditor previewMenu)) startUp
  3382     "
  3383 
  3384     <resource: #menu>
  3385 
  3386     ^ 
  3387      #(Menu
  3388         (
  3389          (MenuItem
  3390             label: 'TileMode'
  3391             translateLabel: true
  3392             indication: tileModeHolder
  3393           )
  3394          (MenuItem
  3395             label: '-'
  3396           )
  3397          (MenuItem
  3398             label: 'Background Color'
  3399             translateLabel: true
  3400             submenu: 
  3401            (Menu
  3402               (
  3403                (MenuItem
  3404                   label: 'Gray'
  3405                   translateLabel: true
  3406                   choice: previewBackgroundColorHolder
  3407                   choiceValue: nil
  3408                 )
  3409                (MenuItem
  3410                   label: 'Black'
  3411                   translateLabel: true
  3412                   choice: previewBackgroundColorHolder
  3413                   choiceValue: black
  3414                 )
  3415                (MenuItem
  3416                   label: 'White'
  3417                   translateLabel: true
  3418                   choice: previewBackgroundColorHolder
  3419                   choiceValue: white
  3420                 )
  3421                (MenuItem
  3422                   label: '-'
  3423                 )
  3424                (MenuItem
  3425                   label: 'Red'
  3426                   translateLabel: true
  3427                   choice: previewBackgroundColorHolder
  3428                   choiceValue: red
  3429                 )
  3430                (MenuItem
  3431                   label: 'Green'
  3432                   translateLabel: true
  3433                   choice: previewBackgroundColorHolder
  3434                   choiceValue: green
  3435                 )
  3436                (MenuItem
  3437                   label: 'Blue'
  3438                   translateLabel: true
  3439                   choice: previewBackgroundColorHolder
  3440                   choiceValue: blue
  3441                 )
  3442                )
  3443               nil
  3444               nil
  3445             )
  3446           )
  3447          )
  3448         nil
  3449         nil
  3450       )
  3451 
  3452     "Modified: / 04-07-2010 / 10:20:09 / cg"
  3453 !
  3454 
  3455 toolsMenuToolbar
  3456     "This resource specification was automatically generated
  3457      by the MenuEditor of ST/X."
  3458 
  3459     "Do not manually edit this!! If it is corrupted,
  3460      the MenuEditor may not be able to read the specification."
  3461 
  3462 
  3463     "
  3464      MenuEditor new openOnClass:ImageEditor andSelector:#toolsMenuToolbar
  3465      (Menu new fromLiteralArrayEncoding:(ImageEditor toolsMenuToolbar)) startUp
  3466     "
  3467 
  3468     <resource: #menu>
  3469 
  3470     ^ 
  3471      #(Menu
  3472         (
  3473          (MenuItem
  3474             activeHelpKey: drawModePoint
  3475             enabled: imageIsLoadedHolder
  3476             label: 'Point'
  3477             translateLabel: true
  3478             isButton: true
  3479             labelImage: (ResourceRetriever ImageEditor pointIcon)
  3480             choice: editMode
  3481             choiceValue: point
  3482           )
  3483          (MenuItem
  3484             activeHelpKey: drawModeSpray
  3485             enabled: imageIsLoadedHolder
  3486             label: 'Spray'
  3487             translateLabel: true
  3488             isButton: true
  3489             labelImage: (ResourceRetriever ImageEditor sprayIcon)
  3490             choice: editMode
  3491             choiceValue: spray
  3492           )
  3493          (MenuItem
  3494             activeHelpKey: drawModeBox
  3495             enabled: imageIsLoadedHolder
  3496             label: 'Rect'
  3497             translateLabel: true
  3498             isButton: true
  3499             labelImage: (ResourceRetriever ImageEditor rectIcon)
  3500             choice: editMode
  3501             choiceValue: box
  3502           )
  3503          (MenuItem
  3504             activeHelpKey: drawModeFilledBox
  3505             enabled: imageIsLoadedHolder
  3506             label: 'FillRect'
  3507             translateLabel: true
  3508             isButton: true
  3509             labelImage: (ResourceRetriever ImageEditor fillRectIcon)
  3510             choice: editMode
  3511             choiceValue: filledBox
  3512           )
  3513          (MenuItem
  3514             activeHelpKey: drawModeCircle
  3515             enabled: imageIsLoadedHolder
  3516             label: 'Circle'
  3517             translateLabel: true
  3518             isButton: true
  3519             labelImage: (ResourceRetriever ImageEditor circleIcon)
  3520             choice: editMode
  3521             choiceValue: circle
  3522           )
  3523          (MenuItem
  3524             activeHelpKey: drawModeFill
  3525             enabled: imageIsLoadedHolder
  3526             label: 'Fill'
  3527             translateLabel: true
  3528             isButton: true
  3529             labelImage: (ResourceRetriever ImageEditor fillIcon)
  3530             choice: editMode
  3531             choiceValue: fill
  3532           )
  3533          (MenuItem
  3534             activeHelpKey: drawModeCopy
  3535             enabled: imageIsLoadedHolder
  3536             label: 'Copy'
  3537             translateLabel: true
  3538             isButton: true
  3539             labelImage: (ResourceRetriever ImageEditor copyIcon)
  3540             choice: editMode
  3541             choiceValue: copy
  3542           )
  3543          (MenuItem
  3544             activeHelpKey: drawModePasteWithMask
  3545             enabled: imageIsLoadedHolder
  3546             label: 'Paste With Mask'
  3547             translateLabel: true
  3548             isButton: true
  3549             labelImage: (ResourceRetriever ImageEditor pasteWithMaskIcon)
  3550             choice: editMode
  3551             choiceValue: pasteWithMask
  3552           )
  3553          (MenuItem
  3554             activeHelpKey: drawModePaste
  3555             enabled: imageIsLoadedHolder
  3556             label: 'Paste'
  3557             translateLabel: true
  3558             isButton: true
  3559             labelImage: (ResourceRetriever ImageEditor pasteIcon)
  3560             choice: editMode
  3561             choiceValue: paste
  3562           )
  3563          (MenuItem
  3564             activeHelpKey: drawModePasteUnder
  3565             enabled: imageIsLoadedHolder
  3566             label: 'Paste Under'
  3567             translateLabel: true
  3568             isButton: true
  3569             labelImage: (ResourceRetriever ImageEditor pasteUnderIcon)
  3570             choice: editMode
  3571             choiceValue: pasteUnder
  3572           )
  3573          (MenuItem
  3574             activeHelpKey: drawModeSpecial
  3575             enabled: imageIsLoadedHolder
  3576             label: 'Special'
  3577             translateLabel: true
  3578             isButton: true
  3579             labelImage: (ResourceRetriever ImageEditor specialIcon)
  3580             choice: editMode
  3581             choiceValue: specialOperation
  3582           )
  3583          )
  3584         nil
  3585         nil
  3586       )
  3587 ! !
  3588 
  3589 !ImageEditor class methodsFor:'tableColumns specs'!
  3590 
  3591 colorTableColumns
  3592     "This resource specification was automatically generated
  3593      by the DataSetBuilder of ST/X."
  3594 
  3595     "Do not manually edit this!! If it is corrupted,
  3596      the DataSetBuilder may not be able to read the specification."
  3597 
  3598     "
  3599      DataSetBuilder new openOnClass:ImageEditor andSelector:#colorTableColumns
  3600     "
  3601 
  3602     <resource: #tableColumns>
  3603 
  3604     ^#(
  3605       (DataSetColumnSpec
  3606          activeHelpKey: ''
  3607          labelButtonType: Button
  3608          rendererType: rowSelector
  3609          backgroundSelector: theColorItself:
  3610          selectedBackgroundSelector: theColorItself:
  3611          isResizeable: false
  3612        )
  3613       (DataSetColumnSpec
  3614          label: 'R'
  3615          labelAlignment: left
  3616          labelButtonType: Button
  3617          columnAlignment: right
  3618          editorType: InputField
  3619          type: number
  3620          model: redFromColor:
  3621          writeSelector: redAtColor:put:
  3622          selectSelector: canSelectRedInColor:
  3623        )
  3624       (DataSetColumnSpec
  3625          label: 'G'
  3626          labelAlignment: left
  3627          labelButtonType: Button
  3628          columnAlignment: right
  3629          editorType: InputField
  3630          type: number
  3631          model: greenFromColor:
  3632          writeSelector: greenAtColor:put:
  3633          selectSelector: canSelectGreenInColor:
  3634        )
  3635       (DataSetColumnSpec
  3636          label: 'B'
  3637          labelAlignment: left
  3638          labelButtonType: Button
  3639          columnAlignment: right
  3640          editorType: InputField
  3641          type: number
  3642          model: blueFromColor:
  3643          writeSelector: blueAtColor:put:
  3644          selectSelector: canSelectBlueInColor:
  3645        )
  3646       )
  3647 
  3648     "Modified: / 22-07-2007 / 13:21:57 / cg"
  3649 ! !
  3650 
  3651 !ImageEditor methodsFor:'accessing'!
  3652 
  3653 image
  3654     "returns the current editing image"
  3655 
  3656     ^ imageEditView image
  3657 !
  3658 
  3659 postOpenAction: anAction
  3660    "sets an action which is evaluated after opening"
  3661 
  3662     postOpenAction := anAction
  3663 !
  3664 
  3665 resourceClass:aClass
  3666     imageEditView resourceClass:aClass
  3667 ! !
  3668 
  3669 !ImageEditor methodsFor:'accessing-behavior'!
  3670 
  3671 allowedToChangeImageDimensionAndDepth
  3672     "used to edit an existing image's contents only (Expecco)"
  3673 
  3674     ^ allowedToChangeImageDimensionAndDepth ? true
  3675 !
  3676 
  3677 allowedToChangeImageDimensionAndDepth:aBoolean
  3678     "used to edit an existing image's contents only (Expecco)"
  3679 
  3680     allowedToChangeImageDimensionAndDepth := aBoolean
  3681 ! !
  3682 
  3683 !ImageEditor methodsFor:'accessing-views'!
  3684 
  3685 colorDataSetView
  3686     "returns the view of the colormap"
  3687 
  3688     ^(self componentAt: #colorDataSetView)
  3689 
  3690     "Created: / 26.7.1998 / 12:02:14 / cg"
  3691 !
  3692 
  3693 coordLabel
  3694     "returns the view the coord label"
  3695 
  3696     ^self componentAt: #coordLabel
  3697 !
  3698 
  3699 imageEditView
  3700     "returns the view of the image"
  3701 
  3702     imageEditView isNil ifTrue:[
  3703         imageEditView := (self componentAt: #imageEditView) scrolledView.
  3704         imageEditView addDependent:self.
  3705     ].
  3706     ^ imageEditView
  3707 
  3708     "Modified: / 10.2.2000 / 23:19:20 / cg"
  3709 !
  3710 
  3711 imagePreView
  3712     "returns the preview of the image"
  3713 
  3714     |imagePreViewSubViews|
  3715 
  3716     imagePreViewSubViews := (self componentAt: #imagePreView) subViews.
  3717 
  3718     "subViews is an empty array at closing image Editor"
  3719     imagePreViewSubViews isEmptyOrNil ifTrue:[
  3720         ^ nil
  3721     ].
  3722 
  3723     ^ imagePreViewSubViews first 
  3724 ! !
  3725 
  3726 !ImageEditor methodsFor:'aspects'!
  3727 
  3728 activityInfoHolder
  3729     ^ self infoLabelHolder
  3730 
  3731     "Modified: / 29.7.1998 / 18:49:03 / cg"
  3732 !
  3733 
  3734 colorColumnAdaptor
  3735     ^ self
  3736 
  3737     "Created: / 26.7.1998 / 12:17:03 / cg"
  3738 !
  3739 
  3740 hasClassAndSelectorDefinedHolder
  3741     ^ [
  3742         |cls|
  3743 
  3744         (cls := imageEditView resourceClass) notNil
  3745         and:[imageEditView resourceSelector notNil]
  3746       ]
  3747 
  3748     "Created: / 04-07-2010 / 10:11:10 / cg"
  3749 !
  3750 
  3751 hasClassDefinedHolder
  3752     ^ [
  3753         imageEditView resourceClass notNil
  3754       ]
  3755 
  3756     "Created: / 04-07-2010 / 10:11:47 / cg"
  3757 !
  3758 
  3759 hasColorSelectedHolder
  3760     ^ [ self selectedColors value notEmptyOrNil "self selectedColorIndexOrNil notNil" ]
  3761 
  3762     "Created: / 04-07-2010 / 10:12:22 / cg"
  3763 !
  3764 
  3765 hasColormap
  3766     ^ self image notNil and:[self image colorMap notNil]
  3767 
  3768     "Created: / 30-09-1998 / 23:53:55 / cg"
  3769     "Modified: / 04-07-2010 / 10:13:26 / cg"
  3770 !
  3771 
  3772 hasColormapAndColorSelected
  3773     ^ [ self hasColormapHolder value and:[self hasColorSelectedHolder value]]
  3774 
  3775     "Modified: / 04-07-2010 / 10:13:13 / cg"
  3776 !
  3777 
  3778 hasColormapAndSingleColorSelected
  3779     ^ [ self hasColormapHolder value and:[self hasSingleColorSelectedHolder value]]
  3780 
  3781     "Modified: / 04-07-2010 / 10:13:13 / cg"
  3782 !
  3783 
  3784 hasColormapHolder
  3785     ^ [self hasColormap]
  3786 
  3787     "Created: / 04-07-2010 / 10:13:05 / cg"
  3788 !
  3789 
  3790 hasSingleColorSelectedHolder
  3791     ^ [ self selectedColors value size == 1 "self selectedColorIndexOrNil notNil" ]
  3792 
  3793     "Created: / 04-07-2010 / 10:12:22 / cg"
  3794 !
  3795 
  3796 imageHasImageSequence
  3797     |img|
  3798 
  3799     ^ (img := self image) notNil and:[img imageSequence notNil]
  3800 
  3801     "Created: / 21-10-2010 / 14:35:45 / cg"
  3802 !
  3803 
  3804 imageHasImageSequenceHolder
  3805     |holder|
  3806 
  3807     (holder := builder bindingAt:#imageHasImageSequenceHolder) isNil ifTrue:[
  3808         builder aspectAt:#imageHasImageSequenceHolder put:(holder := false asValue).
  3809         holder value:(self imageHasImageSequence).    
  3810     ].
  3811     ^ holder
  3812 
  3813     "Modified: / 21-10-2010 / 14:36:57 / cg"
  3814 !
  3815 
  3816 imageHasNextImage
  3817     ^ self imageHasImageSequence and:[ (imageSeqNr ? 1) < self image imageSequence size ]
  3818 
  3819     "Created: / 21-10-2010 / 14:37:10 / cg"
  3820 !
  3821 
  3822 imageHasNextImageHolder
  3823     |holder|
  3824 
  3825     (holder := builder bindingAt:#imageHasNextImageHolder) isNil ifTrue:[
  3826         builder aspectAt:#imageHasNextImageHolder put:(holder := false asValue).
  3827         holder value:(self imageHasNextImage).    
  3828     ].
  3829     ^ holder
  3830 
  3831     "Modified: / 21-10-2010 / 14:37:40 / cg"
  3832 !
  3833 
  3834 imageHasPreviousImage
  3835     ^ self imageHasImageSequence and:[ (imageSeqNr ? 1) > 1 ]
  3836 
  3837     "Created: / 21-10-2010 / 14:37:21 / cg"
  3838 !
  3839 
  3840 imageHasPreviousImageHolder
  3841     |holder|
  3842 
  3843     (holder := builder bindingAt:#imageHasPreviousImageHolder) isNil ifTrue:[
  3844         builder aspectAt:#imageHasPreviousImageHolder put:(holder := false asValue).
  3845         holder value:(self imageHasPreviousImage).    
  3846     ].
  3847     ^ holder
  3848 
  3849     "Modified: / 21-10-2010 / 14:37:48 / cg"
  3850 !
  3851 
  3852 imageInfoHolder
  3853     |holder|
  3854 
  3855     (holder := builder bindingAt:#imageInfoHolder) isNil ifTrue:[
  3856         builder aspectAt:#imageInfoHolder put:(holder :=  '' asValue).
  3857     ].
  3858     ^ holder
  3859 
  3860     "Modified: / 04-07-2010 / 10:15:14 / cg"
  3861 !
  3862 
  3863 imageIsLoadedAndAllowedToChangeImageDimensionAndDepth
  3864     "returns whether an image is loaded as value holder"
  3865 
  3866     ^ [ 
  3867         self imageIsLoadedHolder value
  3868         and:[ self allowedToChangeImageDimensionAndDepth ] 
  3869       ]
  3870 
  3871     "Modified: / 04-07-2010 / 10:15:43 / cg"
  3872 !
  3873 
  3874 imageIsLoadedAndClassDefined
  3875     "returns whether an image is loaded as value holder"
  3876 
  3877     ^ [self hasClassAndSelectorDefinedHolder value
  3878        and:[self imageIsLoadedHolder value]]
  3879 
  3880     "Created: / 31-07-1998 / 02:04:18 / cg"
  3881     "Modified: / 04-07-2010 / 10:15:48 / cg"
  3882 !
  3883 
  3884 imageIsLoadedHolder
  3885     "returns whether an image is loaded as value holder"
  3886 
  3887     |holder|
  3888 
  3889     (holder := builder bindingAt:#imageIsLoaded) isNil ifTrue:[
  3890         builder aspectAt:#imageIsLoaded put:(holder :=  false asValue).
  3891     ].
  3892     ^ holder
  3893 
  3894     "Created: / 04-07-2010 / 10:15:38 / cg"
  3895 !
  3896 
  3897 listOfColors
  3898     "returns the list of colors"
  3899 
  3900     |list|
  3901 
  3902     (list := builder bindingAt:#listOfColors) isNil ifTrue:[
  3903         builder aspectAt:#listOfColors put:(list :=  List new).
  3904         list addDependent:self.
  3905     ].
  3906     ^ list
  3907 !
  3908 
  3909 magnificationHolder
  3910     "returns current magnification of the image as an AspectAdaptor"
  3911 
  3912     |holder|
  3913     (holder := builder bindingAt:#valueOfMagnification) isNil ifTrue:[
  3914         builder aspectAt:#valueOfMagnification put:(
  3915         holder := AspectAdaptor new subject:self; forAspect:#magnification)
  3916     ].
  3917     ^ holder
  3918 !
  3919 
  3920 penWidthHolder
  3921     |holder|
  3922 
  3923     (holder := builder bindingAt:#penWidthHolder) isNil ifTrue:[
  3924         builder aspectAt:#penWidthHolder put:(holder := imageEditView penWidth asValue).
  3925         holder onChangeSend:#penWidthHolderChanged to:self.
  3926     ].
  3927     ^ holder
  3928 
  3929     "Created: / 15-02-2012 / 22:30:58 / cg"
  3930 !
  3931 
  3932 previewBackgroundColorHolder
  3933     |holder|
  3934 
  3935     (holder := builder bindingAt:#previewBackgroundColor) isNil ifTrue:[
  3936         builder aspectAt:#previewBackgroundColor put:(holder := nil asValue).
  3937         holder addDependent:self.
  3938     ].
  3939     ^ holder
  3940 
  3941     "Created: / 04-07-2010 / 10:19:34 / cg"
  3942 !
  3943 
  3944 selectedColors
  3945     "returns a valueHolder for the current set of selected colors."
  3946 
  3947     |holder|
  3948 
  3949     (holder := builder bindingAt:#selectedColors) isNil ifTrue:[
  3950         builder aspectAt:#selectedColors put:(holder := nil asValue).
  3951         holder onChangeSend:#selectedColorsChanged to:self.
  3952     ].
  3953     ^ holder
  3954 !
  3955 
  3956 selectionOfColor
  3957     "returns a valueHolder for the current selection of the edit color.
  3958      Here, an AspectAdaptor which accesses selectedColorIndex is returned."
  3959 
  3960     |holder|
  3961 
  3962     (holder := builder bindingAt:#selectionOfColor) isNil ifTrue:[
  3963         builder aspectAt:#selectionOfColor put:(
  3964         holder := AspectAdaptor new subject:self; forAspect:#selectedColorIndex ).
  3965     ].
  3966     ^ holder
  3967 !
  3968 
  3969 spraySpotHolder
  3970     |holder|
  3971 
  3972     (holder := builder bindingAt:#spraySpotHolder) isNil ifTrue:[
  3973         builder aspectAt:#spraySpotHolder put:(holder := imageEditView spraySpot asValue).
  3974         holder onChangeSend:#spraySpotHolderChanged to:self.
  3975     ].
  3976     ^ holder
  3977 
  3978     "Created: / 15-02-2012 / 22:36:38 / cg"
  3979 !
  3980 
  3981 tileModeHolder
  3982     |holder|
  3983 
  3984     (holder := builder bindingAt:#tileModeHolder) isNil ifTrue:[
  3985         builder aspectAt:#tileModeHolder put:(holder := false asValue).
  3986         holder addDependent:self.
  3987     ].
  3988     ^ holder
  3989 
  3990     "Modified: / 21-10-2010 / 14:35:24 / cg"
  3991 !
  3992 
  3993 valueOfMagnification
  3994     <resource: #obsolete>
  3995     "returns current magnification of the image as an AspectAdaptor"
  3996 
  3997     self obsoleteMethodWarning:'stupid method name - use #magnificationHolder'.
  3998     ^ self magnificationHolder
  3999 ! !
  4000 
  4001 !ImageEditor methodsFor:'change & update'!
  4002 
  4003 findColorMapMode
  4004     "finds the colorMapMode for a new image"
  4005 
  4006     |image newListOfColors colorMapModeKey drawColor1 drawColor2 someOrAllUsedColors|
  4007 
  4008     image := self image.
  4009     image isNil ifTrue:[^ self ].
  4010 
  4011     image mask notNil ifTrue: [             
  4012         colorMapModeKey := 'masked'.
  4013     ] ifFalse:[
  4014         colorMapModeKey := 'depth'.
  4015     ].
  4016     colorMapModeKey := colorMapModeKey , image depth printString.
  4017     self colorMapMode setValue:colorMapModeKey.
  4018 
  4019     image photometric == #palette ifTrue:[
  4020         image colorMap isNil ifTrue:[
  4021             image depth > 16 ifTrue:[
  4022                 image photometric:#rgb
  4023             ].
  4024         ].
  4025     ].
  4026 
  4027     image depth > 12 ifTrue:[
  4028         newListOfColors := OrderedCollection new.
  4029         (image depth > 16 or:[image colorMap isEmptyOrNil]) ifTrue:[
  4030             someOrAllUsedColors := image usedColorsMax:10000.
  4031             someOrAllUsedColors notNil ifTrue:[
  4032                 someOrAllUsedColors := someOrAllUsedColors asArray.
  4033                 someOrAllUsedColors sort:self sortBlockForColors.
  4034                 newListOfColors addAll:someOrAllUsedColors.
  4035                 "/ listOfColors add:Color black; add:Color white.
  4036             ].
  4037             image mask notNil ifTrue:[
  4038                 newListOfColors := (Array with:(Color noColor)),newListOfColors.
  4039             ].
  4040         ] ifFalse:[
  4041             newListOfColors addAll:(image colorMap).
  4042         ].
  4043     ] ifFalse:[
  4044         newListOfColors := OrderedCollection withAll:(self listOfColors).
  4045         newListOfColors isEmpty ifTrue:[   
  4046             self colorMapMode: colorMapMode value.
  4047             image := self image.
  4048         ].                               
  4049         "/ image mask notNil ifTrue:[
  4050         "/     newListOfColors := (Array with:(Color noColor)),newListOfColors.
  4051         "/ ].
  4052     ].  
  4053     newListOfColors notEmptyOrNil ifTrue:[
  4054         drawColor1 := newListOfColors at:1.
  4055         drawColor2 := newListOfColors at:2 ifAbsent:drawColor1.
  4056 
  4057         self hasMask ifTrue: [             
  4058             (newListOfColors includes:(Color colorId:0)) ifFalse:[
  4059                 newListOfColors addFirst:(Color colorId:0).
  4060                 drawColor1 := newListOfColors at:2. 
  4061                 drawColor2 := newListOfColors at:3 ifAbsent:drawColor1.
  4062             ]
  4063         ].
  4064 "/        imageEditView drawingColors:(Array with: drawColor1 with: drawColor2).
  4065 "/        self selectionOfColor 
  4066 "/            setValue: 0;
  4067 "/            value: (listOfColors indexOf: imageEditView selectedColor).
  4068     ].
  4069     self listOfColors asOrderedCollection ~= newListOfColors ifTrue:[
  4070         self listOfColors contents:newListOfColors.
  4071     ].
  4072 
  4073     "Modified: / 06-12-2016 / 12:51:36 / cg"
  4074 !
  4075 
  4076 selectedColorsChanged
  4077     |colorIndices|
  4078 
  4079     (colorIndices := self selectedColors value) isEmptyOrNil ifTrue:[
  4080         self selectionOfColor value:nil
  4081     ] ifFalse:[
  4082         colorIndices size == 1 ifTrue:[
  4083             "/ as single color selected
  4084             self selectionOfColor value:colorIndices first
  4085         ] ifFalse:[
  4086             "/ multipl selected
  4087             self selectionOfColor value:nil
  4088         ].
  4089     ].
  4090 !
  4091 
  4092 update:something with:aParameter from:changedObject
  4093     |clrIndex img imagePreView clr changedColor|
  4094 
  4095     img := self image.
  4096     imagePreView := self imagePreView.
  4097 
  4098     changedObject == self tileModeHolder ifTrue:[
  4099         imagePreView 
  4100             tileMode:(changedObject value) tileOffset:(img extent);
  4101             clear; 
  4102             invalidate.
  4103         ^ self
  4104     ].
  4105     changedObject == self previewBackgroundColorHolder ifTrue:[
  4106         clr := changedObject value isNil 
  4107                     ifTrue:[imageEditView viewBackground]
  4108                     ifFalse:[Color perform:changedObject value].
  4109         imagePreView 
  4110             viewBackground:clr;
  4111             clear; 
  4112             invalidate.
  4113         ^ self
  4114     ].
  4115 
  4116     changedObject == self listOfColors ifTrue:[
  4117         something == #at: ifTrue:[
  4118             "/ colormap entry changed at aParameter
  4119 
  4120             clrIndex := aParameter.
  4121             (self hasMask) ifTrue:[
  4122                 clrIndex := clrIndex - 1.
  4123             ].
  4124             changedColor := changedObject at:aParameter.
  4125             img colorMap notNil ifTrue:[
  4126                 img colorMap at:clrIndex put:changedColor.
  4127                 self colorMapChanged.
  4128             ] ifFalse:[
  4129                 drawingColormap notNil ifTrue:[
  4130                     drawingColormap at:clrIndex put:changedColor.
  4131                 ].
  4132             ].
  4133             ^ self
  4134         ].
  4135         ^ self
  4136     ].
  4137 
  4138     changedObject == imageEditView undoImages ifTrue:[
  4139         self canUndoHolder value:(changedObject notEmpty).
  4140         ^ self.
  4141     ].
  4142 
  4143     changedObject == imageEditView ifTrue:[
  4144         something == #imageColors ifTrue:[
  4145             self updateListOfColorsAndColormapMode.
  4146             ^ self.
  4147         ].
  4148         something == #image ifTrue:[
  4149             self updateAfterImageChange.
  4150             imagePreView image:img scroll:false.
  4151             self updateListOfColorsAndColormapMode.
  4152             self tileModeHolder value ifTrue:[
  4153                 imagePreView tileMode:true tileOffset:(img extent).
  4154             ].
  4155             ^ self.
  4156         ].
  4157         something == #subImageIn ifTrue:[
  4158             imagePreView image ~~ img ifTrue:[
  4159                 self error:'internal error' mayProceed:true.
  4160             ].
  4161             self tileModeHolder value ifTrue:[
  4162                 imagePreView invalidate.
  4163             ] ifFalse:[
  4164                 imagePreView invalidate:aParameter.
  4165             ].
  4166             ^ self.
  4167         ].
  4168         something == #selectedColor ifTrue:[
  4169             (aParameter isNil or:[aParameter = (Color colorId:0)]) ifTrue:[
  4170                 "/ no color/mask */
  4171                 "/ self halt.
  4172                 clrIndex := self hasMask ifTrue:[1] ifFalse:[0].
  4173             ] ifFalse:[
  4174                 clrIndex := self listOfColors indexOf:aParameter.
  4175             ].
  4176             self selectedColors value:{clrIndex}. "/ selectionOfColor value:clrIndex.
  4177             ^ self.
  4178         ].
  4179         ^ self.
  4180     ].
  4181 
  4182     changedObject == imageEditView modifiedHolder ifTrue:[
  4183         "/ self halt:'to be implemented'.
  4184         ^ self
  4185     ].
  4186 
  4187     changedObject == imageEditView image ifTrue:[
  4188         "/ self halt:'to be implemented'.
  4189         self updateAfterImageChange.
  4190         ^ self.
  4191     ].
  4192 
  4193     super update:something with:aParameter from:changedObject
  4194 
  4195     "Modified: / 21-10-2010 / 14:34:31 / cg"
  4196 !
  4197 
  4198 updateAfterImageChange
  4199     |img|
  4200 
  4201     (img := self image) notNil ifTrue:[
  4202         img := img onDevice:device.
  4203         self updateColorsFromImage:img.
  4204         self findColorMapMode.
  4205         self updateLabelsAndHistory.
  4206 
  4207         imageSeqNr isNil ifTrue:[
  4208             imageSeqNr := 1
  4209         ].
  4210         self imageHasImageSequenceHolder value:(self imageHasImageSequence).
  4211         self imageHasNextImageHolder value:(self imageHasNextImage).
  4212         self imageHasPreviousImageHolder value:(self imageHasPreviousImage).
  4213     ] ifFalse:[
  4214         self updateForNoImage
  4215     ]
  4216 
  4217     "Modified: / 21-10-2010 / 14:40:45 / cg"
  4218 !
  4219 
  4220 updateColorsFromImage:image
  4221     |colors|
  4222 
  4223     image depth > 16 ifTrue:[
  4224         self listOfColors contents:#().
  4225         ^ self.
  4226     ].
  4227 
  4228     colors := image colorMap.
  4229     colors isNil ifTrue:[
  4230         Error handle:[:ex |
  4231             colors := OrderedCollection new.
  4232         ] do:[
  4233             colors := image usedColors asSet.
  4234         ].
  4235     ].
  4236     self listOfColors contents:(colors asOrderedCollection).
  4237 
  4238     "Modified: / 18-01-2012 / 13:57:43 / cg"
  4239 !
  4240 
  4241 updateForNoImage
  4242     "updates channels and view, if image is loaded"
  4243 
  4244     self imageIsLoadedHolder value: false.
  4245     self listOfColors removeAll.
  4246     self imagePreView image: nil.
  4247     self imageHasImageSequenceHolder value:false.
  4248 
  4249     "Modified: / 21-10-2010 / 14:39:13 / cg"
  4250 !
  4251 
  4252 updateLabelsAndHistory
  4253     "updates labels and history, if something has changed"
  4254 
  4255     |image|
  4256 
  4257     image := self image.
  4258 
  4259     self imageIsLoadedHolder value: image notNil.
  4260     image isNil ifTrue: [^nil].
  4261 
  4262     self updateInfoLabel.
  4263 
  4264     imageEditView resourceClass notNil ifTrue:[
  4265         imageEditView resourceSelector notNil ifTrue:[
  4266             self addHistoryEntryForClass:imageEditView resourceClass selector:imageEditView resourceSelector.
  4267         ]
  4268     ].
  4269 
  4270     image fileName notNil ifTrue: [
  4271         self addHistoryEntryForFile:image fileName.
  4272     ].
  4273 
  4274     "Modified: / 04-07-2010 / 10:16:02 / cg"
  4275 !
  4276 
  4277 updateListOfColorsAndColormapMode
  4278     |selectedColor colorMap image|
  4279 
  4280     selectedColor := self selectedColorOrNil.
  4281 
  4282     image := self image.
  4283     image isNil ifTrue:[
  4284         self listOfColors removeAll.
  4285     ] ifFalse:[
  4286         colorMap := image colorMap.
  4287         colorMap notNil ifTrue:[
  4288             (colorMap size <= 4096) ifTrue:[
  4289                 image mask notNil ifTrue:[
  4290                     colorMap := (Array with:(Color noColor)),colorMap.
  4291                 ].
  4292                 self listOfColors contents:colorMap.
  4293             ] ifFalse:[
  4294                 self listOfColors removeAll.
  4295                 colorMap isFixedPalette ifTrue:[
  4296                     image colorMap:nil.
  4297                     image photometric:#rgb.
  4298                     image samplesPerPixel:3.
  4299                     
  4300                     image bitsPerSample:(Array 
  4301                                             with:(colorMap bitsRed)
  4302                                             with:(colorMap bitsGreen)
  4303                                             with:(colorMap bitsBlue)).
  4304                 ].
  4305             ]
  4306         ].
  4307     ].
  4308     self findColorMapMode.
  4309     selectedColor notNil ifTrue:[
  4310         self selectColor:selectedColor.
  4311     ].
  4312 ! !
  4313 
  4314 !ImageEditor methodsFor:'data access'!
  4315 
  4316 atColor:anOldColor put:newColor
  4317     "a color changed to a new color"
  4318 
  4319     |index list oldColor image newImage oldSel|
  4320 
  4321     list  := self listOfColors.
  4322     index := list identityIndexOf:anOldColor.
  4323 
  4324     oldSel := self selectionOfColor value.
  4325     index ~~ 0 ifTrue:[
  4326         oldColor := list at:index.
  4327         list at:index put:newColor
  4328     ] ifFalse:[
  4329         self error:'internal error' mayProceed:true.
  4330         list add:newColor
  4331     ].
  4332 
  4333     image := self image.
  4334     (image colorMap isNil 
  4335     and:[drawingColormap isNil]) ifTrue:[
  4336         oldColor notNil ifTrue:[
  4337             imageEditView makeUndo.
  4338             newImage := image copy.
  4339             newImage
  4340                 colorsFromX:0 y:0 toX:(image width-1) y:(image height-1) 
  4341                 do:[:x :y :clr |
  4342                     |newClr|
  4343 
  4344                     newClr := (clr = oldColor) ifTrue:[newColor] ifFalse:[clr].
  4345                     newImage colorAtX:x y:y put:newClr
  4346                 ].
  4347             imageEditView image:newImage.
  4348             imageEditView setModified.
  4349             self updateImage.
  4350             self updateImagePreView.
  4351 
  4352             self selectedColors value:{oldSel}.
  4353             imageEditView selectedColorIndex:oldSel.
  4354             imageEditView selectedColor:(self listOfColors at:oldSel).
  4355         ]
  4356     ].
  4357 !
  4358 
  4359 blueAtColor:aColor put:newBlue
  4360     "helper used to return a new row element, when blue is changed"
  4361 
  4362     |byte|
  4363 
  4364     aColor isNil ifTrue:[^ self].       "/ mask cannot be changed
  4365     byte := newBlue clampBetween:0 and:255.
  4366     byte = aColor blueByte ifTrue:[^ self ].
  4367 
  4368     self atColor:aColor
  4369              put:(Color redByte:(aColor redByte) greenByte:(aColor greenByte) blueByte:byte).
  4370 !
  4371 
  4372 blueFromColor:aColor
  4373     "helper used to access a color as a row in the dataSet view"
  4374 
  4375     aColor isNil ifTrue:[^ 'none'].
  4376     ^ aColor blueByte ? 'mask'
  4377 
  4378     "Created: / 26.7.1998 / 12:30:35 / cg"
  4379     "Modified: / 31.7.1998 / 01:11:18 / cg"
  4380 !
  4381 
  4382 canSelectBlueInColor:aColor
  4383     ^ aColor blueByte notNil
  4384 
  4385     "Created: / 7.8.1998 / 22:50:34 / cg"
  4386     "Modified: / 7.8.1998 / 22:52:57 / cg"
  4387 !
  4388 
  4389 canSelectGreenInColor:aColor
  4390     ^ aColor greenByte notNil
  4391 
  4392     "Created: / 7.8.1998 / 22:50:22 / cg"
  4393     "Modified: / 7.8.1998 / 22:52:46 / cg"
  4394 !
  4395 
  4396 canSelectRedInColor:aColor
  4397     ^ aColor redByte notNil
  4398 
  4399     "Created: / 7.8.1998 / 22:50:00 / cg"
  4400     "Modified: / 7.8.1998 / 22:51:03 / cg"
  4401 !
  4402 
  4403 greenAtColor:aColor put:newGreen
  4404     "helper used to return a new row element, when green is changed"
  4405 
  4406     |byte|
  4407 
  4408     aColor isNil ifTrue:[^ self].       "/ mask cannot be changed
  4409     byte := newGreen clampBetween:0 and:255.
  4410     byte = aColor greenByte ifTrue:[^ self].
  4411 
  4412     self atColor:aColor
  4413              put:(Color redByte:(aColor redByte) greenByte:byte blueByte:(aColor blueByte)).
  4414 !
  4415 
  4416 greenFromColor:aColor
  4417     "helper used to access a color as a row in the dataSet view"
  4418 
  4419     aColor isNil ifTrue:[^ 'none'].
  4420     ^ aColor greenByte ? 'mask'
  4421 
  4422     "Created: / 26.7.1998 / 12:30:29 / cg"
  4423     "Modified: / 31.7.1998 / 01:11:31 / cg"
  4424 !
  4425 
  4426 redAtColor:aColor put:newRed
  4427     "helper used to return a new row element, when red is changed"
  4428 
  4429     |byte|
  4430 
  4431     aColor isNil ifTrue:[^ self].       "/ mask cannot be changed
  4432     byte := newRed clampBetween:0 and:255.
  4433     byte = aColor redByte ifTrue:[^ self].
  4434 
  4435     self atColor:aColor
  4436              put:(Color redByte:byte greenByte:(aColor greenByte) blueByte:(aColor blueByte)).
  4437 !
  4438 
  4439 redFromColor:aColor
  4440     "helper used to access a color as a row in the dataSet view"
  4441 
  4442     aColor isNil ifTrue:[^ 'none'].
  4443     ^ aColor redByte ? 'mask'
  4444 
  4445     "Modified: / 31.7.1998 / 01:11:35 / cg"
  4446 !
  4447 
  4448 theColorItself:aColor
  4449     "an accessor for the table-column"
  4450 
  4451     ^ aColor
  4452 ! !
  4453 
  4454 !ImageEditor methodsFor:'defaults'!
  4455 
  4456 aboutIcon
  4457     ^ self class defaultIcon
  4458 ! !
  4459 
  4460 !ImageEditor methodsFor:'drag & drop'!
  4461 
  4462 canDropObjects:aCollectionOfDropObjects in:aWidget
  4463     ^ (aCollectionOfDropObjects size == 1) 
  4464       and:[ aCollectionOfDropObjects 
  4465                 contains:[:dropObject | dropObject isFileObject]]
  4466 !
  4467 
  4468 dropObjects:aCollectionOfDropObjects in:aWidget at:position
  4469     |dropObject|
  4470 
  4471     dropObject := aCollectionOfDropObjects first.
  4472     dropObject isFileObject ifTrue:[
  4473         self loadFromFile:dropObject asFilename.
  4474     ]
  4475 ! !
  4476 
  4477 !ImageEditor methodsFor:'event handling'!
  4478 
  4479 processEvent:anEvent
  4480     "Return true, if I have eaten the event"
  4481 
  4482     <resource: #keyboard (#Paste #Copy )>
  4483 
  4484     |view focusView p transformation|
  4485 
  4486     view := anEvent view.
  4487     view notNil ifTrue:[
  4488         view == self imagePreView ifTrue:[
  4489             ((anEvent isButtonPressEvent and:[ anEvent button == 1 ])
  4490             or:[ anEvent isButtonMotionEvent and:[ anEvent hasButton1 ]])  ifTrue:[
  4491                 p := anEvent x @ anEvent y.
  4492                 (transformation := view transformation) notNil ifTrue:[
  4493                     p := transformation applyInverseTo:p.
  4494                 ].
  4495                 self imageEditView scrollToMakeVisible:p.    
  4496                 ^ true.
  4497             ].
  4498         ].
  4499 
  4500         anEvent isKeyPressEvent ifTrue:[
  4501             focusView := view windowGroup focusView ? view.
  4502             (focusView isComponentOf:(builder componentAt:#colorDataSetView)) ifTrue:[
  4503                 anEvent key == #Paste ifTrue:[
  4504                     self pasteColorIntoColormap.
  4505                     ^ true.
  4506                 ].
  4507                 anEvent key == #Copy ifTrue:[
  4508                     self copyColorFromColormap.
  4509                     ^ true.
  4510                 ].
  4511             ].
  4512         ].
  4513     ].
  4514     ^ false.
  4515 
  4516     "Modified: / 04-04-2011 / 13:50:09 / cg"
  4517 ! !
  4518 
  4519 !ImageEditor methodsFor:'help'!
  4520 
  4521 defaultInfoLabel
  4522     "returns the text shown in the info label, when the mouse is NOT over
  4523      some widget with a help text."
  4524 
  4525     |resourceClass resourceSelector|
  4526 
  4527     resourceClass := imageEditView resourceClass.
  4528     resourceClass notNil ifTrue:[
  4529         resourceSelector := imageEditView resourceSelector.
  4530         resourceSelector notNil ifTrue:[
  4531             ^ resourceClass name, ' >> ', resourceSelector
  4532         ].
  4533     ].
  4534     ^ 'No class and selector defined.'
  4535 !
  4536 
  4537 openDocumentation
  4538     "opens the documentation file of the Image Editor"
  4539 
  4540     self openHTMLDocument: 'tools/uipainter/ImageEditor.html'
  4541 
  4542 ! !
  4543 
  4544 !ImageEditor methodsFor:'loading'!
  4545 
  4546 loadFromClass:aClass andSelector:aSelector
  4547     "loads an image from the method specified by class and selector"
  4548 
  4549     self assert:(aClass isNil or:[aClass isClass]).
  4550 
  4551     (aClass isNil or:[aSelector isNil]) ifTrue:[
  4552         imageEditView resourceClass:aClass.
  4553         imageEditView resourceSelector:aSelector.
  4554         imageEditView image:nil.
  4555         self clearModified.
  4556         ^ self.
  4557     ].
  4558 
  4559 "/    (imageEditView resourceClass == aClass
  4560 "/    and:[ imageEditView resourceSelector == aSelector ]) ifTrue:[
  4561 "/        imageEditView modified ifFalse:[
  4562 "/            ^ self.
  4563 "/        ].
  4564 "/    ].
  4565 
  4566     (imageEditView loadFromClass:aClass andSelector:aSelector) notNil ifTrue:[
  4567         self updateAfterImageChange.
  4568         self clearModified.
  4569     ]
  4570 
  4571     "Modified: / 16.3.1999 / 21:44:41 / cg"
  4572 !
  4573 
  4574 loadFromFile:aFileName
  4575     "loads an image from aFileName and sets up color map list and other info labels"
  4576 
  4577     self withCursor:Cursor wait do:[
  4578         (imageEditView loadFromFile: aFileName) notNil ifTrue:[
  4579             self updateAfterImageChange
  4580         ]
  4581     ]
  4582 
  4583     "Modified: / 16.3.1999 / 21:44:26 / cg"
  4584 !
  4585 
  4586 loadFromImage:anImage
  4587     "loads an image from anImage and sets up color map list and other info labels"
  4588 
  4589     |img|
  4590 
  4591     anImage notNil ifTrue:[    
  4592         img := anImage onDevice:device.
  4593     ].
  4594 
  4595     imageEditView image:img.
  4596     imageEditView clearModified.
  4597 
  4598     self updateAfterImageChange.
  4599 "/    img notNil ifTrue:[    
  4600 "/        self updateColorsFromImage:img.
  4601 "/        self findColorMapMode.
  4602 "/        self updateLabelsAndHistory.
  4603 "/    ] ifFalse:[
  4604 "/        self updateForNoImage
  4605 "/    ]
  4606 
  4607     "Modified: / 16.3.1999 / 21:43:56 / cg"
  4608 !
  4609 
  4610 loadFromOrPrepareForClass: aClass andSelector: aSelector
  4611     "loads an image by evaluating aMessage;
  4612      if no image could extract from aMessage; do set the class and the selector from 
  4613      the aMessage for a saving at the end of editing"
  4614 
  4615     (imageEditView loadFromClass:aClass andSelector:aSelector) notNil ifTrue: [
  4616         self updateColorsFromImage:self image.
  4617         self findColorMapMode.
  4618     ] ifFalse: [
  4619         imageEditView resourceClass: aClass.
  4620         imageEditView resourceSelector:aSelector.
  4621     ].
  4622     self updateLabelsAndHistory.
  4623 
  4624     "Modified: / 16.3.1999 / 21:45:07 / cg"
  4625 ! !
  4626 
  4627 !ImageEditor methodsFor:'menu modes'!
  4628 
  4629 colorMapMode
  4630     "returns the colorMapMode"
  4631 
  4632     colorMapMode isNil ifTrue: [colorMapMode := '' asValue].
  4633 
  4634     ^colorMapMode
  4635 !
  4636 
  4637 editMode
  4638     "returns editMode"
  4639 
  4640     editMode isNil ifTrue: [
  4641         editMode := #point asValue.
  4642         editMode onChangeEvaluate:[imageEditView editMode:(editMode value)]
  4643     ].
  4644 
  4645     ^editMode
  4646 !
  4647 
  4648 mouseKeyColorMode
  4649     "returns mouseKeyColorMode"
  4650 
  4651     mouseKeyColorMode isNil ifTrue:[
  4652         mouseKeyColorMode := 1 asValue.
  4653         mouseKeyColorMode onChangeEvaluate: [
  4654             imageEditView mouseKeyColorMode:mouseKeyColorMode value. 
  4655             self selectedColors value:{ self listOfColors indexOf:imageEditView selectedColor }.
  4656         ]
  4657     ].
  4658 
  4659     ^mouseKeyColorMode
  4660 
  4661     "Modified: / 10.2.2000 / 23:16:42 / cg"
  4662 ! !
  4663 
  4664 !ImageEditor methodsFor:'private'!
  4665 
  4666 checkModified
  4667     imageEditView modified value ifTrue:[
  4668         (Dialog
  4669             confirm:(resources string:'Image was not saved. Proceed anyway ?')
  4670             yesLabel:(resources string:'Proceed')
  4671             noLabel:(resources string:'Cancel')
  4672             initialAnswer:false
  4673         ) ifFalse: [^false].
  4674 
  4675         imageEditView clearModified.
  4676     ].
  4677     ^ true
  4678 
  4679     "Modified: / 29.7.1998 / 18:55:24 / cg"
  4680 !
  4681 
  4682 pointFromString:aString
  4683     |p s x y|
  4684 
  4685     p := Object readFromString:aString onError:nil.
  4686     p isPoint ifTrue:[^ p].
  4687 
  4688     s := aString readStream.
  4689     x := Number readFrom:s onError:nil.
  4690     x notNil ifTrue:[
  4691         s skipSeparators.
  4692         [s atEnd not and:[s peek isDigit not]] whileTrue:[s next].
  4693         y := Number readFrom:s onError:nil.
  4694         ^ x @ (y ? x)
  4695     ].
  4696     ^ nil
  4697 !
  4698 
  4699 sortBlockForColors
  4700     ^ self sortBlockForColorsByHLS.
  4701 "/    ^ self sortBlockForColorsByRGB
  4702 !
  4703 
  4704 sortBlockForColorsByHLS
  4705     ^ [:a :b |
  4706         |h1 h2 s1 s2 l1 l2|
  4707 
  4708         h1 := a hue ? 0.
  4709         h2 := b hue ? 0.
  4710         (h1 between: h2-30 and:h2+30) ifTrue:[
  4711             l1 := a light.
  4712             l2 := b light.
  4713             l1 = l2 ifTrue:[
  4714                 a saturation < b saturation
  4715             ] ifFalse:[
  4716                 l1 < l2
  4717             ].
  4718 "/            s1 := a saturation.
  4719 "/            s2 := b saturation.
  4720 "/            s1 = s2 ifTrue:[
  4721 "/                a light < b light
  4722 "/            ] ifFalse:[
  4723 "/                s1 < s2 
  4724 "/            ]
  4725         ] ifFalse:[
  4726             h1 < h2 
  4727         ]
  4728       ]
  4729 !
  4730 
  4731 sortBlockForColorsByRGB
  4732     ^ [:a :b |
  4733             a redByte == b redByte ifTrue:[
  4734                 a greenByte == b greenByte ifTrue:[
  4735                     a blueByte < b blueByte
  4736                 ] ifFalse:[
  4737                     a greenByte < b greenByte 
  4738                 ]
  4739             ] ifFalse:[
  4740                 a redByte < b redByte 
  4741             ]
  4742       ]
  4743 !
  4744 
  4745 updateImage
  4746     |img|
  4747 
  4748     img := imageEditView image.
  4749     imageEditView image:img.
  4750     self fetchImageData.
  4751 !
  4752 
  4753 updateImagePreView
  4754     self tileModeHolder value ifTrue:[
  4755         self imagePreView tileMode:true tileOffset:(self image extent).
  4756     ].
  4757     self imagePreView 
  4758         setImage:(self image) scroll:false invalidate:false; "/ true.
  4759         invalidate.
  4760 ! !
  4761 
  4762 !ImageEditor methodsFor:'queries'!
  4763 
  4764 hasLastGrabScreenArea
  4765     ^ [ lastGrabbedScreenArea notNil ]
  4766 !
  4767 
  4768 hasMask
  4769     ^ colorMapMode value notNil and:[colorMapMode value startsWith:'mask']
  4770 
  4771     "Created: / 18.8.1998 / 17:17:38 / cg"
  4772 !
  4773 
  4774 modified
  4775     ^ imageEditView modified
  4776 !
  4777 
  4778 modified:aBoolean
  4779     super modified:aBoolean.
  4780     imageEditView modified:aBoolean
  4781 !
  4782 
  4783 preferredExtent
  4784     "returns the preferred extent"
  4785 
  4786     ^ super preferredExtent max: (Screen current width//3)@(Screen current height//3.5)
  4787 ! !
  4788 
  4789 !ImageEditor methodsFor:'selection'!
  4790 
  4791 magnification
  4792     "returns the magnification of the image"
  4793 
  4794     self imageEditView isNil ifTrue: [^1].
  4795     ^imageEditView magnification x
  4796 !
  4797 
  4798 magnification: aValue
  4799     "sets the magnification of the image"
  4800 
  4801     |magnification|        
  4802     magnification := (aValue ? 1) asPoint.
  4803     (magnification = imageEditView magnification or: [magnification = (0@0)]) ifTrue: [^nil].
  4804     imageEditView magnification: magnification
  4805 !
  4806 
  4807 selectedColorIndex
  4808     "returns the index of the selected color"
  4809 
  4810     ^selectedColorIndex
  4811 !
  4812 
  4813 selectedColorIndex: anIndex
  4814     "sets the index of the selected color"
  4815 
  4816     |clr pixel|
  4817 
  4818     selectedColorIndex := anIndex.
  4819     anIndex isNil ifTrue:[^ self].
  4820     clr := self listOfColors at:anIndex ifAbsent:nil.
  4821     clr isNil ifTrue:[^ self].
  4822 
  4823     pixel := anIndex - 1.
  4824     (self listOfColors at:1) = Color noColor ifTrue:[
  4825         anIndex == 1 ifTrue:[
  4826             pixel := nil.       "/ mask
  4827         ] ifFalse:[
  4828             pixel := pixel - 1
  4829         ]
  4830     ].
  4831     imageEditView selectedColorIndex:pixel.
  4832     imageEditView selectedColor:clr.
  4833 ! !
  4834 
  4835 !ImageEditor methodsFor:'startup & release'!
  4836 
  4837 closeDownViews
  4838     builder notNil ifTrue:[
  4839         DefaultRelativeSizes :=
  4840             Array 
  4841                 with:(builder componentAt:#mainPanel) relativeCorners    
  4842                 with:(builder componentAt:#verticalPanel) relativeCorners.
  4843     ].
  4844     super closeDownViews
  4845 !
  4846 
  4847 closeRequest
  4848     "asks for permission before closing"
  4849 
  4850     imageEditView checkModified ifTrue:[
  4851         super closeRequest
  4852     ]
  4853 !
  4854 
  4855 commonPostBuild
  4856     imageEditView undoImages addDependent:self.
  4857     imageEditView imageInfoHolder:(self imageInfoHolder).
  4858     imageEditView activityInfoHolder:(self activityInfoHolder).
  4859 
  4860     imageEditView clickInfoCallBack:[:button :point | 
  4861                         |mouseButtonColorToolBar|
  4862                         button <= 2 ifTrue:[
  4863                             mouseButtonColorToolBar := self componentAt:#MouseButtonColorToolBar.
  4864                             (mouseButtonColorToolBar itemAt:button) toggleIndication.
  4865                             mouseButtonColorToolBar do: [:i| i updateIndicators].
  4866                         ].
  4867                   ].
  4868 
  4869     imageEditView addDependent:self.
  4870     imageEditView modifiedHolder addDependent:self.
  4871 
  4872     DefaultRelativeSizes notNil ifTrue:[
  4873         (builder componentAt:#mainPanel) relativeCorners:DefaultRelativeSizes first.
  4874         (builder componentAt:#verticalPanel) relativeCorners:DefaultRelativeSizes second.
  4875     ].
  4876 
  4877     "/ using masters infoHolder ?
  4878     (builder aspectAt:#useAlienInfoLabelHolder) == true ifTrue:[
  4879         (builder componentAt:#mainPanel) layout bottomOffset:0.
  4880         (builder componentAt:#infoBarSubSpec) beInvisible
  4881     ]
  4882 !
  4883 
  4884 open
  4885     "after opening, sets the masterApplication of the imageEditView to self"
  4886 
  4887     super open.
  4888 
  4889     imageEditView := (self componentAt: #imageEditView) subViews first.
  4890 !
  4891 
  4892 postOpenWith:aBuilder
  4893     "after opening, sets the masterApplication of the imageEditView to self;
  4894      evaluate the postOpenAction"
  4895 
  4896     postOpenAction value.
  4897 
  4898     super postOpenWith:aBuilder.
  4899 
  4900     aBuilder keyboardProcessor menuBar:nil.
  4901     self windowGroup addPreEventHook:self.
  4902 ! !
  4903 
  4904 !ImageEditor methodsFor:'user actions-colormap'!
  4905 
  4906 addColorToColormap
  4907     self addColorToColormap:(Color black)
  4908 !
  4909 
  4910 addColorToColormap:newColor
  4911     |depth img cMap newColorMap newImage oldCListSize newMode listOfColors|
  4912 
  4913     img := self image.
  4914     img isNil ifTrue:[
  4915         self warn:'No Image.'.
  4916         ^ self
  4917     ].
  4918 
  4919     depth := img depth.
  4920     cMap := img colorMap.
  4921     cMap isNil ifTrue:[
  4922         drawingColormap isNil ifTrue:[
  4923             self information:(resources stringWithCRs:'Image has no colormap.\The shown colorMap is for drawing only.').
  4924             drawingColormap := OrderedCollection new.
  4925         ].
  4926         drawingColormap add:newColor.
  4927         self listOfColors contents:drawingColormap.
  4928         self selectedColors value:{drawingColormap size}.
  4929         "/ self warn:'Image has no colormap.\Change colorMap mode first.' withCRs.
  4930         ^ self
  4931     ].
  4932 
  4933     ("(depth == 1)" false
  4934     or:[cMap size == (1 bitShift:depth)]) ifTrue:[
  4935         depth >= 8 ifTrue:[
  4936             self warn:'No space for more colors in colormap.'.
  4937             ^ self
  4938         ].
  4939         (self confirm:(resources stringWithCRs:'No space for more colors in colormap.\Change depth ?'))
  4940         ifFalse:[
  4941             ^ self
  4942         ].
  4943 
  4944         imageEditView makeUndo.
  4945         img mask notNil ifTrue:[
  4946             newMode := 'masked' , (depth*2) printString.
  4947         ] ifFalse:[
  4948             newMode := 'depth' , (depth*2) printString.
  4949         ].
  4950         self colorMapMode:newMode.
  4951     ] ifFalse:[
  4952         imageEditView makeUndo.
  4953     ].
  4954 
  4955     cMap := cMap asArray.
  4956     listOfColors := self listOfColors.
  4957     oldCListSize := listOfColors size.
  4958 
  4959     newColorMap := cMap copyWith:newColor.
  4960 
  4961     newImage := img species new
  4962                     width:img width
  4963                     height:img height
  4964                     depth:depth
  4965                     fromArray:img bits.
  4966 
  4967     newImage colorMap:newColorMap.  
  4968     newImage fileName:img fileName.
  4969     newImage mask:(img mask copy).
  4970 
  4971     (imageEditView image:newImage) notNil ifTrue:[
  4972         listOfColors contents: newImage colorMap.
  4973         self findColorMapMode.
  4974         "/ mhmh - somehow, we get two colors added ... (sigh findColorMapMode adds another one ...)
  4975         listOfColors size > (oldCListSize + 1) ifTrue:[
  4976             listOfColors removeLast
  4977         ].
  4978         self selectedColors value:{listOfColors size}.
  4979         self updateLabelsAndHistory.
  4980     ]
  4981 
  4982     "Created: / 12.3.1999 / 00:20:28 / cg"
  4983     "Modified: / 16.3.1999 / 21:57:26 / cg"
  4984 !
  4985 
  4986 changeHLS
  4987     "interactive Hue/Light/Saturation editing"
  4988 
  4989     |bindings hueShift lightValue saturationValue originalColormap firstChange acceptChannel 
  4990      shiftAction avgColorHolder avgColor shiftedColor shiftProcess readySema
  4991      originalPixels p previewImage previewImageHolder originalPreviewColormap originalPreviewPixels
  4992      anyChange |
  4993 
  4994     "/ compute the averageColor in the background (while asking user)
  4995     avgColorHolder := nil asValue.
  4996     previewImageHolder := nil asValue.
  4997 
  4998     readySema := Semaphore new.
  4999     [
  5000         |image|
  5001 
  5002         image := imageEditView image.
  5003         originalColormap := image colorMap copy.
  5004         originalPixels := image bits.
  5005         avgColor := image averageColor.
  5006         avgColorHolder value:avgColor.
  5007 
  5008         previewImage := self image magnifiedPreservingRatioTo:100@100.
  5009         previewImageHolder value: previewImage.
  5010         originalPreviewColormap := previewImage colorMap copy.
  5011         originalPreviewPixels := previewImage bits.
  5012 
  5013         readySema signal.
  5014     ] forkAt:7.
  5015 
  5016     acceptChannel := TriggerValue new.
  5017 
  5018     firstChange := true.
  5019     anyChange := false.
  5020 
  5021     shiftedColor := [:clr :hShift :lFactor :sFactor |
  5022                         Color 
  5023                                 hue:((clr hue) ? 0 + hShift) 
  5024                                 light:((clr light * lFactor / 100) min:100)
  5025                                 saturation:((clr saturation * sFactor / 100) min:100)].
  5026 
  5027     shiftAction := 
  5028         [
  5029             |hShift lFactor sFactor|
  5030 
  5031             acceptChannel value:true.
  5032 
  5033             firstChange ifTrue:[
  5034                 imageEditView makeUndo.
  5035                 firstChange := false.
  5036                 anyChange := true.
  5037             ].
  5038             readySema notNil ifTrue:[readySema wait. readySema := nil].
  5039 
  5040             hShift := hueShift value.
  5041             lFactor := lightValue value.
  5042             sFactor := saturationValue value.
  5043 
  5044             avgColorHolder value:(shiftedColor value:avgColor value:hShift value:lFactor value:sFactor).
  5045 
  5046             previewImage
  5047                 colorMap:originalPreviewColormap copy;
  5048                 bits:originalPreviewPixels copy;
  5049                 release;
  5050                 colorMapProcessing:[:clr | shiftedColor value:clr value:hShift value:lFactor value:sFactor].
  5051             previewImageHolder value:nil; value:previewImage.
  5052 
  5053             shiftProcess notNil ifTrue:[
  5054                 shiftProcess terminate.
  5055                 shiftProcess waitUntilTerminated.
  5056                 shiftProcess := nil.
  5057             ].
  5058             shiftProcess := 
  5059                 [
  5060                     [
  5061                         imageEditView image 
  5062                             colorMap:originalColormap copy;
  5063                             bits:originalPixels copy;
  5064                             release;
  5065                             colorMapProcessing:[:clr | shiftedColor value:clr value:hShift value:lFactor value:sFactor].
  5066                         self updateImage.
  5067                         self updateInfoLabel.
  5068                         self updateImagePreView.
  5069                     ] ensure:[ shiftProcess := nil ].    
  5070                 ] forkAt:7.
  5071         ].
  5072 
  5073     bindings := IdentityDictionary new.
  5074     bindings at:#hueShiftAmount put:(hueShift := 0 asValue).
  5075     hueShift onChangeEvaluate:shiftAction.
  5076 
  5077     bindings at:#lightAmount put:(lightValue := 100 asValue).
  5078     lightValue onChangeEvaluate:shiftAction.
  5079 
  5080     bindings at:#saturationAmount put:(saturationValue := 100 asValue).
  5081     saturationValue onChangeEvaluate:shiftAction.
  5082 
  5083     bindings at:#acceptChannel put:acceptChannel.
  5084     bindings at:#hlsColor put:avgColorHolder.
  5085     bindings at:#previewImageHolder put:previewImageHolder.
  5086 
  5087     (self openDialogInterface:#changeHLSDialogSpec withBindings:bindings) 
  5088     ifFalse:[ 
  5089         anyChange ifTrue:[
  5090             imageEditView undo
  5091         ]
  5092     ].
  5093 
  5094     (p := shiftProcess) notNil ifTrue:[
  5095         p waitUntilTerminated.
  5096     ].
  5097 
  5098     anyChange ifTrue:[
  5099         self updateImage.
  5100         self updateImagePreView.
  5101     ].
  5102 !
  5103 
  5104 changeHLSOfColors:colorsToShift
  5105     "interactive Hue/Light/Saturation editing"
  5106 
  5107     |bindings hueShift lightValue saturationValue originalColormap firstChange acceptChannel 
  5108      shiftAction avgColorHolder avgColor shiftedColor shiftProcess readySema
  5109      originalPixels p previewImage previewImageHolder originalPreviewColormap originalPreviewPixels
  5110      anyChange |
  5111 
  5112     "/ compute the averageColor in the background (while asking user)
  5113     avgColorHolder := nil asValue.
  5114     previewImageHolder := nil asValue.
  5115 
  5116     readySema := Semaphore new.
  5117     [
  5118         |image red green blue|
  5119 
  5120         image := imageEditView image.
  5121         originalColormap := image colorMap copy.
  5122         originalPixels := image bits.
  5123         red := (colorsToShift collect:[:clr | clr red]) average.
  5124         green := (colorsToShift collect:[:clr | clr green]) average.
  5125         blue := (colorsToShift collect:[:clr | clr blue]) average.
  5126         avgColor := Color red:red green:green blue:blue.
  5127         avgColorHolder value:avgColor.
  5128 
  5129         previewImage := self image magnifiedPreservingRatioTo:100@100.
  5130         previewImageHolder value: previewImage.
  5131         originalPreviewColormap := previewImage colorMap copy.
  5132         originalPreviewPixels := previewImage bits.
  5133 
  5134         readySema signal.
  5135     ] forkAt:7.
  5136 
  5137     acceptChannel := TriggerValue new.
  5138 
  5139     firstChange := true.
  5140     anyChange := false.
  5141 
  5142     shiftedColor := [:clr :hShift :lFactor :sFactor |
  5143                         Color 
  5144                                 hue:((clr hue) ? 0 + hShift) 
  5145                                 light:((clr light * lFactor / 100) min:100)
  5146                                 saturation:((clr saturation * sFactor / 100) min:100)].
  5147 
  5148     shiftAction := 
  5149         [
  5150             |hShift lFactor sFactor|
  5151 
  5152             acceptChannel value:true.
  5153 
  5154             firstChange ifTrue:[
  5155                 imageEditView makeUndo.
  5156                 firstChange := false.
  5157                 anyChange := true.
  5158             ].
  5159             readySema notNil ifTrue:[readySema wait. readySema := nil].
  5160 
  5161             hShift := hueShift value.
  5162             lFactor := lightValue value.
  5163             sFactor := saturationValue value.
  5164 
  5165             avgColorHolder value:(shiftedColor value:avgColor value:hShift value:lFactor value:sFactor).
  5166 
  5167             previewImage
  5168                 colorMap:originalPreviewColormap copy;
  5169                 bits:originalPreviewPixels copy;
  5170                 release;
  5171                 colorMapProcessing:[:clr | 
  5172                     (colorsToShift includes:clr) ifTrue:[
  5173                         shiftedColor value:clr value:hShift value:lFactor value:sFactor.
  5174                     ] ifFalse:[
  5175                         clr
  5176                     ]
  5177                 ].
  5178             previewImageHolder value:nil; value:previewImage.
  5179 
  5180             shiftProcess notNil ifTrue:[
  5181                 shiftProcess terminate.
  5182                 shiftProcess waitUntilTerminated.
  5183                 shiftProcess := nil.
  5184             ].
  5185 
  5186             shiftProcess := 
  5187                 [
  5188                     [
  5189                         imageEditView image 
  5190                             colorMap:originalColormap copy;
  5191                             bits:originalPixels copy;
  5192                             release;
  5193                             colorMapProcessing:[:clr | 
  5194                                 (colorsToShift includes:clr) ifTrue:[
  5195                                     shiftedColor value:clr value:hShift value:lFactor value:sFactor.
  5196                                 ] ifFalse:[
  5197                                     clr
  5198                                 ]
  5199                             ].
  5200                         self updateImage.
  5201                         self updateInfoLabel.
  5202                         self updateImagePreView.
  5203                     ] ensure:[ shiftProcess := nil ].    
  5204                 ] forkAt:7.
  5205         ].
  5206 
  5207     bindings := IdentityDictionary new.
  5208     bindings at:#hueShiftAmount put:(hueShift := 0 asValue).
  5209     hueShift onChangeEvaluate:shiftAction.
  5210 
  5211     bindings at:#lightAmount put:(lightValue := 100 asValue).
  5212     lightValue onChangeEvaluate:shiftAction.
  5213 
  5214     bindings at:#saturationAmount put:(saturationValue := 100 asValue).
  5215     saturationValue onChangeEvaluate:shiftAction.
  5216 
  5217     bindings at:#acceptChannel put:acceptChannel.
  5218     bindings at:#hlsColor put:avgColorHolder.
  5219     bindings at:#previewImageHolder put:previewImageHolder.
  5220 
  5221     (self openDialogInterface:#changeHLSDialogSpec withBindings:bindings) 
  5222     ifFalse:[ 
  5223         anyChange ifTrue:[
  5224             imageEditView undo
  5225         ]
  5226     ].
  5227 
  5228     (p := shiftProcess) notNil ifTrue:[
  5229         p waitUntilTerminated.
  5230     ].
  5231 
  5232     anyChange ifTrue:[
  5233         self updateImage.
  5234         self updateImagePreView.
  5235     ].
  5236 !
  5237 
  5238 clearColormapEntry0AndMaskedPixels
  5239     "ensure that there is a colorMap entry with 0/0/0 at position
  5240      0 and then clear all masked pixels (to pixelValue 0).
  5241      This is required for windows icons to be really transparent"
  5242 
  5243     |index colorMap| 
  5244 
  5245     self compressColorMap.
  5246     colorMap := self image colorMap.
  5247     (colorMap includes:(Color black)) ifFalse:[
  5248         self addColorToColormap:(Color black).
  5249         colorMap := self image colorMap.
  5250     ].
  5251     index := colorMap indexOf:(Color black).
  5252     index == 1 ifFalse:[
  5253         self sortColorMap.
  5254         colorMap := self image colorMap.
  5255     ].
  5256     self clearMaskedPixels
  5257 !
  5258 
  5259 clearMaskedPixels
  5260     "clear all masked pixels (to pixelValue 0)"
  5261 
  5262     |newImage| 
  5263 
  5264     newImage := self image clearMaskedPixels.
  5265     0 to:newImage height - 1 do:[:y |
  5266         0 to:newImage width - 1 do:[:x |
  5267             (newImage maskAtX:x y:y) == 0 ifTrue:[
  5268                 newImage pixelAtX:x y:y put:0
  5269             ]
  5270         ]
  5271     ].
  5272 
  5273     (imageEditView image:newImage) notNil ifTrue:[
  5274         self fetchImageData.
  5275     ]
  5276 !
  5277 
  5278 colorMapChanged
  5279     |img|
  5280 
  5281     img := self image.
  5282     img release.
  5283 
  5284     self imageEditView invalidate.
  5285     self imagePreView invalidate.
  5286 
  5287 "/    (imageEditView image:img) notNil ifTrue:[
  5288 "/        self updateLabelsAndHistory.
  5289 "/        self imagePreView image:img
  5290 "/    ]
  5291 
  5292     "Created: / 7.8.1998 / 22:26:10 / cg"
  5293     "Modified: / 18.8.1998 / 17:08:55 / cg"
  5294 !
  5295 
  5296 colorMapMode:aMode
  5297     "calculates a new color map for the image from aMode"
  5298 
  5299     |depth numColors newColorMap newImage 
  5300      oldImage image newColors realColorMap oldFileName
  5301      usedColors useNearest usageCounts tmpBits tmpMap quest
  5302      prevMode maskThreshold maskImage| 
  5303 
  5304     self withExecuteCursorDo:[
  5305         oldImage := self image.
  5306 
  5307         prevMode := colorMapMode value.
  5308 
  5309         newColorMap := self class listOfColorMaps at:aMode.
  5310         (aMode == #depth32 or:[aMode == #masked32]) ifTrue:[
  5311             depth := 32. 
  5312         ] ifFalse:[
  5313             (aMode == #depth24 or:[aMode == #masked24]) ifTrue:[
  5314                 depth := 24. 
  5315             ] ifFalse:[
  5316                 (aMode == #depth16 or:[aMode == #masked16]) ifTrue:[
  5317                     depth := 16. 
  5318                 ] ifFalse:[
  5319                     depth := (newColorMap size log:2) asInteger. 
  5320                 ].
  5321             ].
  5322         ].
  5323 
  5324         useNearest := false.
  5325         depth == 1 ifTrue:[
  5326             quest := 'Keep colormap (or use standard B&W)'
  5327         ] ifFalse:[
  5328             prevMode isNil ifTrue:[
  5329                 quest := 'Compute colormap (or use standard)'
  5330             ] ifFalse:[
  5331                 quest := 'Keep colormap (or use standard)'
  5332             ]
  5333         ].
  5334         ((prevMode = aMode)
  5335         or:[depth > oldImage depth
  5336         or:[self confirm:(resources string:quest)]]) ifTrue:[
  5337             (newColorMap isOrderedCollection or:[newColorMap isFixedPalette not]) ifTrue:[
  5338 
  5339                 "/ keep the colormap
  5340                 "/ newColorMap atAllPut:Color black.
  5341                 depth > oldImage depth ifTrue:[
  5342                     "/ easy - simply copy the part
  5343                     numColors := 1 bitShift:oldImage depth.
  5344                     0 to:numColors-1 do:[:pixel |
  5345                         newColorMap at:(pixel+1) put:(oldImage colorFromValue:pixel)
  5346                     ].
  5347                 ] ifFalse:[
  5348                     "/ see if all used color fit the new colormap
  5349                     usedColors := oldImage usedColorsMax:(1 bitShift:depth).
  5350                     (usedColors notNil and:[usedColors size > (1 bitShift:depth)]) ifTrue:[
  5351                         usedColors := oldImage realUsedColors
  5352                     ].
  5353                     (usedColors notNil and:[usedColors size <= (1 bitShift:depth)]) ifTrue:[
  5354                         "/ yea - just install them
  5355                         usedColors asArray keysAndValuesDo:[:idx :clr |
  5356                             newColorMap at:idx put:clr
  5357                         ].
  5358                     ] ifFalse:[
  5359                         "/ copy over those that are most often used.
  5360                         oldImage depth < 8 ifTrue:[
  5361                             tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
  5362                             oldImage bits
  5363                                 expandPixels:(oldImage depth)
  5364                                 width:oldImage width
  5365                                 height:oldImage height 
  5366                                 into:tmpBits
  5367                                 mapping:nil.
  5368                         ] ifFalse:[
  5369                             oldImage depth == 8 ifTrue:[
  5370                                 tmpBits := oldImage bits
  5371                             ] ifFalse:[
  5372                                 colorMapMode value:prevMode.
  5373                                 self findColorMapMode.    
  5374                                 self warn:('Too many used colors in image (', oldImage usedColors size printString , ').').
  5375                                 ^ self
  5376     "/                            (self confirm:('Too many used colors in image (', oldImage usedColors size printString , ').\\Dither ?' withCRs))
  5377     "/                            ifFalse:[.
  5378     "/                                ^ self
  5379     "/                            ].
  5380     "/                            self image: (Image newForDepth:depth) fromImage:oldImage.
  5381     "/                            ^ self.
  5382                             ]
  5383                         ].
  5384                         usageCounts := tmpBits usageCounts.
  5385                         tmpMap := Array new:usageCounts size.
  5386                         oldImage colorMap asArray keysAndValuesDo:[:i :clr |
  5387                             tmpMap at:i put:clr
  5388                         ].
  5389                         usageCounts sort:[:a :b | a > b] with:tmpMap.
  5390 
  5391                         1 to:(1 bitShift:depth) do:[:idx |
  5392                             newColorMap at:idx put:(tmpMap at:idx)
  5393                         ].
  5394 
  5395                         useNearest := Dialog 
  5396                                             confirmWithCancel:(resources 
  5397                                                                   stringWithCRs:'Image requires %1 colors.\ColorMap has only space for %2\\Use nearest (or map to first color) ?'
  5398                                                                   with:usedColors size
  5399                                                                   with:(1 bitShift:depth))
  5400                                             labels:(resources array:#('Cancel' 'First' 'Nearest')).
  5401                         useNearest isNil ifTrue:[
  5402                             colorMapMode value:prevMode.
  5403                             ^ self   "/ cancel
  5404                         ].
  5405                     ]
  5406                 ]
  5407             ]
  5408         ] ifFalse:[
  5409             "/ standard colormap
  5410             usedColors := oldImage usedColors.
  5411             (usedColors conform:[:clr | newColorMap includes:clr]) ifFalse:[
  5412                 useNearest := Dialog 
  5413                                     confirmWithCancel:(resources 
  5414                                                            stringWithCRs:'Not all colors are present in the new colormap.\\Map missing ones to nearest (or map to first color) ?'
  5415                                                        ) 
  5416                                     labels:(resources string:#('Cancel' 'First' 'Nearest')).
  5417                 useNearest isNil ifTrue:[
  5418                     colorMapMode value:prevMode.
  5419                     ^ self   "/ cancel
  5420                 ].
  5421             ].
  5422             newColorMap := oldImage colorMap.
  5423         ].
  5424 
  5425         imageEditView makeUndo.
  5426 
  5427         newImage := Image newForDepth:depth.
  5428         newImage depth:depth.
  5429         depth >= 16 ifTrue:[
  5430             depth == 32 ifTrue:[
  5431                 newImage colorMap:nil.
  5432                 newImage samplesPerPixel:4.
  5433                 newImage photometric:#rgba.
  5434             ] ifFalse:[    
  5435                 newImage colorMap:nil.
  5436                 newImage samplesPerPixel:3.
  5437                 newImage photometric:#rgb.
  5438             ].    
  5439         ].    
  5440 "/        newImage photometric:oldImage photometric.
  5441 
  5442         oldFileName := oldImage fileName.
  5443 
  5444         Image imageErrorSignal handle:[:ex|
  5445             "/ arrive here only if not all colors can be represented;
  5446             "/ then do a more expensive nearest color search
  5447             Color colorErrorSignal handle:[:ex|
  5448                 colorMapMode value:prevMode.
  5449                 imageEditView undo.
  5450                 ^ self warn:(resources string:'Conversion failed !!')
  5451             ] do:[
  5452                 newImage := Image newForDepth:depth.
  5453                 newImage 
  5454                     width:oldImage width height:oldImage height depth:depth;
  5455                     colorMap:newColorMap;
  5456                     photometric:#palette;
  5457                     bits:(ByteArray new:(newImage bytesPerRow * newImage height));
  5458                     mask:oldImage mask.
  5459 
  5460                 oldImage 
  5461                     colorsFromX:0 y:0 
  5462                     toX:(oldImage width-1) y:(oldImage height-1) 
  5463                     do:[:x :y :clr |
  5464                         |newColor|
  5465 
  5466                         (newColorMap includes:clr)
  5467                             ifTrue: [newColor := clr]
  5468                             ifFalse: [
  5469                                 newColor := clr nearestIn:newColorMap.
  5470                                 useNearest ifFalse:[
  5471                                     (newColor deltaFrom:clr) > 0.5 ifTrue:[
  5472                                         newColor := oldImage colorFromValue:0
  5473                                     ]
  5474                                 ]
  5475                             ].
  5476                         newImage colorAtX:x y:y put:newColor.
  5477                     ].
  5478                 
  5479                 image := newImage
  5480             ].
  5481         ] do:[ 
  5482             image := newImage 
  5483                         fromImage:oldImage 
  5484                         photometric:((newColorMap notNil and:[newColorMap isOrderedCollection or:[newColorMap isFixedPalette not]])
  5485                                         ifTrue:[#palette]
  5486                                         ifFalse:[nil]).
  5487                          "/ -- nope; keep the newly determined photometric. photometric:oldImage photometric.
  5488         ].
  5489 
  5490         (aMode asString startsWith:'mask') ifTrue:[
  5491             image mask isNil ifTrue:[
  5492                 false "(Dialog confirm:'Generate mask from black ?' default:false)" ifTrue:[
  5493                     maskThreshold := 0.1.
  5494                     maskImage := Depth1Image fromImage:(image asThresholdMonochromeImage:maskThreshold). 
  5495                 ] ifFalse:[
  5496                     maskImage := ImageMask extent:image extent.
  5497                     maskImage bits:(ByteArray 
  5498                                         new:(maskImage bytesPerRow * maskImage height)
  5499                                         withAll:16rFF).
  5500 
  5501 "/                    maskImage fillRectangle:(image bounds) withColor:(Color colorId:1).
  5502                 ].
  5503                 image mask:maskImage.
  5504             ].
  5505         ] ifFalse:[ 
  5506             image mask: nil.
  5507             oldImage mask notNil ifTrue:[
  5508                 newImage depth == 32 ifTrue:[
  5509                     newImage computeAlphaValuesFromMask:oldImage mask
  5510                 ].
  5511             ].
  5512         ]. 
  5513 
  5514         (newColorMap isOrderedCollection or:[newColorMap isFixedPalette not]) ifTrue:[
  5515             realColorMap := OrderedCollection new.
  5516             image realColorMap do:[:clr|
  5517                 (realColorMap includes: clr) ifFalse: [realColorMap add: clr]
  5518             ].
  5519             newColors := realColorMap copyFrom: 1 to: (newColorMap size min: realColorMap size).
  5520             newColorMap do:[:clr|
  5521                 ((newColors size < newColorMap size) and: [(newColors includes: clr) not]) 
  5522                 ifTrue:[      
  5523                     newColors add: clr
  5524                 ]
  5525             ].                  
  5526             image colorMap: newColors.   
  5527         ].
  5528         image fileName: oldFileName.
  5529 
  5530         (imageEditView image: image) notNil ifTrue:[
  5531             self fetchImageData.
  5532         ]
  5533     ]
  5534 
  5535     "Modified: / 22-11-2016 / 03:44:00 / cg"
  5536 !
  5537 
  5538 colorize
  5539     "interactive Hue editing"
  5540 
  5541     |bindings hueShift lightValue saturationValue originalColormap firstChange acceptChannel 
  5542      shiftAction avgColorHolder avgColor shiftedColor shiftProcess readySema
  5543      originalPixels p|
  5544 
  5545     "/ compute the averageColor in the background (while asking user)
  5546     readySema := Semaphore new.
  5547     [
  5548         |image|
  5549 
  5550         image := imageEditView image.
  5551         originalColormap := image colorMap copy.
  5552         avgColor := image averageColor.
  5553         originalPixels := image bits.
  5554         readySema signal.
  5555     ] forkAt:7.
  5556 
  5557     acceptChannel := TriggerValue new.
  5558     avgColorHolder := avgColor asValue.
  5559 
  5560     firstChange := true.
  5561 
  5562     shiftedColor := [:clr :hShift :lFactor :sFactor |
  5563                         Color 
  5564                                 hue:((clr hue) ? 0 + hShift) 
  5565                                 light:((clr light * lFactor / 100) min:100)
  5566                                 saturation:(((clr saturation max:20) * sFactor / 100) min:100)].
  5567 
  5568 
  5569     shiftAction := 
  5570         [
  5571             |hShift lFactor sFactor|
  5572 
  5573             acceptChannel value:true.
  5574 
  5575             firstChange ifTrue:[
  5576                 imageEditView makeUndo.
  5577                 firstChange := false.
  5578             ].
  5579             readySema notNil ifTrue:[readySema wait. readySema := nil].
  5580 
  5581             hShift := hueShift value.
  5582             lFactor := lightValue value.
  5583             sFactor := saturationValue value.
  5584 
  5585             avgColorHolder value:(shiftedColor value:avgColor value:hShift value:lFactor value:sFactor).
  5586 
  5587             shiftProcess notNil ifTrue:[
  5588                 shiftProcess terminate.
  5589                 shiftProcess waitUntilTerminated.
  5590                 shiftProcess := nil.
  5591             ].
  5592             shiftProcess := 
  5593                 [
  5594                     [
  5595                         imageEditView image 
  5596                             colorMap:originalColormap copy;
  5597                             bits:originalPixels copy;
  5598                             release;
  5599                             colorMapProcessing:[:clr | shiftedColor value:clr value:hShift value:lFactor value:sFactor].
  5600                         self updateImage.
  5601                         self updateInfoLabel.
  5602                         self updateImagePreView.
  5603                     ] ensure:[ shiftProcess := nil ].    
  5604                 ] forkAt:7.
  5605         ].
  5606 
  5607     bindings := IdentityDictionary new.
  5608     bindings at:#hueShiftAmount put:(hueShift := 0 asValue).
  5609     hueShift onChangeEvaluate:shiftAction.
  5610 
  5611     bindings at:#lightAmount put:(lightValue := 100 asValue).
  5612     lightValue onChangeEvaluate:shiftAction.
  5613 
  5614     bindings at:#saturationAmount put:(saturationValue := 100 asValue).
  5615     saturationValue onChangeEvaluate:shiftAction.
  5616 
  5617     bindings at:#acceptChannel put:acceptChannel.
  5618     bindings at:#hlsColor put:avgColorHolder.
  5619 
  5620     (self openDialogInterface:#changeHLSDialogSpec withBindings:bindings) 
  5621     ifFalse:[ 
  5622         firstChange ~~ true ifTrue:[
  5623             imageEditView undo
  5624         ]
  5625     ].
  5626 
  5627     (p := shiftProcess) notNil ifTrue:[
  5628         p waitUntilTerminated.
  5629     ].
  5630     self updateImage.
  5631     self updateImagePreView.
  5632 
  5633     "Created: / 01-11-2007 / 23:27:37 / cg"
  5634 !
  5635 
  5636 compressColorMap
  5637     "calculates a new color map for the image, using only used colors"
  5638 
  5639     |newImage| 
  5640 
  5641     newImage := self image.
  5642     newImage compressColorMap.
  5643 
  5644     (imageEditView image:newImage) notNil ifTrue:[
  5645         self fetchImageData.
  5646     ]
  5647 !
  5648 
  5649 copyColorFromColormap
  5650     imageEditView setClipboardObject:(self selectedColorOrNil)
  5651 !
  5652 
  5653 ditherToDepth
  5654     |depth|
  5655 
  5656     depth := Dialog request:'New depth ?'.
  5657     depth isEmptyOrNil ifTrue:[^ self].
  5658     depth := Number readFrom:depth onError:nil.
  5659     depth isNil ifTrue:[^ self].
  5660 
  5661     self ditherToDepth:depth
  5662 
  5663     "Created: / 07-07-2006 / 13:22:10 / cg"
  5664 !
  5665 
  5666 ditherToDepth:depth
  5667     |ditherColors newImage useStandardColors nGrey greyColorsAlready moreColors d|
  5668 
  5669     useStandardColors := true.
  5670 "/    useStandardColors := Dialog confirmWithCancel:'Dither in standard colors or use a new (optimized) colormap ?'.
  5671 "/    useStandardColors isNil ifTrue:[^ self].
  5672 
  5673     useStandardColors ifTrue:[
  5674         depth = 1 ifTrue:[
  5675             ditherColors := Array with:(Color black) with:(Color white).
  5676         ] ifFalse:[ depth = 2 ifTrue:[
  5677             ditherColors := Array 
  5678                                 with:(Color black) 
  5679                                 with:(Color darkGray)
  5680                                 with:(Color lightGray)
  5681                                 with:(Color white).
  5682         ] ifFalse:[ depth = 3 ifTrue:[
  5683             ditherColors := Color colorCubeWithRed:2 green:2 blue:2. 
  5684         ] ifFalse:[ depth = 4 ifTrue:[
  5685             ditherColors := Color vgaColors. 
  5686         ] ifFalse:[ depth = 5 ifTrue:[
  5687             ditherColors := Color colorCubeWithRed:4 green:4 blue:2. 
  5688         ] ifFalse:[ depth = 6 ifTrue:[
  5689             ditherColors := Color colorCubeWithRed:4 green:4 blue:3.
  5690         ] ifFalse:[ depth <= 8 ifTrue:[
  5691             ditherColors := Color colorCubeWithRed:6 green:6 blue:5. 
  5692         ] ifFalse:[ 
  5693             self error:'unsupported depth'.
  5694         ]]]]]]].
  5695 
  5696         nGrey := (2 raisedTo:depth) - ditherColors size.  
  5697         nGrey > 0 ifTrue:[
  5698             nGrey := nGrey min:128.
  5699             greyColorsAlready := ditherColors select:[:clr | clr isGreyColor].
  5700             d := 1 / nGrey.
  5701             moreColors := (1 to:nGrey-1) 
  5702                             collect:[:i | Color brightness:(d * i)] 
  5703                             thenReject:[:clr | greyColorsAlready includes:clr ].
  5704 
  5705             ditherColors := ditherColors , moreColors.
  5706         ].
  5707     ] ifFalse:[
  5708         self halt:'unhandled dither color setup'.
  5709     ].
  5710 
  5711     self withExecuteCursorDo:[
  5712         "/ newImage := self image asDitheredImageUsing:ditherColors depth:depth.
  5713         newImage := self image asDitheredImageUsing:ditherColors depth:8.
  5714 
  5715         imageEditView makeUndo.
  5716         imageEditView image:newImage.
  5717         imageEditView setModified.
  5718         self updateImage.
  5719         self updateImagePreView.
  5720 
  5721         self fetchImageData.
  5722     ].
  5723 
  5724     "Created: / 07-07-2006 / 13:20:56 / cg"
  5725     "Modified: / 05-09-2006 / 16:13:25 / cg"
  5726 !
  5727 
  5728 doubleClickOnColor:aColorIndex
  5729     self editSelectedColor.
  5730 
  5731     "Created: / 22-07-2007 / 13:14:37 / cg"
  5732 !
  5733 
  5734 editSelectedColor
  5735     self processSelectedColorWith:[:clr | 
  5736         |editor|
  5737 
  5738         editor := ColorEditDialog new.
  5739         editor color:clr.
  5740         editor open.
  5741         editor accepted ifFalse:[
  5742             AbortOperationRequest raise.
  5743         ].
  5744         editor color
  5745     ]
  5746 !
  5747 
  5748 fetchImageData
  5749     |image|
  5750 
  5751     (image := imageEditView image) notNil ifTrue:[
  5752         self findColorMapMode.
  5753         self updateLabelsAndHistory.
  5754     ]
  5755 !
  5756 
  5757 inspectColor
  5758     |clrIndex clr|
  5759 
  5760     self hasColormap ifFalse:[
  5761         clr := self selectedColorOrNil
  5762     ] ifTrue:[
  5763         clrIndex := self selectedColorIndexOrNil.
  5764         clrIndex isNil ifTrue:[
  5765             ^ self
  5766         ].
  5767         clr := self image colorFromValue:clrIndex-1
  5768     ].
  5769     clr inspect
  5770 !
  5771 
  5772 inspectColormap
  5773     self hasColormap ifTrue:[
  5774         self image colorMap inspect
  5775     ].
  5776 !
  5777 
  5778 makeBrighter
  5779     | anyChange|
  5780 
  5781     self withExecuteCursorDo:[
  5782         anyChange := imageEditView makeBrighter.
  5783         anyChange ifFalse:[
  5784             Dialog warn:'Image unchanged'.
  5785         ] ifTrue:[
  5786             self updateImage.
  5787         ]
  5788     ].
  5789 !
  5790 
  5791 makeDarker
  5792     | anyChange|
  5793 
  5794     self withExecuteCursorDo:[
  5795         anyChange := imageEditView makeDarker.
  5796         anyChange ifFalse:[
  5797             Dialog warn:'Image unchanged'.
  5798         ] ifTrue:[
  5799             self updateImage.
  5800         ]
  5801     ].
  5802 !
  5803 
  5804 makeGrayScaleImage
  5805     |anyChange|
  5806 
  5807     self withExecuteCursorDo:[
  5808         anyChange := imageEditView makeGrayScaleImage.
  5809         anyChange ifFalse:[
  5810             Dialog warn:'Image unchanged'.
  5811         ] ifTrue:[
  5812             self updateImage.
  5813         ]
  5814     ].
  5815 !
  5816 
  5817 makeInverse
  5818     | anyChange|
  5819 
  5820     self withExecuteCursorDo:[
  5821         anyChange := imageEditView makeInverse.
  5822         anyChange ifFalse:[
  5823             Dialog warn:'Image unchanged'.
  5824         ] ifTrue:[
  5825             self updateImage.
  5826         ]
  5827     ].
  5828 !
  5829 
  5830 makeSelectedColorBrighter
  5831     self processSelectedColorsWith:[:clr | clr lightened]
  5832 !
  5833 
  5834 makeSelectedColorDarker
  5835     self processSelectedColorsWith:[:clr | clr darkened]
  5836 !
  5837 
  5838 makeSelectedColorGray
  5839     self processSelectedColorsWith:[:clr | Color brightness:(clr brightness)]
  5840 !
  5841 
  5842 makeSelectedColorShifted
  5843     |cMap colors|
  5844 
  5845     cMap := self image colorMap.
  5846     self hasMask ifTrue:[
  5847         colors := self selectedColors value collect:[:idx | cMap at:idx-1].
  5848     ] ifFalse:[
  5849         colors := self selectedColors value collect:[:idx | cMap at:idx].
  5850     ].
  5851     self changeHLSOfColors:colors.
  5852 !
  5853 
  5854 makeSlightlyBrighter
  5855     | anyChange|
  5856 
  5857     self withExecuteCursorDo:[
  5858         anyChange := imageEditView makeSlightlyBrighter.
  5859         anyChange ifFalse:[
  5860             Dialog warn:'Image unchanged'.
  5861         ] ifTrue:[
  5862             self updateImage.
  5863         ]
  5864     ].
  5865 
  5866     "Created: / 24-11-2010 / 11:06:11 / cg"
  5867 !
  5868 
  5869 makeSlightlyDarker
  5870     | anyChange|
  5871 
  5872     self withExecuteCursorDo:[
  5873         anyChange := imageEditView makeSlightlyDarker.
  5874         anyChange ifFalse:[
  5875             Dialog warn:'Image unchanged'.
  5876         ] ifTrue:[
  5877             self updateImage.
  5878         ]
  5879     ].
  5880 
  5881     "Created: / 24-11-2010 / 11:06:23 / cg"
  5882 !
  5883 
  5884 menu_clearColormapEntry0AndMaskedPixels
  5885     "ensure that there is a colorMap entry with 0/0/0 at position
  5886      0 and then clear all masked pixels (to pixelValue 0)"
  5887 
  5888     imageEditView makeUndo.
  5889     self withExecuteCursorDo:[
  5890         self clearColormapEntry0AndMaskedPixels
  5891     ]
  5892 !
  5893 
  5894 menu_clearMaskedPixels
  5895     "clear all masked pixels (to pixelValue 0)"
  5896 
  5897     imageEditView makeUndo.
  5898 
  5899     self withExecuteCursorDo:[
  5900         self clearMaskedPixels
  5901     ]
  5902 !
  5903 
  5904 menu_compressColorMap
  5905     "calculates a new color map for the image, using only used colors"
  5906 
  5907     |depth oldImage usedColors colorMap| 
  5908 
  5909     oldImage := self image.
  5910 
  5911     oldImage photometric ~~ #palette ifTrue:[
  5912         self information:'Compress colorMap: Only palette images have colormaps.'.
  5913         ^ self
  5914     ].
  5915     depth := oldImage depth.
  5916     colorMap := oldImage colorMap asArray.
  5917     usedColors := oldImage realUsedColors.
  5918     usedColors size == colorMap size ifTrue:[
  5919         self information:'Compress colorMap: Colormap already compressed - no compression.'.
  5920         ^ self
  5921     ].
  5922 
  5923     imageEditView makeUndo.
  5924 
  5925     self withExecuteCursorDo:[
  5926         self compressColorMap
  5927     ]
  5928 !
  5929 
  5930 menu_copyMask
  5931     |mask|
  5932 
  5933     mask := self image mask.
  5934     MaskClipboard := mask subImageIn: (0@0 extent:mask extent).
  5935 !
  5936 
  5937 menu_pasteMask
  5938     |img mask|
  5939 
  5940     imageEditView makeUndo.
  5941 
  5942     img := self image.
  5943     mask := img mask.
  5944 
  5945     mask 
  5946          copyFrom:MaskClipboard
  5947          x:0 y:0
  5948          toX:0 y:0 
  5949          width:(mask width min:MaskClipboard width)
  5950          height:(mask height min:MaskClipboard height).
  5951     img mask:mask.
  5952     (imageEditView image:img copy) notNil ifTrue:[
  5953         self fetchImageData.
  5954     ]
  5955 !
  5956 
  5957 menu_sortColorMap
  5958     "calculates a new color map for the image, sorting colors"
  5959 
  5960     self menu_sortColorMapWith:self sortBlockForColors
  5961 !
  5962 
  5963 menu_sortColorMapWith:sortBlock
  5964     "calculates a new color map for the image, sorting colors"
  5965 
  5966     self image photometric ~~ #palette ifTrue:[
  5967         self information:'Compress colorMap: Only palette images have colormaps.'.
  5968         ^ self
  5969     ].
  5970 
  5971     imageEditView makeUndo.
  5972 
  5973     self withExecuteCursorDo:[
  5974         self sortColorMapWith:sortBlock
  5975     ]
  5976 
  5977     "Modified: / 15.9.1998 / 17:53:32 / cg"
  5978     "Created: / 30.9.1998 / 23:51:23 / cg"
  5979 !
  5980 
  5981 pasteColorIntoColormap
  5982     |copyBufferColor|
  5983 
  5984     copyBufferColor := imageEditView getClipboardObject.
  5985     copyBufferColor isColor ifFalse:[
  5986         UserPreferences current beepInEditor ifTrue:[                
  5987             self window beep.
  5988         ].
  5989         ^ self
  5990     ].
  5991 
  5992     self processSelectedColorWith:[:clr |
  5993         copyBufferColor
  5994     ]
  5995 !
  5996 
  5997 pickAndAddColorToColormap
  5998     self addColorToColormap:(Color fromUser)
  5999 !
  6000 
  6001 pickAndPasteColor
  6002     self pickColor.
  6003     self pasteColorIntoColormap.
  6004 !
  6005 
  6006 pickColor
  6007     imageEditView setClipboardObject:(Color fromUser)
  6008 !
  6009 
  6010 processSelectedColorWith:aBlock
  6011     "undoable color processing: 
  6012      the selected color will be replaced by the value of aBlock"
  6013 
  6014     self processSelectedColorsWith:aBlock.
  6015 !
  6016 
  6017 processSelectedColorsWith:aBlock
  6018     "undoable color processing: 
  6019      the selected colors will be replaced by the value of aBlock 
  6020      (which gets a color vector and must return a color vector)"
  6021 
  6022     |img cMap modifiedColormap oldColors newImage selectedColorIndices newColors maskOffset|
  6023 
  6024     selectedColorIndices := self selectedColors value.
  6025     selectedColorIndices isEmptyOrNil ifTrue:[^ self].
  6026 
  6027     img := self image.
  6028     cMap := img colorMap.
  6029     cMap isNil ifTrue:[
  6030         self warn:(resources stringWithCRs:'Image has no colormap.\Please change the colorMap mode first.').
  6031         ^ self
  6032     ].
  6033     self hasMask ifTrue:[
  6034         maskOffset := 1.
  6035     ] ifFalse:[
  6036         maskOffset := 0.
  6037     ].
  6038     oldColors := selectedColorIndices collect:[:idx | cMap at:idx-maskOffset].
  6039     imageEditView makeUndo.
  6040 
  6041     modifiedColormap := cMap asNewArray.
  6042 
  6043     newColors := oldColors collect:aBlock.
  6044     selectedColorIndices with:newColors do:[:idx :newColor | 
  6045         modifiedColormap at:idx-maskOffset put:newColor
  6046     ].
  6047 
  6048     newImage := img species new
  6049                     width:img width
  6050                     height:img height
  6051                     depth:img depth
  6052                     fromArray:img bits.
  6053 
  6054     newImage colorMap:modifiedColormap.  
  6055     newImage fileName:img fileName.
  6056     newImage mask:(img mask copy).
  6057 
  6058     (imageEditView image:newImage) notNil ifTrue:[
  6059         self fetchImageData.
  6060     ].
  6061     self selectedColors value:selectedColorIndices.
  6062 !
  6063 
  6064 reduceNumberOfColors
  6065     |s n anyChange img usedColors|
  6066 
  6067     s := Dialog request:'Number of color bits to strip (1-7) ?' initialAnswer:3.
  6068     s size == 0 ifTrue:[^ self].
  6069 
  6070     n := Integer readFrom:s onError:0.
  6071     (n between:1 and:7) ifFalse:[
  6072         Dialog warn:'Image unchanged'.
  6073         ^ self
  6074     ].
  6075 
  6076     self withExecuteCursorDo:[
  6077         anyChange := imageEditView reduceColorResolutionBy:n.
  6078         anyChange ifFalse:[
  6079             Dialog warn:'Image unchanged'.
  6080         ] ifTrue:[
  6081             img := imageEditView image.
  6082             imageEditView image:img.
  6083 
  6084             self fetchImageData.
  6085             usedColors := img usedColorsMax:10000.
  6086             usedColors size == 10000 ifTrue:[
  6087                 Dialog information:('>= ' , usedColors size printString , ' colors used.')
  6088             ] ifFalse:[
  6089                 Dialog information:(usedColors size printString , ' colors used.')
  6090             ]
  6091         ]
  6092     ].
  6093 
  6094     "Modified: / 29-10-2010 / 18:08:01 / cg"
  6095 !
  6096 
  6097 reduceNumberOfColors2
  6098     |s rndR rndG rndB usedColors image newImage|
  6099 
  6100     s := Dialog request:'Rounding Interval red (2..) ?' initialAnswer:4.
  6101     s size == 0 ifTrue:[^ self].
  6102     rndR := Integer readFrom:s onError:0.
  6103 
  6104     s := Dialog request:'Rounding Interval green (2..) ?' initialAnswer:2.
  6105     s size == 0 ifTrue:[^ self].
  6106     rndG := Integer readFrom:s onError:0.
  6107 
  6108     s := Dialog request:'Rounding Interval blue (2..) ?' initialAnswer:10.
  6109     s size == 0 ifTrue:[^ self].
  6110     rndB := Integer readFrom:s onError:0.
  6111 
  6112     ((rndR > 1) or:[(rndG > 1) or:[(rndB > 1)]]) ifFalse:[
  6113         Dialog warn:'Image unchanged'.
  6114         ^ self
  6115     ].
  6116 
  6117     self withExecuteCursorDo:[
  6118         |reduceColor|
  6119 
  6120         reduceColor :=
  6121             [:clr |
  6122                 |r g b nr ng nb|
  6123 
  6124                 r := clr redByte.
  6125                 g := clr greenByte.
  6126                 b := clr blueByte. 
  6127                 nr := (r roundTo:rndR) min:255.
  6128                 ng := (g roundTo:rndG) min:255.
  6129                 nb := (b roundTo:rndB) min:255. 
  6130 
  6131                 Color redByte:nr greenByte:ng blueByte:nb.
  6132             ].
  6133 
  6134         image := self image.
  6135         "/ usedColors := image usedColorsMax:4096.
  6136         imageEditView makeUndo.
  6137 
  6138         newImage := image copy.
  6139         newImage photometric == #palette ifTrue:[
  6140             newImage colorMap:(image colorMap collect:reduceColor).
  6141         ] ifFalse:[
  6142             image
  6143                 colorsFromX:0 y:0 toX:(image width-1) y:(image height-1) 
  6144                 do:[:x :y :clr |
  6145                     newImage colorAtX:x y:y put:(reduceColor value:clr)
  6146                 ].
  6147         ].
  6148         imageEditView image:newImage.
  6149         imageEditView setModified.
  6150         self updateImage.
  6151         self updateImagePreView.
  6152 
  6153         self fetchImageData.
  6154         usedColors := newImage usedColorsMax:10000.
  6155         usedColors size == 10000 ifTrue:[
  6156             Dialog information:('>= ' , usedColors size printString , ' colors used.')
  6157         ] ifFalse:[
  6158             Dialog information:(usedColors size printString , ' colors used.')
  6159         ]
  6160     ].
  6161 
  6162     "Modified: / 07-07-2006 / 13:10:42 / cg"
  6163 !
  6164 
  6165 selectColor:aColor
  6166     |idx img cMap|
  6167 
  6168     aColor isNil ifTrue:[
  6169         idx := nil.
  6170     ] ifFalse:[
  6171         img := self image.
  6172         img notNil ifTrue: [
  6173             aColor == Color noColor ifTrue:[
  6174                 (img mask notNil) ifTrue:[
  6175                     idx := 1.
  6176                 ]
  6177             ] ifFalse:[
  6178                 (cMap := self listOfColors) notNil ifTrue:[
  6179                     idx := cMap indexOf:aColor ifAbsent:nil.
  6180                 ].
  6181                 idx isNil ifTrue:[
  6182                     "/ should not happen...
  6183                     (cMap := img colorMap) notNil ifTrue:[
  6184                         idx := cMap indexOf:aColor ifAbsent:nil.
  6185                         idx notNil ifTrue:[
  6186                             img mask notNil ifTrue:[
  6187                                 idx := idx + 1.
  6188                             ].
  6189                         ]
  6190                     ].
  6191                 ].
  6192             ].
  6193         ].
  6194     ].
  6195     self selectedColors value:{idx}.
  6196 
  6197     "Modified: / 02-07-2010 / 12:06:07 / cg"
  6198 !
  6199 
  6200 selectedColorIndexOrNil
  6201     |img clrIndex|
  6202 
  6203     img := self image.
  6204     img isNil ifTrue:[
  6205         "/ self warn:'No Image.'.
  6206         ^ nil
  6207     ].
  6208     clrIndex := self selectionOfColor value.
  6209     self hasMask "img mask notNil" ifTrue: [ 
  6210         (clrIndex isInteger and:[clrIndex > 1]) ifTrue:[
  6211             ^ clrIndex - 1 
  6212         ].
  6213         ^ nil
  6214     ].
  6215     ^ clrIndex
  6216 !
  6217 
  6218 selectedColorOrNil
  6219     |cmapIndex img cMap colorList|
  6220 
  6221     cmapIndex := self selectedColorIndexOrNil.
  6222     cmapIndex isNil ifTrue:[^ nil].
  6223     cmapIndex == 0 ifTrue:[^ nil].
  6224 
  6225     img := self image.
  6226     cMap := img colorMap.
  6227     cMap isNil ifTrue:[
  6228         "/ self warn:(resources stringWithCRs:'Image has no colormap.\Please change the colorMap mode first.').
  6229         colorList := self listOfColors.
  6230         colorList notNil ifTrue:[
  6231             ^ colorList at:cmapIndex ifAbsent:nil
  6232         ].
  6233         ^ nil
  6234     ].
  6235     ^ cMap at:cmapIndex.
  6236 !
  6237 
  6238 sortColorMap
  6239     "calculates a new color map for the image, sorting colors"
  6240 
  6241     self sortColorMapWith:self sortBlockForColorsByRGB
  6242 !
  6243 
  6244 sortColorMapWith:sortBlock
  6245     "calculates a new color map for the image, sorting colors"
  6246 
  6247     |depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits
  6248      expectedSize w h| 
  6249 
  6250     oldImage := self image.
  6251     depth := oldImage depth.
  6252     w := oldImage width.
  6253     h := oldImage height.
  6254 
  6255     usedColors := oldImage realColorMap.
  6256 
  6257     "/ translation table
  6258     oldToNew := ByteArray new:(1 bitShift:depth).
  6259     newColorMap := usedColors asArray.
  6260     newColorMap sort:sortBlock.
  6261 
  6262     oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
  6263         |newPixel|
  6264 
  6265         (usedColors includes:clr) ifTrue:[
  6266             newPixel := newColorMap indexOf:clr.
  6267             oldToNew at:oldIdx put:newPixel-1.
  6268         ]
  6269     ].
  6270 
  6271     oldBits := oldImage bits.
  6272     "/ sanity check...
  6273     expectedSize := ((w * h * depth + 7) // 8).
  6274     (oldBits size < expectedSize) ifTrue:[
  6275         self halt:'incorrect pixeldata size'.
  6276         oldBits := (ByteArray new:expectedSize) replaceFrom:1 with:oldBits; yourself.
  6277     ].
  6278     newBits := ByteArray new:(oldBits size).
  6279     depth ~~ 8 ifTrue:[
  6280 
  6281         "/ expand/compress can only handle 8bits
  6282         tmpBits := ByteArray uninitializedNew:(w*h).
  6283         oldBits
  6284             expandPixels:depth
  6285             width:w height:h 
  6286             into:tmpBits
  6287             mapping:oldToNew.
  6288         tmpBits
  6289             compressPixels:depth 
  6290             width:w height:h 
  6291             into:newBits 
  6292             mapping:nil
  6293     ] ifFalse:[
  6294         oldBits
  6295             expandPixels:depth
  6296             width:w height:h 
  6297             into:newBits
  6298             mapping:oldToNew.
  6299     ].
  6300 
  6301     newImage := oldImage species new
  6302                     width:w height:h depth:depth
  6303                     fromArray:newBits.
  6304 
  6305     newImage colorMap:newColorMap.  
  6306     newImage fileName:oldImage fileName.
  6307     newImage mask:(oldImage mask copy).
  6308 
  6309     (imageEditView image:newImage) notNil ifTrue:[
  6310         self fetchImageData.
  6311     ]
  6312 
  6313     "Modified: / 15.9.1998 / 17:53:32 / cg"
  6314     "Created: / 30.9.1998 / 23:51:23 / cg"
  6315 ! !
  6316 
  6317 !ImageEditor methodsFor:'user actions-editing'!
  6318 
  6319 do3DProjection
  6320     |box dx1 dx2 image|
  6321 
  6322     image := imageEditView image.
  6323 
  6324     box := EnterBox new.
  6325     box title:(resources string:'dX1 (0 < dx < 0.5):').
  6326     box okText:(resources string:'OK').
  6327     box abortText:(resources string:'Cancel').
  6328     box initialText:'0.1'.
  6329     box showAtPointer.
  6330 
  6331     (box accepted 
  6332     and: [(dx1 := Number readFrom:(box contents) onError:nil) notNil])
  6333     ifTrue:[
  6334         box title:(resources string:'dX2 (0 < dx < 0.5):').
  6335         box initialText:(dx1 printString).
  6336         box showAtPointer.
  6337         (box accepted 
  6338         and: [(dx2 := Number readFrom:(box contents) onError:nil) notNil])
  6339         ifTrue:[
  6340             imageEditView threeDProjection:dx1 and:dx2.
  6341         ]
  6342     ].
  6343 
  6344     self updateInfoLabel
  6345 !
  6346 
  6347 doBrightenImage
  6348     imageEditView brightenImage.
  6349     self listOfColors removeAll.
  6350     self findColorMapMode.     
  6351     "/ imageEditView removelastUndo
  6352 !
  6353 
  6354 doBrowseClass
  6355     "opens a System Browser on the resourceClass and the resourceSelector"
  6356 
  6357     |cls|
  6358 
  6359     cls := imageEditView resourceClass.
  6360     cls isNil ifTrue:[^ self warn:'No Class specified'].
  6361 
  6362     cls browserClass
  6363         openInClass:cls class 
  6364         selector:(imageEditView resourceSelector)
  6365 
  6366     "Modified: / 31.7.1998 / 02:01:15 / cg"
  6367 !
  6368 
  6369 doCopyImageToClipboard
  6370     imageEditView copyImageToClipboard.
  6371 !
  6372 
  6373 doCropAll
  6374     "find all borders and cut them off"
  6375 
  6376     imageEditView cropLeft:true right:true top:true bottom:true.   
  6377     self updateInfoLabel
  6378 
  6379     "Modified: / 7.9.1998 / 14:26:23 / cg"
  6380     "Created: / 7.9.1998 / 16:33:43 / cg"
  6381 !
  6382 
  6383 doCropBottom
  6384     "find a bottom border and cut it off"
  6385 
  6386     imageEditView cropLeft:false right:false top:false bottom:true.   
  6387     self updateInfoLabel
  6388 
  6389     "Created: / 7.9.1998 / 13:00:20 / cg"
  6390     "Modified: / 7.9.1998 / 14:26:23 / cg"
  6391 !
  6392 
  6393 doCropLeft
  6394     "find a left border and cut it off"
  6395 
  6396     imageEditView cropLeft:true right:false top:false bottom:false.   
  6397     self updateInfoLabel
  6398 
  6399     "Created: / 7.9.1998 / 13:00:14 / cg"
  6400     "Modified: / 7.9.1998 / 14:26:34 / cg"
  6401 !
  6402 
  6403 doCropManual
  6404     "let user specify borders and cut them off"
  6405 
  6406     |bindings left top right bottom img firstChange gropAction acceptChannel|
  6407 
  6408     acceptChannel := TriggerValue new.
  6409 
  6410     firstChange := true.
  6411 
  6412     gropAction := 
  6413         [:lV :rV :tV :bV | |l r t b|
  6414             acceptChannel value:true.
  6415 
  6416             l := lV value.
  6417             r := rV value.
  6418             t := tV value.
  6419             b := bV value.
  6420             (l + r + t + b) == 0 ifTrue:[
  6421                 UserPreferences current beepInEditor ifTrue:[                
  6422                     self window beep
  6423                 ]
  6424             ] ifFalse:[
  6425                 img := imageEditView image.
  6426                 firstChange ifTrue:[
  6427                     imageEditView makeUndo.
  6428                     firstChange := false.
  6429                 ].
  6430                 imageEditView
  6431                     makeSubImageX:l y:t 
  6432                     width:(img width - l - r)
  6433                     height:(img height - t - b).
  6434 
  6435                 self updateImagePreView.
  6436                 self updateInfoLabel
  6437             ].
  6438         ].
  6439 
  6440     bindings := IdentityDictionary new.
  6441     bindings at:#left put:(left := 1 asValue).
  6442     bindings at:#right put:(right := 1 asValue).
  6443     bindings at:#top put:(top := 1 asValue).
  6444     bindings at:#bottom put:(bottom := 1 asValue).
  6445     bindings at:#acceptChannel put:acceptChannel.
  6446 
  6447     bindings at:#gropLeftNow   put:[ gropAction value:left value:0 value:0 value:0 ].
  6448     bindings at:#gropRightNow  put:[ gropAction value:0 value:right value:0 value:0 ].
  6449     bindings at:#gropTopNow    put:[ gropAction value:0 value:0 value:top value:0 ].
  6450     bindings at:#gropBottomNow put:[ gropAction value:0 value:0 value:0 value:bottom ].
  6451 
  6452     bindings at:#applyAction   put:[ gropAction value:left value:right value:top value:bottom ].
  6453 
  6454     (self openDialogInterface:#cropDialogSpec withBindings:bindings) 
  6455     ifFalse:[ 
  6456         firstChange ~~ true ifTrue:[
  6457             imageEditView undo.
  6458             self updateImagePreView.
  6459         ]
  6460     ].
  6461 
  6462     "Created: / 7.9.1998 / 18:16:07 / cg"
  6463     "Modified: / 7.9.1998 / 18:20:42 / cg"
  6464 !
  6465 
  6466 doCropRight
  6467     "find a right border and cut it off"
  6468 
  6469     imageEditView cropLeft:false right:true top:false bottom:false.   
  6470     self updateInfoLabel
  6471 
  6472     "Created: / 7.9.1998 / 13:00:14 / cg"
  6473     "Modified: / 7.9.1998 / 14:26:44 / cg"
  6474 !
  6475 
  6476 doCropTop
  6477     "find a top border and cut it off"
  6478 
  6479     imageEditView cropLeft:false right:false top:true bottom:false.   
  6480     self updateInfoLabel
  6481 
  6482     "Created: / 7.9.1998 / 13:00:19 / cg"
  6483     "Modified: / 7.9.1998 / 14:26:52 / cg"
  6484 !
  6485 
  6486 doDarkenImage
  6487     imageEditView darkenImage.
  6488     self listOfColors removeAll.
  6489     self findColorMapMode.     
  6490     "/ imageEditView removelastUndo
  6491 !
  6492 
  6493 doEditMask
  6494     self image mask edit
  6495 !
  6496 
  6497 doFlipHorizontal
  6498     "flips horizontally current image"
  6499 
  6500     imageEditView flipHorizontal
  6501 !
  6502 
  6503 doFlipVertical
  6504     "flips vertically current image"
  6505 
  6506     imageEditView flipVertical
  6507 !
  6508 
  6509 doInsertTextFromUser
  6510     |text tempForm tempImage maskImage font w h paintColor|
  6511 
  6512     text := Dialog request:'Text to be inserted (placed as bitmap into clipboard for paste):'.
  6513     text isEmptyOrNil ifTrue:[^ self ].
  6514 
  6515     font := Font family:'arial' size:20.
  6516     font := font onDevice:Screen current.
  6517     w := font widthOf:text.
  6518     h := font heightOf:text.
  6519 
  6520     tempForm := Form extent:(w@h) depth:1 onDevice:(Screen current).
  6521     tempForm clear.
  6522     tempForm font:font.
  6523     tempForm paint:(Color colorId:1).
  6524     tempForm displayString:text at:(0@font ascent).
  6525 
  6526     tempImage := tempForm asImage.
  6527     maskImage := tempForm asImage.
  6528 
  6529     paintColor := imageEditView selectedColor.
  6530     paintColor  colorId == 0 ifTrue:[
  6531         paintColor := Color black
  6532     ].
  6533     tempImage   
  6534         photometric:#palette;
  6535         colorMap:(Array 
  6536                     with:Color white 
  6537                     with:paintColor);
  6538         mask:maskImage.
  6539 
  6540     ImageEditView copyImageToClipboard:tempImage.
  6541     self editMode value:#paste.
  6542 
  6543     "Modified: / 11-11-2007 / 12:32:55 / cg"
  6544 !
  6545 
  6546 doInspectImage
  6547     "opens a System Browser on the resourceClass and the resourceSelector"
  6548 
  6549     self image inspect
  6550 !
  6551 
  6552 doMagnifyDown
  6553     "magnifies the current image one step down"
  6554 
  6555     |magHolder mag|
  6556 
  6557     magHolder := self magnificationHolder.
  6558     (mag := magHolder value) > 1 ifTrue: [
  6559         magHolder value: mag - 1
  6560     ]
  6561 
  6562     "Modified: / 26.7.1998 / 20:24:08 / cg"
  6563 !
  6564 
  6565 doMagnifyImage
  6566     "magnifies the current image to a new size"
  6567 
  6568     |box newSize image antiAliased|
  6569 
  6570     antiAliased := false asValue.
  6571     image := imageEditView image.
  6572 
  6573     box := EnterBox new.
  6574     box title:(resources string:'Images new size:').
  6575     box okText:(resources string:'OK').
  6576     box abortText:(resources string:'Cancel').
  6577     box initialText:image extent printString.
  6578     box addCheckBox:(resources string:'Antialiased') on:antiAliased.
  6579     box showAtPointer.
  6580 
  6581     (box accepted 
  6582     and: [(newSize := self pointFromString:(box contents)) notNil])
  6583     ifTrue:[
  6584         newSize isPoint ifFalse:[
  6585             self warn:'Please enter the new size as ''x @ y''.'.
  6586             ^ self.    
  6587         ].
  6588         antiAliased value ifTrue:[
  6589             imageEditView magnifyAntiAliasedImageTo:newSize.
  6590         ] ifFalse:[
  6591             imageEditView magnifyImageTo:newSize.
  6592         ].
  6593     ].
  6594 
  6595     self updateInfoLabel
  6596 !
  6597 
  6598 doMagnifyImageBy
  6599     "magnifies the current image (by a scale)"
  6600 
  6601     |oldSize newSize scaleString scale image antiAliased|
  6602 
  6603     image := imageEditView image.
  6604     oldSize := image extent.
  6605 
  6606     antiAliased := false asValue.
  6607 
  6608     Dialog modifyingBoxWith:[:box |
  6609         box addCheckBox:(resources string:'Antialiased') on:antiAliased.
  6610     ] do:[
  6611         scaleString := Dialog 
  6612                    request:(resources string:'Scale factor (<1 to shrink; >1 to magnify):') 
  6613                    initialAnswer:'1'
  6614                    list:#('0.25' '0.5' '2' '4').     
  6615     ].
  6616     scaleString isNil ifTrue:[^ self].
  6617 
  6618 "/    box := EnterBox new.
  6619 "/    box title:(resources string:'Scale factor (<1 to shrink; >1 to magnify):').
  6620 "/    box okText:(resources string:'OK').
  6621 "/    box abortText:(resources string:'Cancel').
  6622 "/    box initialText:1 printString.
  6623 "/    box showAtPointer.
  6624 "/    box accepted ifTrue:[
  6625 "/        scaleString := box contents.
  6626 "/    ].
  6627 
  6628     scale := Object readFromString:scaleString onError:nil.
  6629 
  6630     scale notNil ifTrue:[
  6631         scale isNumber ifFalse:[
  6632             self warn:'please enter a scale factor (<1 to shrink; >1 to magnify).'.
  6633             ^ self.    
  6634         ].
  6635         newSize := oldSize * scale.
  6636         antiAliased value ifTrue:[
  6637             imageEditView magnifyAntiAliasedImageTo:newSize.
  6638         ] ifFalse:[
  6639             imageEditView magnifyImageTo:newSize.
  6640         ].
  6641     ].
  6642 
  6643     self updateInfoLabel
  6644 !
  6645 
  6646 doMagnifyUp
  6647     "magnifies the current image one step up"
  6648 
  6649     |magHolder mag|
  6650 
  6651     magHolder := self magnificationHolder.
  6652     (mag := magHolder value) < 63 ifTrue: [
  6653         magHolder value: mag + 1
  6654     ]
  6655 
  6656     "Modified: / 26.7.1998 / 20:23:52 / cg"
  6657 !
  6658 
  6659 doNegativeImage
  6660     "negates current image by negating the color map"
  6661 
  6662     self image depth ~~ 1 ifTrue:[
  6663         Dialog warn:'Only useful for depth 1 images'.
  6664         ^ self
  6665     ].
  6666     imageEditView negativeImage.
  6667     self listOfColors removeAll.
  6668     self findColorMapMode.     
  6669     "/ imageEditView removelastUndo
  6670 !
  6671 
  6672 doResizeImage
  6673     "resizes the current image"
  6674 
  6675     |box newSize image|
  6676 
  6677     image := imageEditView image.
  6678 
  6679     box := EnterBox new.
  6680     box title:(resources string:'Images new size:').
  6681     box okText:(resources string:'OK').
  6682     box abortText:(resources string:'Cancel').
  6683     box initialText:image extent printString.
  6684     box showAtPointer.
  6685     (box accepted 
  6686     and: [(newSize := self pointFromString:(box contents)) notNil])
  6687     ifTrue:[
  6688         imageEditView resizeImageTo:newSize.
  6689     ].
  6690 !
  6691 
  6692 doRotateImage
  6693     "rotates current image"
  6694 
  6695     |rotationString box rotation|
  6696 
  6697     rotationString := Dialog 
  6698                         request:(resources string:'Rotate by (degrees, clockwise):')
  6699                         list:#( '-90' '90' '180' '45' '-45'  '135' '-135' ) 
  6700                         initialAnswer:90.
  6701     rotationString isEmptyOrNil ifTrue:[^ self].    "/ cancelled
  6702     rotation := Number readFrom:rotationString onError:[nil].
  6703     rotation isNil ifTrue:[^ self].   
  6704 
  6705 "/    box := EnterBox new.
  6706 "/    box title:(resources string:'Rotate by (degrees, clockwise):').
  6707 "/    box okText:(resources string:'OK').
  6708 "/    box abortText:(resources string:'Cancel').
  6709 "/    box initialText: '0'.
  6710 "/    box showAtPointer.
  6711 "/    (box accepted and: [(rotation := Number readFromString: box contents onError:nil) notNil])
  6712 "/    ifFalse:[ ^ self ].
  6713 
  6714     imageEditView rotateImageBy:rotation.
  6715     self updateInfoLabel.
  6716 
  6717     "Modified: / 18-03-2012 / 14:41:14 / cg"
  6718 !
  6719 
  6720 doShiftManual
  6721     "let user specify amount and shift"
  6722