author | tz |
Tue, 07 Apr 1998 00:50:20 +0200 | |
changeset 839 | c77a86a62ac2 |
parent 827 | 155b4ed10c7c |
child 840 | 93f209fc0f7a |
permissions | -rw-r--r-- |
636 | 1 |
" |
704 | 2 |
COPYRIGHT (c) 1997 by eXept Software AG |
636 | 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 |
||
1 | 13 |
ImageView subclass:#ImageEditView |
686 | 14 |
instanceVariableNames:'magnification selectColors imageReaderClass resourceClass |
694 | 15 |
resourceSelector mouseKeyColorMode undoImage modified |
737 | 16 |
masterApplication editMode' |
17 |
classVariableNames:'Clipboard GridMagnification' |
|
161 | 18 |
poolDictionaries:'' |
19 |
category:'Views-Misc' |
|
1 | 20 |
! |
21 |
||
636 | 22 |
!ImageEditView class methodsFor:'documentation'! |
23 |
||
24 |
copyright |
|
25 |
" |
|
704 | 26 |
COPYRIGHT (c) 1997 by eXept Software AG |
636 | 27 |
All Rights Reserved |
28 |
||
29 |
This software is furnished under a license and may be used |
|
30 |
only in accordance with the terms of that license and with the |
|
31 |
inclusion of the above copyright notice. This software may not |
|
32 |
be provided or otherwise made available to, or used by, any |
|
33 |
other person. No title to or ownership of the software is |
|
34 |
hereby transferred. |
|
35 |
" |
|
36 |
! |
|
37 |
||
38 |
documentation |
|
39 |
" |
|
40 |
The ImageEditView is a view class which can be used by applications |
|
41 |
like the Image Editor for modifying or inspecting images. |
|
42 |
||
43 |
[see also:] |
|
44 |
ImageEditor Image |
|
45 |
||
46 |
[author:] |
|
47 |
Thomas Zwick |
|
48 |
" |
|
49 |
! ! |
|
353 | 50 |
|
7 | 51 |
!ImageEditView methodsFor:'accessing'! |
52 |
||
624 | 53 |
magnification |
54 |
||
55 |
^magnification |
|
56 |
||
255 | 57 |
! |
58 |
||
636 | 59 |
magnification: aPoint |
255 | 60 |
|
627 | 61 |
magnification ~= aPoint |
624 | 62 |
ifTrue: |
63 |
[ |
|
627 | 64 |
magnification := aPoint asPoint. |
624 | 65 |
self scrollToTopLeft. |
66 |
self contentsChanged. |
|
686 | 67 |
self invalidate |
68 |
] |
|
624 | 69 |
! |
255 | 70 |
|
662 | 71 |
masterApplication |
72 |
||
73 |
^masterApplication |
|
74 |
! |
|
75 |
||
76 |
masterApplication: anApplicationModel |
|
77 |
||
78 |
masterApplication := anApplicationModel |
|
79 |
! |
|
80 |
||
627 | 81 |
resourceClass |
82 |
||
83 |
^resourceClass |
|
84 |
! |
|
85 |
||
86 |
resourceClass: aClassOrSymbol |
|
87 |
||
686 | 88 |
resourceClass := aClassOrSymbol isClass ifTrue: [aClassOrSymbol name] ifFalse: [aClassOrSymbol asSymbol] |
627 | 89 |
! |
90 |
||
91 |
resourceMessage |
|
92 |
||
93 |
^resourceClass, ' ', resourceSelector |
|
94 |
! |
|
95 |
||
636 | 96 |
resourceMessage: aString |
627 | 97 |
|
636 | 98 |
(aString isString and: [aString trimBlanks size > 0]) |
627 | 99 |
ifTrue: |
100 |
[ |
|
636 | 101 |
resourceClass := (aString readStream upTo: Character space) asSymbol. |
686 | 102 |
resourceSelector := (aString copy reverse readStream upTo: Character space) reverse asSymbol |
627 | 103 |
] |
104 |
ifFalse: |
|
105 |
[ |
|
106 |
^nil |
|
686 | 107 |
] |
627 | 108 |
|
109 |
||
110 |
! |
|
111 |
||
112 |
resourceSelector |
|
113 |
||
114 |
^resourceSelector |
|
115 |
! |
|
116 |
||
117 |
resourceSelector: aStringOrSymbol |
|
118 |
||
119 |
resourceSelector := aStringOrSymbol asSymbol |
|
120 |
! |
|
121 |
||
633 | 122 |
selectColor: anArrayTwoColors |
123 |
||
124 |
selectColors := anArrayTwoColors |
|
125 |
! |
|
126 |
||
627 | 127 |
selectedColor |
128 |
||
633 | 129 |
^selectColors at: mouseKeyColorMode |
627 | 130 |
! |
131 |
||
132 |
selectedColor: aColor |
|
133 |
||
134 |
selectColors at: mouseKeyColorMode put: aColor |
|
135 |
! ! |
|
136 |
||
137 |
!ImageEditView methodsFor:'drawing'! |
|
138 |
||
662 | 139 |
fillFramedRectangle: aRectangle |
140 |
||
141 |
self fillRectangle: aRectangle. |
|
142 |
self drawFramesIn: aRectangle |
|
143 |
! |
|
144 |
||
627 | 145 |
redrawImageX:x y:y width:w height:h |
636 | 146 |
|
662 | 147 |
|ih iw magX magY minX maxX minY maxY color lastColor lastY runW x0 xI yI maskColor sizeOfMaskPoint| |
627 | 148 |
|
149 |
ih := image height. |
|
150 |
iw := image width. |
|
662 | 151 |
magX := magnification x. |
152 |
magY := magnification y. |
|
627 | 153 |
|
662 | 154 |
minX := (x // magX - 1) max: 0. |
725 | 155 |
minX >= iw ifTrue:[minX := (iw - 1) max: 0]. |
662 | 156 |
minY := (y // magY - 1) max: 0. |
725 | 157 |
minY >= ih ifTrue:[minY := (ih - 1) max: 0]. |
662 | 158 |
maxX := (x + w) // magX + 1. |
627 | 159 |
maxX > iw ifTrue:[maxX := iw]. |
662 | 160 |
maxY := (y + h) // magY + 1. |
627 | 161 |
maxY > ih ifTrue:[maxY := ih]. |
162 |
||
163 |
lastY := -1. |
|
164 |
||
165 |
x0 := minX. |
|
166 |
runW := 0. |
|
167 |
maskColor := false. |
|
662 | 168 |
sizeOfMaskPoint := magnification//3. |
169 |
image colorsFromX: minX y: minY toX: maxX-1 y: maxY-1 do: |
|
627 | 170 |
[:xx :yy :color| |
633 | 171 |
yy ~~ lastY |
172 |
ifTrue: |
|
627 | 173 |
[ |
633 | 174 |
runW ~~ 0 |
175 |
ifTrue: |
|
627 | 176 |
[ |
177 |
|origin| |
|
662 | 178 |
origin := (x0 * magX + margin)@(lastY * magY + margin). |
179 |
self fillFramedRectangle: (origin extent: (runW@magY)). |
|
627 | 180 |
maskColor ifTrue: |
181 |
[ |
|
662 | 182 |
self xoring: [self fillRectangle: (origin + sizeOfMaskPoint extent: sizeOfMaskPoint)] |
627 | 183 |
]. |
184 |
runW := 0. |
|
185 |
]. |
|
186 |
x0 := xx. |
|
187 |
lastY := yy. |
|
188 |
]. |
|
624 | 189 |
|
662 | 190 |
color ~~ lastColor |
633 | 191 |
ifTrue: |
627 | 192 |
[ |
633 | 193 |
runW ~~ 0 |
194 |
ifTrue: |
|
627 | 195 |
[ |
196 |
|origin| |
|
662 | 197 |
origin := (x0 * magX + margin)@(yy * magY + margin). |
198 |
self fillFramedRectangle: (origin extent: (runW@magY)). |
|
627 | 199 |
maskColor ifTrue: |
200 |
[ |
|
662 | 201 |
self xoring: [self fillRectangle: (origin + sizeOfMaskPoint extent: sizeOfMaskPoint)] |
627 | 202 |
]. |
203 |
runW := 0. |
|
204 |
]. |
|
205 |
||
662 | 206 |
self paint: (lastColor := color). |
627 | 207 |
image mask notNil ifTrue: |
208 |
[ |
|
209 |
maskColor := false. |
|
210 |
(image mask colorAt: xx@yy) = Color black ifTrue: |
|
211 |
[ |
|
662 | 212 |
self paint: (lastColor := self viewBackground). |
627 | 213 |
maskColor := true. |
214 |
]. |
|
662 | 215 |
lastColor := nil. |
627 | 216 |
]. |
217 |
runW := 0. |
|
218 |
x0 := xx. |
|
219 |
]. |
|
662 | 220 |
runW := runW + magX |
627 | 221 |
]. |
222 |
runW ~~ 0 ifTrue: |
|
223 |
[ |
|
224 |
|origin| |
|
662 | 225 |
origin := (x0 * magX + margin)@(lastY * magY + margin). |
226 |
self fillFramedRectangle: (origin extent: runW@magY). |
|
627 | 227 |
maskColor ifTrue: |
228 |
[ |
|
662 | 229 |
self xoring: [self fillRectangle: (origin + sizeOfMaskPoint extent: sizeOfMaskPoint)] |
627 | 230 |
]. |
231 |
runW := 0. |
|
232 |
]. |
|
233 |
! |
|
234 |
||
235 |
redrawX:x y:y width:w height:h |
|
636 | 236 |
|
627 | 237 |
|ih iw xI yI| |
238 |
||
662 | 239 |
magnification = (1@1) ifTrue: [^super redrawX:x y:y width:w height:h]. |
240 |
||
627 | 241 |
image isNil ifTrue:[^self]. |
242 |
||
662 | 243 |
self clippingRectangle: (x@y extent: w@h). |
627 | 244 |
|
245 |
self redrawImageX:x y:y width:w height:h. |
|
246 |
||
247 |
"/ right of image ? |
|
248 |
adjust == #center ifTrue: |
|
249 |
[ |
|
633 | 250 |
xI := (width - ih) // 2 - margin. |
251 |
yI := (height - iw) // 2 - margin. |
|
627 | 252 |
] |
253 |
ifFalse: |
|
254 |
[ |
|
255 |
xI := yI := margin |
|
256 |
]. |
|
257 |
(x + w - 1) > (xI + (magnification x * image width)) ifTrue: |
|
258 |
[ |
|
259 |
self clearRectangleX:(xI + (magnification x * image width)) |
|
260 |
y:y |
|
261 |
width:(x + w - (magnification x * image width) - xI) |
|
262 |
height:h |
|
263 |
]. |
|
264 |
(y + h - 1) > (yI + (magnification y * image height)) ifTrue: |
|
265 |
[ |
|
266 |
self clearRectangleX:margin |
|
267 |
y:(yI + (magnification y * image height)) |
|
268 |
width:w |
|
269 |
height:(y + h - (magnification y * image height) - yI) |
|
270 |
]. |
|
271 |
self drawFrame. |
|
272 |
self clippingRectangle: nil. |
|
273 |
! ! |
|
274 |
||
275 |
!ImageEditView methodsFor:'edit modes'! |
|
276 |
||
277 |
editMode |
|
278 |
||
737 | 279 |
^editMode ? (editMode := 'point') |
627 | 280 |
! |
281 |
||
282 |
editMode:aMode |
|
283 |
||
737 | 284 |
editMode := aMode |
627 | 285 |
! |
286 |
||
287 |
mouseKeyColorMode |
|
288 |
||
289 |
^mouseKeyColorMode printString |
|
290 |
! |
|
291 |
||
292 |
mouseKeyColorMode:aMode |
|
293 |
||
294 |
mouseKeyColorMode := aMode asInteger |
|
295 |
! ! |
|
296 |
||
297 |
!ImageEditView methodsFor:'event handling'! |
|
298 |
||
299 |
buttonMotion:state x:x y:y |
|
300 |
||
632 | 301 |
self drawCursorAt: x@y. |
686 | 302 |
state ~~ 0 |
303 |
ifTrue: |
|
304 |
[ |
|
737 | 305 |
self selectedColor notNil & image notNil & (self imageContainsPoint: x@y) & (editMode = 'point') |
686 | 306 |
ifTrue: [^self pointAt: x@y] |
307 |
] |
|
624 | 308 |
! |
255 | 309 |
|
627 | 310 |
buttonPress:button x:x y:y |
311 |
||
632 | 312 |
self drawCursorAt: x@y. |
627 | 313 |
self selectedColor notNil & image notNil & (self imageContainsPoint: x@y) |
314 |
ifTrue: |
|
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
315 |
[ |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
316 |
|mouseButtonColorToolBar| |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
317 |
mouseKeyColorMode := button. |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
318 |
mouseButtonColorToolBar := masterApplication builder componentAt: #MouseButtonColorToolBar. |
627 | 319 |
undoImage := image copy. |
724 | 320 |
masterApplication valueOfCanUndo value: true. |
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
321 |
(mouseButtonColorToolBar itemAt: mouseKeyColorMode) toggleIndication. |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
322 |
mouseButtonColorToolBar do: [:i| i updateIndicators]. |
737 | 323 |
self perform: (editMode, 'At:') asSymbol with: x@y |
686 | 324 |
] |
632 | 325 |
! |
326 |
||
686 | 327 |
pointerLeave:state |
328 |
||
688 | 329 |
super pointerLeave: state. |
686 | 330 |
|
783 | 331 |
self drawLabel: self imageInfoString. |
686 | 332 |
Cursor normal show |
627 | 333 |
! ! |
334 |
||
636 | 335 |
!ImageEditView methodsFor:'image editing'! |
627 | 336 |
|
337 |
boxAt: aPoint |
|
338 |
||
662 | 339 |
|choosedBox imageBox| |
636 | 340 |
choosedBox := self drawRectangleStartingAt: aPoint emphasis: #box. |
662 | 341 |
image rectangle: (imageBox := choosedBox origin//magnification extent: (choosedBox extent//magnification)) withColor: self selectedColor. |
632 | 342 |
image restored. |
662 | 343 |
self redraw: (choosedBox expandedBy: 1). |
724 | 344 |
masterApplication imagePreView redraw: (imageBox expandedBy: 1). |
676 | 345 |
modified := true |
632 | 346 |
! |
347 |
||
348 |
copyAt: aPoint |
|
349 |
||
350 |
|choosedBox| |
|
636 | 351 |
choosedBox := self drawRectangleStartingAt: aPoint emphasis: #inverseFilledBox. |
632 | 352 |
Clipboard := image subImageIn: (choosedBox origin//magnification extent: (choosedBox extent//magnification)). |
662 | 353 |
self redraw: (choosedBox expandedBy: 1) |
632 | 354 |
|
355 |
! |
|
356 |
||
357 |
fillAt: aPoint |
|
627 | 358 |
|
632 | 359 |
Cursor execute showWhile: |
360 |
[ |
|
361 |
|filledPoints| |
|
362 |
filledPoints := image floodFillAt: aPoint//magnification withColor: self selectedColor. |
|
363 |
image restored. |
|
633 | 364 |
filledPoints size < 300 |
632 | 365 |
ifTrue: |
366 |
[ |
|
662 | 367 |
filledPoints do: [:p| self redraw: ((p * magnification extent: magnification) expandedBy: 1)] |
632 | 368 |
] |
369 |
ifFalse: |
|
370 |
[ |
|
371 |
self invalidate |
|
372 |
]. |
|
724 | 373 |
masterApplication imagePreView invalidate. |
632 | 374 |
modified := true |
375 |
] |
|
376 |
! |
|
377 |
||
378 |
filledBoxAt: aPoint |
|
379 |
||
662 | 380 |
|choosedBox imageBox| |
636 | 381 |
choosedBox := self drawRectangleStartingAt: aPoint emphasis: #filledBox. |
662 | 382 |
image fillRectangle: (imageBox := choosedBox origin//magnification extent: (choosedBox extent//magnification)) withColor: self selectedColor. |
632 | 383 |
image restored. |
662 | 384 |
self redraw: (choosedBox expandedBy: 1). |
724 | 385 |
masterApplication imagePreView redraw: (imageBox expandedBy: 1). |
686 | 386 |
modified := true |
632 | 387 |
! |
388 |
||
636 | 389 |
flipHorizontal |
390 |
||
725 | 391 |
self image: image copy flipHorizontal |
636 | 392 |
|
393 |
! |
|
394 |
||
395 |
flipVertical |
|
396 |
||
725 | 397 |
self image: image copy flipVertical |
636 | 398 |
|
399 |
! |
|
400 |
||
401 |
magnifyImage |
|
402 |
||
403 |
|box newSize| |
|
404 |
box := EnterBox new. |
|
405 |
box title:'Image new size:'. |
|
406 |
box okText:'OK'. |
|
407 |
box abortText:'Cancel'. |
|
408 |
box initialText:image extent printString. |
|
409 |
box showAtPointer. |
|
410 |
(box accepted and: [(newSize := Object readFromString: box contents onError:nil) notNil]) |
|
411 |
ifTrue: |
|
412 |
[ |
|
413 |
self image: (image magnifiedBy: newSize/image extent) |
|
686 | 414 |
] |
636 | 415 |
! |
416 |
||
417 |
negativeImage |
|
418 |
||
725 | 419 |
self image: image copy negative |
636 | 420 |
|
421 |
! |
|
422 |
||
423 |
pasteAt: aPoint |
|
424 |
||
425 |
Object errorSignal handle: |
|
426 |
[:ex| |
|
427 |
self warn: 'Pasting at selected point failed!!' |
|
428 |
] |
|
429 |
do: |
|
430 |
[ |
|
662 | 431 |
|imagePoint imageBox| |
636 | 432 |
imagePoint := aPoint//magnification. |
433 |
image copyFrom: Clipboard x:0 y:0 toX: imagePoint x y: imagePoint y width: Clipboard width height: Clipboard height. |
|
434 |
image restored. |
|
662 | 435 |
self redraw: (imageBox := (imagePoint * magnification extent: (Clipboard extent * magnification)) expandedBy: 1@1). |
724 | 436 |
masterApplication imagePreView redraw: (imageBox expandedBy: 1). |
676 | 437 |
modified := true |
636 | 438 |
] |
439 |
! |
|
440 |
||
441 |
pointAt: aPoint |
|
442 |
||
662 | 443 |
|imagePoint imageBox| |
636 | 444 |
imagePoint := aPoint//magnification. |
445 |
image atImageAndMask: imagePoint put: self selectedColor. |
|
446 |
image restored. |
|
662 | 447 |
self redraw: (imageBox := (imagePoint * magnification extent: magnification) expandedBy: 1). |
796 | 448 |
masterApplication imagePreView redraw: ((imagePoint - 1) extent: 3@3). |
449 |
modified := true. |
|
450 |
||
636 | 451 |
! |
452 |
||
453 |
resizeImage |
|
454 |
||
455 |
|box newSize| |
|
456 |
box := EnterBox new. |
|
457 |
box title:'Image new size:'. |
|
458 |
box okText:'OK'. |
|
459 |
box abortText:'Cancel'. |
|
460 |
box initialText:image extent printString. |
|
461 |
box showAtPointer. |
|
462 |
(box accepted and: [(newSize := Object readFromString: box contents onError:nil) notNil]) |
|
463 |
ifTrue: |
|
464 |
[ |
|
465 |
|newImage| |
|
466 |
newImage := image class width: newSize x height: newSize y depth: image depth. |
|
467 |
newImage photometric:image photometric. |
|
468 |
newImage colorMap:image colorMap copy. |
|
469 |
newImage bits: (ByteArray new: newImage bytesPerRow * newSize y). |
|
470 |
||
471 |
image mask notNil |
|
472 |
ifTrue: |
|
473 |
[ |
|
474 |
|newMaskImage| |
|
475 |
newMaskImage := Depth1Image width: newSize x height: newSize y. |
|
476 |
newMaskImage photometric: image mask photometric. |
|
477 |
newMaskImage colorMap: image mask colorMap copy. |
|
478 |
newMaskImage bits:(ByteArray new: newMaskImage bytesPerRow * newSize y). |
|
479 |
newImage mask: newMaskImage |
|
480 |
]. |
|
481 |
||
482 |
newImage copyFrom:image x:0 y:0 toX:0 y:0 width: (image width min:newSize x) height: (image height min:newSize y). |
|
827 | 483 |
self image: newImage. |
686 | 484 |
] |
636 | 485 |
! |
486 |
||
487 |
rotateImage |
|
488 |
||
489 |
|box rotation| |
|
490 |
box := EnterBox new. |
|
491 |
box title:'Image new rotation:'. |
|
492 |
box okText:'OK'. |
|
493 |
box abortText:'Cancel'. |
|
494 |
box initialText: '0'. |
|
495 |
box showAtPointer. |
|
496 |
(box accepted and: [(rotation := Object readFromString: box contents onError:nil) notNil]) |
|
497 |
ifTrue: |
|
498 |
[ Object errorSignal handle: |
|
499 |
[:ex| |
|
500 |
self warn: 'Image rotation failed.\' withCRs, 'An increase of image depth could help.'. |
|
501 |
] |
|
502 |
do: |
|
503 |
[ |
|
504 |
self image: (image hardRotated: rotation) |
|
505 |
] |
|
686 | 506 |
] |
636 | 507 |
! |
508 |
||
509 |
undo |
|
510 |
||
511 |
undoImage notNil |
|
512 |
ifTrue: |
|
725 | 513 |
[ |
636 | 514 |
modified := false. |
515 |
self image: undoImage. |
|
839 | 516 |
masterApplication findColorMapMode. |
724 | 517 |
masterApplication valueOfCanUndo value: false. |
636 | 518 |
self invalidate |
519 |
] |
|
520 |
! ! |
|
521 |
||
522 |
!ImageEditView methodsFor:'image emphasis'! |
|
523 |
||
524 |
drawCursorAt: aPoint |
|
525 |
||
783 | 526 |
image isNil ifTrue: [self drawLabel: self imageInfoString. ^Cursor stop show]. |
636 | 527 |
((0@0 extent: image extent * magnification) containsPoint: aPoint) |
783 | 528 |
ifFalse:[self drawLabel: self imageInfoString. Cursor stop show] |
693 | 529 |
ifTrue: [self drawLabel: (aPoint//magnification + 1) printString.Cursor crossHair show]. |
688 | 530 |
|
531 |
! |
|
532 |
||
533 |
drawCursorAt: aPoint withLabel: aLabel |
|
534 |
||
535 |
((0@0 extent: image extent * magnification) containsPoint: aPoint) |
|
536 |
ifFalse:[Cursor stop show] |
|
694 | 537 |
ifTrue: [Cursor crossHair show]. |
538 |
self drawLabel: aLabel. |
|
636 | 539 |
! |
540 |
||
541 |
drawFrame |
|
542 |
||
543 |
self paint:Color black. |
|
544 |
self lineWidth: (magnification x//3 min: 3). |
|
545 |
self displayRectangle: ((0@0) extent:(image extent * magnification) + 2). |
|
546 |
self lineWidth:1. |
|
547 |
! |
|
548 |
||
662 | 549 |
drawFramesIn: aRectangle |
636 | 550 |
|
686 | 551 |
magnification > GridMagnification |
636 | 552 |
ifTrue: |
553 |
[ |
|
662 | 554 |
|origin lineStartingPoint lineEndingPoint oldColor| |
555 |
origin := aRectangle origin - 1. |
|
556 |
lineStartingPoint := origin + (0@magnification y). |
|
557 |
lineEndingPoint := lineStartingPoint + (aRectangle width@0). |
|
636 | 558 |
oldColor := self paint. |
559 |
self xoring: |
|
560 |
[ |
|
662 | 561 |
self displayLineFrom: lineStartingPoint to: lineEndingPoint. |
562 |
lineStartingPoint x to: lineStartingPoint x + aRectangle width - magnification x by: magnification x do: |
|
563 |
[:x| |
|
564 |
self displayLineFrom: x@(origin y) to: x@(origin y + magnification y) |
|
565 |
]. |
|
636 | 566 |
]. |
567 |
self paint: oldColor. |
|
568 |
] |
|
662 | 569 |
|
570 |
||
571 |
||
636 | 572 |
! |
573 |
||
574 |
drawLabel: aLabel |
|
575 |
||
686 | 576 |
(masterApplication respondsTo: #coordLabel) |
636 | 577 |
ifTrue: |
688 | 578 |
[ |
579 |
masterApplication coordLabel label ~= aLabel |
|
580 |
ifTrue: |
|
693 | 581 |
[ |
688 | 582 |
masterApplication coordLabel label: aLabel printString. |
583 |
masterApplication coordLabel redraw |
|
584 |
] |
|
636 | 585 |
] |
586 |
! |
|
587 |
||
588 |
drawRectangleStartingAt: aPoint emphasis: emphasis |
|
632 | 589 |
|
688 | 590 |
|currentPoint currentExtent firstPoint lastCurrentPoint gridCorrection p whichQuarter| |
632 | 591 |
firstPoint := currentPoint := lastCurrentPoint := aPoint//magnification*magnification. |
686 | 592 |
magnification > GridMagnification ifFalse: [gridCorrection := 0] ifTrue: [gridCorrection := 1]. |
593 |
[device anyButtonPressed] |
|
627 | 594 |
whileTrue: |
595 |
[ |
|
632 | 596 |
currentPoint := (0@0) max: (image extent * magnification min: (p := self translation negated + (device translatePoint: self sensor mousePoint from:device rootView id to:self id))). |
627 | 597 |
currentPoint := currentPoint//magnification*magnification. |
598 |
currentExtent := (firstPoint - currentPoint) abs. |
|
688 | 599 |
whichQuarter := (firstPoint x - currentPoint x) > 0 |
600 |
ifTrue: [(firstPoint y - currentPoint y) > 0 ifTrue: ["4"1@1] ifFalse: ["3"1@0]] |
|
601 |
ifFalse: [(firstPoint y - currentPoint y) > 0 ifTrue: ["1"0@1] ifFalse: ["2"0@0]]. |
|
602 |
||
747 | 603 |
self drawCursorAt: p withLabel: |
604 |
((firstPoint//magnification - whichQuarter + 1) printString, |
|
605 |
' to: ', |
|
606 |
(currentPoint//magnification + whichQuarter) printString), |
|
607 |
' (extent: ', |
|
608 |
(currentExtent//magnification) printString, ')'. |
|
632 | 609 |
|
627 | 610 |
currentPoint ~= lastCurrentPoint ifTrue: |
632 | 611 |
[ |
612 |
emphasis = #inverseFilledBox |
|
627 | 613 |
ifTrue: |
614 |
[ |
|
662 | 615 |
self redraw: ((firstPoint min: lastCurrentPoint) - 1 extent: (firstPoint - lastCurrentPoint) abs + 2). |
633 | 616 |
self xoring: [self fillRectangle: ((firstPoint min: currentPoint) + 1 extent: currentExtent - gridCorrection)] |
627 | 617 |
]. |
632 | 618 |
emphasis = #box |
627 | 619 |
ifTrue: |
620 |
[ |
|
662 | 621 |
|origin extent lineWidthY lineWidthX| |
622 |
origin := (firstPoint min: lastCurrentPoint) - 1. |
|
623 |
extent := (firstPoint - lastCurrentPoint) abs + 2. |
|
624 |
lineWidthY := extent y min: (magnification y + 2). |
|
625 |
lineWidthX := extent x min: (magnification x + 2). |
|
626 |
self redraw: (origin extent: (extent x@lineWidthY)). |
|
627 |
self redraw: ((origin x@(origin y + extent y - lineWidthY)) extent: (extent x@lineWidthY)). |
|
628 |
self redraw: ((origin x@(origin y + lineWidthY)) extent: (lineWidthX@(0 max: (extent y - (lineWidthY * 2))))). |
|
629 |
self redraw: (((origin x + extent x - lineWidthX)@(origin y + lineWidthY)) extent: (lineWidthX@(extent y - (lineWidthY * 2)))). |
|
627 | 630 |
self selectedColor ~= Color noColor |
631 |
ifTrue: [self paint: self selectedColor] |
|
632 |
ifFalse: [self paint: self viewBackground]. |
|
662 | 633 |
origin := (firstPoint min: currentPoint) + 1. |
634 |
extent := currentExtent - gridCorrection. |
|
635 |
lineWidthY := extent y min: magnification y. |
|
636 |
lineWidthX := extent x min: magnification x. |
|
637 |
(lineWidthY > 0) & (lineWidthX > 0) |
|
638 |
ifTrue: |
|
639 |
[ |
|
640 |
self fillRectangle: (origin extent: (extent x@lineWidthY)). |
|
641 |
self fillRectangle: ((origin x@(origin y + extent y - lineWidthY)) extent: (extent x@lineWidthY)). |
|
642 |
self fillRectangle: ((origin x@(origin y + lineWidthY)) extent: (lineWidthX@(0 max: (extent y - (lineWidthY * 2))))). |
|
643 |
self fillRectangle: (((origin x + extent x - lineWidthX)@(origin y + lineWidthY)) extent: (lineWidthX@(extent y - (lineWidthY * 2)))). |
|
644 |
] |
|
632 | 645 |
]. |
646 |
emphasis = #filledBox |
|
647 |
ifTrue: |
|
648 |
[ |
|
662 | 649 |
self redraw: ((firstPoint min: lastCurrentPoint) - 1 extent: (firstPoint - lastCurrentPoint) abs + 2). |
632 | 650 |
self selectedColor ~= Color noColor |
651 |
ifTrue: [self paint: self selectedColor] |
|
652 |
ifFalse: [self paint: self viewBackground]. |
|
633 | 653 |
self fillRectangle: ((firstPoint min: currentPoint) + 1 extent: currentExtent - gridCorrection). |
632 | 654 |
]. |
627 | 655 |
]. |
656 |
lastCurrentPoint := currentPoint. |
|
657 |
]. |
|
662 | 658 |
|
694 | 659 |
^((0@0) max: (firstPoint min: currentPoint)) extent: (firstPoint - currentPoint) abs |
627 | 660 |
! ! |
661 |
||
662 |
!ImageEditView methodsFor:'image setting'! |
|
663 |
||
664 |
image:anImage |
|
665 |
||
688 | 666 |
anImage isImage |
627 | 667 |
ifTrue: |
725 | 668 |
[ |
688 | 669 |
(image isNil or: [self checkModified]) |
670 |
ifTrue: |
|
671 |
[ |
|
827 | 672 |
|fileName| |
725 | 673 |
undoImage := image. |
796 | 674 |
masterApplication notNil |
675 |
ifTrue: |
|
676 |
[ |
|
677 |
undoImage notNil ifTrue: [masterApplication valueOfCanUndo value: true]. |
|
678 |
masterApplication imagePreView image: anImage |
|
679 |
]. |
|
827 | 680 |
image notNil |
681 |
ifTrue: |
|
682 |
[ |
|
683 |
fileName := image fileName. |
|
684 |
anImage fileName isNil ifTrue: [anImage fileName: fileName]. |
|
685 |
]. |
|
688 | 686 |
super image: anImage. |
687 |
^self |
|
688 |
]. |
|
689 |
^nil |
|
674 | 690 |
] |
691 |
ifFalse: |
|
692 |
[ |
|
693 |
super image: nil. |
|
694 |
^nil |
|
695 |
] |
|
627 | 696 |
! |
697 |
||
698 |
loadFromFile: aFileName |
|
624 | 699 |
|
676 | 700 |
aFileName isNil ifTrue: [^nil]. |
624 | 701 |
Object errorSignal handle: |
702 |
[:exeption| |
|
674 | 703 |
modified := false. |
632 | 704 |
self warn: exeption errorString. |
624 | 705 |
^nil |
706 |
] |
|
707 |
do: |
|
676 | 708 |
[ |
709 |
|imageFromFile| |
|
710 |
(imageFromFile := Image fromFile: aFileName) notNil |
|
632 | 711 |
ifTrue: |
712 |
[ |
|
676 | 713 |
self image: imageFromFile. |
632 | 714 |
imageReaderClass := ImageReader allSubclasses |
715 |
detect: [:cls| cls isValidImageFile: aFileName] |
|
716 |
ifNone: [self error: 'Unknown image file format!!'] |
|
717 |
] |
|
718 |
ifFalse: |
|
719 |
[ |
|
720 |
self error: 'Image on file not found!!' |
|
721 |
] |
|
676 | 722 |
] |
624 | 723 |
! |
255 | 724 |
|
633 | 725 |
loadFromMessage: aMessage |
726 |
||
727 |
(self resourceMessage: aMessage) isNil |
|
728 |
ifTrue: |
|
729 |
[ |
|
730 |
^nil |
|
731 |
]. |
|
624 | 732 |
|
633 | 733 |
^self loadfromClass: resourceClass andSelector: resourceSelector |
734 |
||
735 |
||
736 |
! |
|
737 |
||
738 |
loadfromClass: aClassOrSymbol andSelector: aStringOrSymbol |
|
739 |
||
678 | 740 |
|aClass| |
741 |
||
627 | 742 |
imageReaderClass := nil. |
743 |
self resourceClass: aClassOrSymbol. |
|
744 |
self resourceSelector: aStringOrSymbol. |
|
678 | 745 |
|
746 |
((aClass := Smalltalk at: resourceClass) isClass and: |
|
747 |
[aClass class implements: resourceSelector]) |
|
624 | 748 |
ifTrue: |
749 |
[ |
|
627 | 750 |
^self image: (aClass perform: resourceSelector) copy |
674 | 751 |
] |
752 |
ifFalse: |
|
753 |
[ |
|
754 |
modified := false. |
|
755 |
^nil |
|
756 |
] |
|
757 |
||
161 | 758 |
! ! |
759 |
||
1 | 760 |
!ImageEditView methodsFor:'initialization'! |
761 |
||
161 | 762 |
initialize |
624 | 763 |
|
161 | 764 |
super initialize. |
627 | 765 |
|
686 | 766 |
self enableMotionEvents. |
767 |
GridMagnification := GridMagnification ? (8@8). |
|
783 | 768 |
magnification := GridMagnification + 2. |
627 | 769 |
modified := false. |
770 |
mouseKeyColorMode := 1. |
|
771 |
resourceClass := resourceSelector := ''. |
|
772 |
selectColors := Array with: nil with: nil. |
|
1 | 773 |
! ! |
774 |
||
636 | 775 |
!ImageEditView methodsFor:'printing & storing'! |
1 | 776 |
|
724 | 777 |
loadFromClass |
404 | 778 |
|
676 | 779 |
^self loadFromMessage: |
636 | 780 |
(ResourceSelectionBrowser |
662 | 781 |
request: 'Load Image From Class' |
724 | 782 |
onSuperclass: nil |
636 | 783 |
andClass: self resourceClass |
784 |
andSelector: self resourceSelector |
|
785 |
withResourceTypes: #(image fileImage)) |
|
786 |
||
477 | 787 |
|
161 | 788 |
! |
789 |
||
627 | 790 |
|
624 | 791 |
|
686 | 792 |
image notNil |
793 |
ifTrue: |
|
636 | 794 |
[ |
686 | 795 |
|stream| |
796 |
Printer supportsPostscript ifFalse: |
|
797 |
[ |
|
798 |
^self warn:'No postscript printer detected!!' |
|
799 |
]. |
|
800 |
stream := Printer newNative. |
|
801 |
stream isNil ifTrue: |
|
802 |
[ |
|
803 |
^self warn:'Cannot open printer stream!!' |
|
804 |
]. |
|
805 |
self withWaitCursorDo: |
|
806 |
[ |
|
807 |
|psgc| |
|
823 | 808 |
psgc := PSGraphicsContext on:stream. |
686 | 809 |
psgc displayForm: (image magnifiedBy: magnification) x:0 y:0. |
810 |
psgc close |
|
811 |
] |
|
398
7b7255a4db0d
show a wait cursor while printing
Claus Gittinger <cg@exept.de>
parents:
362
diff
changeset
|
812 |
] |
624 | 813 |
! |
814 |
||
815 |
save |
|
816 |
||
632 | 817 |
self saveImageOrMask: #image. |
818 |
||
624 | 819 |
! |
820 |
||
297 | 821 |
saveAs |
822 |
||
627 | 823 |
self saveImageFileAs |
297 | 824 |
! |
825 |
||
627 | 826 |
saveImageFileAs |
827 |
||
633 | 828 |
self saveImageFileAs: |
829 |
(FileSelectionBrowser |
|
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
830 |
request: 'Save Image To File' |
827 | 831 |
fileName: self image fileName |
832 |
withFileFilters: FileSelectionBrowser saveImageFileNameFilters) |
|
627 | 833 |
! |
297 | 834 |
|
627 | 835 |
saveImageFileAs: aFileName |
297 | 836 |
|
633 | 837 |
aFileName isNil ifTrue: [^nil]. |
636 | 838 |
image notNil |
627 | 839 |
ifTrue: |
840 |
[ |
|
841 |
image fileName: aFileName. |
|
632 | 842 |
self saveImageOrMask: #image |
843 |
] |
|
844 |
ifFalse: |
|
845 |
[ |
|
633 | 846 |
self warn: 'No image or file name for saving detected!!' |
632 | 847 |
] |
848 |
! |
|
849 |
||
850 |
saveImageMaskFileAs |
|
851 |
||
633 | 852 |
self saveImageMaskFileAs: |
636 | 853 |
(FileSelectionBrowser |
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
854 |
request: 'Save Image Mask To File' |
827 | 855 |
fileName: self image fileName |
856 |
withFileFilters: FileSelectionBrowser saveImageFileNameFilters) |
|
632 | 857 |
! |
858 |
||
859 |
saveImageMaskFileAs: aFileName |
|
860 |
||
633 | 861 |
aFileName isNil ifTrue: [^nil]. |
632 | 862 |
(image notNil and: [image mask notNil]) |
863 |
ifTrue: |
|
864 |
[ |
|
865 |
image mask fileName: aFileName. |
|
866 |
self saveImageOrMask: #mask |
|
627 | 867 |
] |
868 |
ifFalse: |
|
869 |
[ |
|
632 | 870 |
self warn: 'No image or image mask detected!!' |
627 | 871 |
] |
628 | 872 |
! |
873 |
||
632 | 874 |
saveImageOrMask: what |
628 | 875 |
|
632 | 876 |
Object errorSignal handle: |
877 |
[:ex| |
|
878 |
self warn: ex errorString. |
|
879 |
^nil |
|
880 |
] |
|
881 |
do: |
|
882 |
[ |
|
883 |
|fileName| |
|
884 |
image isNil ifTrue: [^self error: 'No image to save!!']. |
|
885 |
what = #image |
|
886 |
ifTrue: |
|
887 |
[ |
|
888 |
image fileName isNil ifTrue: [^self error: 'No file name for image detected!!']. |
|
889 |
fileName := image fileName asFilename |
|
890 |
]. |
|
891 |
what = #mask |
|
892 |
ifTrue: |
|
893 |
[ |
|
894 |
image mask isNil ifTrue: [^self error: 'No image mask to save!!']. |
|
895 |
image mask fileName isNil ifTrue: [^self error: 'No file name for image mask detected!!']. |
|
896 |
fileName := image mask fileName asFilename |
|
897 |
]. |
|
678 | 898 |
fileName name size = 0 ifTrue: [^self error: 'No file name detected!!']. |
632 | 899 |
(fileName suffix = 'tiff') | (fileName suffix = 'tif') ifTrue: [imageReaderClass := TIFFReader]. |
900 |
fileName suffix = 'xpm' ifTrue: [imageReaderClass := XPMReader]. |
|
901 |
fileName suffix = 'xbm' ifTrue: [imageReaderClass := XBMReader]. |
|
678 | 902 |
fileName suffix = 'gif' ifTrue: [imageReaderClass := GIFReader]. |
632 | 903 |
(fileName suffix = 'jpg') | (fileName suffix = 'jpeg') ifTrue: [imageReaderClass := JPEGReader]. |
904 |
imageReaderClass isNil ifTrue: [imageReaderClass := XPMReader. image fileName: image fileName, '.xpm']. |
|
905 |
what = #image ifTrue: [image saveOn: image fileName using: imageReaderClass. modified := false]. |
|
906 |
what = #mask ifTrue: [image mask saveOn: image mask fileName using: imageReaderClass]. |
|
678 | 907 |
] |
632 | 908 |
|
909 |
||
633 | 910 |
! |
911 |
||
912 |
saveMethod |
|
913 |
||
914 |
Object errorSignal handle: |
|
915 |
[:ex| |
|
916 |
self warn: ex errorString. |
|
917 |
^nil |
|
918 |
] |
|
919 |
do: |
|
920 |
[ |
|
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
921 |
|category imageStoreStream cls sel mthd imageKey| |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
922 |
|
633 | 923 |
(self resourceSelector trimBlanks size = 0) | (cls := Smalltalk at: self resourceClass) isClass not |
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
924 |
ifTrue: [^self saveMethodAs]. |
690 | 925 |
|
633 | 926 |
self image storeOn: (imageStoreStream := WriteStream on: ''). |
690 | 927 |
sel := self resourceSelector. |
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
928 |
|
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
929 |
"/ if that method already exists, do not overwrite the category |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
930 |
category := 'image specs'. |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
931 |
(mthd := cls class compiledMethodAt:sel) notNil ifTrue:[ |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
932 |
category := mthd category. |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
933 |
]. |
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
934 |
|
690 | 935 |
imageKey := (cls name, ' ', sel) asSymbol. |
936 |
Icon constantNamed: imageKey put:nil. |
|
633 | 937 |
ByteCodeCompiler |
823 | 938 |
compile: ((sel, |
939 |
'\', (ResourceSpecEditor codeGenerationCommentForClass: ImageEditor), |
|
940 |
'\\' , |
|
941 |
' "\', |
|
942 |
' ImageEditor openOnClass:self andSelector:#', self resourceSelector, |
|
943 |
'\ "', |
|
944 |
'\\', |
|
945 |
' <resource: #image>', |
|
946 |
'\\', |
|
947 |
' ^Icon\') withCRs, |
|
948 |
' constantNamed:#''', imageKey, '''\' withCRs, |
|
949 |
' ifAbsentPut:[', imageStoreStream contents, ']') |
|
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
950 |
forClass: cls class inCategory: category. |
633 | 951 |
modified := false. |
952 |
] |
|
953 |
! |
|
954 |
||
955 |
saveMethodAs |
|
956 |
||
636 | 957 |
(self resourceMessage: |
958 |
(ResourceSelectionBrowser |
|
822
cace81f0a86b
do not overwrite method categories + toggle between mouse button colors
tz
parents:
796
diff
changeset
|
959 |
request: 'Save Image In Class' |
693 | 960 |
onSuperclass: #Object |
636 | 961 |
andClass: self resourceClass |
962 |
andSelector: self resourceSelector |
|
963 |
withResourceTypes: #(image fileImage))) notNil |
|
633 | 964 |
ifTrue: |
674 | 965 |
[ |
633 | 966 |
^self saveMethod |
674 | 967 |
]. |
633 | 968 |
^nil |
1 | 969 |
! ! |
970 |
||
161 | 971 |
!ImageEditView methodsFor:'queries'! |
5 | 972 |
|
161 | 973 |
heightOfContents |
974 |
||
686 | 975 |
image isNil ifTrue:[^0]. |
976 |
^(image height * magnification y) rounded |
|
5 | 977 |
! |
978 |
||
627 | 979 |
imageContainsPoint: aPoint |
632 | 980 |
|
981 |
^image notNil and: |
|
982 |
[((0@0 corner:(image extent) - 1) containsPoint: (((aPoint - margin + 1) / magnification) floor))] |
|
627 | 983 |
! |
984 |
||
783 | 985 |
imageInfoString |
986 |
||
987 |
|imageInfoString usedColors| |
|
988 |
image isNil ifTrue: [imageInfoString := 'No image loaded.'] ifFalse: [ |
|
989 |
image colorMap isNil ifTrue: [usedColors := '?'] ifFalse: [usedColors := image usedColors size]. |
|
990 |
imageInfoString := image width printString, 'x', |
|
991 |
image height printString, 'x', |
|
992 |
(2 raisedTo: image depth) printString, |
|
993 |
(image mask notNil ifTrue: [' (mask + '] ifFalse: ['(']), |
|
994 |
usedColors printString, |
|
995 |
' used colors)']. |
|
996 |
||
997 |
^imageInfoString |
|
998 |
! |
|
999 |
||
161 | 1000 |
widthOfContents |
5 | 1001 |
|
686 | 1002 |
image isNil ifTrue:[^0]. |
1003 |
^(image width * magnification x) rounded |
|
5 | 1004 |
! ! |
1005 |
||
627 | 1006 |
!ImageEditView methodsFor:'release'! |
1007 |
||
1008 |
destroy |
|
1009 |
||
686 | 1010 |
Clipboard := undoImage := nil. |
1011 |
||
1012 |
super destroy |
|
627 | 1013 |
|
1014 |
! ! |
|
1015 |
||
632 | 1016 |
!ImageEditView methodsFor:'testing'! |
1017 |
||
1018 |
checkModified |
|
1019 |
||
1020 |
modified |
|
1021 |
ifTrue: |
|
1022 |
[ |
|
1023 |
((YesNoBox title:'Image was modified!!') |
|
1024 |
noText:'Cancel'; |
|
1025 |
yesText:'Waste it and proceed'; |
|
1026 |
showAtPointer; |
|
1027 |
accepted) ifFalse: [^false]. |
|
1028 |
modified := false |
|
1029 |
]. |
|
1030 |
^true |
|
1031 |
! ! |
|
1032 |
||
255 | 1033 |
!ImageEditView class methodsFor:'documentation'! |
161 | 1034 |
|
1035 |
version |
|
839 | 1036 |
^ '$Header: /cvs/stx/stx/libwidg2/ImageEditView.st,v 1.74 1998-04-06 22:50:20 tz Exp $' |
161 | 1037 |
! ! |