webglade.ls (28349B)
1 ;; TODO remove & fix push/pop etc 2 3 (defun member (item lst) 4 (when lst 5 (dolist (i lst) 6 (when (= i item) 7 (return true))))) 8 9 (defun pop (place) 10 (return (.pop place))) 11 12 (defun push (item place) 13 (.push place item)) 14 15 (defun pushnew (item place) 16 (unless (member item place) 17 (push item place)) 18 (return place)) 19 20 (defun object2alist (obj) 21 (when (and obj 22 (= "object" (typeof obj)) 23 (not (length obj))) 24 (let ((result (list))) 25 (doeach (i obj) 26 (push (cons i (slot-value obj i)) result)) 27 (return result)))) ;; note push adds on the tail! 28 29 (defun copy-seq (seq) 30 (when seq 31 (let ((result (list))) 32 (dolist (i seq) 33 (push i result)) ;; careful, push puts it at the end! (should be reverse) 34 (return result)))) 35 36 (defun nreverse (seq) 37 (when seq 38 (return (.reverse seq)))) 39 40 (defun reverse (seq) 41 (return (nreverse (copy-seq seq)))) 42 43 ;;(let ((lst (list 1 2 3 4))) (alert (+ lst #\newline (copy-seq lst)))) 44 ;;(let ((lst (list 1 2 3 4))) (alert (+ lst #\newline (reverse lst)))) 45 ;;(let ((lst (list 1 2 3 4))) (alert (+ lst #\newline (nreverse lst)))) 46 47 (defun sort (sequence predicate) 48 ;; < relationship 49 (.sort sequence 50 (lambda (x y) 51 (return (if (predicate x y) -1 1)))) 52 (return sequence)) 53 54 ;;; 55 56 (defvar ns (create "xul" "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 57 "html" "http://www.w3.org/1999/xhtml")) 58 59 (defun wget (id doc) 60 (return (if doc 61 (doc.get-element-by-id id) ;; why this doesn't work (on glade)? 62 (document.get-element-by-id id)))) 63 64 (defvar *whandler* (create)) 65 66 (defun whandler (sig) 67 (when sig 68 (let ((h (aref *whandler* sig))) 69 (if h 70 (return h) 71 (return (lambda (e) 72 (alert (+ "Unhandled event " sig ".")))))))) 73 74 (defun wgetp (w prop) 75 ;;(return (w.get-attribute prop))) 76 (return (slot-value w prop))) 77 78 (defun wsetp (w prop value) 79 (w.set-attribute prop value) 80 ;;(setf (slot-value w prop) value) 81 (return value)) 82 83 (defun wgets (w style) 84 (return (slot-value w.style style))) 85 86 (defun wsets (w style value) 87 (setf (slot-value w.style style) value) 88 ;;tempEl.style.setAttribute('cssText', 'left:150px; top:150px;', 0) 89 ;;(w.set-style style value) 90 (return value)) 91 92 (defun wsete (w event handler use-capture) 93 (w.add-event-listener event handler (if use-capture true false))) 94 95 (defun wunsete (w event handler use-capture) 96 (w.remove-event-listener event handler (if use-capture true false))) 97 98 (defun wmake (pw tag props sigs) 99 (if (= tag "string") 100 ;; text 101 (let ((w (document.create-text-node props))) 102 (when pw 103 (pw.append-child w)) 104 (return w)) 105 ;; xul or html 106 (let ((w (if (tag.match "^xul:") 107 (document.create-element-n-s ns.xul (tag.substring 4)) 108 (document.create-element-n-s ns.html tag)))) 109 (when pw 110 (pw.append-child w)) 111 (when props 112 (doeach (i props) 113 (unless (= undefined (slot-value props i)) 114 ;;(w.set-attribute i (slot-value props i)) 115 (wsetp w i (slot-value props i))))) 116 (when sigs 117 (doeach (i sigs) 118 (unless (= undefined (slot-value sigs i)) 119 #+nil(w.add-event-listener i (whandler (slot-value sigs i)) false) 120 (wsete w i (whandler (slot-value sigs i)))))) 121 ;;(pw.append-child w) 122 (return w)))) 123 124 (defun wadda (w child) 125 (.insert-before (.first-child w) child) 126 (return child)) 127 128 (defun waddz (w child) 129 (.append-child w child) 130 (return child)) 131 132 ;; function insertAfter(newElement, targetElement) 133 ;; { 134 ;; var parent = targetElement.parentNode; 135 ;; if(parent.lastChild == targetElement) 136 ;; { 137 ;; parent.appendChild(newElement); 138 ;; } 139 ;; else 140 ;; { 141 ;; parent.insertBefore(newElement, targetElement.nextSibling); 142 ;; } 143 ;; } 144 145 ;; (defun winsert (w pid) 146 ;; (.insert-before (wget pid) id)) 147 148 (defun wreplace (w ow nw) 149 (.replace-child w nw ow) 150 (return nw)) 151 152 (defun wshow (w) 153 (wsets w "visibility" "visible") 154 (wsets w "display" "")) 155 156 (defun whide (w) 157 (wsets w "visibility" "hidden") 158 (wsets w "display" "none")) 159 160 (defun change-visibility (w show) 161 (if show 162 (wshow w) 163 (whide w))) 164 165 (defun toggle-visibility (w) 166 (if (= "hidden" (wgets w "visibility")) 167 (wshow w) 168 (whide w))) 169 170 ;; widget constructors 171 172 (defun wempty (w) 173 (when (w.has-child-nodes) 174 (dolist (child w.child-nodes) 175 (w.remove-child child)))) 176 177 (defun wremove (w) 178 (w.parent-node.remove-child w)) 179 180 (defun xml-to-string (doc) 181 (let ((s (new (*x-m-l-serializer)))) 182 (return (s.serialize-to-string doc)))) 183 184 (defun load-xml (url callback) 185 ;; http://dean.edwards.name/weblog/2006/04/easy-xml/ 186 ;; http://www.w3schools.com/xml/xml_parser.asp 187 (if window.*active-x-object 188 (let ((doc (new (*active-x-object "Microsoft.XMLDOM")))) 189 (setf doc.async false) 190 (doc.load url) 191 (callback doc)) 192 #+nil(let ((xml (wmake "xml"))) 193 (setf xml.src url) 194 (waddz (wget "body") xml) 195 (let ((doc xml.*x-m-l-document)) 196 (document.body.remove-child xml) 197 (callback doc))) 198 (if (and document.implementation 199 document.implementation.create-document) 200 (let ((doc (document.implementation.create-document "" "" nil))) 201 (setf doc.onload (lambda () (callback doc))) 202 (doc.load url)) 203 (alert "Your browser cannot handle this script.")))) 204 205 (defvar *wbuild* (create)) 206 207 (defvar *wpack* (create)) 208 209 (defun wclass (widget) 210 (if (= widget.class "Custom") 211 (return (get-property widget "creation_function")) 212 (return widget.class))) 213 214 (defun parse-glade (glade) 215 ;;(netscape.security.*privilege-manager.enable-privilege "UniversalXPConnect") 216 (let ((widgets (create))) 217 (labels ((attrs (node) 218 (let ((name (node.get-attribute "name")) 219 (value (when node.child-nodes[0] 220 node.child-nodes[0].node-value)) 221 (result (create :name name))) 222 (when value 223 (setf result.value value)) 224 (dolist (a node.attributes) 225 (setf (slot-value result a.node-name) a.node-value)) 226 (return result))) 227 (rec-widget (parent node) 228 (let ((id (node.get-attribute "id")) 229 (class (node.get-attribute "class")) 230 (widget (create :id id 231 :parent parent 232 :children (list) 233 :class class 234 :property (create) 235 :signal (create) 236 :packing (create)))) 237 (when parent 238 (pushnew widget parent.children)) ;; appends! 239 (setf (slot-value widgets id) widget) 240 (rec widget node.child-nodes) 241 ;; TODO return local to widget! 242 (return widget))) 243 (rec-child (parent node) 244 (let ((current nil)) 245 (dolist (child node.child-nodes) 246 (case child.tag-name 247 ("widget" (setf current (rec-widget parent child))) 248 ("packing" (rec-packing parent child current)))))) 249 (rec-property (parent node) 250 (let ((as (attrs node))) 251 (setf (slot-value parent.property as.name) as))) 252 (rec-signal (parent node) 253 (let ((as (attrs node))) 254 (setf (slot-value parent.signal as.name) as))) 255 (rec-packing (parent node current) 256 (dolist (child node.child-nodes) 257 (when (= "property" child.tag-name) 258 (let ((as (attrs child))) 259 (setf (slot-value current.packing as.name) as))))) 260 (rec (parent nodes current) 261 (dolist (node nodes) 262 (case node.tag-name 263 ("glade-interface" (rec parent node.child-nodes)) 264 ("widget" (rec-widget parent node)) 265 ("child" (rec-child parent node)) 266 ("property" (rec-property parent node)) 267 ("signal" (rec-signal parent node)) 268 ("packing" (rec-packing parent node current)))))) 269 (rec nil (list glade.document-element))) 270 (return widgets))) 271 272 (defun wbuild (pw widgets) 273 (let ((result nil)) 274 (dolist (widget widgets) 275 (let ((fbuild (aref *wbuild* (wclass widget))) 276 (fpack (when (and widget widget.parent) 277 (aref *wpack* (wclass widget.parent)))) 278 (w (if fbuild 279 (fbuild pw widget) 280 (wmake pw "string" (+ "{ " (wclass widget) " not implemented! }"))))) 281 (when fpack 282 (fpack pw w widget)) 283 (setf result w))) 284 (return result))) ;; return only one for whole container??? 285 286 (defun get-property (widget name) 287 (awhen (slot-value widget.property name) 288 (return (slot-value it 'value)))) 289 290 (defun get-signal (widget name) 291 (awhen (slot-value widget.signal name) 292 (return (slot-value it 'handler)))) 293 294 (defun get-packing (widget name) 295 (awhen (slot-value widget.packing name) 296 (return (slot-value it 'value)))) 297 298 (defbuild "GtkWindow" () 299 (with-properties (title) 300 (if (= "window" pw.tag-name) 301 (progn 302 (wsetp pw "id" self.id) 303 (wsetp pw "title" title) 304 (wbuild pw self.children) 305 (return pw)) ;; ??? 306 (let ((w (wmake pw "xul:window" (create :id self.id :title title)))) 307 (wbuild w self.children) 308 (return w))))) 309 310 ;; <property name="decorated">True</property> 311 ;; <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> 312 313 (defpack "GtkWindow" () 314 (let ((resizable (= "True" (get-property self.parent "resizable")))) 315 (when resizable 316 (wsetp w "flex" 1)))) 317 318 (defbuild "GtkDialog" () 319 (return (funcall (aref *wbuild* "GtkWindow") pw self))) 320 321 (defpack "GtkDialog" () 322 (return (funcall (aref *wpack* "GtkWindow") pw w self))) 323 324 (defbuild "GtkButton" () 325 (with-properties (tooltip label sensitive) 326 (with-signals (clicked) 327 (let ((w (wmake pw "xul:button" 328 (create :id self.id 329 ;;:class-name (get-property self "class-name") 330 :tooltip tooltip 331 :disabled (= "False" sensitive) 332 :label label) 333 (create :command clicked)))) 334 (wbuild w self.children) 335 (return w))))) 336 337 (defbuild "GtkCheckButton" () 338 (with-properties (active label) 339 (with-signals (toggled) 340 (return (wmake pw "xul:checkbox" 341 (create :id self.id 342 :checked (when active true) 343 :label label) 344 (create :command toggled)))))) 345 346 (defbuild "GtkLabel" () 347 (with-properties (label) 348 (return (wmake pw "xul:label" (create :id self.id :value label))))) 349 350 (defbuild "GtkEntry" () 351 (with-properties (text tooltip editable) 352 (with-signals (changed) 353 (return (wmake pw "xul:textbox" 354 (create :id self.id 355 :value text 356 :tooltip tooltip 357 ;; ff3 cant be just (= "False" editable) 358 :readonly (if (= "False" editable) 359 true 360 undefined)) 361 (create :change changed)))))) 362 363 (defbuild "GtkTextView" () 364 (with-properties (text tooltip editable) 365 (with-signals (changed) 366 (return (wmake pw "xul:textbox" 367 (create :id self.id 368 :value text 369 :tooltip tooltip 370 ;; ff3 cant be just (= "False" editable) 371 :readonly (if (= "False" editable) 372 true 373 undefined) 374 :multiline t) 375 (create :change changed)))))) 376 377 (defbuild "GtkFrame" () 378 (let ((w (wmake pw "xul:groupbox" (create :id self.id))) 379 (w2 (wmake w "xul:caption")) 380 (label (list)) 381 (body (list))) 382 (dolist (child self.children) 383 ;; TODO fix label_item... (alert (+ (object2alist child) #\newline "---" #\newline child.packing.type)) 384 (if (= "label_item" (get-packing child "type")) 385 (push child label) 386 (push child body))) 387 (wbuild w2 label) 388 (wbuild w body))) 389 390 ;; TODO do something meaningful 391 (defbuild "GtkAlignment" () 392 (wbuild pw self.children) 393 #+nil(return ???)) 394 395 (defbuild "GtkComboBox" () 396 ;; why must be created first and then inserted? 397 (with-properties (items) 398 (with-signals (changed) 399 (let ((w (wmake nil "xul:menulist" 400 (create :id self.id) 401 (create :command changed))) 402 (w2 (wmake w "xul:menupopup")) 403 (n 0)) 404 ;;(alert (get-property self "active")) 405 (when items 406 (dolist (item (.split items #\newline)) 407 (let ((pair (.split item "|"))) 408 (wmake w2 "xul:menuitem" 409 (create :value (aref pair 0) 410 :label (or (aref pair 1) (aref pair 0)) 411 ;; TODO :selected (when (= n (get-property self "active")) t) 412 ))) 413 (incf n))) 414 (waddz pw w) 415 (return w))))) 416 417 (defbuild "GtkMenuBar" () 418 (let ((w (wmake nil "xul:menubar" (create :id self.id)))) 419 (wbuild w self.children) 420 (waddz pw w) 421 (return w))) 422 423 (defbuild "GtkMenu" () 424 (let ((w (wmake pw "xul:menupopup" (create :id self.id)))) 425 (wbuild w self.children) 426 (return w))) 427 428 (defbuild "GtkSeparatorMenuItem" () 429 (return (wmake pw "xul:menuseparator" (create :id self.id)))) 430 431 (defun find-access-key (str) 432 ;; use (position item seq)? 433 (let ((pos (str.index-of #\_))) 434 (unless (minusp pos) 435 ;; use (subseq str (1+ pos) (+ 2 pos)))))? 436 (return (aref str (1+ pos)))))) 437 438 ;;(alert (find-access-key "hell_o")) 439 ;;(alert (find-access-key "hi")) 440 441 (defun remove-access-key (str) 442 (return (str.replace #\_ ""))) 443 444 (defbuild "GtkMenuItem" () 445 ;; used to be (= "menubar" pw.tag-name) 446 (with-properties (label) 447 (with-signals (activate) 448 (if (or (= "GtkMenuBar" (wclass self.parent)) 449 (plusp (length self.children))) 450 (let ((w (wmake pw "xul:menu" 451 (create :id self.id 452 :label (remove-access-key label) 453 ;; TODO :acceltext (find-access-key label) 454 :accesskey (find-access-key label)) 455 (create :command activate)))) 456 (if (plusp (length self.children)) 457 (wbuild w self.children) 458 (wmake w "xul:menupopup")) 459 (return w)) 460 (return (wmake pw "xul:menuitem" 461 (create :id self.id 462 :label (remove-access-key label) 463 ;; TODO :acceltext (find-access-key label) 464 :accesskey (find-access-key label)) 465 (create :command activate))))))) 466 467 (defbuild "GtkHBox" () 468 (let ((w (wmake pw "xul:hbox" 469 (create :id self.id 470 ;; TODO align for label & combo 471 ;;:equalsize (when (= "True" (get-property self "homogeneous")) "always") 472 ;;:pack "center" 473 :align "center")))) 474 (wbuild w self.children) 475 (return w))) 476 477 (defpack "GtkHBox" () 478 (with-packing (padding expand fill pack_type) 479 (when (= "True" expand) 480 (wsetp w "flex" 1)) 481 ;;(wsetp w "pack" "end") 482 #+nil(when (= "GTK_PACK_END" pack_type) 483 (wsetp w "pack" "end")))) 484 485 (defbuild "GtkVBox" () 486 (let ((w (wmake pw "xul:vbox" (create :id self.id)))) 487 (wbuild w self.children) 488 (return w))) 489 490 (defpack "GtkVBox" () 491 (with-packing (padding expand fill pack_type) 492 (when (= "True" expand) 493 (wsetp w "flex" 1)) 494 ;;(wsetp w "pack" "end") 495 #+nil(when (= "GTK_PACK_END" pack_type) 496 (wsetp w "pack" "end")))) 497 498 (defbuild "GtkHButtonBox" () 499 (let ((w (wmake pw "xul:hbox" (create :id self.id)))) 500 (wbuild w self.children) 501 (return w))) 502 503 (defbuild "GtkVButtonBox" () 504 (let ((w (wmake pw "xul:vbox" (create :id self.id)))) 505 (wbuild w self.children) 506 (return w))) 507 508 (defbuild "GtkHSeparator" () 509 (return (wmake pw "xul:separator" 510 (create :id self.id 511 :orient "horizontal" 512 :class "groove")))) 513 514 (defbuild "GtkVSeparator" () 515 (return (wmake pw "xul:separator" 516 (create :id self.id 517 :orient "vertical" 518 :class "groove")))) 519 520 (defbuild "GtkHPaned" () 521 (let ((w (wmake pw "xul:hbox" (create :id self.id))) 522 (left self.children[0]) 523 (right self.children[1])) 524 (wbuild w (list left)) 525 ;; splitters are poor in xul, we do not worry about collapse & resize 526 (let ((w2 (wmake w "xul:splitter" (create :id (+ self.id "-splitter"))))) 527 (wmake w2 "xul:grippy" (create :id (+ self.id "-grippy")))) 528 (wbuild w (list right)) 529 (return w))) 530 531 (defpack "GtkHPaned" () 532 (with-packing (shrink resize) 533 ;; is this the right test? 534 (when (= "True" resize) 535 (wsetp w "flex" 1)))) 536 537 (defbuild "GtkVPaned" () 538 (let ((w (wmake pw "xul:vbox" (create :id self.id))) 539 (top self.children[0]) 540 (bottom self.children[1])) 541 (wbuild w (list top)) 542 (let ((w2 (wmake w "xul:splitter" (create :resizeafter "grow")))) 543 (wmake w2 "xul:grippy")) 544 (wbuild w (list bottom)) 545 (return w))) 546 547 (defpack "GtkVPaned" () 548 (with-packing (shrink resize) 549 ;; TODO 550 #+nil(when (= "True" resize) 551 (wsetp w "flex" 1)))) 552 553 (defbuild "GtkNotebook" () 554 (let ((tabs (list)) 555 (bodies (list))) 556 (dolist (child self.children) 557 (if (== "tab" (get-packing child "type")) 558 (push child tabs) ;; appends! 559 (push child bodies))) 560 (let ((w (wmake nil "xul:tabbox" (create :id self.id))) 561 (w2 (wmake w "xul:tabs")) 562 (w3 (wmake w "xul:tabpanels" (create :flex 1)))) 563 (dolist (tab tabs) 564 (let ((w4 (wmake w2 "xul:tab"))) 565 ;; TODO image? 566 (if (= "GtkLabel" tab.class) 567 (wsetp w4 "label" tab.property.label.value) 568 (wbuild w4 (list tab))))) 569 (dolist (body bodies) 570 (let ((w5 (wmake w3 "xul:tabpanel"))) 571 (wbuild w5 (list body)))) 572 (waddz pw w) 573 (return w)))) 574 575 (defpack "GtkNotebook" () 576 (with-packing (type) 577 (let ((expand (= "True" (get-packing self "tab_expand"))) 578 (fill (= "True" (get-packing self "tab_fill")))) 579 (unless (= "tab" type) 580 (wsetp w "flex" 1))))) 581 582 (defbuild "GtkToolbar" () 583 (let ((w (wmake pw "xul:toolbar" 584 (create :id self.id 585 :align "center")))) ;; like hbox 586 (wbuild w self.children) 587 (return w))) 588 589 (defpack "GtkToolbar" () 590 (with-packing (expand homogeneous) 591 ;; TODO homogeneous 592 (when (= "True" expand) 593 (wsetp w "flex" 1)))) 594 595 (defbuild "GtkToolItem" () 596 (let ((w (wmake pw "xul:toolbaritem" (create :id self.id)))) 597 (wbuild w self.children) 598 (return w))) 599 600 (defbuild "GtkSeparatorToolItem" () 601 ;; why not draw line? 602 (let ((w (wmake pw "xul:toolbarseparator" (create :id self.id)))) 603 ;; TODO why need children? 604 (wbuild w self.children) 605 (return w))) 606 607 (defun image-url (url) 608 (when url 609 ;; TODO and more like http etc? 610 (return (+ "images/" url)))) 611 612 (defbuild "GtkToolButton" () 613 ;; TODO show label/image 614 (with-properties (label icon tooltip) 615 (with-signals (clicked) 616 (let ((show-label t) 617 (show-image t)) 618 (return (wmake pw "xul:toolbarbutton" 619 (create :id self.id 620 :label (when show-label label) 621 :image (when show-image (image-url icon)) 622 :tooltiptext tooltip) 623 (create :command clicked))))))) 624 625 (defbuild "GtkImage" () 626 (with-properties (pixbuf) 627 (return (wmake pw "xul:image" 628 (create :id self.id :src (image-url pixbuf)))))) 629 630 (defbuild "GtkProgressBar" () 631 (return (wmake pw "xul:progressmeter" 632 (create :id self.id :mode "determined")))) 633 634 (defbuild "GtkStatusbar" () 635 (return (wmake pw "xul:statusbarpanel" (create :id self.id :flex 1))) 636 ;; TODO need packhook to set flex of the panel 637 #+nil(let ((w (wmake pw "xul:statusbar" (create :id self.id)))) 638 (wmake w "xul:statusbarpanel" (create :flex 1)) 639 (return w))) 640 641 (defun scan (regexp string) 642 (when string 643 (return (.match string regexp)))) 644 645 ;;(alert (scan "expand" "asfdexpandasfd")) 646 647 ;; TODO empty table??? 648 (defbuild "GtkTable" () 649 (let ((n-rows (get-property self "n_rows")) 650 (n-columns (get-property self "n_columns")) 651 (row-spacing (get-property self "row_spacing")) 652 (column-spacing (get-property self "column_spacing")) 653 (homogeneous (= "True" (get-property self "homogeneous")))) 654 (flet ((earlier (x y) 655 (let ((xleft (get-packing x "left_attach")) 656 (xright (get-packing x "right_attach")) 657 (xtop (get-packing x "top_attach")) 658 (xbottom (get-packing x "bottom_attach")) 659 (yleft (get-packing y "left_attach")) 660 (yright (get-packing y "right_attach")) 661 (ytop (get-packing y "top_attach")) 662 (ybottom (get-packing y "bottom_attach")) 663 ;;(c1 (< xtop ytop)) 664 ;;(c2 (and (= xtop ytop) 665 ;;(< xleft yleft))) 666 #+nil(c (or c1 c2))) 667 #+nil(return (if c -1 1)) 668 (return (or (< xtop ytop) 669 (and (= xtop ytop) 670 (< xleft yleft)))))) 671 (getfcols (sorted) 672 (unless homogeneous 673 (let ((fcols (list)) 674 (sorted (copy-seq sorted)) 675 (child (pop sorted))) 676 (dotimes (row n-rows) 677 (dotimes (col n-columns) 678 (let ((left (get-packing child "left_attach")) 679 (right (get-packing child "right_attach")) 680 (top (get-packing child "top_attach")) 681 (bottom (get-packing child "bottom_attach")) 682 (x-options (get-packing child "x_options"))) 683 (when (and (= top row) (= left col)) 684 ;; missing x_options = expand|fill 685 (when (or (null child.packing.x_options) 686 (scan "expand" x-options)) 687 (dotimes (i (1+ (- right left))) ;; 1+? 688 (pushnew col fcols)) ;; appends! 689 #+nil(loop for c from left to right 690 do (pushnew col fcols))) 691 (setf child (pop sorted)))))) 692 (return fcols))))) 693 (let ((n-rows (get-property self "n_rows")) 694 (n-columns (get-property self "n_columns")) 695 (row-spacing (get-property self "row_spacing")) 696 (column-spacing (get-property self "column_spacing")) 697 (homogeneous (= "True" (get-property self "homogeneous"))) 698 (sorted (reverse (sort (copy-seq self.children) earlier))) ;; pop works reverse 699 (fcols (getfcols sorted)) 700 (w (wmake pw "xul:grid" (create :id self.id))) 701 (w2 (wmake w "xul:columns")) 702 (w3 (wmake w "xul:rows"))) 703 (dotimes (col n-columns) 704 ;; TODO homogeneous 705 (wmake w2 "xul:column" 706 (create :flex (when (or homogeneous 707 (member col fcols)) 708 1)))) 709 (let ((child (pop sorted))) 710 (dotimes (row n-rows) 711 ;; TODO homogeneous/height 712 (let ((w4 (wmake w3 "xul:row" (create :align "center")))) 713 (dotimes (col n-columns) 714 (let ((left (get-packing child "left_attach")) 715 (right (get-packing child "right_attach")) 716 (top (get-packing child "top_attach")) 717 (bottom (get-packing child "bottom_attach"))) 718 (when (and (= top row) (= left col)) 719 (wbuild w4 (list child)) 720 (setf child (pop sorted)))))))) 721 (return w))))) 722 723 (defbuild "GtkScrolledWindow" () 724 ;; have one child only; packing applies to the child 725 (let ((child self.children[0]) 726 (w (wbuild pw (list child)))) 727 ;; TODO 728 ;;(wsets w "overflow" "auto") 729 (return w))) 730 731 (defbuild "GtkTreeView" () 732 (return (wmake pw "xul:tree" (create :id self.id))) 733 #+nil(labels ((draw-rows (rows) 734 (html (:treechildren 735 (dolist (row rows) 736 (let ((cells (cells row)) 737 (children (children row))) 738 (html ((:treeitem 739 :when (:container self.children :true) 740 ;;:when (:open self.children :true) 741 ) 742 (:treerow (dolist (cell cells) 743 (html ((:treecell :label cell))))) 744 (when self.children 745 (draw-rows self.children)))))))))) 746 (with-properties (model) self 747 ;;(format t "~s~%" model) 748 (let ((flex (eq (type-of (parent self)) 'GtkScrolledWindow)) 749 (cols (columns model)) 750 (scrollbar (eq (type-of (parent self)) 'GtkScrolledWindow)) 751 (hide-header-row (hide-header-row model))) 752 (html ((:tree :id (wid self) :class "GtkTreeView" 753 ;;:when (:style scrollbar "overflow:auto") 754 :when (:hidecolumnpicker (or hide-header-row 755 (< (length cols) 2)) :true) 756 :when (:flex flex 1) 757 ;;:enableColumnDrag :true 758 ;;:seltype :single :multiple 759 ;;:disabled :true 760 ;;:when (:align scrollbar :stretch) 761 ) 762 (when model 763 (html 764 (:treecols 765 (loop for col in cols 766 for n from 0 767 do (destructuring-bind 768 (cname ctitle cflex chidden cprimary) 769 col 770 (html 771 ((:treecol 772 :id cname 773 :when (:primary cprimary :true) 774 :when (:hideheader hide-header-row :true) 775 ;;:ignoreincolumnpicker :true 776 :when (:label (and (not hide-header-row) 777 ctitle) 778 ctitle) 779 :when (:flex cflex cflex) 780 :when (:hidden chidden :true)))))))) 781 (draw-rows (children model))))))))) 782 783 (defbuild "xul:iframe" () 784 (with-properties (string1 string2) 785 (return (wmake pw "xul:iframe" 786 (create :id self.id :src string1) 787 (create :load string2))))) 788 789 (defun close-window () 790 ;; http://www.interwebby.com/blog/2006/02/04/3/ 791 (window.open "javascript:window.close();" "_self" "")) 792 793 (defun gtk-main-quit () 794 (close-window))