diff -r f3e9c2ded641 -r 14b7babca4f5 ImageEditor.st --- a/ImageEditor.st Mon Feb 13 09:51:09 2006 +0100 +++ b/ImageEditor.st Mon Feb 13 09:53:10 2006 +0100 @@ -12,7 +12,7 @@ "{ Package: 'stx:libtool2' }" -ToolApplicationModel subclass:#ImageEditor +ResourceSpecEditor subclass:#ImageEditor instanceVariableNames:'imageEditView colorMapMode editMode mouseKeyColorMode selectedColorIndex postOpenAction imageSeqNr drawingColormap lastShiftUsedWrap' @@ -57,10 +57,22 @@ !ImageEditor class methodsFor:'instance creation'! +openLoadingImageWith:aBlock + "opens an Image Editor on anImage" + + |editor| + + editor := self new. + editor allButOpen. + aBlock value:editor. + editor openWindow +! + openModalOnClass: aClass andSelector: aSelector - "opens a modal Image Editor on aClass and aSelector" - - |imageEditor imageEditView className resourceClassName resourceSelector| + "opens a modal Image Editor on aClass and aSelector. + Returns the real name of the edited resource method (in case, user changed it)." + + |imageEditor imageEditView className resourceClass resourceSelector| imageEditor := self new. @@ -68,16 +80,15 @@ aClass isString ifTrue: [className := aClass]. aClass isNil ifTrue: [className := '']. - imageEditor postOpenAction: [imageEditView := imageEditor imageEditView. imageEditor loadFromOrPrepareForMessage: className, ' ', aSelector]. + imageEditor postOpenAction: [imageEditView := imageEditor imageEditView. + imageEditor loadFromOrPrepareForClass: aClass andSelector: aSelector]. imageEditor openModal. - resourceClassName := imageEditView resourceClass name. - resourceSelector := imageEditView resourceSelector. - - ((className asString ~= resourceClassName) - or:[aSelector asString ~= resourceSelector]) - ifTrue: [^resourceClassName, ' ', resourceSelector] - ifFalse:[^nil] + resourceClass := imageEditView resourceClass. + resourceSelector := imageEditView resourceSelector. + + (resourceClass isNil or:[resourceSelector isNil]) ifTrue:[^ nil]. + ^ Array with:resourceClass with:resourceSelector " self openModalOnClass: self andSelector: #leftMouseKeyIcon @@ -87,12 +98,7 @@ openOnClass:aClass andSelector:aSelector "opens an Image Editor on aClass and aSelector" - |editor| - - editor := self new. - editor allButOpen. - editor loadFromClass:aClass selector:aSelector. - editor openWindow + self openLoadingImageWith:[:editor | editor loadFromClass:aClass theNonMetaclass andSelector:aSelector.] " self openOnClass:self andSelector:#leftMouseKeyIcon @@ -105,15 +111,10 @@ openOnFile:aFileName "opens an Image Editor on aFileName" - |editor| - - editor := self new. - editor allButOpen. - editor loadFromFile:aFileName. - editor openWindow + self openLoadingImageWith:[:editor | editor loadFromFile:aFileName.] " - self openOnFile: 'bitmaps/SmalltalkX.xbm' + self openOnFile: '../../goodies/bitmaps/gifImages/back.gif' " "Modified: / 16.3.1999 / 21:33:25 / cg" @@ -122,12 +123,7 @@ openOnImage:anImage "opens an Image Editor on anImage" - |editor| - - editor := self new. - editor allButOpen. - editor loadFromImage: anImage. - editor openWindow + self openLoadingImageWith:[:editor | editor loadFromImage: anImage.] " self openOnImage: Icon startIcon @@ -465,7 +461,7 @@ ^Icon constantNamed:#'ImageEditor class copyIcon' - 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?O?8??#?>O?8_? G>@@a') ; yourself); yourself] + 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& +@@@@@@@@@@@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?8??#?>O?8_? G>@@a') ; yourself); yourself] ! pasteUnderIcon @@ -565,8 +561,8 @@ ^Icon constantNamed:#'ImageEditor class pasteUnderIcon' - 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@@SL0L0A&@@D3LC@@A @AL3@3@FX@@QDPY&Y& -@@@@@@@@@@@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?8??#?>O?8_? G>@@a') ; yourself); yourself] + 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& +@@@@@@@@@@@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?8??#?>O?8_? G>@@a') ; yourself); yourself] ! pasteWithMaskIcon @@ -607,7 +603,7 @@ ^Icon constantNamed:#'ImageEditor class pointIcon' - ifAbsentPut:[(Depth1Image new) width: 14; height: 14; photometric:(#palette); bitsPerSample:(#(1 )); samplesPerPixel:(1); bits:(ByteArray fromPackedString:'@@@@@@@A@@@@@@@@@@@@@@@C@@@@@B@@@@@@@@@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@B@@@@@@@@@a') ; yourself); yourself] + 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] ! rectIcon @@ -693,7 +689,7 @@ label: 'HLS Edit Dialog' name: 'HLS Edit Dialog' min: (Point 10 10) - bounds: (Rectangle 14 46 326 229) + bounds: (Rectangle 0 0 312 183) ) component: (SpecCollection @@ -779,8 +775,8 @@ (LabelSpec name: 'HueColorLabel' layout: (LayoutFrame 10 0.0 109 0 -10 1.0 148 0) + backgroundChannel: hlsColor translateLabel: true - backgroundChannel: hlsColor ) (HorizontalPanelViewSpec name: 'HorizontalPanel1' @@ -1542,12 +1538,12 @@ enableChannel: imageIsLoaded model: valueOfMagnification type: numberInRange - acceptOnReturn: false - acceptOnTab: false + acceptOnReturn: true + acceptOnTab: true numChars: 2 minValue: 1 maxValue: 99 - acceptOnPointerLeave: false + acceptOnPointerLeave: true ) ) @@ -1781,7 +1777,7 @@ label: 'Next in Sequence' itemValue: nextImageInSequence translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem label: '-' @@ -1799,7 +1795,7 @@ label: 'Save As...' itemValue: doSaveMethodAs translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem activeHelpKey: fileSaveAs @@ -1857,7 +1853,7 @@ ) (MenuItem label: '-' - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem activeHelpKey: fileBrowseClass @@ -1865,24 +1861,24 @@ label: 'Browse Class' itemValue: doBrowseClass translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem label: 'Inspect Image' itemValue: doInspectImage translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem label: '-' - isVisible: notInBrowser + isVisible: isStandAlone ) (MenuItem activeHelpKey: fileExit label: 'Exit' itemValue: closeRequest translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone ) ) nil @@ -2319,7 +2315,7 @@ (MenuItem label: 'History' translateLabel: true - isVisible: notInBrowser + isVisible: isStandAlone submenuChannel: menuHistory ) (MenuItem @@ -2410,7 +2406,7 @@ itemValue: doLoadFromClass translateLabel: true isButton: true - isVisible: notInBrowser + isVisible: isStandAlone submenuChannel: menuHistory labelImage: (ResourceRetriever XPToolbarIconLibrary loadImageFromMethodIcon) keepLinkedMenu: true @@ -2422,7 +2418,7 @@ itemValue: doSaveMethodAs translateLabel: true isButton: true - isVisible: notInBrowser + isVisible: isStandAlone labelImage: (ResourceRetriever XPToolbarIconLibrary saveImageAsMethodAsIcon) ) (MenuItem @@ -2432,7 +2428,7 @@ itemValue: doSaveMethod translateLabel: true isButton: true - isVisible: onlyInBrowser + isVisible: isNotStandAlone labelImage: (ResourceRetriever XPToolbarIconLibrary saveImageAsMethodAsIcon) ) (MenuItem @@ -2772,7 +2768,7 @@ the DataSetBuilder may not be able to read the specification." " - DataSetBuilder new openOnClass:ImageEditor andSelector:#tableColumns + DataSetBuilder new openOnClass:ImageEditor andSelector:#colorTableColumns " @@ -2819,6 +2815,7 @@ selectSelector: canSelectBlueInColor: ) ) + ! ! !ImageEditor methodsFor:'accessing'! @@ -3010,16 +3007,6 @@ ^ holder ! ! -!ImageEditor methodsFor:'aspects-menu item visibility'! - -notInBrowser - ^ self masterApplication isNil -! - -onlyInBrowser - ^ self masterApplication notNil -! ! - !ImageEditor methodsFor:'change & update'! findColorMapMode @@ -3028,6 +3015,7 @@ |image listOfColors colorMapModeKey drawColor1 drawColor2 someOrAllUsedColors| image := self image. + image isNil ifTrue:[^ self ]. image mask notNil ifTrue: [ colorMapModeKey := 'masked'. @@ -3216,31 +3204,39 @@ self updateInfoLabel. - imageEditView resourceMessage asCollectionOfWords size = 2 - ifTrue: [self addToHistory: imageEditView resourceMessage -> #loadFromMessage:]. - - image fileName notNil - ifTrue: [self addToHistory: image fileName -> #loadFromFile:]. + imageEditView resourceClass notNil ifTrue:[ + imageEditView resourceSelector notNil ifTrue:[ + self addHistoryEntryForClass:imageEditView resourceClass selector:imageEditView resourceSelector. + ] + ]. + + image fileName notNil ifTrue: [ + self addHistoryEntryForFile:image fileName. + ]. ! updateListOfColorsAndColormapMode |colorMap image| image := self image. - colorMap := image colorMap. - colorMap size <= 4096 ifTrue:[ - self listOfColors contents:colorMap. - ] ifFalse:[ + image isNil ifTrue:[ self listOfColors removeAll. - colorMap isFixedPalette ifTrue:[ - image colorMap:nil. - image photometric:#rgb. - image samplesPerPixel:3. - - image bitsPerSample:(Array - with:(colorMap bitsRed) - with:(colorMap bitsGreen) - with:(colorMap bitsBlue)). + ] ifFalse:[ + colorMap := image colorMap. + colorMap size <= 4096 ifTrue:[ + self listOfColors contents:colorMap. + ] ifFalse:[ + self listOfColors removeAll. + colorMap isFixedPalette ifTrue:[ + image colorMap:nil. + image photometric:#rgb. + image samplesPerPixel:3. + + image bitsPerSample:(Array + with:(colorMap bitsRed) + with:(colorMap bitsGreen) + with:(colorMap bitsBlue)). + ]. ]. ]. self findColorMapMode. @@ -3411,26 +3407,30 @@ !ImageEditor methodsFor:'loading'! -loadFromClass:class selector:selector - "loads an image by evaluating aMessage and sets up color map list and other info labels" - - (class isNil or:[selector]) isNil ifTrue:[ - imageEditView resourceClass:class. - imageEditView resourceSelector:selector. +loadFromClass:aClass andSelector:aSelector + "loads an image from the method specified by class and selector" + + self assert:(aClass isNil or:[aClass isClass]). + + (aClass isNil or:[aSelector]) isNil ifTrue:[ + imageEditView resourceClass:aClass. + imageEditView resourceSelector:aSelector. imageEditView image:nil. ^ self. ]. - (imageEditView resourceClass == class - and:[ imageEditView resourceSelector == selector ]) ifTrue:[ + (imageEditView resourceClass == aClass + and:[ imageEditView resourceSelector == aSelector ]) ifTrue:[ imageEditView modified ifFalse:[ ^ self. ]. ]. - (imageEditView loadFromClass:class selector:selector) notNil ifTrue:[ + (imageEditView loadFromClass:aClass andSelector:aSelector) notNil ifTrue:[ self updateAfterImageChange. ] + + "Modified: / 16.3.1999 / 21:44:41 / cg" ! loadFromFile: aFileName @@ -3469,26 +3469,17 @@ "Modified: / 16.3.1999 / 21:43:56 / cg" ! -loadFromMessage: aMessage - "loads an image by evaluating aMessage and sets up color map list and other info labels" - - (imageEditView loadFromMessage: aMessage) notNil ifTrue:[ - self updateAfterImageChange. - ] - - "Modified: / 16.3.1999 / 21:44:41 / cg" -! - -loadFromOrPrepareForMessage: aMessage +loadFromOrPrepareForClass: aClass andSelector: aSelector "loads an image by evaluating aMessage; if no image could extract from aMessage; do set the class and the selector from the aMessage for a saving at the end of editing" - (imageEditView loadFromMessage: aMessage) notNil ifTrue: [ + (imageEditView loadFromClass:aClass andSelector:aSelector) notNil ifTrue: [ self updateColorsFromImage:self image. self findColorMapMode. ] ifFalse: [ - imageEditView resourceMessage: aMessage. + imageEditView resourceClass: aClass. + imageEditView resourceSelector:aSelector. ]. self updateLabelsAndHistory. @@ -3547,6 +3538,22 @@ !ImageEditor methodsFor:'private'! +checkModified + imageEditView modified value ifTrue:[ + (Dialog + confirm:(resources string:'Image was not saved. Proceed anyway ?') + yesLabel:(resources string:'Proceed') + noLabel:(resources string:'Cancel') + initialAnswer:false + ) ifFalse: [^false]. + + imageEditView clearModified. + ]. + ^ true + + "Modified: / 29.7.1998 / 18:55:24 / cg" +! + pointFromString:aString |p s x y| @@ -3601,6 +3608,10 @@ "Created: / 18.8.1998 / 17:17:38 / cg" ! +modified + ^ imageEditView modified +! + preferredExtent "returns the preferred extent" @@ -3685,6 +3696,21 @@ postBuildWith:aBuilder super postBuildWith:aBuilder. + imageEditView undoImages addDependent:self. + imageEditView imageInfoHolder:(self imageInfoHolder). + imageEditView activityInfoHolder:(self activityInfoHolder). + + imageEditView clickInfoCallBack:[:button :point | + |mouseButtonColorToolBar| + + mouseButtonColorToolBar := self componentAt:#MouseButtonColorToolBar. + (mouseButtonColorToolBar itemAt:button) toggleIndication. + mouseButtonColorToolBar do: [:i| i updateIndicators]. + ]. + + imageEditView addDependent:self. + imageEditView modifiedHolder addDependent:self. + DefaultRelativeSizes notNil ifTrue:[ (aBuilder componentAt:#horizontalPanel) relativeCorners:DefaultRelativeSizes first. (aBuilder componentAt:#verticalPanel) relativeCorners:DefaultRelativeSizes second. @@ -3695,19 +3721,6 @@ "after opening, sets the masterApplication of the imageEditView to self; evaluate the postOpenAction" - imageEditView undoImages addDependent:self. - imageEditView imageInfoHolder:(self imageInfoHolder). - imageEditView activityInfoHolder:(self activityInfoHolder). - imageEditView clickInfoCallBack:[:button :point | - |mouseButtonColorToolBar| - - mouseButtonColorToolBar := self componentAt:#MouseButtonColorToolBar. - (mouseButtonColorToolBar itemAt:button) toggleIndication. - mouseButtonColorToolBar do: [:i| i updateIndicators]. - ]. - imageEditView addDependent:self. - imageEditView modifiedHolder addDependent:self. - postOpenAction value. super postOpenWith:aBuilder. @@ -4639,7 +4652,7 @@ imageEditView brightenImage. self listOfColors removeAll. self findColorMapMode. - imageEditView undoImages removeLast + imageEditView removelastUndo ! doBrowseClass @@ -4774,7 +4787,7 @@ imageEditView darkenImage. self listOfColors removeAll. self findColorMapMode. - imageEditView undoImages removeLast + imageEditView removelastUndo ! doEditMask @@ -4892,7 +4905,7 @@ imageEditView negativeImage. self listOfColors removeAll. self findColorMapMode. - imageEditView undoImages removeLast + imageEditView removelastUndo ! doResizeImage @@ -5020,6 +5033,8 @@ |img| + self checkModified ifFalse:[ ^ self ]. + (imageEditView loadFromClass) notNil ifTrue:[ imageSeqNr := nil. (img := self image) notNil ifTrue: [ @@ -5037,6 +5052,8 @@ |img file filters| + self checkModified ifFalse:[ ^ self ]. + imageSeqNr := nil. img := self image. img notNil ifTrue: [ @@ -5065,22 +5082,24 @@ doNewImage "opens a dialog with choices of size and color map for creating a new image" - |aspects width height cMapString cMapMode cMap imageClass image szString defaultSize ext| + |dialogAspects width height cMapString cMapMode cMap imageClass image szString defaultSize ext| + + self checkModified ifFalse:[ ^ self ]. defaultSize := (self class listOfDefaultSizes includes:'32x32') ifTrue:['32x32'] ifFalse:[self class listOfDefaultSizes first]. - aspects := IdentityDictionary new + dialogAspects := IdentityDictionary new at:#listOfSizes put: self class listOfDefaultSizes asValue; at:#listOfColorMaps put: self class namesOfColorMaps values asSortedCollection asValue; at:#selectionOfSize put: (LastSizeString ? defaultSize) asValue; at:#selectionOfColorMap put: (LastColormapMode ? self class namesOfColorMaps values asSortedCollection first) asValue; yourself. - (self openDialogInterface:#dialogSpecForNewImage withBindings:aspects) + (self openDialogInterface:#dialogSpecForNewImage withBindings:dialogAspects) ifTrue:[ - szString := (aspects at:#selectionOfSize) value. + szString := (dialogAspects at:#selectionOfSize) value. ext := self pointFromString:szString. ext isNil ifTrue:[ width := height := 32 @@ -5091,7 +5110,7 @@ "/ width := "128 min: "(Integer readFromString: (szString upTo: $x) onError:[32]). "/ height := "128 min: " (Integer readFromString: (szString copy reverse upTo: $x) reverse onError:[32]). - cMapString := (aspects at:#selectionOfColorMap) value. + cMapString := (dialogAspects at:#selectionOfColorMap) value. cMapMode := self class namesOfColorMaps keyAtEqualValue:cMapString. cMap := self class listOfColorMaps at:cMapMode. imageClass := Image implementorForDepth:(cMap size highBit-1). @@ -5116,10 +5135,12 @@ doNewImageFromClipboard |image| + self checkModified ifFalse:[ ^ self ]. + image := imageEditView clipBoard. - - (imageEditView image:image) notNil - ifTrue:[ + imageEditView image:image. + + image notNil ifTrue:[ self updateColorsFromImage:image. self findColorMapMode. self updateLabelsAndHistory. @@ -5129,6 +5150,8 @@ grabScreenImage "let user choose an area and grab that are for editing" + self checkModified ifFalse:[ ^ self ]. + Processor addTimedBlock:[ |image d8image img| @@ -5259,11 +5282,9 @@ ! doSaveMethod - "saves current image on current class and selector" - - imageEditView saveMethod notNil - ifTrue: - [ + "saves the image in current class and selector" + + imageEditView saveMethod ifTrue:[ self updateLabelsAndHistory ] ! @@ -5271,9 +5292,7 @@ doSaveMethodAs "opens a dialog for saving current image on a class and a selector" - imageEditView saveMethodAs notNil - ifTrue: - [ + imageEditView saveMethodAs ifTrue:[ self updateLabelsAndHistory ] ! @@ -5286,6 +5305,12 @@ img := imageEditView image. TextBox openOn:img storeString +! + +save + "saves current image on current class and selector" + + self doSaveMethod ! ! !ImageEditor methodsFor:'user actions-settings'!