Added some support for adding widget into text view
[cl-gtk2.git] / gtk / gtk.demo.lisp
index 68e0a54..f517183 100644 (file)
@@ -21,7 +21,8 @@
            #:test-notebook
            #:test-calendar
            #:test-box-child-property
-           #:test-builder))
+           #:test-builder
+           #:demo-text-editor))
 
 (in-package :gtk-demo)
 
 (defun test-text-view ()
   (using* ((window (make-instance 'gtk-window :type :toplevel :title "Testing text view" :width-request 400 :height-request 300))
            (button (make-instance 'button :label "Do"))
+           (button-insert (make-instance 'button :label "Insert a button!"))
            (bold-btn (make-instance 'button :label "Bold"))
            (buffer (make-instance 'text-buffer :text "Some text buffer with some text inside"))
            (v (make-instance 'text-view :buffer buffer :wrap-mode :word))
                                                  (if (text-iter-has-tag start tag)
                                                      (text-buffer-remove-tag buffer tag start end)
                                                      (text-buffer-apply-tag buffer tag start end)))))))
+    (g-signal-connect button-insert "clicked" (lambda (b) (declare (ignore b))
+                                                (let* ((iter (text-buffer-get-iter-at-mark buffer (text-buffer-get-mark buffer "insert")))
+                                                       (anchor (text-buffer-insert-child-anchor buffer iter))
+                                                       (button (make-instance 'button :label "A button!")))
+                                                  (widget-show button)
+                                                  (text-view-add-child-at-anchor v button anchor))))
     (let ((tag (make-instance 'text-tag :name "bold" :weight 700)))
       (text-tag-table-add (text-buffer-tag-table buffer) tag)
       (g-signal-connect tag "event"
     (container-add window box)
     (container-add scrolled v)
     (box-pack-start box button :expand nil)
+    (box-pack-start box button-insert :expand nil)
     (box-pack-start box bold-btn :expand nil)
     (box-pack-start box scrolled)
     (widget-show window)
     (g-signal-connect (builder-get-object builder "window1") "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit)))
     (status-bar-push (builder-get-object builder "statusbar1") "times" "0 times")
     (widget-show (builder-get-object builder "window1"))
-    (gtk-main)))
\ No newline at end of file
+    (gtk-main)))
+
+(defun read-text-file (file-name)
+  (with-output-to-string (str)
+    (with-open-file (file file-name)
+      (loop
+         for line = (read-line file nil nil)
+         while line
+         do (fresh-line str)
+         do (write-string line str)))))
+
+(defun demo-text-editor ()
+  (let* ((builder (aprog1 (make-instance 'builder)
+                    (builder-add-from-file it (namestring (merge-pathnames "demo/text-editor.ui" *src-location*)))))
+         (window (builder-get-object builder "window1"))
+         (text-view (builder-get-object builder "textview1"))
+         (status-bar (builder-get-object builder "statusbar1"))
+         (file-name nil)
+         (modified-p t))
+    (status-bar-push status-bar "filename" "Untitled *")
+    (labels ((set-properties ()
+               (status-bar-pop status-bar "filename")
+               (status-bar-push status-bar "filename" (format nil "~A~:[~; *~]" (or file-name "Untitled") modified-p)))
+             (new (&rest args) (declare (ignore args))
+               (setf file-name nil
+                     modified-p t
+                     (text-buffer-text (text-view-buffer text-view)) "")
+               (set-properties))
+             (cb-open (&rest args) (declare (ignore args))
+               (let ((d (make-instance 'file-chooser-dialog :action :open :title "Open file")))
+                 (when file-name (setf (file-chooser-filename d) file-name))
+                 (dialog-add-button d "gtk-open" :accept)
+                 (dialog-add-button d "gtk-cancel" :cancel)
+                 (when (eq :accept (dialog-run d))
+                   (setf file-name (file-chooser-filename d)
+                         (text-buffer-text (text-view-buffer text-view)) (read-text-file file-name)
+                         modified-p nil)
+                   (set-properties))
+                 (object-destroy d)))
+             (save (&rest args) (declare (ignore args))
+               (if file-name
+                   (progn
+                     (with-open-file (file file-name :direction :output :if-exists :supersede)
+                       (write-string (text-buffer-text (text-view-buffer text-view)) file))
+                     (setf modified-p nil)
+                     (set-properties))
+                   (save-as)))
+             (save-as (&rest args) (declare (ignore args))
+               (let ((d (make-instance 'file-chooser-dialog :action :save :title "Save file")))
+                 (when file-name (setf (file-chooser-filename d) file-name))
+                 (dialog-add-button d "gtk-save" :accept)
+                 (dialog-add-button d "gtk-cancel" :cancel)
+                 (if (eq :accept (dialog-run d))
+                     (progn
+                       (setf file-name (file-chooser-filename d))
+                       (object-destroy d)
+                       (save))
+                     (object-destroy d))))
+             (cut (&rest args) (declare (ignore args))
+               (text-buffer-cut-clipboard (text-view-buffer text-view) (get-clipboard "CLIPBOARD")))
+             (copy (&rest args) (declare (ignore args))
+               (text-buffer-copy-clipboard (text-view-buffer text-view) (get-clipboard "CLIPBOARD")))
+             (paste (&rest args) (declare (ignore args))
+               (text-buffer-paste-clipboard (text-view-buffer text-view) (get-clipboard "CLIPBOARD")))
+             (cb-delete (&rest args) (declare (ignore args))
+               (let ((buffer (text-view-buffer text-view)))
+                 (multiple-value-bind (i1 i2) (text-buffer-get-selection-bounds buffer)
+                   (when (and i1 i2)
+                     (text-buffer-delete buffer i1 i2)))))
+             (about (&rest args) (declare (ignore args))
+               (let ((d (make-instance 'about-dialog
+                                       :program-name "Lisp Gtk+ Binding Demo Text Editor"
+                                       :version (format nil "0.0.0.1 ~A" #\GREEK_SMALL_LETTER_ALPHA)
+                                       :authors '("Kalyanov Dmitry")
+                                       :license "Public Domain"
+                                       :logo-icon-name "accessories-text-editor")))
+                 (dialog-run d)
+                 (object-destroy d)))
+             (quit (&rest args) (declare (ignore args)) (object-destroy window))
+             (cb-eval (&rest args) (declare (ignore args))
+               (let ((buffer (text-view-buffer text-view)))
+                 (multiple-value-bind (i1 i2) (text-buffer-get-selection-bounds buffer)
+                   (when (and i1 i2)
+                     (with-gtk-message-error-handler
+                       (let* ((text (text-buffer-slice buffer i1 i2))
+                              (value (eval (read-from-string text)))
+                              (value-str (format nil "~A" value))
+                              (pos (max (text-iter-offset i1) (text-iter-offset i2))))
+                         (text-buffer-insert buffer " => " :position (text-buffer-get-iter-at-offset buffer pos))
+                         (incf pos (length " => "))
+                         (text-buffer-insert buffer value-str :position (text-buffer-get-iter-at-offset buffer pos)))))))))
+      (builder-connect-signals-simple builder `(("new" ,#'new)
+                                                ("open" ,#'cb-open)
+                                                ("save" ,#'save)
+                                                ("save-as" ,#'save-as)
+                                                ("cut" ,#'cut)
+                                                ("copy" ,#'copy)
+                                                ("paste" ,#'paste)
+                                                ("delete" ,#'cb-delete)
+                                                ("about" ,#'about)
+                                                ("quit" ,#'quit)
+                                                ("eval" ,#'cb-eval)))
+      (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit)))
+      (g-signal-connect (text-view-buffer text-view) "changed" (lambda (b) (declare (ignore b)) (setf modified-p t) (set-properties)))
+      (widget-show window)
+      (gtk-main))))
\ No newline at end of file