moo/moo/kernel/X11.moo

837 lines
17 KiB
Smalltalk
Raw Normal View History

#include "Moo.moo".
2017-04-05 16:48:20 +00:00
interface X11able
{
method(#dual) abc.
method(#dual,#liberal) def(x, y).
}
interface X11able2
{
method(#dual) abc2.
method(#dual) def.
}
interface X11able3
{
method(#dual) class.
}
class QQQ(Object)
{
}
extend QQQ [X11able]
{
method(#dual) abc { ^nil }
method(#dual,#liberal) def(x, z) { ^nil }
}
class X11(Object) [X11able,selfns.X11able3] from "x11"
2017-04-05 16:48:20 +00:00
{
// =====================================================================
// this part of the class must match the internal
// definition struct x11_t defined in _x11.h
// ---------------------------------------------------------------------
2017-06-18 17:29:32 +00:00
var display_base := nil.
// =====================================================================
2017-06-23 16:09:07 +00:00
var shell_container := nil.
var window_registrar. // all windows registered
2017-06-23 16:09:07 +00:00
var event_loop_sem, event_loop_proc.
var llevent_blocks.
2017-04-05 16:48:20 +00:00
method(#dual) abc { ^nil }
method(#dual,#liberal) def(x, z) { ^nil }
//#method(#dual) abc3 { ^nil }
interface X11able3
{
method(#dual) abc55.
}
class Exception(System.Exception)
{
}
class Point(Object)
{
var(#get,#set) x := 0, y := 0.
}
class Dimension(Object)
{
var(#get,#set) width := 0, height := 0.
}
class Rectangle(Object)
{
var(#get,#set)
x := 0,
y := 0,
width := 0,
height := 0.
}
extend Point
{
method print
{
x dump.
y dump.
}
}
/*
TODO: TODO: compiler enhancement
class X11(Object)
{
class Rectangl(Object)
{
}
}
class XRect(X11.X11.Rectangl) -> X11 in X11.Rectangl is not the inner X11. as long as a period is found, the search begins at top.
{
}
----> should i support soemthign like ::X11.Rectangle and X11.Rectangle? ::X11.Rectangle alwasy from the top???
-----> or .X11.Rectangle -> to start search from the current name space???
*/
2017-06-23 16:09:07 +00:00
method(#primitive,#liberal) _open_display(name).
method(#primitive) _close_display.
method(#primitive) _get_fd.
method(#primitive) _get_llevent(llevent).
2017-06-16 09:45:22 +00:00
method(#primitive) _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
method(#primitive) _destroy_window(window_handle).
2017-06-23 16:09:07 +00:00
method(#primitive) _create_gc (window_handle).
method(#primitive) _destroy_gc (gc). // note this one accepts a GC object.
method(#primitive) _apply_gc (gc). // note this one accepts a GC object, not a GC handle.
2017-06-23 16:09:07 +00:00
method(#primitive) _draw_rectangle(window_handle, gc_handle, x, y, width, height).
method(#primitive) _fill_rectangle(window_handle, gc_handle, x, y, width, height).
method(#primitive) _draw_string(gc, x, y, string).
method __create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor, owner)
2017-06-23 16:09:07 +00:00
{
| w |
w := self _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
2017-06-23 16:09:07 +00:00
if (w notError) { self.window_registrar at: w put: owner }.
^w
}
2017-06-27 16:03:29 +00:00
method __destroy_window(window_handle)
2017-06-23 16:09:07 +00:00
{
| w |
//#('DESTROY ' & window_handle asString) dump.
2017-06-23 16:09:07 +00:00
w := self _destroy_window(window_handle).
if (w notError) { self.window_registrar removeKey: window_handle }
}
2017-04-05 16:48:20 +00:00
}
// ---------------------------------------------------------------------------
// Event
// ---------------------------------------------------------------------------
2017-06-23 16:09:07 +00:00
pooldic X11.LLEventType
2017-04-05 16:48:20 +00:00
{
KEY_PRESS := 2.
KEY_RELEASE := 3.
BUTTON_PRESS := 4.
BUTTON_RELEASE := 5.
MOTION_NOTIFY := 6.
ENTER_NOTIFY := 7.
LEAVE_NOTIFY := 8.
EXPOSE := 12.
VISIBILITY_NOTIFY := 15.
DESTROY_NOTIFY := 17.
2017-04-07 15:50:05 +00:00
CONFIGURE_NOTIFY := 22.
2017-04-05 16:48:20 +00:00
CLIENT_MESSAGE := 33.
2017-06-27 16:03:29 +00:00
SHELL_CLOSE := 65537.
2017-04-05 16:48:20 +00:00
}
2017-06-23 16:09:07 +00:00
class X11.LLEvent(Object)
{
var(#get) type := 0, window := 0, x := 0, y := 0, width := 0, height := 0.
}
2017-04-05 16:48:20 +00:00
class X11.Event(Object)
{
}
class X11.KeyEvent(X11.Event)
2017-04-05 16:48:20 +00:00
{
}
pooldic X11.MouseButton
2017-04-05 16:48:20 +00:00
{
LEFT := 1.
MIDDLE := 2.
RIGHT := 3.
2017-04-05 16:48:20 +00:00
}
class X11.MouseEvent(X11.Event)
2017-04-05 16:48:20 +00:00
{
2017-06-16 09:45:22 +00:00
var(#get,#set)
x := 0,
y := 0,
button := 0. // X11.MouseButton
2017-04-05 16:48:20 +00:00
}
class X11.MouseWheelEvent(X11.Event)
2017-04-05 16:48:20 +00:00
{
2017-06-16 09:45:22 +00:00
var(#get,#set)
x := 0,
y := 0,
amount := 0.
2017-04-05 16:48:20 +00:00
}
class X11.ExposeEvent(X11.Event)
{
2017-06-16 09:45:22 +00:00
var(#get,#set)
x := 0,
y := 0,
width := 0,
height := 0.
2017-04-05 16:48:20 +00:00
}
2017-06-18 17:29:32 +00:00
// ---------------------------------------------------------------------------
// X11 Context
// ---------------------------------------------------------------------------
pooldic X11.GCLineStyle
{
SOLID := 0.
ON_OFF_DASH := 1.
DOUBLE_DASH := 2.
}
pooldic X11.GCFillStyle
2017-06-23 16:09:07 +00:00
{
SOLID := 0.
TILED := 1.
STIPPLED := 2.
OPAQUE_STIPPLED := 3.
}
class X11.GC(Object)
{
// note these fields must match the x11_gc_t structure defined in _x11.h
2017-06-23 16:09:07 +00:00
var(#get) widget := nil, gcHandle := nil.
var(#get,#set)
foreground := 0,
background := 1,
2017-06-23 16:09:07 +00:00
lineWidth := 1,
lineStyle := X11.GCLineStyle.SOLID,
fillStyle := X11.GCFillStyle.SOLID,
fontName := nil.
var fontPtr := nil.
var fontSet := nil.
method(#class) new
{
self messageProhibited: #new.
}
2017-06-23 16:09:07 +00:00
method(#class) new: widget
{
^(super new) __make_gc_on: widget
}
method __make_gc_on: widget
{
| gc |
widget displayServer dump.
widget windowHandle dump.
2017-06-23 16:09:07 +00:00
gc := widget displayServer _create_gc (widget windowHandle).
if (gc isError) { selfns.Exception signal: "Cannot create a graphics context" }.
2017-06-23 16:09:07 +00:00
self.gcHandle := gc.
self.widget := widget.
}
method drawRectangle(x, y, width, height)
{
^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
}
2017-06-23 16:09:07 +00:00
method fillRectangle(x, y, width, height)
{
^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
}
method drawString(x, y, string)
2017-06-23 16:09:07 +00:00
{
^self.widget displayServer _draw_string (self, x, y, string).
}
method dispose
{
if (self.gcHandle notNil)
{
self.widget displayServer _destroy_gc (self).
self.gcHandle := nil
}
}
method apply
{
if (self.gcHandle notNil)
{
if (self.widget displayServer _apply_gc (self) isError)
{
X11.Exception signal: "Cannot apply GC settings"
}
}
2017-06-23 16:09:07 +00:00
}
}
// ---------------------------------------------------------------------------
// X11 Widgets
// ---------------------------------------------------------------------------
2017-06-18 17:29:32 +00:00
2017-06-16 09:45:22 +00:00
class X11.Widget(Object)
2017-04-05 16:48:20 +00:00
{
var(#get) windowHandle := nil.
2017-06-18 17:29:32 +00:00
var(#get,#set)
parent := nil,
x := 0,
y := 0,
width := 0,
height := 0,
fgcolor := 16r1188FF,
2017-06-18 17:29:32 +00:00
bgcolor := 0,
realized := false.
2017-06-23 16:09:07 +00:00
method displayServer
2017-04-05 16:48:20 +00:00
{
2017-06-23 16:09:07 +00:00
if (self.parent isNil) { ^nil }.
^self.parent displayServer.
2017-04-07 15:50:05 +00:00
}
method parentWindowHandle
2017-06-18 17:29:32 +00:00
{
if (self.parent isNil) { ^nil }.
2017-06-23 16:09:07 +00:00
^self.parent windowHandle.
}
method realize
{
| disp wind |
if (self.windowHandle notNil) { ^self }.
disp := self displayServer.
if (disp isNil)
{
X11.Exception signal: "Cannot realize a widget not added to a display server"
}.
wind := disp __create_window(self parentWindowHandle, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor, self).
if (wind isError)
{
self.Exception signal: "Cannot create widget window".
}.
self.windowHandle := wind.
}
2017-06-27 16:03:29 +00:00
method dispose
2017-06-23 16:09:07 +00:00
{
| disp |
2017-06-27 16:03:29 +00:00
'Widget dispose XXXXXXXXXXXXXX' dump.
disp := self displayServer.
if (disp notNil)
{
if (self.windowHandle notNil)
{
disp __destroy_window (self.windowHandle).
self.windowHandle := nil.
}.
}
2017-06-18 17:29:32 +00:00
}
2017-04-05 16:48:20 +00:00
2017-06-27 16:03:29 +00:00
method onPaintEvent: paint_event
2017-06-18 17:29:32 +00:00
{
}
2017-04-05 16:48:20 +00:00
method onMouseButtonEvent: event
{
}
method onKeyEvent: event
2017-06-27 16:03:29 +00:00
{
}
method onCloseEvent
2017-06-18 17:29:32 +00:00
{
2017-06-23 16:09:07 +00:00
}
2017-04-05 16:48:20 +00:00
}
2017-06-18 17:29:32 +00:00
class X11.Label(X11.Widget)
2017-04-05 16:48:20 +00:00
{
2017-06-18 17:29:32 +00:00
var(#get) text := ''.
2017-06-16 09:45:22 +00:00
2017-06-18 17:29:32 +00:00
method text: text
{
self.text := text.
2017-06-27 16:03:29 +00:00
if (self windowHandle notNil) { self onPaintEvent: nil }
2017-06-18 17:29:32 +00:00
}
2017-04-05 16:48:20 +00:00
2017-06-18 17:29:32 +00:00
method realize
2017-04-05 16:48:20 +00:00
{
super realize.
2017-04-05 16:48:20 +00:00
}
2017-06-18 17:29:32 +00:00
method dispose
2017-04-05 16:48:20 +00:00
{
2017-06-27 16:03:29 +00:00
'Label dispose XXXXXXXXXXXXXX' dump.
super dispose.
2017-06-18 17:29:32 +00:00
}
method onPaintEvent: paint_event
{
| gc |
gc := selfns.GC new: self.
[
gc foreground: self.bgcolor;
fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1';
apply.
gc fillRectangle (0, 0, self.width, self.height).
gc foreground: self.fgcolor; apply.
gc drawRectangle (0, 0, self.width - 1, self.height - 1).
gc drawString(10, 10, self.text).
] ensure: [ gc dispose ]
}
2017-06-18 17:29:32 +00:00
}
class X11.Button(X11.Label)
{
method onMouseButtonEvent: llevent
{
| type x |
type := llevent type.
if (type == X11.LLEventType.BUTTON_PRESS)
{
x := self.fgcolor.
self.fgcolor := self.bgcolor.
self.bgcolor := x.
self onPaintEvent: llevent.
}
elsif (type == X11.LLEventType.BUTTON_RELEASE)
{
x := self.fgcolor.
self.fgcolor := self.bgcolor.
self.bgcolor := x.
self onPaintEvent: llevent.
}
}
}
2017-06-18 17:29:32 +00:00
class X11.Composite(X11.Widget)
{
var children.
2017-04-07 15:50:05 +00:00
2017-06-18 17:29:32 +00:00
method initialize
{
self.children := LinkedList new.
}
method add: widget
{
if (widget parent notNil)
2017-06-16 09:45:22 +00:00
{
selfns.Exception signal: "Cannot add an already added widget".
2017-06-16 09:45:22 +00:00
}.
2017-04-07 15:50:05 +00:00
2017-06-18 17:29:32 +00:00
self.children addLast: widget.
widget parent: self.
}
method remove: widget
{
| link |
2017-06-27 16:03:29 +00:00
if (widget parent ~~ self)
2017-04-05 16:48:20 +00:00
{
selfns.Exception sinal: "Cannot remove an unknown widget"
2017-04-05 16:48:20 +00:00
}.
2017-04-07 15:50:05 +00:00
2017-06-27 16:03:29 +00:00
link := self.children findIdenticalLink: widget.
2017-06-18 17:29:32 +00:00
self.children removeLink: link.
widget parent: nil.
}
2017-06-18 17:29:32 +00:00
method childrenCount
{
^self.children size
2017-04-05 16:48:20 +00:00
}
method realize
{
super realize.
[
self.children do: [:child | child realize ].
] on: System.Exception do: [:ex |
self dispose.
ex pass
].
}
2017-06-16 09:45:22 +00:00
method dispose
2017-04-07 15:50:05 +00:00
{
2017-06-27 16:03:29 +00:00
'Composite dispose XXXXXXXXXXXXXX' dump.
self.children do: [:child |
child dispose.
self remove: child.
].
super dispose
}
method onPaintEvent: event
{
super onPaintEvent: event.
self.children do: [:child |
// TODO: adjust event relative to each child...
child onPaintEvent: event.
2017-06-27 16:03:29 +00:00
]
2017-06-18 17:29:32 +00:00
}
}
2017-04-05 16:48:20 +00:00
2017-06-18 17:29:32 +00:00
class X11.Shell(X11.Composite)
{
2017-06-23 16:09:07 +00:00
var(#get) title := ''.
var(#get,#set) displayServer := nil.
2017-04-05 16:48:20 +00:00
2017-06-18 17:29:32 +00:00
method new: title
{
self.title := title.
}
2017-04-05 16:48:20 +00:00
//// TODO:
//// redefine x:, y:, width:, height: to return actual geometry values...
////
2017-06-18 17:29:32 +00:00
method title: title
{
self.title := title.
2017-06-23 16:09:07 +00:00
if (self.windowHandle notNil)
2017-06-18 17:29:32 +00:00
{
// set window title of this window.
2017-04-07 15:50:05 +00:00
}
2017-04-05 16:48:20 +00:00
}
2017-06-18 17:29:32 +00:00
method realize
2017-04-05 16:48:20 +00:00
{
'SHELL REALIZE XXXXXXXXXXX' dump.
super realize.
2017-06-23 16:09:07 +00:00
}
method dispose
{
2017-06-27 16:03:29 +00:00
'Shell dispose XXXXXXXXXXXXXX' dump.
super dispose.
self.displayServer removeShell: self.
2017-04-05 16:48:20 +00:00
}
2017-06-27 16:03:29 +00:00
method onCloseEvent
{
'ON CLOSE EVENT .............' dump.
self dispose.
}
2017-04-05 16:48:20 +00:00
}
// ---------------------------------------------------------------------------
// X11 server
// ---------------------------------------------------------------------------
2017-04-05 16:48:20 +00:00
extend X11
{
2017-04-07 15:50:05 +00:00
method(#class) new
{
2017-06-18 17:29:32 +00:00
^(super new) __connect_to: nil.
2017-04-07 15:50:05 +00:00
}
2017-06-18 17:29:32 +00:00
method __connect_to: name
2017-04-05 16:48:20 +00:00
{
2017-06-23 16:09:07 +00:00
if (self _open_display(name) isError)
{
self.Exception signal: 'cannot open display'
}.
2017-06-23 16:09:07 +00:00
self.display_base dump.
2017-04-07 15:50:05 +00:00
}
2017-06-18 17:29:32 +00:00
method dispose
2017-04-07 15:50:05 +00:00
{
2017-06-18 17:29:32 +00:00
if (self.shell_container notNil)
{
self.shell_container dispose.
self.shell_container := nil.
}.
if (self.display_base notNil)
{
2017-06-23 16:09:07 +00:00
self _close_display.
self.display_base := nil.
2017-06-23 16:09:07 +00:00
}.
2017-04-05 16:48:20 +00:00
}
2017-04-07 15:50:05 +00:00
2017-04-05 16:48:20 +00:00
method initialize
{
super initialize.
2017-06-23 16:09:07 +00:00
self.shell_container := self.Composite new.
self.window_registrar := System.Dictionary new: 100.
/*
2017-06-23 16:09:07 +00:00
self.llevent_blocks := System.Dictionary new.
self.llevent_blocks
2017-06-27 16:03:29 +00:00
at: self.LLEventType.KEY_PRESS put: #__handle_key_event:on:;
at: self.LLEventType.KEY_RELEASE put: #__handle_key_event:on:;
at: self.LLEventType.BUTTON_PRESS put: #__handle_button_event:on:;
at: self.LLEventType.BUTTON_RELEASE put: #__handle_button_event:on:;
at: self.LLEventType.MOTION_NOTIFY put: #__handle_notify:on:;
at: self.LLEventType.ENTER_NOTIFY put: #__handle_notify:on:;
at: self.LLEventType.LEAVE_NOTIFY put: #__handle_notify:on:;
at: self.LLEventType.EXPOSE put: #__handle_expose:on:;
at: self.LLEventType.DESTROY_NOTIFY put: #__handle_destroy_notify:on:;
at: self.LLEventType.CONFIGURE_NOTIFY put: #__handle_configure_notify:on:;
at: self.LLEventType.CLIENT_MESSAGE put: #__handle_client_message:on:.
*/
self.llevent_blocks := ##{
2017-06-27 16:03:29 +00:00
self.LLEventType.KEY_PRESS -> #__handle_key_event:on:,
self.LLEventType.KEY_RELEASE -> #__handle_key_event:on:,
self.LLEventType.BUTTON_PRESS -> #__handle_button_event:on:,
self.LLEventType.BUTTON_RELEASE -> #__handle_button_event:on:,
self.LLEventType.MOTION_NOTIFY -> #__handle_notify:on:,
self.LLEventType.ENTER_NOTIFY -> #__handle_notify:on:,
self.LLEventType.LEAVE_NOTIFY -> #__handle_notify:on:,
self.LLEventType.EXPOSE -> #__handle_expose:on:,
self.LLEventType.DESTROY_NOTIFY -> #__handle_destroy_notify:on:,
self.LLEventType.CONFIGURE_NOTIFY -> #__handle_configure_notify:on:,
self.LLEventType.CLIENT_MESSAGE -> #__handle_client_message:on:,
self.LLEventType.SHELL_CLOSE -> #__handle_shell_close:on:
2017-06-16 09:45:22 +00:00
}.
2017-06-23 16:09:07 +00:00
2017-04-05 16:48:20 +00:00
}
2017-06-18 17:29:32 +00:00
method addShell: shell
2017-04-05 16:48:20 +00:00
{
2017-06-23 16:09:07 +00:00
if (shell displayServer isNil)
2017-04-05 16:48:20 +00:00
{
2017-06-18 17:29:32 +00:00
self.shell_container add: shell.
2017-06-23 16:09:07 +00:00
shell displayServer: self.
2017-04-05 16:48:20 +00:00
}
}
2017-06-18 17:29:32 +00:00
method removeShell: shell
2017-04-05 16:48:20 +00:00
{
2017-06-23 16:09:07 +00:00
if (shell displayServer notNil)
2017-04-05 16:48:20 +00:00
{
2017-06-18 17:29:32 +00:00
self.shell_container remove: shell.
2017-06-23 16:09:07 +00:00
shell displayServer: nil.
2017-04-05 16:48:20 +00:00
}
}
2017-06-16 09:45:22 +00:00
2017-04-05 16:48:20 +00:00
method enterEventLoop
{
if (self.event_loop_sem isNil)
{
self.event_loop_sem := Semaphore new.
self.event_loop_sem signalOnInput: (self _get_fd).
2017-06-16 09:45:22 +00:00
self.event_loop_proc := [
| llevtbuf llevent ongoing |
2017-06-16 09:45:22 +00:00
llevtbuf := X11.LLEvent new.
2017-04-05 16:48:20 +00:00
ongoing := true.
2017-06-18 17:29:32 +00:00
while (self.shell_container childrenCount > 0)
2017-04-05 16:48:20 +00:00
{
2017-06-23 16:09:07 +00:00
'Waiting for X11 event...' dump.
2017-04-05 16:48:20 +00:00
self.event_loop_sem wait.
if (ongoing not) { break }.
while ((llevent := self _get_llevent(llevtbuf)) notNil)
2017-04-05 16:48:20 +00:00
{
if (llevent isError)
2017-04-05 16:48:20 +00:00
{
//System logNl: ('Error while getting a event from server ' & self.cid asString).
2017-04-05 16:48:20 +00:00
ongoing := false.
break.
}
2017-06-16 09:45:22 +00:00
else
{
self __dispatch_llevent: llevent.
2017-04-05 16:48:20 +00:00
}.
}.
}.
'CLOSING X11 EVENT LOOP' dump.
self.event_loop_sem unsignal.
// TODO: LOOK HERE FOR RACE CONDITION
2017-04-05 16:48:20 +00:00
self.event_loop_sem := nil.
2017-07-21 16:54:43 +00:00
self.event_loop_proc := nil.
2017-06-18 17:29:32 +00:00
self dispose.
2017-04-05 16:48:20 +00:00
] fork.
}
}
2017-06-16 09:45:22 +00:00
2017-04-05 16:48:20 +00:00
method exitEventLoop
{
if (self.event_loop_sem notNil)
{
// TODO: handle race-condition with the part maked 'LOOK HERE FOR RACE CONDITION'
2017-04-05 16:48:20 +00:00
self.event_loop_proc terminate.
self.event_loop_proc := nil.
self.event_loop_sem := nil.
}
}
method signal_event_loop_semaphore
{
self.event_loop_sem signal.
}
method __dispatch_llevent: llevent
2017-04-05 16:48:20 +00:00
{
| widget mthname |
2017-06-16 09:45:22 +00:00
2018-10-08 13:17:11 +00:00
widget := self.window_registrar at: llevent window ifAbsent: [
System logNl: 'Event on unknown widget - ' & (llevent window asString).
^nil
2018-10-08 13:17:11 +00:00
].
2017-06-23 16:09:07 +00:00
2018-10-08 13:17:11 +00:00
mthname := self.llevent_blocks at: llevent type ifAbsent: [
System logNl: 'Unknown event type ' & (llevent type asString).
^nil
2018-10-08 13:17:11 +00:00
].
2018-10-08 13:17:11 +00:00
^self perform(mthname, llevent, widget).
2017-06-27 16:03:29 +00:00
}
method __handle_notify: llevent on: widget
{
2017-04-05 16:48:20 +00:00
}
2017-06-27 16:03:29 +00:00
method __handle_expose: llevent on: widget
2017-04-05 16:48:20 +00:00
{
widget onPaintEvent: llevent
2017-04-05 16:48:20 +00:00
}
method __handle_button_event: llevent on: widget
2017-04-05 16:48:20 +00:00
{
widget onMouseButtonEvent: llevent
2017-04-05 16:48:20 +00:00
}
2017-06-27 16:03:29 +00:00
method __handle_destroy_notify: event on: widget
2017-04-05 16:48:20 +00:00
{
}
2017-04-07 15:50:05 +00:00
2017-06-27 16:03:29 +00:00
method __handle_configure_notify: event on: widget
{
widget onPaintEvent: event.
}
2017-06-16 09:45:22 +00:00
2017-06-27 16:03:29 +00:00
method __handle_client_message: event on: widget
2017-04-07 15:50:05 +00:00
{
2017-06-27 16:03:29 +00:00
widget close: event.
2017-04-07 15:50:05 +00:00
}
method __handle_key_event: llevent on: widget
2017-04-05 16:48:20 +00:00
{
widget onKeyEvent: llevent
2017-04-05 16:48:20 +00:00
}
2017-06-27 16:03:29 +00:00
method __handle_shell_close: llevent on: widget
2017-04-05 16:48:20 +00:00
{
2017-06-27 16:03:29 +00:00
widget onCloseEvent.
2017-04-05 16:48:20 +00:00
}
}
class Fx(Object)
{
2017-07-21 16:54:43 +00:00
var(#class) X := 20.
var x.
method initialize
{
2017-07-21 16:54:43 +00:00
self.X := self.X + 1.
self.x := self.X.
self addToBeFinalized.
}
2017-06-16 09:45:22 +00:00
method finalize
{
2017-07-21 16:54:43 +00:00
System logNl: ('Greate... FX instance finalized' & self.x asString).
}
}
2017-06-18 17:29:32 +00:00
class MyObject(Object)
{
var disp1, disp2, shell1, shell2, shell3.
2017-04-05 16:48:20 +00:00
2017-06-18 17:29:32 +00:00
method main1
2017-04-05 16:48:20 +00:00
{
| comp1 |
2017-07-21 16:54:43 +00:00
2017-06-18 17:29:32 +00:00
self.disp1 := X11 new.
self.disp2 := X11 new.
2017-04-05 16:48:20 +00:00
2017-06-18 17:29:32 +00:00
shell1 := (X11.Shell new title: 'Shell 1').
shell2 := (X11.Shell new title: 'Shell 2').
shell3 := (X11.Shell new title: 'Shell 3').
shell1 x: 10; y: 20; width: 500; height: 500.
2017-06-18 17:29:32 +00:00
shell2 x: 200; y: 200; width: 200; height: 200.
shell3 x: 500; y: 200; width: 200; height: 200.
2017-04-07 15:50:05 +00:00
2017-06-18 17:29:32 +00:00
self.disp1 addShell: shell1.
self.disp1 addShell: shell2.
self.disp2 addShell: shell3.
2017-04-07 15:50:05 +00:00
comp1 := X11.Composite new x: 10; y: 10; width: 400; height: 500.
self.shell1 add: comp1.
comp1 add: (X11.Label new text: '간다'; width: 100; height: 100).
comp1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
// self.shell1 add: (X11.Label new text: 'xxxxxxxx'; width: 100; height: 100).
self.shell1 add: (X11.Button new text: '크레용crayon'; x: 90; y: 90; width: 100; height: 100).
self.shell2 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
self.shell3 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
2017-06-18 17:29:32 +00:00
self.shell1 realize.
self.shell2 realize.
self.shell3 realize.
2017-04-05 16:48:20 +00:00
self.disp1 enterEventLoop. // this is not a blocking call. it spawns another process.
self.disp2 enterEventLoop.
comp1 := Fx new.
Fx new.
2017-07-21 16:54:43 +00:00
comp1 := Fx new.
Fx new.
2017-06-18 17:29:32 +00:00
}
2017-04-05 16:48:20 +00:00
2017-06-16 09:45:22 +00:00
method(#class) main
{
2017-06-18 17:29:32 +00:00
^self new main1
2017-04-05 16:48:20 +00:00
}
}
2017-06-18 17:29:32 +00:00