summaryrefslogtreecommitdiff
path: root/Experimental/standalone-sheet.lisp
blob: c8ea06d0f483dda013aa817d32e19d0ae180e45f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
(in-package #:clim-user)

;;; A complete sheet should subclass basic-sheet and pick its mixins:
;;;
;;;   Input protocol (xor):
;;;
;;;     standard-sheet-input-mixin
;;;     delegate-sheet-input-mixin
;;;     immediate-sheet-input-mixin
;;;     sheet-mute-input-mixin
;;;
;;;   Output protocol:
;;;
;;;     standard-sheet-output-mixin xor sheet-mute-output-mixin
;;;     sheet-with-medium-mixin
;;;         permanent-medium-sheet-output-mixin
;;;         temporary-medium-sheet-output-mixin
;;;
;;;   Genealogy:
;;;
;;;     sheet-parent-mixin
;;;     sheet-leaf-mixin xor sheet-single-child-mixin xor sheet-multiple-child-mixin
;;;
;;;   Repainting (xor):
;;;
;;;     standard-repainting-mixin
;;;     immediate-repainting-mixin
;;;     sheet-mute-repainting-mixin
;;;
;;;   Geometry (xor):
;;;
;;;     sheet-identity-transformation-mixin
;;;     sheet-translation-mixin
;;;     sheet-y-inverting-transformation-mixin
;;;     sheet-transformation-mixin
;;;
;;;   Windowing (zero or more, may be mixed, the order of mixins is important)
;;;
;;;     top-level-sheet-mixin
;;;     unmanaged-sheet-mixin
;;;     mirrored-sheet-mixin
;;;

(defvar *glider*
  (make-pattern-from-bitmap-file
   (asdf:component-pathname
    (asdf:find-component "clim-examples" '("images" "glider.png")))))

(defclass plain-sheet (;; repainting
                       immediate-repainting-mixin
                       ;; input
                       immediate-sheet-input-mixin
                       ;; output
                       permanent-medium-sheet-output-mixin
                       ;temporary-medium-sheet-output-mixin
                       ;sheet-with-medium-mixin
                       ;sheet-mute-output-mixin
                       ;; geometry
                       sheet-transformation-mixin
                       ;; genealogy
                       sheet-parent-mixin
                       sheet-leaf-mixin
                       ;; windowing
                       top-level-sheet-mixin
                       mirrored-sheet-mixin
                       ;; the base class
                       basic-sheet)
  ()
  (:default-initargs :icon *glider*
                     :pretty-name "McCLIM Test Sheet"
                     :region (make-rectangle* -200 -200 200 200)
                     :transformation (make-scaling-transformation 2 2)))

(defmethod handle-event ((sheet plain-sheet) event)
  )

(defvar *title* "McCLIM Test Sheet")
(defvar *extra* nil)

(defun update-title (sheet)
  (setf (sheet-pretty-name sheet)
        (format nil "~a ~{~s~^ ~}" *title* *extra*)))

(defun open-plain-sheet (path sheet)
  (let ((port (find-port :server-path path)))
    (let ((graft (find-graft :port port)))
      (sheet-adopt-child graft sheet)
      ;; FIXME CLX thinks that every tpl sheet is adopted by a frame.
      (climb:enable-mirror port sheet)
      sheet)))

(defun make-plain-sheet ()
  (make-instance 'plain-sheet))

(defun close-plain-sheet (sheet)
  (sheet-disown-child (graft sheet) sheet)
  nil)

(defmethod handle-event ((sheet plain-sheet) (event window-manager-delete-event))
  (sheet-disown-child (graft sheet) sheet))

(defmethod handle-event ((sheet plain-sheet) (event window-repaint-event))
  (dispatch-repaint sheet (window-event-region event)))

;;; It may be surprising that nobody updates SHEET-MIRROR-GEOMETRY but
;;; HANDLE-SDL2-WINDOW-EVENT gets correct values. This is because of a
;;; HANDLE-EVENT :BEFORE method specialized to MIRRORED-SHEET-MIXIN in core.
;;; Whether that method stays depends on how we resolve the FIXME above.

(defmethod handle-event ((sheet plain-sheet) (event window-configuration-event))
  (with-bounding-rectangle* (x1 y1 x2 y2 :width w :height h)
                            (window-event-native-region event)
    (let ((climi::*configuration-event-p* sheet))
      (let ((new-transformation (make-translation-transformation x1 y1))
            (new-region (make-bounding-rectangle 0 0 w h)))
        ;; This indirectly modifies the native region.
        (climi::%set-sheet-region-and-transformation sheet new-region new-transformation)))
    (setf (getf *extra* :dims)
          (format nil "[~s ~s ~s ~s] (~s x ~s)" x1 y1 x2 y2 w h))
    (update-title sheet)))

(defmethod handle-event ((sheet plain-sheet) (event window-manager-focus-event))
  (setf (port-keyboard-input-focus (port sheet)) sheet))

(defmethod handle-event ((sheet plain-sheet) (event pointer-enter-event))
  (setf (getf *extra* :pointer) "y")
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event pointer-exit-event))
  (setf (getf *extra* :pointer) "n")
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event key-press-event))
  (setf (getf *extra* :key) (keyboard-event-key-name event))
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event key-release-event))
  (setf (getf *extra* :key) nil)
  (update-title sheet))

#+ (or)
(defmethod handle-event ((sheet plain-sheet) (event text-input-event))
  (setf (getf *extra* :str) (text-input-event-string event))
  (when (string= " " (text-input-event-string event))
    (dispatch-repaint sheet +everywhere+))
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event pointer-motion-event))
  (setf (getf *extra* :pointer)
        (format nil "ptr+~s [~s ~s]"
                (event-modifier-state event)
                (pointer-event-x event)
                (pointer-event-y event)))
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event climb:pointer-scroll-event))
  (setf (getf *extra* :pointer)
        (format nil "scr+~s [~s ~s]"
                (event-modifier-state event)
                (climi::pointer-event-delta-x event)
                (climi::pointer-event-delta-y event)))
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event pointer-button-press-event))
  (setf (getf *extra* :pointer)
        (format nil "bdn+~s ~s"
                (event-modifier-state event)
                (pointer-event-button event)))
  (update-title sheet))

(defmethod handle-event ((sheet plain-sheet) (event pointer-button-release-event))
  (setf (getf *extra* :pointer)
        (format nil "bup+~s ~s"
                (event-modifier-state event)
                (pointer-event-button event)))
  (update-title sheet))

;;; Repainting protocol
(defmethod handle-repaint ((sheet plain-sheet) region)
  (let ((medium sheet))
    (with-bounding-rectangle* (x1 y1 x2 y2) medium
      (medium-clear-area medium x1 y1 x2 y2)
      (draw-rectangle* medium (+ x1 10) (+ y1 10) (- x2 10) (- y2 10)
                       :ink +deep-pink+)
      (draw-circle* medium 0 0 75 :ink (alexandria:random-elt
                                        (make-contrasting-inks 8)))
                                        ;(draw-text* medium "(0,0)" 0 0)
                                        ;(sleep 1)
      (medium-finish-output medium))))

(defun start (server-path)
  (open-plain-sheet server-path (make-plain-sheet)))

;;; This function migrates a frame from one port to another without
;;; reconstructing the pane hierarchy.
(defun wololo (frame port)
  (let ((tpl-sheet (frame-top-level-sheet frame))
        (new-graft (find-graft :port port)))
    (sheet-disown-child (sheet-parent tpl-sheet) tpl-sheet)
    (sheet-adopt-child new-graft tpl-sheet)
    (climb:enable-mirror port tpl-sheet)))