#BUGFIX by stefan
class: FontDescription
changed: #fromLiteralArrayEncoding:
set sizeUnit
"{ Encoding: utf8 }"
"{ Package: 'stx:libview' }"
"{ NameSpace: Smalltalk }"
DeviceWorkstation subclass:#ElectronWorkstation
instanceVariableNames:'bridge rendererBridgePerBrowserWindow eventQueue'
classVariableNames:'ExposureMask StructureNotifyMask KeyPressMask KeyReleaseMask
PointerMotionMask EnterWindowMask LeaveWindowMask ButtonPressMask
ButtonMotionMask ButtonReleaseMask PropertyChangeMask'
poolDictionaries:''
category:'Interface-Graphics'
!
DeviceGraphicsContext subclass:#ElectronGraphicsContext
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
privateIn:ElectronWorkstation
!
!ElectronWorkstation class methodsFor:'documentation'!
documentation
"
experimental work in progress: a Display which draws in an electron application.
"
!
example1
|dpy result|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
result := dpy bridge
callFunction:'helloE'
withArguments:#().
Transcript showCR:result.
self assert:result == 123.
dpy close.
"
Display2 close
"
!
example2
|dpy result|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
result := dpy bridge
eval:'return 10+20'
withArguments:#().
Transcript showCR:result.
self assert:result == 30.
result := dpy bridge
eval:'return arguments[0]+arguments[1]+1'
withArguments:#(10 20).
Transcript showCR:result.
self assert:result == 31.
dpy close.
"
Display2 close
"
!
example3a
|v1 dpy|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
v1 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello1';
open.
Delay waitForSeconds:3.
v1 close.
Delay waitForSeconds:1.
dpy close.
"
Display2 close
"
!
example3b
|v1 v2 dpy|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
v1 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello1';
open.
v2 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello2';
open.
Delay waitForSeconds:3.
v1 close.
Delay waitForSeconds:3.
v2 close.
Delay waitForSeconds:1.
dpy close.
"
Display2 close
"
!
example4
|v1 v2 dpy|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
v1 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello1';
open.
v2 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello2';
open.
Delay waitForSeconds:1.
v1 unrealize.
Delay waitForSeconds:1.
v1 realize.
Delay waitForSeconds:1.
v1 close.
Delay waitForSeconds:1.
v2 unrealize.
Delay waitForSeconds:1.
v2 realize.
Delay waitForSeconds:1.
v2 close.
Delay waitForSeconds:1.
dpy close.
"
Display2 close
"
!
example5
|v1 dpy|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
v1 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello1';
open.
Delay waitForSeconds:1.
v1 extent:(400@300).
Delay waitForSeconds:1.
v1 extent:(200@150).
Delay waitForSeconds:1.
v1 close.
Delay waitForSeconds:1.
dpy close.
"
Display2 close
"
!
example5b
|v1 dpy|
Smalltalk at:#Display2 put:(dpy := ElectronWorkstation newFor:'localhost:8888').
v1 := (TopView onDevice:dpy)
extent:(200 @ 150);
label:'Hello1';
open.
Delay waitForSeconds:1.
v1 origin:(0@0).
Delay waitForSeconds:1.
v1 origin:(200@200).
Delay waitForSeconds:1.
v1 close.
Delay waitForSeconds:1.
dpy close.
"
Display2 close
"
! !
!ElectronWorkstation class methodsFor:'class initialization'!
initialize
ExposureMask := 1 bitShift:0.
StructureNotifyMask := 1 bitShift:1.
KeyPressMask := 1 bitShift:2.
KeyReleaseMask := 1 bitShift:3.
PointerMotionMask := 1 bitShift:4.
EnterWindowMask := 1 bitShift:5.
LeaveWindowMask := 1 bitShift:6.
ButtonPressMask := 1 bitShift:7.
ButtonMotionMask := 1 bitShift:8.
ButtonReleaseMask := 1 bitShift:9.
PropertyChangeMask := 1 bitShift:10.
! !
!ElectronWorkstation class methodsFor:'logging'!
logFacility
"the 'log facility';
this is used by the Logger both as a prefix to the log message,
and maybe (later) used to filter and/or control per-facility log thresholds."
^ self nameWithoutPrefix
! !
!ElectronWorkstation methodsFor:'accessing'!
bridge
^ bridge
!
rendererBridge
^ rendererBridge
! !
!ElectronWorkstation methodsFor:'accessing & queries'!
defaultEventMask
"return a mask to enable some events by default."
^ ExposureMask | StructureNotifyMask |
KeyPressMask | KeyReleaseMask |
PointerMotionMask |
EnterWindowMask | LeaveWindowMask |
ButtonPressMask | ButtonMotionMask | ButtonReleaseMask |
PropertyChangeMask
!
isOpen
"return true, if there is a valid connection to the display"
^ bridge notNil and:[bridge isConnected]
!
supportsPNGImages
"return true, if this device directly supports png images.
Currently none does (except browser windows)"
^ true
! !
!ElectronWorkstation methodsFor:'event handling'!
eventMaskFor:anEventSymbol
^ 1
!
eventPending
^ eventQueue notNil and:[eventQueue notEmpty]
!
setEventMask:eventMask in:drawableId
^ self
! !
!ElectronWorkstation methodsFor:'font stuff'!
ascentOf:aFontId
"/ the font name is its ID
Logger info:'unimplemented: ascentOf'.
^ 17
!
descentOf:aFontId
"/ the font name is its ID
Logger info:'unimplemented: descentOf'.
^ 17
!
getFontWithFamily:familyString face:faceString style:styleString size:sizeArg sizeUnit:sizeUnit encoding:encodingSym
"try to get the specified font, return id.
If not available, try next smaller font.
If no font fits, return nil"
"/ return the font name as ID
^ '%1-%2-%3-%4-%5-%6'
bindWith:familyString
with:faceString
with:styleString
with:sizeArg
with:sizeUnit
with:encodingSym
!
maxAscentOf:aFontId
"/ the font name is its ID
Logger info:'unimplemented: maxAscentOf'.
^ 17
!
maxDescentOf:aFontId
"/ the font name is its ID
Logger info:'unimplemented: maxDescentOf'.
^ 17
!
maxWidthOfFont:aFontId
"/ the font name is its ID
Logger info:'unimplemented: maxWidthOfFont'.
^ 20
!
minWidthOfFont:aFontId
"/ the font name is its ID
Logger info:'unimplemented: minWidthOfFont'.
^ 20
!
widthOf:aString from:index1 to:index2 inFont:aFontId
"/ the font name is its ID
Logger info:'unimplemented: widthOf'.
^ (index2-index1+1) * 20
! !
!ElectronWorkstation methodsFor:'initialization & release'!
closeConnection
"close down connection to Display - usually never done"
|b|
(b := bridge) notNil ifTrue:[
bridge := nil.
b close
].
"Created: 13.1.1997 / 22:10:07 / cg"
!
connectToRenderer:port
|rendererBridge|
[
rendererBridge := bridge class newBridgeForHost:(bridge host) port:port.
rendererBridge connectWithTimeoutMS:5000.
] ifCurtailed:[
rendererBridge notNil ifTrue:[ rendererBridge close ].
rendererBridge := nil.
].
!
initializeFor:aHostAndPortStringOrNil
|nodeBridge _ElectronBridge|
nodeBridge := Smalltalk requirePackage:'exept:bridgeFramework/nodeJSBridge'.
_ElectronBridge := nodeBridge classNamed:'NodeJSBridge::ElectronBridge'.
bridge := _ElectronBridge newBridgeForHostAndPort:aHostAndPortStringOrNil.
[
bridge startBridgeIn:'.' debug:true.
bridge connectWithTimeoutMS:5000.
] ifCurtailed:[
bridge notNil ifTrue:[ bridge close ].
bridge := nil.
].
"/ every browser window has its own renderer!!
rendererBridgePerBrowserWindow := Dictionary new.
self initializeScreenProperties.
self initializeDefaultValues.
self initializeKeyboardMap.
self initializeDeviceSignals.
self initializeDeviceResourceTables.
Screen default isNil ifTrue:[
"not initialized yet?"
self initializeViewStyle.
].
"
ElectronWorkstation newFor:'localhost:8098'
"
!
initializeScreenProperties
super initializeScreenProperties.
monitorType := #unknown.
visualType := #TrueColor.
depth := 24.
redShift := 16.
greenShift := 8.
blueShift := 0.
Display notNil ifTrue:[
width := Display width.
height := Display height.
] ifFalse:[
width := 1280.
height := 1024.
].
! !
!ElectronWorkstation methodsFor:'keyboard stuff'!
ungrabKeyboard
Logger info:'unimplemented: ungrabKeyboard'.
! !
!ElectronWorkstation methodsFor:'pointer stuff'!
pointerPosition
Logger info:'unimplemented: pointerPosition'.
^ 0@0
!
ungrabPointer
Logger info:'unimplemented: ungrabPointer'.
! !
!ElectronWorkstation methodsFor:'private'!
jsonEncode:aReferenceOrObject
aReferenceOrObject isBridgeProxy ifFalse:[^ aReferenceOrObject].
^ Dictionary new
at:'__ref__' put:aReferenceOrObject bridgeRefId;
yourself.
! !
!ElectronWorkstation methodsFor:'window stuff'!
createWindowFor:aView type:typeSymbol origin:org extent:ext
minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:superViewOrNil
style:styleSymbol inputOnly:inp
label:label owner:owner
icon:icn iconMask:icnM iconView:icnV
"returns a remote window handle"
|result args|
"/ does not work - BrowserWindow is invisible
"/ result := bridge
"/ eval:'var win = new BrowserWindow(
"/ {
"/ width: arguments[0],
"/ height: arguments[1]
"/ });
"/ return makeRef(win, "electronWindow");'
"/ withArguments:{ ext x . ext y }.
args := OrderedDictionary new
at:'width' put:ext x;
at:'height' put:ext y;
at:'x' put:org x;
at:'y' put:org y;
yourself.
superViewOrNil notNil ifTrue:[
args at:'parent' put:(self jsonEncode:superViewOrNil id)
].
result := bridge callFunction:'createWindow' withArguments:{ args }.
^ result
!
destroyView:aView withId:aWindowHandle
"/ close is sent to the bridgeObject
aWindowHandle close.
"/ bridge
"/ invokeMethod:'close'
"/ object:aWindowHandle
"/ arguments:#()
!
mapWindow:aWindowId
"map a window"
"/ show is sent to the bridgeObject
aWindowId show.
!
moveWindow:aWindowHandle x:x y:y
"resize a window"
bridge
callFunction:'win_setOrigin'
withArguments:{ aWindowHandle .
(OrderedDictionary new
at:'x' put:x;
at:'y' put:y;
yourself)
}
!
resizeWindow:aWindowHandle width:w height:h
"resize a window"
bridge
callFunction:'win_setExtent'
withArguments:{ aWindowHandle .
(OrderedDictionary new
at:'width' put:w;
at:'height' put:h;
yourself)
}
!
setWindowBackground:aColorIndex in:aWindowHandle
"set a windows background color"
"/ aWindowHandle getBackgroundColor
aWindowHandle setBackgroundColor:(aColorIndex printfPrintString:'#%06x')
"/ Logger info:'unimplemented: setWindowBackground:'.
!
setWindowName:aString in:aWindowHandle
"define a windows name (i.e. windowTitle)"
aWindowHandle setTitle:aString.
"/ Logger info:'unimplemented: setWindowName:'.
!
testResize:windowHandle
bridge callFunction:'testResize' withArguments:{ windowHandle }.
!
unmapWindow:aWindowId
"unmap a window"
"/ hide is sent to the bridgeObject
aWindowId hide.
! !
!ElectronWorkstation::ElectronGraphicsContext class methodsFor:'documentation'!
documentation
"
documentation to be added.
class:
<a short class summary here, describing what instances represent>
responsibilities:
<describing what my main role is>
collaborators:
<describing with whom and how I talk to>
API:
<public api and main messages>
example:
<a one-line examples on how to use - can also be in a separate example method>
implementation:
<implementation points>
[author:]
exept MBP
[instance variables:]
[class variables:]
[see also:]
"
! !
!ElectronWorkstation class methodsFor:'documentation'!
version_CVS
^ '$Header$'
! !
ElectronWorkstation initialize!