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