# HG changeset patch # User Claus Gittinger # Date 1487342125 -3600 # Node ID 86d2e0cd49701c6bb7f2f665ec453a046acce7c0 # Parent 2e0024e012e92c94cc86831e021cff0629760926 #FEATURE by cg class: ImageEditor improved flood fill; needed to auto-fill uninteresting areas in guiBrowser. added: #cropBoxIsNotDialog #floodFillMaxHueError #floodFillMaxLightError changed: #cropDialogSpec #doCropManual #helpPairs #selectedColorsChanged diff -r 2e0024e012e9 -r 86d2e0cd4970 ImageEditor.st --- a/ImageEditor.st Fri Feb 17 14:29:17 2017 +0100 +++ b/ImageEditor.st Fri Feb 17 15:35:25 2017 +0100 @@ -280,70 +280,13 @@ the UIHelpTool may not be able to read the specification." " - UIHelpTool openOnClass:ImageEditor + UIHelpTool openOnClass:ImageEditor " ^ #( -#xdrawModeBox -'Rectangle' - -#xdrawModeCopy -'Copy' - -#xdrawModeFill -'Flood-fill' - -#xdrawModeFilledBox -'Filled rectangle' - -#xdrawModePaste -'Paste' - -#xdrawModePasteUnder -'Paste under' - -#xdrawModePasteWithMask -'Paste with Mask' - -#xdrawModePoint -'Point' - -#xfileGrabImage -'Pick from screen' - -#xfileLoadFromClass -'Load from method...' - -#xfileLoadFromFile -'Load from file...' - -#xfileNewImage -'New image' - -#filePrint -'Print' - -#xfileSaveAs -'Save to file...' - -#xfileSaveMaskAs -'Save mask to file...' - -#xfileSaveMethod -'Save as method' - -#xfileSaveMethodAs -'Save as Method...' - -#nextImageInSequence -'Go to the next image in the animated gif image sequence.' - -#previousImageInSequence -'Go to the previous image in the animated gif image sequence.' - #colorMap 'ColorMap functions' @@ -416,6 +359,15 @@ #drawModeFilledBox 'Filled Rectangle Drawing Mode' +#drawModeFilledCircle +'Filled Circle Drawing Mode' + +#drawModeMaskOutsideCircle +'Mask everything outside a Circle' + +#drawModeMaskOutsideRectangle +'Mask everything outside a Rectangle' + #drawModePaste 'Paste Mode' @@ -434,6 +386,9 @@ #drawModeSpray 'Spray Drawing Mode' +#edit3DProjection +'Generate a 3D projection' + #editFlipHorizontal 'Flip the image horizontally' @@ -452,6 +407,9 @@ #editRotate 'Rotate the image' +#fileEditMask +'Load Mask from a File' + #fileGrabImageFromScreen 'Pick an image from the screen (specify area)' @@ -477,6 +435,9 @@ 'Paste the image in the clipboard as a mask. Must be a depth-1 image' #filePrint +'Print' + +#filePrint 'Print the image on a postscript printer' #fileSave @@ -497,42 +458,11 @@ #fileSaveMethodAs 'Save the image as resource method in a class' -#magnificationNumber -'Shows the current magnification' - -#magnifyImageDown -'Decrease magnification' - -#magnifyImageUp -'Increase magnification' - -#mouseKeyColorMode -'Toggle between left and right mouse button color' - -#previewView -'Shows a preview of the image' - -#settingsGridMagnification -'Change the grid magnification of the edit view' - - - - -#drawModeFilledCircle -'Filled Circle Drawing Mode' - -#drawModeMaskOutsideCircle -'Mask everything outside a Circle' - -#drawModeMaskOutsideRectangle -'Mask everything outside a Rectangle' - -#edit3DProjection -'Generate a 3D projection' - -#fileEditMask -'Load Mask from a File' - +#floodFillMaxError +'Specify the max. allowed deviation from the clicked pixel in a flood-fill operation.\Pixels where the hue/light values differ less than that fraction\will be included in the fill.\The range must be between 0 and 1. With 0, only areas with exactly the same pixel will be filled.\With 1, every other pixel is included.\\When filling gradiented areas, start with small values, such as 0.05, and increase slowly.' + +#gropAll +'Crop (cut off) all four sides by the amounts entered into the above fields.' #gropBottom 'Cut off the specified number of pixels at the bottom' @@ -546,10 +476,81 @@ #gropTop 'Cut off the specified number of pixels at the top' +#magnificationNumber +'Shows the current magnification' + +#magnifyImageDown +'Decrease magnification' + +#magnifyImageUp +'Increase magnification' + +#mouseKeyColorMode +'Toggle between left and right mouse button color' + +#nextImageInSequence +'Go to the next image in the animated gif image sequence.' + +#previewView +'Shows a preview of the image' + +#previousImageInSequence +'Go to the previous image in the animated gif image sequence.' + +#settingsGridMagnification +'Change the grid magnification of the edit view' + +#xdrawModeBox +'Rectangle' + +#xdrawModeCopy +'Copy' + +#xdrawModeFill +'Flood-fill' + +#xdrawModeFilledBox +'Filled rectangle' + +#xdrawModePaste +'Paste' + +#xdrawModePasteUnder +'Paste under' + +#xdrawModePasteWithMask +'Paste with Mask' + +#xdrawModePoint +'Point' + +#xfileGrabImage +'Pick from screen' + +#xfileLoadFromClass +'Load from method...' + +#xfileLoadFromFile +'Load from file...' + +#xfileNewImage +'New image' + +#xfileSaveAs +'Save to file...' + +#xfileSaveMaskAs +'Save mask to file...' + +#xfileSaveMethod +'Save as method' + +#xfileSaveMethodAs +'Save as Method...' ) - "Created: / 16-02-2017 / 12:29:54 / cg" + "Modified: / 17-02-2017 / 15:32:45 / cg" ! helpSpec @@ -1462,7 +1463,7 @@ label: 'Crop Border(s)' name: 'Crop Border(s)' min: (Point 10 10) - bounds: (Rectangle 0 0 343 225) + bounds: (Rectangle 0 0 364 312) ) component: (SpecCollection @@ -1587,6 +1588,17 @@ autoRepeat: true usePreferredWidth: true ) + (ActionButtonSpec + label: 'Crop All' + name: 'Button4' + layout: (LayoutFrame 133 0 148 0 237 0 176 0) + activeHelpKey: gropAll + visibilityChannel: cropBoxIsNotDialog + translateLabel: true + resizeForLabel: true + tabable: true + model: applyCropAction + ) (HorizontalPanelViewSpec name: 'HorizontalPanel1' layout: (LayoutFrame 0 0.0 -30 1 -16 1.0 0 1) @@ -1602,12 +1614,11 @@ (ActionButtonSpec label: 'Cancel' name: 'Button1' - visibilityChannel: cropBoxIsDialog translateLabel: true resizeForLabel: true tabable: true model: cancel - extent: (Point 103 28) + extent: (Point 110 28) ) (ActionButtonSpec label: 'Apply' @@ -1615,24 +1626,72 @@ translateLabel: true resizeForLabel: true tabable: true - model: applyAction - extent: (Point 104 28) + model: applyCropAction + extent: (Point 111 28) ) (ActionButtonSpec label: 'OK' name: 'Button2' - visibilityChannel: cropBoxIsDialog translateLabel: true resizeForLabel: true tabable: true model: accept - extent: (Point 104 28) + extent: (Point 111 28) ) ) ) keepSpaceForOSXResizeHandleH: true ) + (LabelSpec + label: 'Floodfill Tolerance:' + name: 'Label1' + layout: (LayoutFrame 14 0 192 0 242 0 214 0) + activeHelpKey: floodFillMaxError + visibilityChannel: cropBoxIsNotDialog + translateLabel: true + adjust: left + ) + (LabelSpec + label: 'Hue:' + name: 'Label2' + layout: (LayoutFrame 51 0 220 0 127 0 242 0) + activeHelpKey: floodFillMaxError + visibilityChannel: cropBoxIsNotDialog + translateLabel: true + adjust: left + ) + (InputFieldSpec + name: 'EntryField2' + layout: (LayoutFrame 132 0 220 0 190 0 242 0) + activeHelpKey: floodFillMaxError + visibilityChannel: cropBoxIsNotDialog + tabable: true + model: floodFillMaxHueError + type: number + acceptChannel: acceptChannel + acceptOnPointerLeave: true + ) + (LabelSpec + label: 'Light:' + name: 'Label3' + layout: (LayoutFrame 51 0 246 0 127 0 268 0) + activeHelpKey: floodFillMaxError + visibilityChannel: cropBoxIsNotDialog + translateLabel: true + adjust: left + ) + (InputFieldSpec + name: 'EntryField3' + layout: (LayoutFrame 132 0 246 0 190 0 268 0) + activeHelpKey: floodFillMaxError + visibilityChannel: cropBoxIsNotDialog + tabable: true + model: floodFillMaxLightError + type: number + acceptChannel: acceptChannel + acceptOnPointerLeave: true + ) ) ) @@ -3973,6 +4032,12 @@ "Created: / 03-02-2017 / 11:23:50 / cg" ! +cropBoxIsNotDialog + ^ self cropBoxIsDialog not + + "Created: / 17-02-2017 / 14:38:04 / cg" +! + cropBoxVisibleHolder |holder| @@ -3984,6 +4049,30 @@ "Created: / 03-02-2017 / 11:20:13 / cg" ! +floodFillMaxHueError + |holder| + + (holder := builder bindingAt:#floodFillMaxHueError) isNil ifTrue:[ + builder aspectAt:#floodFillMaxHueError put:(holder := 0 asValue). + holder onChangeEvaluate:[ imageEditView floodFillMaxHueError:holder value ]. + ]. + ^ holder + + "Created: / 17-02-2017 / 15:19:17 / cg" +! + +floodFillMaxLightError + |holder| + + (holder := builder bindingAt:#floodFillMaxLightError) isNil ifTrue:[ + builder aspectAt:#floodFillMaxLightError put:(holder := 0 asValue). + holder onChangeEvaluate:[ imageEditView floodFillMaxLightError:holder value ]. + ]. + ^ holder + + "Created: / 17-02-2017 / 15:19:11 / cg" +! + hasClassAndSelectorDefinedHolder ^ [ |cls| @@ -4356,19 +4445,15 @@ ! selectedColorsChanged - |colorIndices| - - (colorIndices := self selectedColors value) isEmptyOrNil ifTrue:[ - self selectionOfColor value:nil - ] ifFalse:[ - colorIndices size == 1 ifTrue:[ - "/ as single color selected - self selectionOfColor value:colorIndices first - ] ifFalse:[ - "/ multipl selected - self selectionOfColor value:nil - ]. - ]. + |colorIndices selectedIndex| + + (colorIndices := self selectedColors value) size == 1 ifTrue:[ + "/ a single color selected + selectedIndex := colorIndices first + ]. + self selectionOfColor value:selectedIndex + + "Modified: / 17-02-2017 / 14:40:33 / cg" ! update:something with:aParameter from:changedObject @@ -6821,7 +6906,7 @@ bindings at:#gropTopNow put:[ gropAction value:0 value:0 value:top value:0 ]. bindings at:#gropBottomNow put:[ gropAction value:0 value:0 value:0 value:bottom ]. - bindings at:#applyAction put:[ gropAction value:left value:right value:top value:bottom ]. + bindings at:#applyCropAction put:[ gropAction value:left value:right value:top value:bottom ]. (self openDialogInterface:#cropDialogSpec withBindings:bindings) ifFalse:[ @@ -6832,7 +6917,7 @@ ]. "Created: / 07-09-1998 / 18:16:07 / cg" - "Modified: / 16-02-2017 / 01:33:36 / cg" + "Modified: / 17-02-2017 / 14:33:19 / cg" ! doCropRight