|
1 " |
|
2 COPYRIGHT (c) 1997 by Claus Gittinger / eXept Software AG |
|
3 All Rights Reserved |
|
4 |
|
5 This software is furnished under a license and may be used |
|
6 only in accordance with the terms of that license and with the |
|
7 inclusion of the above copyright notice. This software may not |
|
8 be provided or otherwise made available to, or used by, any |
|
9 other person. No title to or ownership of the software is |
|
10 hereby transferred. |
|
11 " |
|
12 |
|
13 |
|
14 |
|
15 NoteBookView subclass:#UIGalleryView |
|
16 instanceVariableNames:'majorKey minorKeys minorKeysHolder' |
|
17 classVariableNames:'' |
|
18 poolDictionaries:'' |
|
19 category:'Interface-UIPainter' |
|
20 ! |
|
21 |
|
22 View subclass:#Canvas |
|
23 instanceVariableNames:'dragMode clientSpecHolder inputView selection specification |
|
24 lastClickPoint menuSelector raiseMenuSelector uiBuilder' |
|
25 classVariableNames:'' |
|
26 poolDictionaries:'' |
|
27 privateIn:UIGalleryView |
|
28 ! |
|
29 |
|
30 DropObject subclass:#DropSpec |
|
31 instanceVariableNames:'' |
|
32 classVariableNames:'' |
|
33 poolDictionaries:'' |
|
34 privateIn:UIGalleryView::Canvas |
|
35 ! |
|
36 |
|
37 !UIGalleryView class methodsFor:'documentation'! |
|
38 |
|
39 copyright |
|
40 " |
|
41 COPYRIGHT (c) 1997 by Claus Gittinger / eXept Software AG |
|
42 All Rights Reserved |
|
43 |
|
44 This software is furnished under a license and may be used |
|
45 only in accordance with the terms of that license and with the |
|
46 inclusion of the above copyright notice. This software may not |
|
47 be provided or otherwise made available to, or used by, any |
|
48 other person. No title to or ownership of the software is |
|
49 hereby transferred. |
|
50 " |
|
51 |
|
52 |
|
53 ! |
|
54 |
|
55 documentation |
|
56 " |
|
57 implements a selection panel, keeping widgets which could be placed |
|
58 into other components by drag & drop or copy @ paste. The objects |
|
59 which are draged/droped must be kind of UISpecification's. |
|
60 The UISelectionPanel used by the UIPainter is implemented in this way. |
|
61 |
|
62 [author:] |
|
63 Claus Gittinger |
|
64 Claus Atzkern |
|
65 |
|
66 [see also:] |
|
67 UIPainter |
|
68 UISelectionPanel |
|
69 " |
|
70 |
|
71 ! |
|
72 |
|
73 examples |
|
74 " |
|
75 opens a gallery |
|
76 |
|
77 [exBegin] |
|
78 |top sel| |
|
79 |
|
80 top := StandardSystemView new label:'gallery'; extent:500@300. |
|
81 sel := UIGalleryView origin:0.0 @ 0.0 corner:1.0 @ 1.0 in:top. |
|
82 |
|
83 sel labels:#( 'Buttons' |
|
84 'Panels' |
|
85 'Text' |
|
86 ). |
|
87 |
|
88 sel minorKeys:#( #standartButtonToggle |
|
89 #standartPanels |
|
90 #standartText |
|
91 ). |
|
92 |
|
93 sel majorKey:UISelectionPanel. |
|
94 top open. |
|
95 [exEnd] |
|
96 " |
|
97 ! ! |
|
98 |
|
99 !UIGalleryView methodsFor:'accessing'! |
|
100 |
|
101 builder |
|
102 "get the builder used to setup a window from a specification (or nil in case |
|
103 of using a new builder) |
|
104 " |
|
105 ^ canvas builder |
|
106 ! |
|
107 |
|
108 builder:aBuilderOrNil |
|
109 "set the builder used to setup a window from a specification (or nil in case |
|
110 of using a new builder) |
|
111 " |
|
112 canvas builder:aBuilderOrNil |
|
113 ! |
|
114 |
|
115 canvas:aCanvas |
|
116 ^ self |
|
117 |
|
118 ! |
|
119 |
|
120 labels:listOfLabels minorKeys:listOfMinorKeys majorKey:aMajorKey |
|
121 "setup for labels, selectors and class provider |
|
122 " |
|
123 self labels:listOfLabels. |
|
124 minorKeys := listOfMinorKeys. |
|
125 majorKey := aMajorKey. |
|
126 ! |
|
127 |
|
128 majorKey |
|
129 "get the class providing the window specifications |
|
130 " |
|
131 ^ majorKey |
|
132 ! |
|
133 |
|
134 majorKey:aKey |
|
135 "get the class providing the window specifications |
|
136 " |
|
137 (majorKey := aKey) notNil ifTrue:[ |
|
138 aKey isBehavior ifFalse:[ |
|
139 majorKey := Smalltalk at:aKey asSymbol |
|
140 ] |
|
141 ]. |
|
142 self selection:nil |
|
143 ! |
|
144 |
|
145 minorKeys |
|
146 "get the list of selector keys |
|
147 " |
|
148 ^ minorKeys |
|
149 ! |
|
150 |
|
151 minorKeys:aListOfSelectors |
|
152 "set the list of selectors |
|
153 " |
|
154 minorKeys := aListOfSelectors. |
|
155 tabRaw selection:nil. |
|
156 ! ! |
|
157 |
|
158 !UIGalleryView methodsFor:'accessing holders'! |
|
159 |
|
160 clientSpecHolder |
|
161 "get the holder which keeps the current selection or in case of |
|
162 no selection the specification under the cursor |
|
163 " |
|
164 ^ canvas clientSpecHolder |
|
165 ! |
|
166 |
|
167 clientSpecHolder:aHolder |
|
168 "set the holder which keeps the current selection or in case of |
|
169 no selection the specification under the cursor |
|
170 " |
|
171 canvas clientSpecHolder:aHolder |
|
172 ! |
|
173 |
|
174 menuSelector |
|
175 ^ canvas menuSelector |
|
176 ! |
|
177 |
|
178 menuSelector:aSelector |
|
179 ^ canvas menuSelector:aSelector |
|
180 ! |
|
181 |
|
182 minorKeysHolder |
|
183 "get the holder keeping the minor keys; the selectors to access |
|
184 specifications from a class associated with the majorKey. |
|
185 " |
|
186 ^ minorKeysHolder |
|
187 ! |
|
188 |
|
189 minorKeysHolder:aValueHolder |
|
190 "set the holder keeping the minor keys; the selectors to access |
|
191 specifications from a class associated with the majorKey. |
|
192 " |
|
193 minorKeysHolder notNil ifTrue:[ |
|
194 minorKeysHolder removeDependent:self. |
|
195 ]. |
|
196 |
|
197 (minorKeysHolder := aValueHolder) notNil ifTrue:[ |
|
198 minorKeysHolder addDependent:self. |
|
199 ]. |
|
200 self minorKeys:(minorKeysHolder value) |
|
201 ! ! |
|
202 |
|
203 !UIGalleryView methodsFor:'change & update'! |
|
204 |
|
205 selectionChangedTo:something |
|
206 "selection changed |
|
207 " |
|
208 |specification selector selection application| |
|
209 |
|
210 selection := tabRaw listIndexOf:something. |
|
211 |
|
212 (selection notNil and:[minorKeys size >= selection]) ifTrue:[ |
|
213 selector := minorKeys at:selection. |
|
214 |
|
215 (majorKey respondsTo:selector) ifTrue:[ |
|
216 specification := majorKey perform:selector |
|
217 ] ifFalse:[ |
|
218 (application := self application) notNil ifTrue:[ |
|
219 Object messageNotUnderstoodSignal handle:[:ex| |
|
220 (application class respondsTo:selector) ifTrue:[ |
|
221 specification := application class perform:selector |
|
222 ] |
|
223 ] do:[ |
|
224 specification := application aspectFor:selector |
|
225 ] |
|
226 ] |
|
227 ] |
|
228 ]. |
|
229 canvas specification:specification. |
|
230 |
|
231 ! |
|
232 |
|
233 update |
|
234 self selectionChangedTo:(tabRaw selection). |
|
235 ! |
|
236 |
|
237 update:something with:aParameter from:changedObject |
|
238 "one of my models changed its value |
|
239 " |
|
240 changedObject == minorKeysHolder ifTrue:[ |
|
241 ^ self minorKeys:( minorKeysHolder value) |
|
242 ]. |
|
243 super update:something with:aParameter from:changedObject. |
|
244 |
|
245 ! ! |
|
246 |
|
247 !UIGalleryView methodsFor:'initialization'! |
|
248 |
|
249 destroy |
|
250 minorKeysHolder notNil ifTrue:[ |
|
251 minorKeysHolder removeDependent:self. |
|
252 minorKeysHolder := nil. |
|
253 ]. |
|
254 super destroy. |
|
255 ! |
|
256 |
|
257 initialize |
|
258 "setup default attributes |
|
259 " |
|
260 canvas := Canvas. |
|
261 |
|
262 super initialize. |
|
263 tabRaw action:[:something| self selectionChangedTo:something ]. |
|
264 |
|
265 ! ! |
|
266 |
|
267 !UIGalleryView::Canvas methodsFor:'accessing'! |
|
268 |
|
269 builder |
|
270 "get the builder used to setup a window from a specification (or nil in case |
|
271 of using a new builder) |
|
272 " |
|
273 ^ uiBuilder |
|
274 ! |
|
275 |
|
276 builder:something |
|
277 "set the builder used to setup a window from a specification (or nil in case |
|
278 of using a new builder) |
|
279 " |
|
280 uiBuilder := something. |
|
281 ! |
|
282 |
|
283 clientSpecHolder |
|
284 "get the holder which keeps the current selection or in case of |
|
285 no selection the specification under the cursor |
|
286 " |
|
287 ^ clientSpecHolder |
|
288 ! |
|
289 |
|
290 clientSpecHolder:aHolder |
|
291 "set the holder which keeps the current selection or in case of |
|
292 no selection the specification under the cursor |
|
293 " |
|
294 (clientSpecHolder := aHolder) notNil ifTrue:[ |
|
295 clientSpecHolder value:selection |
|
296 ]. |
|
297 ! |
|
298 |
|
299 menuSelector |
|
300 "return the value of the instance variable 'menuSelector' (automatically generated)" |
|
301 |
|
302 ^ menuSelector! |
|
303 |
|
304 menuSelector:something |
|
305 "set the value of the instance variable 'menuSelector' (automatically generated)" |
|
306 |
|
307 menuSelector := something.! |
|
308 |
|
309 specification |
|
310 "get current specification |
|
311 " |
|
312 ^ specification |
|
313 |
|
314 |
|
315 ! |
|
316 |
|
317 specification:aSpecOrSpecArray |
|
318 "set a new specification |
|
319 " |
|
320 |builder| |
|
321 |
|
322 self selection:nil. |
|
323 |
|
324 self subViews copy do:[:aSubView| |
|
325 aSubView ~~ inputView ifTrue:[ |
|
326 aSubView destroy |
|
327 ] |
|
328 ]. |
|
329 |
|
330 aSpecOrSpecArray notNil ifTrue:[ |
|
331 specification := UISpecification from:aSpecOrSpecArray. |
|
332 builder := uiBuilder ? UIBuilder new. |
|
333 specification buildViewFor:builder in:self. |
|
334 |
|
335 subViews do:[:v| |
|
336 (v ~~ inputView and:[(self findSpecFor:v) notNil]) ifTrue:[ |
|
337 v borderWidth:1. |
|
338 ] |
|
339 ]. |
|
340 self shown ifTrue:[ |
|
341 self realizeAllSubViews. |
|
342 inputView raise |
|
343 ] |
|
344 ] ifFalse:[ |
|
345 specification := nil |
|
346 ] |
|
347 |
|
348 |
|
349 |
|
350 ! ! |
|
351 |
|
352 !UIGalleryView::Canvas methodsFor:'building'! |
|
353 |
|
354 buildSpecFrom:aSpec |
|
355 "build spec out of spec |
|
356 " |
|
357 |spec comp coll| |
|
358 |
|
359 (aSpec notNil and:[aSpec canUIDrag]) ifFalse:[ |
|
360 ^ nil |
|
361 ]. |
|
362 |
|
363 spec := aSpec copy. |
|
364 |
|
365 (aSpec class supportsSubComponents and:[aSpec component notNil]) ifFalse:[ |
|
366 ^ spec |
|
367 ]. |
|
368 comp := aSpec component. |
|
369 spec component:nil. |
|
370 |
|
371 comp canUIDrag ifFalse:[ |
|
372 ^ spec |
|
373 ]. |
|
374 coll := OrderedCollection new. |
|
375 |
|
376 comp do:[:anEntry||spc| |
|
377 (spc := self buildSpecFrom:anEntry) notNil ifTrue:[ |
|
378 coll add:spc |
|
379 ] |
|
380 ]. |
|
381 coll isEmpty ifTrue:[ |
|
382 ^ spec |
|
383 ]. |
|
384 comp := comp copy. |
|
385 comp collection:coll. |
|
386 spec component:comp. |
|
387 ^ spec |
|
388 |
|
389 |
|
390 |
|
391 |
|
392 ! ! |
|
393 |
|
394 !UIGalleryView::Canvas methodsFor:'drag & drop'! |
|
395 |
|
396 startDrag |
|
397 "start drag of selection |
|
398 " |
|
399 |dragObj spec name| |
|
400 |
|
401 spec := self findSpecFor:selection. |
|
402 |
|
403 spec notNil ifTrue:[ |
|
404 spec := self buildSpecFrom:spec. |
|
405 name := spec className asString. |
|
406 name := name copyFrom:1 to:(name size - ('Spec' size) + 1). |
|
407 name at:1 put:(name at:1) asLowercase. |
|
408 name at:(name size) put:$1. |
|
409 spec name:name. |
|
410 |
|
411 self showUnselected. |
|
412 dragObj := DropSpec for:selection specification:spec. |
|
413 self showSelected. |
|
414 DragAndDropManager startDrag:dragObj from:inputView. |
|
415 ] |
|
416 |
|
417 ! ! |
|
418 |
|
419 !UIGalleryView::Canvas methodsFor:'event handling'! |
|
420 |
|
421 buttonMotion:state x:x y:y |
|
422 "start a drag on selection |
|
423 " |
|
424 |sensor| |
|
425 |
|
426 (lastClickPoint notNil and:[selection notNil]) ifTrue:[ |
|
427 sensor := self sensor. |
|
428 sensor anyButtonPressed ifTrue:[ |
|
429 (lastClickPoint dist:(x@y)) > 10.0 ifTrue:[ |
|
430 ^ self startDrag |
|
431 ] |
|
432 ] |
|
433 ] |
|
434 |
|
435 |
|
436 ! |
|
437 |
|
438 buttonPress:button x:x y:y |
|
439 "change selection |
|
440 " |
|
441 |application| |
|
442 |
|
443 button == 1 ifTrue:[ |
|
444 lastClickPoint := Point x:x y:y. |
|
445 self selection:(self findObjectAtX:x y:y). |
|
446 ] ifFalse:[ |
|
447 lastClickPoint := nil. |
|
448 |
|
449 (menuSelector notNil and:[(application := self application) notNil]) ifTrue:[ |
|
450 Object messageNotUnderstoodSignal handle:[:ex| |
|
451 ] do:[ |
|
452 application aspectFor:menuSelector |
|
453 ] |
|
454 ] |
|
455 ] |
|
456 |
|
457 ! |
|
458 |
|
459 exposeX:x y:y width:w height:h |
|
460 "handle an expose event from device; redraw selection |
|
461 " |
|
462 super exposeX:x y:y width:w height:h. |
|
463 |
|
464 (selection notNil and:[self sensor hasExposeEventFor:selection]) ifFalse:[ |
|
465 self showSelected. |
|
466 ]. |
|
467 |
|
468 |
|
469 ! ! |
|
470 |
|
471 !UIGalleryView::Canvas methodsFor:'initialization'! |
|
472 |
|
473 initialize |
|
474 super initialize. |
|
475 |
|
476 inputView := InputView origin:0.0@0.0 extent:1.0@1.0 in:self. |
|
477 inputView eventReceiver:self. |
|
478 inputView enableButtonEvents. |
|
479 inputView enableButtonMotionEvents. |
|
480 inputView enableMotionEvents. |
|
481 |
|
482 |
|
483 ! ! |
|
484 |
|
485 !UIGalleryView::Canvas methodsFor:'searching'! |
|
486 |
|
487 findObjectAtX:x y:y |
|
488 "find the origin/corner of the currentWidget |
|
489 " |
|
490 |point id p e| |
|
491 |
|
492 point := Point x:x y:y. |
|
493 id := inputView id. |
|
494 |
|
495 subViews do:[:v| |
|
496 v ~~ inputView ifTrue:[ |
|
497 p := device translatePoint:point from:id to:(v id). |
|
498 ( p x >= 0 and:[p x <= v width |
|
499 and:[p y >= 0 and:[p y <= v height |
|
500 and:[(self findSpecFor:v) notNil]]]] |
|
501 ) ifTrue:[ |
|
502 ^ v |
|
503 ] |
|
504 ] |
|
505 ]. |
|
506 ^ nil |
|
507 |
|
508 |
|
509 ! |
|
510 |
|
511 findSpecFor:anObject |
|
512 "returns subspec assigned to instance or nil |
|
513 " |
|
514 |name components spec| |
|
515 |
|
516 anObject notNil ifTrue:[ |
|
517 name := anObject name. |
|
518 |
|
519 specification do:[:aSpec| |
|
520 aSpec name = name ifTrue:[ |
|
521 aSpec canUIDrag ifTrue:[^ aSpec] |
|
522 ifFalse:[^ nil] |
|
523 ] |
|
524 ] |
|
525 ]. |
|
526 ^ nil |
|
527 |
|
528 |
|
529 ! ! |
|
530 |
|
531 !UIGalleryView::Canvas methodsFor:'selection'! |
|
532 |
|
533 handlesOf:aComponent do:aOneArgBlock |
|
534 "evaluate the block on each handle; the argument to the block |
|
535 is a rectangle |
|
536 " |
|
537 aComponent notNil ifTrue:[ |
|
538 aOneArgBlock value:(aComponent origin - (2@2) extent:6@6). |
|
539 aOneArgBlock value:(aComponent corner - (1@1) extent:6@6). |
|
540 aOneArgBlock value:(aComponent topRight - (1@2) extent:6@6). |
|
541 aOneArgBlock value:(aComponent bottomLeft - (2@1) extent:6@6). |
|
542 aOneArgBlock value:(aComponent leftCenter - (2@0) extent:6@6). |
|
543 aOneArgBlock value:(aComponent rightCenter - (1@0) extent:6@6). |
|
544 aOneArgBlock value:(aComponent topCenter - (0@2) extent:6@6). |
|
545 aOneArgBlock value:(aComponent bottomCenter - (0@1) extent:6@6). |
|
546 ] |
|
547 |
|
548 |
|
549 ! |
|
550 |
|
551 selection:anObject |
|
552 "selection changed |
|
553 " |
|
554 |name spec| |
|
555 |
|
556 selection ~~ anObject ifTrue:[ |
|
557 self showUnselected. |
|
558 spec := self findSpecFor:anObject. |
|
559 |
|
560 spec notNil ifTrue:[ |
|
561 selection := anObject. |
|
562 self showSelected |
|
563 ] ifFalse:[ |
|
564 selection := nil |
|
565 ]. |
|
566 clientSpecHolder notNil ifTrue:[ |
|
567 clientSpecHolder value:spec |
|
568 ] |
|
569 ] |
|
570 |
|
571 |
|
572 ! |
|
573 |
|
574 showSelected |
|
575 "show selected |
|
576 " |
|
577 self shown ifFalse:[^ self]. |
|
578 |
|
579 selection notNil ifTrue:[ |
|
580 self clippedByChildren:false. |
|
581 |
|
582 self handlesOf:selection do:[:aRectangle| |
|
583 self fillRectangle:aRectangle |
|
584 ]. |
|
585 self clippedByChildren:true. |
|
586 ]. |
|
587 |
|
588 |
|
589 ! |
|
590 |
|
591 showUnselected |
|
592 "show unselected |
|
593 " |
|
594 |r currSel| |
|
595 |
|
596 (currSel := selection) isNil ifTrue:[ |
|
597 ^ self |
|
598 ]. |
|
599 selection := nil. |
|
600 self shown ifFalse:[^ self]. |
|
601 |
|
602 self clippedByChildren:false. |
|
603 |
|
604 self handlesOf:currSel do:[:aRectangle| |
|
605 self clearRectangle:aRectangle |
|
606 ]. |
|
607 self clippedByChildren:true. |
|
608 r := currSel bounds. |
|
609 |
|
610 subViews do:[:sv| |
|
611 |absOrg absFrame| |
|
612 |
|
613 sv ~~ inputView ifTrue:[ |
|
614 (sv bounds intersects:r) ifTrue:[ |
|
615 sv borderColor:(Color gray:5). |
|
616 sv borderColor:(Color black). |
|
617 |
|
618 sv withAllSubViewsDo:[:v| |
|
619 v fill:v viewBackground. |
|
620 v exposeX:0 y:0 width:9999 height:9999. |
|
621 ] |
|
622 ] |
|
623 ] |
|
624 ]. |
|
625 selection := currSel. |
|
626 |
|
627 ! ! |
|
628 |
|
629 !UIGalleryView::Canvas::DropSpec class methodsFor:'instance creation'! |
|
630 |
|
631 for:aView specification:aSpec |
|
632 "create drop object for a view derived from a specification |
|
633 " |
|
634 |point extent root device| |
|
635 |
|
636 device := aView device. |
|
637 root := device rootView. |
|
638 extent := aView extent. |
|
639 point := device translatePoint:0@0 from:(aView id) to:(root id). |
|
640 |
|
641 DisplayObject := nil. |
|
642 |
|
643 (point x > 0 and:[point y > 0]) ifTrue:[ |
|
644 point := point + extent. |
|
645 (point x < root width and:[point y < root height]) ifTrue:[ |
|
646 aView topView raise. |
|
647 device sync. |
|
648 aView invalidate. |
|
649 aView windowGroup processExposeEvents. |
|
650 DisplayObject := Image fromView:aView grab:false. |
|
651 ] |
|
652 ]. |
|
653 DisplayObject isNil ifTrue:[ |
|
654 DisplayObject := Form extent:extent depth:1. |
|
655 DisplayObject colorMap:(Array with:Color white with:Color black). |
|
656 DisplayObject fill:(Color colorId:0). |
|
657 DisplayObject paint:(Color colorId:1). |
|
658 DisplayObject displayRectangleX:0 y:0 width:aView extent x height:aView extent y. |
|
659 ]. |
|
660 aSpec class == UISubSpecification ifTrue:[ |
|
661 aSpec layout:(LayoutOrigin fromPoint:0@0) |
|
662 ]. |
|
663 ^ self new theObject:aSpec |
|
664 ! ! |
|
665 |
|
666 !UIGalleryView class methodsFor:'documentation'! |
|
667 |
|
668 version |
|
669 ^ '$Header$' |
|
670 ! ! |