CursorWithAlpha subclass: #GCursor instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! GPeripheralDevice subclass: #GDisplay instanceVariableNames: 'bounds views activeView extent damageRecorder backgroundSurface overlaySurface history' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GDisplay commentStamp: 'FernandoOlivero 11/25/2011 18:58' prior: 0! I'm the world, which hosts one or more views, and handle the interactions with the user. Each view, represents a portion of a scene (dictacted by the window), viewed at certain region of the world (dictated by the viewport). On every user input, i create the proper GauchoEvent and dispatch it to the colliding view, which in turn, dispatches it to the colliding morph. ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 1/23/2012 21:25'! activeView ^ activeView! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 12/21/2011 09:28'! add: aScene viewedAt: anOrigin presentedAt: aViewport | win | win := GSceneWindow on: aScene at: anOrigin extending: self extent. ^ self add: aScene viewedThrough: win presentedAt: aViewport ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 11/26/2011 09:39'! add: aScene viewedThrough: aWindow presentedAt: aViewport ^ GView on: aScene viewedThrough: aWindow presentedAt: aViewport in: self. ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/16/2012 14:58'! basicAdd: aGSceneView views add: aGSceneView. activeView notNil ifTrue:[ activeView passivate]. activeView := aGSceneView. activeView activate. ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/8/2012 23:56'! damageRecorder ^ damageRecorder! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:16'! dismiss: aGView history add: (GFinishedViewSession from: aGView). self remove: aGView. ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:09'! history ^ history! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/27/2012 08:26'! layouter ^ GDisplayLayouter new! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 11/25/2011 18:56'! numberOfViews ^ self views size! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/27/2012 11:14'! remove: aGauchoSceneView | viewports | views remove: aGauchoSceneView. views isEmpty ifTrue:[ activeView := nil. ^ self ]. activeView = aGauchoSceneView ifTrue:[activeView := views anyOne ] . viewports := self layouter viewportsFor: views size. views with: viewports do:[:v :vp| v viewport: vp]. ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/26/2012 21:36'! shutdown userInterface shutdown.! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 2/27/2012 08:41'! spawnNewScene | viewport viewports | viewports := self layouter viewportsFor: views size + 1. views with: viewports allButLast do:[:v :vp| v viewport: vp]. self add: self newScene viewedAt: 0@0 presentedAt: viewports last. ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 11/25/2011 18:58'! theme ^ GTheme current ! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 1/23/2012 12:52'! themeChanged self views do:#themeChanged.! ! !GDisplay methodsFor: 'accessing' stamp: 'FernandoOlivero 11/25/2011 18:57'! views ^ views! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 09:21'! backgroundColor ^ Color gray! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/10/2012 02:33'! clearOverlay overlaySurface drawDuring:[:canvas| | paint | paint := canvas setPaint: backgroundSurface. paint loadOn: canvas at: 0@0; paintOn: canvas ]. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 1/26/2012 02:40'! displayBackground | form | form := backgroundSurface asForm. form displayAt: 0@0. Display deferUpdates: false; forceDisplayUpdate. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 1/26/2012 13:20'! displayOverlay | form | form := overlaySurface asForm. form displayAt: 0@0. Display deferUpdates: false; forceDisplayUpdate. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/10/2012 13:23'! drawMarker: aMarker at: aDisplayPoint | markerExtent | overlaySurface drawDuring:[:canvas| markerExtent := GShapeRenderer default drawMarker: aMarker at: aDisplayPoint on: canvas]. damageRecorder overlayedChangedAt: (aDisplayPoint - markerExtent x /2 extent: markerExtent) ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 08:10'! drawOverlayOn: aCanvas "the mouse is hovering over me" ^ self! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/9/2012 14:44'! exportToPng: aFileRef self redraw. overlaySurface writeToPng: aFileRef fullName.! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/8/2012 22:53'! recordKeyboardFocusChanged: aGSceneShape on: aGView damageRecorder keyboardFocusChanged: aGSceneShape on: activeView. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/8/2012 23:19'! recordPanningFrom: aMouseDownDisplayPoint to: aDisplayPoint on: aGView damageRecorder panningFrom: aMouseDownDisplayPoint to: aDisplayPoint on: aGView.! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 1/27/2012 15:39'! redraw self redrawBackground. self redrawOverlay.! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 08:53'! redrawBackground backgroundSurface drawDuring:[:canvas| canvas setPaint: self backgroundColor; drawShape: (0@0 extent: extent ). views do:[:each| each drawBackgroundOn: canvas] ]. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/2/2012 14:11'! redrawIfNeeded damageRecorder redraw: self. damageRecorder reset. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/14/2012 12:30'! redrawOverlay overlaySurface drawDuring:[:canvas| | paint | paint := canvas setPaint: backgroundSurface. paint loadOn: canvas at: 0@0; paintOn: canvas. views do:[:each| each drawOverlayOn: canvas] ]. ! ! !GDisplay methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 08:09'! redrawOverlaysOf: aDictionaryOfViewsAndShapes overlaySurface drawDuring:[:canvas| | paint | paint := canvas setPaint: backgroundSurface. paint loadOn: canvas at: 0@0; paintOn: canvas. aDictionaryOfViewsAndShapes keysAndValuesDo:[:view :shapes| canvas pathTransform save. view loadTransformOn: canvas. shapes do:[:each| (each is:#scene) not ifTrue:[each drawOverlayOn: canvas]]. ((view keyboardFocus is:#scene ) not and: [(shapes includes: view keyboardFocus ) not] ) ifTrue:[ view keyboardFocus drawOverlayOn: canvas ]. canvas pathTransform restore ] ]. ! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 09:52'! extent ^ extent ! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 14:48'! extent: anExtent extent := anExtent . self extentChanged ! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 1/24/2012 12:09'! extentChanged ^ self! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 2/3/2012 10:55'! shapeAround: aDisplayPoint | view x y | x := aDisplayPoint x max: 0. y := aDisplayPoint y max: 0. view := self viewAround: x@y. view isNil ifTrue:[^ self ] ifFalse:[^ view shapeAround: x@y ]! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 1/24/2012 09:47'! viewAround: aDisplayPoint ^ self views detect:[:each| each containsPoint: aDisplayPoint ] ifNone: nil ! ! !GDisplay methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 00:35'! viewOn: aScene ^ self views detect:[:each| each scene = aScene ] ifNone: nil ! ! !GDisplay methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/25/2012 14:53'! initializeAttachedTo: aGUserInterface super initializeAttachedTo: aGUserInterface. views := OrderedCollection new. damageRecorder := GDamageRecorder new. self extent: self primActualScreenSize . self initializeSurfaces. self initializeViews. history := GDisplayHistory on: self.! ! !GDisplay methodsFor: 'initialize-release' stamp: 'FernandoOlivero 1/26/2012 13:09'! initializeSurfaces backgroundSurface := AthensCairoSurface extent: extent. overlaySurface := AthensCairoSurface extent: extent. ! ! !GDisplay methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 08:31'! initializeViews self add: self newScene viewedAt: 0@0 presentedAt: self layouter viewportForSingleView! ! !GDisplay methodsFor: 'testing' stamp: 'FernandoOlivero 2/3/2012 10:59'! is: aSymbol ^ aSymbol = #display or:[ super is: aSymbol ].! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/8/2012 23:19'! keystroke: aGKeystroke from: aGKeyboard self activeView keystroke: aGKeystroke from: aGKeyboard.! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/8/2012 22:50'! mouse: aGMouse clicked: aGShape at: aDisplayPoint activeView passivate. activeView := self viewOn: aGShape scene. activeView activate. activeView mouse: aGMouse clicked: aGShape at: aDisplayPoint. ! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 13:01'! mouse: aGMouse dragggedAndDropped: aGDragOperation | dropPoint | activeView passivate. dropPoint := aGDragOperation dropPoint. activeView := self viewAround: dropPoint. activeView activate. activeView mouse: aGMouse dragggedAndDropped: aGDragOperation ! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/3/2012 10:34'! mouse: aGMouse entered: aGShape aGShape mouseEntered. damageRecorder entered: aGShape on: activeView.! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 1/26/2012 03:16'! mouse: aGMouse left: aGShape aGShape mouseLeft. damageRecorder left: aGShape on: activeView.! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 3/3/2012 00:08'! mouse: aGMouse movedTo: aDisplayPoint activeView passivate. activeView := self viewAround: aDisplayPoint. activeView isNil ifTrue:[ ^ self ]. activeView activate. activeView mouse: aGMouse movedTo: aDisplayPoint! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 13:00'! mouse: aGMouse pannedFrom: aMouseDownDisplayPoint to: aDisplayPoint activeView passivate. activeView := self viewAround: aDisplayPoint. activeView activate. activeView mouse: aGMouse pannedFrom: aMouseDownDisplayPoint to: aDisplayPoint. ! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/8/2012 23:14'! mouse: aGMouse secondaryClicked: aGShape at: aDisplayPoint activeView passivate. activeView := self viewOn: aGShape scene. activeView activate. activeView mouse: aGMouse secondaryClicked: aGShape at: aDisplayPoint. ! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/11/2012 01:31'! mouse: aGMouse startedDragging: aGShape at: aDisplayPoint activeView passivate. activeView := self viewAround: aDisplayPoint. activeView activate. activeView mouse: aGMouse startedDragging: aGShape at: aDisplayPoint.! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/3/2012 10:34'! mouseEntered ! ! !GDisplay methodsFor: 'interactions' stamp: 'FernandoOlivero 2/3/2012 10:34'! mouseLeft ! ! !GDisplay methodsFor: 'private' stamp: 'FernandoOlivero 2/27/2012 08:24'! newScene ^ GScene extending: extent * 10! ! !GDisplay methodsFor: 'apply primitives' stamp: 'FernandoOlivero 1/23/2012 14:48'! primActualScreenSize ^ 640@480 ! ! !GDisplay methodsFor: 'updating' stamp: 'FernandoOlivero 2/19/2012 10:48'! view: aGView added: aGShape damageRecorder added: aGShape to: aGView. ! ! !GDisplay methodsFor: 'updating' stamp: 'FernandoOlivero 2/19/2012 10:48'! view: aGView moved: aGShape damageRecorder added: aGShape to: aGView. ! ! !GDisplay methodsFor: 'updating' stamp: 'FernandoOlivero 2/19/2012 10:48'! view: aGView removed: aGShape at: aBounds activeView = aGView ifTrue:[ "if the view is active, then possibly a pointing device peripheral was over the removed shape, notify the userinterface so he notify the peripheral devices" userInterface view: aGView in: self removed: aGShape ]. damageRecorder removed: aGShape from: aGView at: aBounds. ! ! !GDisplay methodsFor: 'updating' stamp: 'FernandoOlivero 2/19/2012 10:47'! view: aGView resized: aGShape from: anExtent activeView = aGView ifTrue:[ "if the view is active, then possibly a pointing device peripheral was over the removed shape, notify the userinterface so he notify the peripheral devices" userInterface view: aGView in: self resized: aGShape ]. damageRecorder resized: aGShape from: aGView from: anExtent. ! ! Object subclass: #GView instanceVariableNames: 'scene keyBindings viewport window display session history initialSnapshot mousePosition searchShape overlayedWidget menu addShape' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 12/21/2011 09:35'! activate "noop" ^ self ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:21'! initialSnapshot ^ initialSnapshot. ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 1/26/2012 14:17'! keyboardFocus ^ scene keyboardFocus! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 3/3/2012 00:10'! overlayedWidget ^ overlayedWidget! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 12/21/2011 09:35'! passivate "noop" ^ self ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 11/26/2011 08:31'! scene ^ scene! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 1/23/2012 13:05'! scene: aGScene self uninstallAnnouncements. scene := aGScene. self installAnnouncements. window scene: aGScene. ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:21'! snapshot ^ GViewSnapshot from: self! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/26/2012 21:58'! theme ^ GTheme current! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/3/2012 10:14'! viewport ^ viewport! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/3/2012 10:14'! viewport: aNDCViewport viewport := aNDCViewport ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/3/2012 00:01'! window ^ window ! ! !GView methodsFor: 'accessing' stamp: 'FernandoOlivero 2/3/2012 10:13'! window: aSceneWindow window := aSceneWindow! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/27/2012 07:59'! addWasAccepted addShape accept. self basicAddShapeNamed: addShape editedContents at: mousePosition. self addWasRemoved. ! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/27/2012 07:51'! addWasRemoved self removeOverlayedWidget! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/27/2012 09:42'! basicAddShapeNamed: aName at: aPosition | rg target targetShape scenePoint | scenePoint := self internalize: aPosition . target := Smalltalk globals classNamed: aName. rg := GRingClassTarget on: target. targetShape := GWidgetsBuilder default newClassShape. targetShape initializeOn: rg. ^ scene add: targetShape at: scenePoint. ! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/26/2012 21:34'! closeMenu self removeOverlayedWidget! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/27/2012 07:50'! openAddShape addShape target: self; modelChanged. addShape selectAll. self openOverlayedWidget: addShape.! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/26/2012 21:51'! openMenu | menuSpec | menuSpec := GWidgetsBuilder default menuSpecDescribedByKeyword: 'sceneMenu'. menu initializeOn: menuSpec. self openOverlayedWidget: menu! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/26/2012 16:27'! openSearchWith: aCharacter | strategy | strategy := CollectionMatchingStrategy on: (GSystem current allClassNames ). searchShape completionStrategy: strategy ; initializeOn: aCharacter asUppercase asString . self openOverlayedWidget: searchShape. ! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/26/2012 21:34'! performMenuAction: anAction self closeMenu. self perform: anAction ! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/27/2012 09:42'! searchWasAccepted | shape targetClassName scenePoint | scenePoint := self internalize: mousePosition . targetClassName := searchShape contents. shape := scene shapes detect:[:each| each shape target targetName = targetClassName] ifNone: nil. shape notNil ifTrue:[ scene move: shape to: scenePoint ] ifFalse:[ shape := self basicAddShapeNamed: targetClassName at: mousePosition]. scene keyboardFocus: shape. self searchWasRemoved.! ! !GView methodsFor: 'widgets' stamp: 'FernandoOlivero 2/26/2012 16:04'! searchWasRemoved self removeOverlayedWidget! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 1/26/2012 02:49'! addedShape: anAnn display view: self added: anAnn shape.! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/23/2012 14:45'! attachedMovedShape: anAnn display view: self moved: anAnn shape.! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/23/2012 14:43'! installAnnouncements scene announcer on: GAdded send: #addedShape: to: self; on: GRemoved send: #removedShape: to: self; on: GRemovedAll send: #removedAllShapes: to: self ; on: GResized send: #resizedShape: to: self; on: GAttachedMoved send: #attachedMovedShape: to: self ; on: GMoved send: #movedShape: to: self ; on: GSnowplowed send: #snowplowedShape: to: self .! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/10/2012 16:36'! movedShape: anAnn display view: self moved: anAnn shape.! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/16/2012 13:35'! removedAllShapes: anAnn display view: self removedAll: anAnn shapes at: anAnn positions.! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/16/2012 13:37'! removedShape: anAnn display view: self removed: anAnn shape at: anAnn bounds.! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/19/2012 10:57'! resizedShape: anAnn ^ display view: self resized: anAnn shape from: anAnn previousExtent ! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 2/22/2012 20:35'! snowplowedShape: anAnn anAnn shape isCollection ifTrue:[ display view: self added: anAnn shape first ] ifFalse:[ display view: self added: anAnn shape ]. "the snowplowing?" "animations?"! ! !GView methodsFor: 'announcements' stamp: 'FernandoOlivero 12/21/2011 09:35'! uninstallAnnouncements scene notNil ifTrue:[ scene announcer unsubscribe: self ]. ! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:15'! applyKeystroke: aGKeystroke to: focus | change | focus recordDamageTo: self whenApplying: aGKeystroke. change := aGKeystroke asAppliedKeystrokeTo: focus. session addChange: change. aGKeystroke applyTo: focus. ! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:25'! applyKeystrokeToScene: aGKeystroke | success | success := aGKeystroke appliesTo: scene . success ifTrue:[ aGKeystroke applyTo: scene. self recordOverlayDamage. ^ self ]. aGKeystroke isCharacter ifTrue:[ self openSearchWith: aGKeystroke asCharacter ].! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:55'! applyToOverlayedWidgetKeystroke: aGKeystroke aGKeystroke applyTo: overlayedWidget. overlayedWidget notNil ifTrue:[ self recordOverlayedWidgetDamage ].! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/3/2012 01:25'! applyZoomFrom: aGKeystroke aGKeystroke unicode = self theme settings zoomOutKeystroke unicode ifTrue:[ window zoomOut ] ifFalse:[ window zoomIn ]. ! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:50'! openOverlayedWidget: aShape overlayedWidget := aShape. self recordOverlayedWidgetDamage! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:48'! recordOverlayedWidgetDamage self recordOverlayDamageAt: (mousePosition extent: overlayedWidget extent).! ! !GView methodsFor: 'private' stamp: 'FernandoOlivero 2/26/2012 15:54'! removeOverlayedWidget self recordOverlayedWidgetDamage. overlayedWidget := nil. ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 15:29'! bounds ^ viewport boundsIn: display extent.! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 13:26'! containsPoint: aDisplayPoint ^ self bounds containsPoint: aDisplayPoint ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 21:46'! externalize: aScenePoint | ndcPoint | ndcPoint := window externalize: aScenePoint to: viewport. ^ viewport externalize: ndcPoint into: display. ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/30/2012 14:49'! externalizeBounds: aSceneRectangle |ndcBounds| ndcBounds := window externalizeBounds: aSceneRectangle to: self. ^ viewport externalizeBounds: ndcBounds into: display. ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/24/2012 12:50'! internalize: aDisplayPoint | ndcPoint | ndcPoint := viewport internalize: aDisplayPoint from: display. ^ window internalize: ndcPoint from: viewport ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/30/2012 14:49'! internalizeBounds: aDisplayBounds |ndcBounds| ndcBounds := viewport internalizeBounds: aDisplayBounds from: display. ^ window internalizeBounds: ndcBounds from: self. ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 2/27/2012 08:19'! loadTransformOn: aCanvas aCanvas pathTransform save; translateBy:self bounds origin ; scaleBy: viewport extent ; translateBy: window origin negated. ! ! !GView methodsFor: 'geometry' stamp: 'FernandoOlivero 1/30/2012 14:52'! shapeAround: aDisplayPoint | scenePoint | scenePoint := self internalize: aDisplayPoint. ^ scene shapeAround: scenePoint! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/27/2012 08:42'! dismiss self uninstallAnnouncements. self recordOverlayDamage. display dismiss: self. display damageRecorder markDirty. display := nil. ! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/27/2012 07:47'! keystroke: aGKeystroke from: aGKeyboard | focus | "fix me, i shoul have keybindings as well, instead of the ifs" overlayedWidget notNil ifTrue:[ ^ self applyToOverlayedWidgetKeystroke: aGKeystroke ] . aGKeystroke isZooming ifTrue:[ ^ self applyZoomFrom: aGKeystroke ]. focus := self keyboardFocus. focus = scene ifTrue:[ aGKeystroke isTab ifTrue:[ ^ self openMenu ]. (aGKeystroke isModified: $n ) ifTrue:[ ^ self openAddShape ]. self applyKeystrokeToScene: aGKeystroke ] ifFalse:[ self applyKeystroke: aGKeystroke to: focus ].! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/24/2012 03:37'! mouse: aGMouse clicked: aGSceneShape at: aDisplayPoint | scenePoint previous shape shapePoint | previous := self keyboardFocus. scene keyboardFocus: aGSceneShape. scenePoint := self internalize: aDisplayPoint. aGSceneShape = scene ifTrue:[ scene clickedAt: scenePoint. previous ~= scene ifTrue:[ self recordDamageOf: previous ] . ^ self ]. shape := self shapeAround: scenePoint. shapePoint := shape internalize: scenePoint. shape clickedAt: shapePoint. self recordDamageOf: previous. previous ~= aGSceneShape ifTrue:[ display recordKeyboardFocusChanged: shape on: self ]! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 17:00'! mouse: aGMouse dragggedAndDropped: aGDragOperation aGDragOperation applyIn: self. scene keyboardFocus: scene. ! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/26/2012 22:06'! mouse: aGMouse movedTo: aDisplayPoint (overlayedWidget notNil and:[ (mousePosition dist: aDisplayPoint) > 10 ] ) ifTrue:[ self removeOverlayedWidget ] ifFalse:[ mousePosition := aDisplayPoint ] ! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 02:26'! mouse: aGMouse pannedFrom: aMouseDownDisplayPoint to: aDisplayPoint | origin destination | origin := self internalize: aMouseDownDisplayPoint. destination := self internalize: aDisplayPoint. window panFrom: origin to: destination. scene keyboardFocus: scene. display recordPanningFrom: aMouseDownDisplayPoint to: aDisplayPoint on: self.! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 02:12'! mouse: aGMouse secondaryClicked: aGSceneShape at: aDisplayPoint | scenePoint previous shape shapePoint | previous := self keyboardFocus. scene keyboardFocus: aGSceneShape. scenePoint := self internalize: aDisplayPoint. aGSceneShape = scene ifTrue:[ ^ scene secondaryClickedAt: scenePoint]. shape := self shapeAround: scenePoint. shapePoint := shape internalize: scenePoint. shape secondaryClickedAt: shapePoint. previous = aGSceneShape ifTrue:[ ^ self ]. display recordKeyboardFocusChanged: shape on: self. ! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/26/2012 15:30'! mouse: aGMouse startedDragging: aGShape at: aDisplayPoint | bounds aBounds | aGShape hasAttachments not ifTrue:[ ^ self recordOverlayDamageOf: aGShape ]. bounds := self externalizeBounds: aGShape attachments bounds . self recordOverlayDamageAt: bounds.! ! !GView methodsFor: 'interactions' stamp: 'FernandoOlivero 2/25/2012 15:23'! todoooooooooooo "reify all the changes to the viewport itself, panning, zooming,viewport, etc.."! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 08:54'! drawBackgroundOn: aCanvas | bounds color paint origin stroke| color := GTheme current activeColor . bounds := self bounds. aCanvas pathTransform save; translateBy: bounds origin . paint := aCanvas setPaint: color . aCanvas drawShape: (0@0 extent: bounds extent). display views size >1 ifTrue:[ stroke := aCanvas setStrokePaint: display backgroundColor . stroke width: 4. aCanvas drawShape: (0@0 extent: bounds extent)]. aCanvas pathTransform scaleBy: viewport extent. origin := window origin. window visibleShapes do:[:each| each drawOn: aCanvas at: each bounds origin - origin ] . aCanvas pathTransform restore. ! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 3/3/2012 00:20'! drawOverlayOn: aCanvas |origin | aCanvas pathTransform save; translateBy: self bounds origin ; scaleBy: viewport extent. GTheme current settings showTiles ifTrue:[ GShapeRenderer default drawTiles: window visibleTiles of: scene plane on: aCanvas ]. origin := window origin. window visibleShapes do:[:each| each drawOverlayOn: aCanvas at: each bounds origin - origin ] . overlayedWidget notNil ifTrue:[ overlayedWidget fullDrawOn: aCanvas at: mousePosition + 10]. aCanvas pathTransform restore. ! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 2/16/2012 17:27'! recordDamageOf: aGSceneShape display damageRecorder markDirty: aGSceneShape in: self.! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 2/26/2012 14:44'! recordOverlayDamage display damageRecorder markDirtyOverlay.! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 2/26/2012 15:31'! recordOverlayDamageAt: aBounds display damageRecorder markDirtyOverlayAt: aBounds. ! ! !GView methodsFor: 'drawing' stamp: 'FernandoOlivero 2/11/2012 01:28'! recordOverlayDamageOf: aGSceneShape display damageRecorder markDirtyOverlayOf: aGSceneShape in: self.! ! !GView methodsFor: 'sessions' stamp: 'FernandoOlivero 2/25/2012 14:39'! history ^ history! ! !GView methodsFor: 'sessions' stamp: 'FernandoOlivero 2/25/2012 14:39'! session ^ session! ! !GView methodsFor: 'sessions' stamp: 'FernandoOlivero 2/25/2012 13:37'! startNewSession | finished | finished := session finish. history add: finished. session := GViewSession on: self.! ! !GView methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 07:45'! initializeAddShape addShape := GAddClassShape new. addShape announcer on: GAccepted send: #addWasAccepted to: self ; on: GRemoved send: #addWasRemoved to: self. addShape extent: (GTheme current namedRefactoringShapeValues at: #extent)! ! !GView methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/26/2012 15:37'! initializeOn: aScene viewedThrough: aWindow presentedAt: aNDCViewport in: aDisplay window := aWindow. window scene: aScene. viewport := aNDCViewport . display := aDisplay . display basicAdd: self. self scene: aScene . initialSnapshot := GViewSnapshot from: self. session := GViewSession on: self. history := OrderedCollection new. self initializeWidgets. ! ! !GView methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/26/2012 15:56'! initializeSearchShape | fDesc entryTarget| fDesc := AthensFontDescription new. fDesc family: 'monospace'; fontSize: GTheme current headerFontSize. searchShape := GWidgetsBuilder default newEntryField. searchShape layoutSpec padding: {1. 1. 1. 4}. searchShape style: #fontDescription at: #default with: fDesc. searchShape announcer on: GAccepted send: #searchWasAccepted to: self ; on: GRemoved send: #searchWasRemoved to: self. searchShape extent: (GTheme current namedRefactoringShapeValues at: #extent)! ! !GView methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 07:44'! initializeWidgets self initializeSearchShape . self initializeAddShape. menu := GWidgetsBuilder default newPieMenu. menu parent: self. menu style: #paint at: #default with: self theme activeColor. ! ! !GView methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 08:32'! pieMenuExtent ^ (self theme shapeValues at:#extent ) ! ! !GView methodsFor: 'menu-actions' stamp: 'FernandoOlivero 2/26/2012 21:35'! revealDeveloper! ! !GView methodsFor: 'menu-actions' stamp: 'FernandoOlivero 2/26/2012 21:35'! shutdown display shutdown! ! !GView methodsFor: 'menu-actions' stamp: 'FernandoOlivero 2/27/2012 08:42'! spawnNewScene display spawnNewScene. "cheating the visual garbage collector!!" display damageRecorder markDirty! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GView class instanceVariableNames: ''! !GView class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 11/26/2011 09:35'! on: aScene viewedThrough: aWindow presentedAt: aNDCViewport in: aDisplay |view| view := self new. view initializeOn: aScene viewedThrough: aWindow presentedAt: aNDCViewport in: aDisplay. ^ view ! ! Object subclass: #GLog instanceVariableNames: 'logFile file' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GLog methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/2/2012 10:59'! clear file writeStreamDo:[:str| str truncateTo: 0]. ! ! !GLog methodsFor: 'initialize-release' stamp: 'FernandoOlivero 1/25/2012 16:02'! initialize file := FSFilesystem disk workingDirectory / 'GLog.log'. ! ! !GLog methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/2/2012 12:29'! start file writeStreamDo:[:str| str position: (str contents size max: 1); nextPutAll: 'START--'; space; nextPutAll: TimeStamp now asString; cr; cr]. ! ! !GLog methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/2/2012 12:29'! stop file writeStreamDo:[:str| str position: (str contents size max: 1); cr; nextPutAll: 'STOP--'; space; nextPutAll: TimeStamp now asString; cr].! ! !GLog methodsFor: 'logging' stamp: 'FernandoOlivero 2/2/2012 14:02'! log: anObject file writeStreamDo:[:str| str position: (str contents size max: 1). anObject printOn: str. str cr; cr]. ! ! TestCase subclass: #GTransformationsTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GTransformationsTest methodsFor: 'viewport' stamp: 'FernandoOlivero 12/20/2011 16:01'! testViewportToDisplay " self debug: #testViewportToDisplay. " | viewport display | display := 0@0 extent: 500@500. viewport := NDCViewport all. self assert:( viewport boundsIn: display) = (0@0 extent: 500@500). viewport := NDCViewport upperLeft. self assert:( viewport boundsIn: display) = (0@0 extent: 250@250). viewport := NDCViewport bottomLeft. self assert:( viewport boundsIn: display) = (0@250 extent: 250@250). viewport := NDCViewport bottomRight. self assert:( viewport boundsIn: display) = (250@250 extent: 250@250). ! ! !GTransformationsTest methodsFor: 'window' stamp: 'FernandoOlivero 1/24/2012 12:28'! testWindowToViewport " self debug: #testWindowToViewport. The rectangle in the scene, is at 0@0->10@10 of the window, and the window is in the same size as the screen. therefore, when transformed into the whole viewport, its at 0.1@0.1. " | rect scene win view| rect := GShape new. rect extent: 10@10. scene := GScene extending: 4000@4000. scene add: rect at: 0@0. win := GSceneWindow at: 0@0 extending: 100@100. view := NDCViewport all. self assert: (win externalize: 10@10 to: view ) = ((1/10)@(1/10)). self assert: (win internalize: 0.1@0.1 from: view ) = (10@10). view := NDCViewport upperLeft. self assert: (win externalize: 10@10 to: view ) = ((1/10)@(1/10)). self assert: (win internalize: 0.1@0.1 from: view ) = (10@10). ! ! !GTransformationsTest methodsFor: 'window' stamp: 'FernandoOlivero 1/24/2012 12:28'! testZoomedInWindowToViewport " self debug: #testZoomedInWindowToViewport. The rectangle in the scene, is at 0@0->10@10 of the window, but the window just fits the scene. therefore, when transformed into the whole viewport, its at 1.@1. " | rect scene win view| rect := GShape new. rect extent: 10@10. scene := GScene extending: 4000@4000. scene add: rect at: 0@0. win := GSceneWindow at: 0@0 extending: 10@10. view := NDCViewport all. self assert: (win externalize: 10@10 to: view ) = (1@1). view := NDCViewport upperLeft. self assert: (win externalize: 10@10 to: view ) = (1@1).! ! !GTransformationsTest methodsFor: 'window' stamp: 'FernandoOlivero 1/24/2012 12:28'! testZoomedOutWindowToViewport " self debug: #testZoomedOutWindowToViewport. The rectangle in the scene, is at 0@0->10@10 of the window, but the window is ten times the size of the scene. therefore, when transformed into the whole viewport, its at 0.01@0.01. " | rect scene win view| rect := GShape new. rect extent: 10@10. scene := GScene extending: 4000@4000. scene add: rect at: 0@0. win := GSceneWindow at: 0@0 extending: 1000@1000. view := NDCViewport all. self assert: (win externalize: 10@10 to: view ) = ((1/100)@(1/100)). view := NDCViewport upperLeft. self assert: (win externalize: 10@10 to: view ) = ((1/100)@(1/100)).! ! AthensCairoSurface subclass: #GauchoSurface instanceVariableNames: 'session' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GauchoSurface methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 3/6/2012 12:09'! checkSession session == NativeBoost uniqueSessionObject ifFalse: [ self initializeForNewSession. ].! ! !GauchoSurface methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 3/6/2012 12:11'! createPaints "create and cache all the shape paints"! ! !GauchoSurface methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 3/6/2012 12:12'! createPaths "create and cache all the paths: rounded shape, pie menu, icons"! ! !GauchoSurface methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 3/6/2012 12:09'! initialize super initialize. session := NativeBoost uniqueSessionObject. self createPaths; createPaints.! ! !GauchoSurface methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 3/6/2012 12:09'! initializeForNewSession session := NativeBoost uniqueSessionObject. self createPaths; createPaints.! ! Object subclass: #GDamageRecorder instanceVariableNames: 'added removed entered lefts keyboardFocusChanged pannings overlayInvalidRects records backgroundInvalidRects dirtyOverlayShapes dirtyBackgroundShapes dirtyOverlayRectangles changedOverlayRectangles resized overlayDirty fullRedraw' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 1/26/2012 03:05'! added: aGShape to: aGView | shapes | shapes := added at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/8/2012 23:46'! backgroundChangedAt: aDisplayRectangle backgroundInvalidRects add: aDisplayRectangle! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 1/26/2012 03:17'! entered: aGShape on: aGView | shapes | shapes := entered at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 1/27/2012 11:27'! keyboardFocusChanged: aGShape on: aGView | shapes | shapes := keyboardFocusChanged at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 1/26/2012 03:17'! left: aGShape on: aGView | shapes | shapes := lefts at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/27/2012 08:38'! markDirty fullRedraw := true.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/11/2012 01:29'! markDirty: aGSceneShape in: aGView | shapes | shapes := dirtyBackgroundShapes at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGSceneShape. ! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/26/2012 14:45'! markDirtyOverlay overlayDirty := true.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/17/2012 17:35'! markDirtyOverlayAt: aDisplayBounds dirtyOverlayRectangles add: aDisplayBounds! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/11/2012 01:29'! markDirtyOverlayOf: aGSceneShape in: aGView | shapes | shapes := dirtyOverlayShapes at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGSceneShape. ! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/17/2012 17:34'! overlayedChangedAt: aDisplayBounds changedOverlayRectangles add: aDisplayBounds! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/2/2012 14:06'! panningFrom: aMouseDownDisplayPoint to: aDisplayPoint on: aGView | shapes | shapes := pannings at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: {aGView. aDisplayPoint}! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/16/2012 13:37'! removed: aGShape from: aGView at: aBounds | shapes | shapes := removed at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/16/2012 13:38'! removedAll: aCollectionOfGShape from: aGView at: aCollectionOfBounds | shapes | shapes := removed at: aGView ifAbsentPut:[OrderedCollection new]. shapes addAll: aCollectionOfGShape.! ! !GDamageRecorder methodsFor: 'recording' stamp: 'FernandoOlivero 2/19/2012 10:52'! resized: aGShape from: aGView from: anExtent | shapes | shapes := resized at: aGView ifAbsentPut:[OrderedCollection new]. shapes add: aGShape.! ! !GDamageRecorder methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 08:38'! initialize super initialize. fullRedraw := overlayDirty := false. entered := Dictionary new. lefts := Dictionary new. added := Dictionary new. resized := Dictionary new. removed := Dictionary new. keyboardFocusChanged := Dictionary new. pannings := Dictionary new. dirtyBackgroundShapes := Dictionary new. dirtyOverlayShapes := Dictionary new. dirtyOverlayRectangles := OrderedCollection new. changedOverlayRectangles := OrderedCollection new. records := { dirtyOverlayRectangles. changedOverlayRectangles. dirtyBackgroundShapes. dirtyOverlayShapes. keyboardFocusChanged. entered. lefts. added. resized. removed. pannings }! ! !GDamageRecorder methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/27/2012 08:38'! reset records do: #removeAll. fullRedraw := overlayDirty := false.! ! !GDamageRecorder methodsFor: 'drawing' stamp: 'FernandoOlivero 2/27/2012 08:38'! redraw: aGDisplay self updateIsNeeded not ifTrue:[ ^ self ]. fullRedraw ifTrue:[ ^ aGDisplay redraw; displayOverlay ]. "MAJOR Change to the pampas: do a full redraw" (resized notEmpty or:[removed notEmpty or:[added notEmpty]]) ifTrue:[ "self log: #majorchange. " aGDisplay redrawBackground. resized notEmpty ifTrue:[ ^ self redrawHoveredOverlayOf: resized on: aGDisplay]. added notEmpty ifTrue:[ ^ self redrawHoveredOverlayOf: added on: aGDisplay]. aGDisplay displayBackground. ^ self]. dirtyBackgroundShapes notEmpty ifTrue:[ "self log: #dirtyBackgroundShapes." ^ aGDisplay redraw; displayOverlay ]. dirtyOverlayShapes notEmpty ifTrue:[ " self log: #dirtyOverlayShapes." ^ self redrawHoveredOverlayOf: dirtyOverlayShapes on: aGDisplay ]. dirtyOverlayRectangles notEmpty ifTrue:[ "self log: #dirtyOverlayRectangles." ^ aGDisplay redrawOverlay; displayOverlay ]. changedOverlayRectangles notEmpty ifTrue:[ ^ aGDisplay displayOverlay ]. "MAJOR Change to the pampas: do a background redraw, omit the overlay since the scene should be the focus when finishing the pan" pannings notEmpty ifTrue:[ ^ aGDisplay clearOverlay ; redrawBackground; displayBackground ]. (entered notEmpty or:[ lefts notEmpty ] ) ifTrue:[ "self log: #hovering." "MOUSE ENTER: redraw the overlay to show hovering and keyboard focus" entered notEmpty ifTrue:[ self redrawHoveredOverlayOf: entered on: aGDisplay]. "MOUSE LEAVE: omit the overlay, and simply display the background" lefts notEmpty ifTrue:[ "if a shape has the focus, then render the overlay, otherwise display the background" (aGDisplay activeView keyboardFocus is: #scene) not ifTrue:[ self redrawHoveredOverlayOf: lefts on: aGDisplay ] ifFalse:[ aGDisplay displayBackground ] ]. ^ self]. "a shape has lost or gained keyboardFocus If the scene gained focus, simply redisplay the background, to ditch the overlayed keyboard indicator of the previous focused shape " keyboardFocusChanged notEmpty ifTrue:[ "self log: #keyboardFocusChanged. " (keyboardFocusChanged anySatisfy:[:shapes| shapes anySatisfy:[:each| each is: #scene]]) ifTrue:[ aGDisplay displayBackground ] ifFalse:[ self redrawHoveredOverlayOf: keyboardFocusChanged on: aGDisplay ]. ^ self]. overlayDirty ifTrue:[ ^ aGDisplay redrawOverlay; displayOverlay]. "nothing happened , so dont redraw at all" "self log: #nothing"! ! !GDamageRecorder methodsFor: 'drawing' stamp: 'FernandoOlivero 1/26/2012 03:14'! redrawBackground: aGDisplay aGDisplay redrawBackground. aGDisplay displayBackground.! ! !GDamageRecorder methodsFor: 'drawing' stamp: 'FernandoOlivero 2/10/2012 02:05'! redrawHoveredOverlayOf: aDictionary on: aGDisplay aGDisplay redrawOverlaysOf: aDictionary. aGDisplay displayOverlay. ! ! !GDamageRecorder methodsFor: 'drawing' stamp: 'FernandoOlivero 2/4/2012 00:52'! redrawOverlayed: aGDisplay aGDisplay redrawOverlay. aGDisplay displayOverlay.! ! !GDamageRecorder methodsFor: 'testing' stamp: 'FernandoOlivero 2/27/2012 08:38'! updateIsNeeded "Return true if the display needs to be updated." ^ fullRedraw or:[ overlayDirty or:[records anySatisfy:#notEmpty ]]! ! Object subclass: #GUserInterface instanceVariableNames: 'keyboard mouse display lastCycleTime sensor process log interrupted' classVariableNames: 'MinCycleLapse' poolDictionaries: '' category: 'GauchoUI-Core'! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 2/2/2012 01:53'! display ^ display .! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 2/9/2012 14:42'! exportToPng: aFileRef display exportToPng: aFileRef! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 1/22/2012 12:34'! keyboard ^ keyboard! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 1/25/2012 15:49'! log ^ log ! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 2/2/2012 14:01'! log: anObject self log log: anObject ! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 1/22/2012 12:34'! mouse ^ mouse! ! !GUserInterface methodsFor: 'accessing' stamp: 'FernandoOlivero 2/2/2012 13:34'! uiProcess ^ process! ! !GUserInterface methodsFor: 'cycling' stamp: 'FernandoOlivero 2/16/2012 12:45'! doOneCycle "Do one cycle of the interaction loop. This method is called repeatedly when the world is running. This is a moderately private method; a better alternative is usually either to wait for events or to check the state of things from #step methods." | debuggers milliSecs wait currentTime | interrupted ifTrue:[ self log log: 'interrupted cycling'. ^ self ]. "Inter cycle Pause-----------------------------------------------------" milliSecs := MinCycleLapse. currentTime := Time millisecondClockValue. wait := lastCycleTime + milliSecs - currentTime. (wait > 0 and: [ wait <= milliSecs ] ) ifTrue: [ (Delay forMilliseconds: wait) wait ]. lastCycleTime := Time millisecondClockValue. "Process Events ---------------------------------------------------" sensor processEventsQueue. "Stepping -----------------------------------------------------------" self runStepMethods. "Display ------------------------------------------------------------" display redrawIfNeeded.! ! !GUserInterface methodsFor: 'cycling' stamp: 'FernandoOlivero 2/16/2012 11:43'! newUIProcess ^[ | morphic events manager| "NO MORPHIC HERE" manager := GauchoUIManager new. manager beDefault. self log log: 'DISPLAY'. display redrawOverlay; displayOverlay. self log log: 'START SENSOR'. Sensor unregister. sensor subscribe: SystemInputEvent send: #process: to: self. sensor start. "event loop forever, until a debugger pops up, or the user interrupts" interrupted := false. [ self doOneCycle. Processor yield. interrupted not ] whileTrue: []. self log log: 'INTERRUPTED'. sensor unsubscribe: self. sensor stop. self log log: 'SENSOR STOPPED'. events := InputEventFetcher default. Sensor flushEvents. (events eventHandlers includes: Sensor) not ifTrue:[ Sensor registerIn: events]. self log log: 'Morphic SENSOR Resumed'. morphic := MorphicUIManager new. morphic beDefault; spawnNewProcess. World changed. self log log: 'MORPHIC RESUMED'. self log stop. "ALLOW MORPHIC to take over" Cursor normal beCursor. Processor yield. ] newProcess priority: Processor userSchedulingPriority. ! ! !GUserInterface methodsFor: 'cycling' stamp: 'FernandoOlivero 2/4/2012 11:41'! processUserInterruption self log log: 'USER INTERRUPT'. interrupted := true. ! ! !GUserInterface methodsFor: 'cycling' stamp: 'FernandoOlivero 1/23/2012 16:02'! runStepMethods ^ self ! ! !GUserInterface methodsFor: 'cycling' stamp: 'FernandoOlivero 2/26/2012 21:36'! shutdown self log log: 'SHUTDOWN'. interrupted := true. ! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/3/2012 17:58'! drawMarker: aMarker at: aDisplayPoint display drawMarker: aMarker at: aDisplayPoint! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/3/2012 01:16'! keystroke: aGKeystroke from: aGKeyboard aGKeystroke isUserInterrupt ifTrue:[ self processUserInterruption ] ifFalse:[ display keystroke: aGKeystroke from: aGKeyboard ]. ! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 1/26/2012 00:29'! mouse: aGMouse clicked: aGShape at: aDisplayPoint display mouse: aGMouse clicked: aGShape at: aDisplayPoint.! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/10/2012 13:00'! mouse: aGMouse dragggedAndDropped: aGDragOperation display mouse: aGMouse dragggedAndDropped: aGDragOperation! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 1/26/2012 00:30'! mouse: aGMouse entered: aGShape display mouse: aGMouse entered: aGShape! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 1/26/2012 00:30'! mouse: aGMouse left: aGShape display mouse: aGMouse left: aGShape! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/26/2012 15:10'! mouse: aGMouse movedTo: aDisplayPoint display mouse: aGMouse movedTo: aDisplayPoint ! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/2/2012 14:05'! mouse: aGMouse pannedFrom: aMouseDownDisplayPoint to: aDisplayPoint. display mouse: aGMouse pannedFrom: aMouseDownDisplayPoint to: aDisplayPoint.! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 1/26/2012 00:28'! mouse: aGMouse secondaryClicked: aGShape at: aDisplayPoint display mouse: aGMouse secondaryClicked: aGShape at: aDisplayPoint. ! ! !GUserInterface methodsFor: 'interactions' stamp: 'FernandoOlivero 2/11/2012 01:21'! mouse: aGMouse startedDragging: aGShape at: aDisplayPoint display mouse: aGMouse startedDragging: aGShape at: aDisplayPoint. ! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:40'! handleComplexInputEvent: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:40'! handleDragDropFilesInputEvent: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/26/2012 14:13'! handleKeyboardInputEvent: aSysEvent self isInstalled ifTrue:[ keyboard process: aSysEvent ]! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:40'! handleMenuInputEvent: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:22'! handleMouseInputEvent: aSysEvent mouse process: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:41'! handleUnknownInputEvent: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/23/2012 14:40'! handleWindowInputEvent: aSysEvent! ! !GUserInterface methodsFor: 'events' stamp: 'FernandoOlivero 1/26/2012 12:55'! process: sysEvent self isInstalled ifTrue:[ sysEvent accept: self ]! ! !GUserInterface methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/2/2012 13:04'! initialize super initialize. keyboard := GKeyboard attachedTo: self. mouse := GMouse attachedTo: self. display := GDisplay attachedTo: self . log := GLog new. lastCycleTime := Time millisecondClockValue. sensor := SystemInputEventAnnouncer new. ! ! !GUserInterface methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/2/2012 12:19'! initializePeripherals mouse resetAt: 0@0. ! ! !GUserInterface methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/19/2012 19:56'! install self isInstalled not ifTrue:[ self resume ]. ! ! !GUserInterface methodsFor: 'testing' stamp: 'FernandoOlivero 11/25/2011 16:16'! isInstalled ^ self class current == self ! ! !GUserInterface methodsFor: 'debugging' stamp: 'FernandoOlivero 2/8/2012 14:30'! openDebuggerOn: aProcess context: aContext label: aTitle contents: aContentsStringOrNil fullView: aBool self log log: 'Debugger'. interrupted := true. Processor yield. ! ! !GUserInterface methodsFor: 'debugging' stamp: 'FernandoOlivero 2/8/2012 14:30'! openInspector: anInspector asMorphOn: anObject withLabel: aLabel self log log: 'Inspector'. interrupted := true. Processor yield. ! ! !GUserInterface methodsFor: 'debugging' stamp: 'FernandoOlivero 2/19/2012 19:57'! resume "to resume after a morphic session" self log clear;start. self log log: 'RESUME-Gaucho'. self class current: self. self initializePeripherals. process := self newUIProcess. process run. ! ! !GUserInterface methodsFor: 'debugging' stamp: 'FernandoOlivero 2/8/2012 14:30'! unhandledErrorDefaultAction: anException self log log: anException. interrupted := true. Processor yield. ! ! !GUserInterface methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 01:23'! shapeAround: aDisplayPoint ^ display shapeAround: aDisplayPoint! ! !GUserInterface methodsFor: 'updating' stamp: 'FernandoOlivero 1/27/2012 15:34'! view: aGView in: aGDisplay removed: aGShape "if the view is active, then possibly a pointing device peripheral was over the removed shape, notify the userinterface so he notify the peripheral devices" "For now we only have a mouse" mouse removedShape: aGShape! ! !GUserInterface methodsFor: 'updating' stamp: 'FernandoOlivero 2/19/2012 10:49'! view: aGView in: aGDisplay resized: aGShape "if the view is active, then possibly a pointing device peripheral was over the removed shape, notify the userinterface so he notify the peripheral devices" "For now we only have a mouse" mouse resizedShape: aGShape! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GUserInterface class instanceVariableNames: 'current'! !GUserInterface class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 1/23/2012 16:28'! MinCycleLapse: milliseconds "set the minimum amount of time that may transpire between two calls to doOneCycle" MinCycleLapse := milliseconds ifNotNil: [ milliseconds rounded ].! ! !GUserInterface class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 11/25/2011 16:16'! current ^ current ! ! !GUserInterface class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 2/2/2012 12:59'! current: aGUserInterface current := aGUserInterface. MinCycleLapse := 20. "allows 50 frames per second..." ! ! !GUserInterface class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 2/2/2012 01:52'! releaseCurrent current := nil . ! ! Object subclass: #GauchoUI instanceVariableNames: 'session renderer' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GauchoUI methodsFor: 'initialize-release' stamp: 'FernandoOlivero 3/6/2012 11:47'! finalize session == NativeBoost uniqueSessionObject ifTrue: [ renderer finalize. session := renderer := nil. ] ! ! !GauchoUI methodsFor: 'initialize-release' stamp: 'FernandoOlivero 3/6/2012 11:48'! initialize super initialize. session := NativeBoost uniqueSessionObject. self finalizationRegistry add: self.! ! Object subclass: #GDisplayLayouter instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GDisplayLayouter methodsFor: 'accessing' stamp: 'FernandoOlivero 2/27/2012 08:31'! viewportForSingleView ^ (self viewportsFor:1) first! ! !GDisplayLayouter methodsFor: 'accessing' stamp: 'FernandoOlivero 2/27/2012 08:47'! viewportsFor: aNumber aNumber = 1 ifTrue:[ ^ {NDCViewport all} ]. aNumber = 2 ifTrue:[ ^ {NDCViewport at: 0.1@0.1 extending: 0.5@0.5. NDCViewport at: 0.65@0.3 extending: 0.3@0.3} ]. aNumber = 3 ifTrue:[ ^ {NDCViewport upperLeft. NDCViewport upperRight. NDCViewport bottomLeft. } ]. aNumber = 4 ifTrue:[ ^ {NDCViewport upperLeft. NDCViewport upperRight. NDCViewport bottomLeft. NDCViewport bottomRight } ]. ! ! Object subclass: #NDCViewport instanceVariableNames: 'minX maxX minY maxY' classVariableNames: 'All BottomLeft BottomRight UpperLeft UpperRight' poolDictionaries: '' category: 'GauchoUI-Core'! !NDCViewport commentStamp: 'FernandoOlivero 6/15/2011 15:06' prior: 0! Viewport: rectangular region on device. The standardized coordinate system for all devices. The user may want to create images on different parts of the screen so we define a viewport in Normalized Device Coordinates (NDC). Normalized Device Coordinates: Let the entire display surface have coordinate values 0.0 <= x,y <= 1.0 http://www.siggraph.org/education/materials/HyperGraph/viewing/view2d/pviep.htm http://omega.di.unipi.it/web/IUM/Waterloo/node14.html! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 1/23/2012 15:30'! boundsIn: anExtent ^ (anExtent * self origin) extent: (anExtent * self extent) ! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:09'! extent ^ maxX - minX @ (maxY - minY)! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 7/2/2011 13:41'! height ^ maxY - minY ! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:11'! maxX ^ maxX! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:11'! maxY ^ maxY! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:11'! minX ^ minX! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:11'! minY ^ minY! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 6/15/2011 11:11'! origin ^ minX @ minY! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:19'! snapshot ^ {minX. maxX. minY. maxY}! ! !NDCViewport methodsFor: 'accessing' stamp: 'FernandoOlivero 7/2/2011 13:41'! width ^ maxX - minX ! ! !NDCViewport methodsFor: 'transformation' stamp: 'FernandoOlivero 1/24/2012 12:48'! externalize: aNDCPoint into: aDisplay | x y | x := aNDCPoint x * aDisplay extent x . y := aNDCPoint y * aDisplay extent y . ^ x @ y! ! !NDCViewport methodsFor: 'transformation' stamp: 'FernandoOlivero 1/24/2012 13:26'! externalizeBounds: aNDCRectangle into: aDisplay | x y cornerX cornerY | x := aNDCRectangle left * aDisplay extent x . y := aNDCRectangle top * aDisplay extent y . cornerX := aNDCRectangle right * aDisplay extent x . cornerY := aNDCRectangle bottom * aDisplay extent y . ^ x @ y corner: cornerX @ cornerY! ! !NDCViewport methodsFor: 'transformation' stamp: 'FernandoOlivero 2/27/2012 09:18'! internalize: aDisplayPoint from: aDisplay | x y offset external | offset := self origin * aDisplay extent. external := aDisplayPoint - offset . x := external x / aDisplay extent x. y := external y / aDisplay extent y. ^ x@y! ! !NDCViewport methodsFor: 'transformation' stamp: 'FernandoOlivero 1/30/2012 14:43'! internalizeBounds: aRectangle from: aDisplay | x y cx cy | x := aRectangle origin x / aDisplay extent x. y := aRectangle origin y / aDisplay extent y. cx := aRectangle corner x / aDisplay extent x. cy := aRectangle corner y / aDisplay extent y. ^ x @ y extent: cx@cy! ! !NDCViewport methodsFor: 'initialize-release' stamp: 'FernandoOlivero 6/15/2011 19:16'! initializeAt: aPoint extendingTo: aCorner minX := aPoint x. maxX := aCorner x. minY := aPoint y. maxY := aCorner y.! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! NDCViewport class instanceVariableNames: ''! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 7/9/2011 10:07'! all All isNil ifTrue:[ All := self at: 0 @ 0 extendingTo: 1.0 @ 1.0 ]. ^ All! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 6/15/2011 08:43'! at: aPoint extending: anExtent ^ self at: aPoint extendingTo: (aPoint + anExtent ) ! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 6/15/2011 08:42'! at: anOrigin extendingTo: aCorner | v | v := self new. v initializeAt: anOrigin extendingTo: aCorner. ^ v! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 12/20/2011 15:57'! bottomLeft BottomLeft isNil ifTrue:[ BottomLeft := self at: 0 @ 0.5 extendingTo: 0.5 @ 1.0 ]. ^ BottomLeft! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 12/20/2011 15:58'! bottomRight BottomRight isNil ifTrue:[ BottomRight := self at: 0.5 @ 0.5 extendingTo: 1.0 @ 1.0 ]. ^ BottomRight! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 2/27/2012 08:07'! insetBy: aDelta ^ self at: aDelta@aDelta extendingTo: (1.0 @ 1.0) - aDelta ! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 12/20/2011 15:59'! upperLeft UpperLeft isNil ifTrue:[ UpperLeft := self at: 0 @ 0 extendingTo: 0.5 @ 0.5 ]. ^ UpperLeft ! ! !NDCViewport class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 12/20/2011 15:59'! upperRight UpperRight isNil ifTrue:[ UpperRight := self at: 0.5 @ 0 extendingTo: 1.0 @ 0.5 ]. ^ UpperRight ! ! Object subclass: #GSceneWindow instanceVariableNames: 'bounds scene internalizedBounds planeRect' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GSceneWindow commentStamp: 'FernandoOlivero 12/20/2011 12:09' prior: 0! Window: rectangular region of interest in scene. When we model an image in World Device Coordinates (WDC) we are not interested in the entire world but only a portion of it. Therefore we define the portion of interest which is a polygonal area specified in world coordinates, called the "window". Zooming: Now increase the window size and the house appears smaller, i.e., you have zoomed out: If you decrease the window size the house appears larger, i.e., you have zoomed in. Panning: Moving all objects in the scene by changing the window is called "panning". http://www.siggraph.org/education/materials/HyperGraph/viewing/view2d/2dview1.htm http://omega.di.unipi.it/web/IUM/Waterloo/node14.html http://www.di.ubi.pt/~agomes/cg/teoricas/04e-windows.pdf! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 12/21/2011 15:34'! atOrigin bounds origin: 0@0.! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 6/16/2011 12:46'! bounds ^ bounds ! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 2/26/2012 19:59'! bounds: aBounds self intializeAt: aBounds origin extending: aBounds extent ! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 6/16/2011 12:46'! extent ^ bounds extent ! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 2/26/2012 20:13'! extent: aPoint bounds extent: aPoint. self boundsChanged! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 7/2/2011 13:41'! height ^ bounds height! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 10/24/2011 15:00'! origin ^ bounds origin! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 12/21/2011 10:02'! scene: aGScene scene := aGScene! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 2/25/2012 15:18'! snapshot ^ {bounds}! ! !GSceneWindow methodsFor: 'accessing' stamp: 'FernandoOlivero 7/2/2011 13:41'! width ^ bounds width! ! !GSceneWindow methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/26/2012 20:13'! boundsChanged | planeOrigin | planeOrigin := scene internalize: bounds bottomLeft. planeRect := YAxisUpRectangle at: planeOrigin extending: bounds extent. ! ! !GSceneWindow methodsFor: 'initialize-release' stamp: 'FernandoOlivero 2/26/2012 20:13'! intializeAt: anOrigin extending: anExtent bounds := anOrigin extent: anExtent. self boundsChanged. ! ! !GSceneWindow methodsFor: 'initialize-release' stamp: 'FernandoOlivero 12/21/2011 09:44'! intializeOn: aScene at: anOrigin extending: anExtent self scene: aScene. self intializeAt: anOrigin extending: anExtent! ! !GSceneWindow methodsFor: 'geometry' stamp: 'FernandoOlivero 2/26/2012 20:18'! externalize: aWDCPoint to: aViewport | widthScale heightScale resultX resultY | "first translate to origin, then scale down to viewport viewport is always 0=>1 here, the viewport origin is taken into account in the viewport->display transformation" widthScale := 1 / self width . heightScale := 1 / self height. resultX := widthScale * (aWDCPoint x - bounds left ) . resultY := heightScale * (aWDCPoint y - bounds top ) . ^ resultX @ resultY ! ! !GSceneWindow methodsFor: 'geometry' stamp: 'FernandoOlivero 1/23/2012 13:17'! externalizeBounds: aWDCRectangle to: aViewport | origin corner | origin := self externalize: aWDCRectangle origin to: aViewport. corner := self externalize: aWDCRectangle corner to: aViewport. ^ origin corner: corner.! ! !GSceneWindow methodsFor: 'geometry' stamp: 'FernandoOlivero 2/26/2012 20:17'! internalize: aNDCPoint from: aViewport | widthScale heightScale resultX resultY | "first scale up from viewport, second translate from origin" widthScale := bounds width . heightScale := bounds height. resultX := (widthScale * aNDCPoint x) + bounds left . resultY := (heightScale * aNDCPoint y) + bounds top . ^ resultX @ resultY ! ! !GSceneWindow methodsFor: 'panning-zooming' stamp: 'FernandoOlivero 2/26/2012 20:14'! panBy: aDelta " aPoint is in World device coordinates WDC" self bounds:( bounds translateBy: aDelta)! ! !GSceneWindow methodsFor: 'panning-zooming' stamp: 'FernandoOlivero 2/26/2012 20:15'! panFrom: origin to: destination "point is in World device coordinates WDC: Scene coordinates" | delta octant direction | octant := origin octantOf: destination. direction := { {'left->right'. {1. 8}. (destination x - origin x @ 0)}. {'top->bottom'. {2. 3}. 0@(destination y - origin y) abs}. {'right->left'. {4. 5}. ( (destination x - origin x) abs negated @ 0)}. {'bottom->top'. {6. 7} . (0@ (destination y - origin y ) abs negated)} } detect:[:each| each second includes: octant ]. self bounds:( bounds translateBy: direction third).! ! !GSceneWindow methodsFor: 'clipping' stamp: 'FernandoOlivero 2/26/2012 20:13'! visibleShapes ^ (scene plane enumerateNonEmptyTilesUnder: planeRect ) collect:#value ! ! !GSceneWindow methodsFor: 'clipping' stamp: 'FernandoOlivero 2/26/2012 20:13'! visibleTiles ^ scene plane enumerateTilesUnder: planeRect ! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GSceneWindow class instanceVariableNames: ''! !GSceneWindow class methodsFor: 'instance creation' stamp: 'FernandoOlivero 12/21/2011 09:43'! at: anOrigin extending: anExtent | w | w := self new. w intializeAt: anOrigin extending: anExtent. ^ w! ! !GSceneWindow class methodsFor: 'instance creation' stamp: 'FernandoOlivero 12/21/2011 09:28'! on: aScene at: anOrigin extending: anExtent | w | w := self new. w intializeOn: aScene at: anOrigin extending: anExtent. ^ w! ! UIManager subclass: #GauchoUIManager instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GauchoUI-Core'! !GauchoUIManager methodsFor: 'accessing' stamp: 'FernandoOlivero 2/29/2012 12:20'! checkForNewDisplaySize Display extent = DisplayScreen actualScreenSize ifTrue: [^ self]. DisplayScreen startUp. ! ! !GauchoUIManager methodsFor: 'accessing' stamp: 'FernandoOlivero 2/2/2012 11:52'! theme ^ GTheme current! ! !GauchoUIManager methodsFor: 'accessing' stamp: 'FernandoOlivero 2/2/2012 13:51'! uiProcess ^ GUserInterface current uiProcess.! ! !GauchoUIManager methodsFor: 'debugging' stamp: 'FernandoOlivero 2/24/2012 04:13'! informUserDuring: aBlock aBlock value: [:string | ].! ! !GauchoUIManager methodsFor: 'debugging' stamp: 'FernandoOlivero 2/2/2012 11:46'! openDebuggerOn: process context: context label: title contents: contentsStringOrNil fullView: bool GUserInterface current openDebuggerOn: process context: context label: title contents: contentsStringOrNil fullView: bool ! ! !GauchoUIManager methodsFor: 'debugging' stamp: 'FernandoOlivero 2/8/2012 14:24'! openInspector: anInspector asMorphOn: anObject withLabel: aLabel GUserInterface current openInspector: anInspector asMorphOn: anObject withLabel: aLabel! ! !GauchoUIManager methodsFor: 'debugging' stamp: 'FernandoOlivero 2/2/2012 13:30'! unhandledErrorDefaultAction: anException GUserInterface current unhandledErrorDefaultAction: anException! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GauchoUIManager class instanceVariableNames: ''! !GauchoUIManager class methodsFor: 'as yet unclassified' stamp: 'FernandoOlivero 2/2/2012 13:32'! isActiveManager "Answer whether I should act as the active ui manager" ^ true! !