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