Lisp HUG Maillist Archive

How to redisplay capi interface?

Hi,

If I define an interface as such:

(define-interface demo ()
  ()
  (:panes
   (page-up push-button 
            :text "Page Up")
   (page-down push-button
              :text "Page Down")
   (open-file push-button
              :text "Open File"))
  (:layouts
   (row-of-buttons row-layout
                   '(page-up page-down open-file)))
  (:default-initargs :title "Demo"))

(setf d (make-instance 'demo) 
(display d)

then redefine it as such: 

(define-interface demo ()
  ()
 (:panes
  (page-up push-button 
           :text "Page Up")
  (page-down push-button
             :text "Page Down")
  (open-file push-button
             :text "Open File")
  ;;; added a viewer pane
  (viewer editor-pane
          :title "File:"
          :text "No file selected."
          :visible-min-height '(:character 8)
          :reader viewer-pane))
 (:layouts
   (main-layout column-layout 
                '(row-of-buttons row-with-editor-pane))
   (row-of-buttons row-layout
                   '(page-up page-down open-file))
   (row-with-editor-pane row-layout
                         '(viewer)))
  (:default-initargs :title "Demo"))

(redisplay-interface d) 
===============
redisplay-interface does not work. How to redraw an existing displayed instance of an interface without redrawing it, in a similar way that I can redraw an output-pane using display-callback? 

Ideally just hovering the mouse over the interface should redraw it? How to achieve this, without going down the update-instance-for-redefined-class route?

Thanks,
Deepak
         







Re: How to redisplay capi interface?

I am using LW 6.1 32 Bit on OS X 10.10.

On Sun, Aug 2, 2015 at 11:14 PM, Deepak Surti <dmsurti@gmail.com> wrote:
Hi,

If I define an interface as such:

(define-interface demo ()
  ()
  (:panes
   (page-up push-button 
            :text "Page Up")
   (page-down push-button
              :text "Page Down")
   (open-file push-button
              :text "Open File"))
  (:layouts
   (row-of-buttons row-layout
                   '(page-up page-down open-file)))
  (:default-initargs :title "Demo"))

(setf d (make-instance 'demo) 
(display d)

then redefine it as such: 

(define-interface demo ()
  ()
 (:panes
  (page-up push-button 
           :text "Page Up")
  (page-down push-button
             :text "Page Down")
  (open-file push-button
             :text "Open File")
  ;;; added a viewer pane
  (viewer editor-pane
          :title "File:"
          :text "No file selected."
          :visible-min-height '(:character 8)
          :reader viewer-pane))
 (:layouts
   (main-layout column-layout 
                '(row-of-buttons row-with-editor-pane))
   (row-of-buttons row-layout
                   '(page-up page-down open-file))
   (row-with-editor-pane row-layout
                         '(viewer)))
  (:default-initargs :title "Demo"))

(redisplay-interface d) 
===============
redisplay-interface does not work. How to redraw an existing displayed instance of an interface without redrawing it, in a similar way that I can redraw an output-pane using display-callback? 

Ideally just hovering the mouse over the interface should redraw it? How to achieve this, without going down the update-instance-for-redefined-class route?

Thanks,
Deepak
         










--
http://deepaksurti.com
To see a miracle, be the miracle.

Re: How to redisplay capi interface?

I meant "How to redraw an existing displayed instance of an interface without displaying it again" instead of 
"How to redraw an existing displayed instance of an interface without redrawing it".

On Sun, Aug 2, 2015 at 11:14 PM, Deepak Surti <dmsurti@gmail.com> wrote:
I am using LW 6.1 32 Bit on OS X 10.10.

On Sun, Aug 2, 2015 at 11:14 PM, Deepak Surti <dmsurti@gmail.com> wrote:
Hi,

If I define an interface as such:

(define-interface demo ()
  ()
  (:panes
   (page-up push-button 
            :text "Page Up")
   (page-down push-button
              :text "Page Down")
   (open-file push-button
              :text "Open File"))
  (:layouts
   (row-of-buttons row-layout
                   '(page-up page-down open-file)))
  (:default-initargs :title "Demo"))

(setf d (make-instance 'demo) 
(display d)

then redefine it as such: 

(define-interface demo ()
  ()
 (:panes
  (page-up push-button 
           :text "Page Up")
  (page-down push-button
             :text "Page Down")
  (open-file push-button
             :text "Open File")
  ;;; added a viewer pane
  (viewer editor-pane
          :title "File:"
          :text "No file selected."
          :visible-min-height '(:character 8)
          :reader viewer-pane))
 (:layouts
   (main-layout column-layout 
                '(row-of-buttons row-with-editor-pane))
   (row-of-buttons row-layout
                   '(page-up page-down open-file))
   (row-with-editor-pane row-layout
                         '(viewer)))
  (:default-initargs :title "Demo"))

(redisplay-interface d) 
===============
redisplay-interface does not work. How to redraw an existing displayed instance of an interface without redrawing it, in a similar way that I can redraw an output-pane using display-callback? 

Ideally just hovering the mouse over the interface should redraw it? How to achieve this, without going down the update-instance-for-redefined-class route?

Thanks,
Deepak
         










--
http://deepaksurti.com
To see a miracle, be the miracle.



--
http://deepaksurti.com
To see a miracle, be the miracle.

Re: How to redisplay capi interface?

Unable to parse email body. Email id is 13520

Re: How to redisplay capi interface?

Hi Madhu,

Thanks for the detailed explanation.

The instance `d' does not have any of the new slots when you redefined
the class.  Were you expecting to see the new slot in the old instance
`d' automatically?  CLOS does not work this way.

Yes, I expected to see the new `viewer` slot in the instance `d` automatically. However when I checked for redefinition as explained here: http://cl-cookbook.sourceforge.net/clos-tutorial/, I can see the a new slot gets added to an existing instance after redefinition. I have attached a log of the REPL session. On the same lines, I expected that when I redefine the `demo` interface, the instance `d` would get updated. So if you can shed any light on why the update machinery does not work in this case? Sorry, if I this is trivial question, but I don't seem to understand why `d` is not getting updated.
 
| Ideally just hovering the mouse over the interface should redraw it?
| How to achieve this, without going down the
| update-instance-for-redefined-class route?

I'm pretty sure you cannot, in practice, do this.  You have to create
a new instance when you change the CAPI interface class, and deal with
that.

I wanted to incrementally develop a GUI while modifying an existing displayed interface instead of redisplaying it all over again and I got this idea from this SO post: , the relevant part posted here again (emphasis mine). So I thought this workflow should be possible with CAPI as well. 

------------

There are some extremely cool use cases. One example is in GUI programming - I saw this while developing a GUI app in real time as it was running beside my Emacs: I added code for a new button and hit "C-c C-c" to compile that single function, and the button just appeared in the window! Didn't have to close and reopen the app. Then I began tweaking widgets and manipulating the layout, and the open window would instantly rearrange itself - buttons would move around, new text fields would just pop into being, etc. as soon as I executed each little change I'd made.

............. [Comments section]

Regarding the first paragraph of your answer, which GUI toolkit did you use? –  Matthias Benkard

Matthias, I was actually working with McCLIM in Common Lisp at the time. -- –  Jeremy Rahman

-----------

So, during development, how do we incrementally write a GUI in CAPI without having to redisplay it whenever interface definitions need to change? Or is that just not possible as you have explained.

Thanks again.

Best,
Deepak

 

--- Madhu

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


-- 
http://deepaksurti.com
To see a miracle, be the miracle.

Re: How to redisplay capi interface?

Sorry, missed the link to the SO Post: http://stackoverflow.com/questions/5074781/editing-programs-while-they-are-running-why

On Mon, Aug 3, 2015 at 12:16 PM, Deepak Surti <dmsurti@gmail..com> wrote:
Hi Madhu,

Thanks for the detailed explanation.

The instance `d' does not have any of the new slots when you redefined
the class.  Were you expecting to see the new slot in the old instance
`d' automatically?  CLOS does not work this way.

Yes, I expected to see the new `viewer` slot in the instance `d` automatically. However when I checked for redefinition as explained here: http://cl-cookbook.sourceforge.net/clos-tutorial/, I can see the a new slot gets added to an existing instance after redefinition. I have attached a log of the REPL session. On the same lines, I expected that when I redefine the `demo` interface, the instance `d` would get updated. So if you can shed any light on why the update machinery does not work in this case? Sorry, if I this is trivial question, but I don't seem to understand why `d` is not getting updated.
 
| Ideally just hovering the mouse over the interface should redraw it?
| How to achieve this, without going down the
| update-instance-for-redefined-class route?

I'm pretty sure you cannot, in practice, do this.  You have to create
a new instance when you change the CAPI interface class, and deal with
that.

I wanted to incrementally develop a GUI while modifying an existing displayed interface instead of redisplaying it all over again and I got this idea from this SO post: , the relevant part posted here again (emphasis mine). So I thought this workflow should be possible with CAPI as well. 

------------

There are some extremely cool use cases. One example is in GUI programming - I saw this while developing a GUI app in real time as it was running beside my Emacs: I added code for a new button and hit "C-c C-c" to compile that single function, and the button just appeared in the window! Didn't have to close and reopen the app. Then I began tweaking widgets and manipulating the layout, and the open window would instantly rearrange itself - buttons would move around, new text fields would just pop into being, etc. as soon as I executed each little change I'd made.

............. [Comments section]

Regarding the first paragraph of your answer, which GUI toolkit did you use? –  Matthias Benkard

Matthias, I was actually working with McCLIM in Common Lisp at the time. -- –  Jeremy Rahman

-----------

So, during development, how do we incrementally write a GUI in CAPI without having to redisplay it whenever interface definitions need to change? Or is that just not possible as you have explained.

Thanks again.

Best,
Deepak

 

--- Madhu

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html


-- 
http://deepaksurti.com
To see a miracle, be the miracle.



--
http://deepaksurti.com
To see a miracle, be the miracle.

How to redisplay capi interface?

Unable to parse email body. Email id is 13524

Re: How to redisplay capi interface?

Hi Madhu,

Sincerely, thanks a ton for your time for the detailed explanation. I also tried out the approach to do incremental development with CAPI as you described, which works for me.

Best,
Deepak



On Mon, Aug 3, 2015 at 8:32 PM, Madhu <enometh@meer.net> wrote:


* Deepak Surti <CAMg5xVqY72HUz4GLarzQbNd-hY8Qjb08g7Bcjy_gbZqKhiz78A@mail.gmail.com> :
Wrote on Mon, 3 Aug 2015 12:16:25 +0530:

| The instance `d' does not have any of the new slots when you redefined
|> the class.  Were you expecting to see the new slot in the old instance
|> `d' automatically?  CLOS does not work this way.
|
| Yes, I expected to see the new `viewer` slot in the instance `d`
| automatically. However when I checked for redefinition as explained here:
| http://cl-cookbook.sourceforge.net/clos-tutorial/, I can see the a new slot
| gets added to an existing instance after redefinition. I have attached a
| log of the REPL session.

[This may be my cue to stop posting answers here... However please see
 till the end of this post...]

| On the same lines, I expected that when I redefine the `demo`
| interface, the instance `d` would get updated. So if you can shed any
| light on why the update machinery does not work in this case?  Sorry,
| if I this is trivial question, but I don't seem to understand why `d`
| is not getting updated.


Quoting from:
<http://www.lispworks.com/documentation/lw61/CAPUG-W/html/capiuser-w-7.htm>

        The CAPI provides an abstract hierarchy of classes which
        represent different sorts of window interface elements, along
        with functions for interacting with them.

        Instances of these classes represent window objects in an
        application, with their slots representing different aspects of
        the object, such as the text on a button, or the items on a
        menu. These instances are not actual window objects but provide
        a convenient representation of them for you.

        When you ask the CAPI to display your object, it creates a real
        window system object to represent it. This means that if you
        display a CAPI button, a real Windows button is created for it
        when running on Microsoft Windows, a real GTK+ button when
        running on GTK+, and a real Cocoa button when running on Cocoa.


This means that the protocols work by forwarding calls on the CAPI
objects to the windowing-system representations, appropriately.  These
windowing-system representations are initialized (following whatever
"CAPI protocol) when the corresponding CAPI objects are initialized, and
they are updated only in ways supported by the CAPI.

Now you remember that CAPI:DEFINE-INTERFACE is just a simple (but
convenient) convenience wrapper macro.  You can macroexpand it and see
the DEFCLASS and the AFTER method on CAPI::INITIALIZE-INTERFACE.  The
slots are actually initialized in this AFTER method.  So when you
redefine the class, the slot `viewer' now exists for but is unbound in
instance `d'.  You could call the code in the AFTER method to initialize
the new instance, but this will NOT automatically update the
windowing-system representations of these objects,

Moreover, most importantly the interface object tree hangs of a single
root `layout' slot (specified with a :layout initarg), and
DEFINE-INTERFACE lets you specify the layout descriptions are later
realised when displaying the object.  This is where the flexibility is
limited, and an INTERFACE becomes a full "integral" displayable unit,
whose "definition" you do not want to change after you fix it.


|> | Ideally just hovering the mouse over the interface should redraw
|> | it?  How to achieve this, without going down the
|> | update-instance-for-redefined-class route?
|>
|> I'm pretty sure you cannot, in practice, do this.  You have to create
|> a new instance when you change the CAPI interface class, and deal
|> with that.
|>
|
| I wanted to incrementally develop a GUI while modifying an existing
| displayed interface instead of redisplaying it all over again and I got
| this idea from this SO post: , the relevant part posted here again
| (emphasis mine). So I thought this workflow should be possible with CAPI as
| well.
|
| ------------
|
| There are some extremely cool use cases. One example is in GUI programming
| - I saw this while developing a GUI app in real time as it was running
| beside my Emacs: I added code for a new button and hit "C-c C-c" to compile
| that single function, and the button just *appeared* in the window! *Didn't
| have to close and reopen the app*. Then I began tweaking widgets and
| manipulating the layout, and the open window would instantly rearrange
| itself - buttons would move around, new text fields would just pop into
| being, etc. as soon as I executed each little change I'd made.
|
|
| So, during development, how do we incrementally write a GUI in CAPI
| without having to redisplay it whenever interface definitions need to
| change? Or is that just not possible as you have explained.


The flexibility of incremental development is still available in CAPI:
All that is mentioned is available, It just does not extend to cover the
flexibility of the "convenience" aggregation abstraction of
DEFINE-INTERFACE.  Which defines a unit.

Now in the following example you may need to wrap your calls
appropriately in CAPI:EXECUTE-WITH-INTERFACE or
CAPI:APPLY-IN-PANE-PROCESS

Here is how you might start developing your app line by line executing
C-c C-x on each line:


(defvar $d (make-instance 'capi:interface
             :layout (make-instance 'capi:simple-layout))) <-- set later!

(defvar $up (make-instance 'capi:push-button :text "Page Up"))

(capi:contain $up) ;;; <-- debug it in isolation

(defvar $down (make-instance 'capi:push-button :text "Page Down"))
(defvar $open (make-instance 'capi:push-button :text "Open File"))

(defvar $row-layout (make-instance 'capi:row-layout :description (list $up $down $open)))
;; add remove buttons etc.

(setf (capi:layout-description (slot-value $d 'capi:layout))
      (list $row-layout))

(capi:display $d)

(defvar $viewer
  (make-instance 'capi:editor-pane
    :title "File:"
    :text "No file selected."
    :visible-min-height '(:character 8)))

(setf (capi:layout-description (slot-value $d 'capi:layout))
      (list (make-instance 'capi:column-layout
              :description (list $row-layout
                                 $viewer))))

;; clicking on a button --- should show you the new layout! as you
;; wanted!


At the point your application is working, you could wrap it up into a
DEFINE-INTERFACE, making each variable a slot of the interface.  I've
not used the GUI builder but it probably wraps up a lot of this, and you
can wrap this in any way you like.  The sticky point is how the main
LAYOUT gets defined via a define-interface..

I should stop here, but now just rambling... the layout is the important
part, this suggests a way to take advantage of a class redefinitions via
define-interface, by hacking the :layout default-initarg!

This is hackish, and calls unexported functions. Someone who knows
better can shoot it down...

So first you define a layout which you can set later:

(defvar $s (make-instance 'capi:simple-layout))

(capi:define-interface demo ()
  ()
  (:panes ...)
  (:layouts ...)
 (:default-initargs :title
   "Demo"
   :layout $s)) ;; <---- NOTE!


(setq $e (make-instance 'demo))
(capi:display $e)

;; now set the layout

(capi:execute-with-interface
 $e #'(lambda ()
        (setf (capi:layout-description $s)
              (list (slot-value $e 'row-of-buttons)))))

;; now redefine your class here

(define-interface demo ()
  (:panes ...
     ;;; added a viewer pane
   )
  (:layouts (... main-layout ...))
 (:default-initargs :title
   "Demo"
   :layout $s)) <--- NOTE AGAIN!!


;; this redefines the class. the next call should update the
;; slots. then we set the new layout.

(capi::initialize-instance $e)
(capi:execute-with-interface
 $e #'(lambda ()
        (setf (capi:layout-description $s)
              (list (slot-value $e 'main-layout)))))


--- Madhu

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html




--
http://deepaksurti.com
To see a miracle, be the miracle.
Updated at: 2020-12-10 08:33 UTC