caption bars of the panes in wx AuiManager() - accesibility, events?

Hi I am just trying to solve another task in the aui layout of my app
and would like to to ask about the status of caption bars in
AuiManager.
Currently, some longer caption texts aren't fully visible and I'd like
to show them in some way.
Unfortunately I couldn't figure out, whether the caption bars are
somehow programatically accessible (besides setting text or style).
Using the widget inspection tool it seems, that they are part of the
main AUI frame, as its events are triggerd on them (EVT_MOTION and
EVT_ENTER_WINDOW - but a bit strangely not EVT_LEAVE_WINDOW).

I'd like to determine the respective associated pane for the events
triggered on the caption bars; is something like this possible?

I managed to make a popup window with a static text, which copies the
full caption text and displayes it over the (reduced) caption, but
it's rather difficult to call this popup properly (currently I'm
trying the EVT_ENTER_WINDOW of the pane, but this obviously doesn't
work on the children widgets of the panes).
Do I have to bind all single widgets individually, or is there maybe a
more elegant way (or even a better solution to the whole problem with
shortened captions - e.g. setting simple tooltips somehow ...)?

any suggestions are much appreciated,
   thanks in advance
        Vlasta

Hi Vlasta,

Hi I am just trying to solve another task in the aui layout of my app
and would like to to ask about the status of caption bars in
AuiManager.
Currently, some longer caption texts aren't fully visible and I'd like
to show them in some way.
Unfortunately I couldn't figure out, whether the caption bars are
somehow programatically accessible (besides setting text or style).
Using the widget inspection tool it seems, that they are part of the
main AUI frame, as its events are triggerd on them (EVT_MOTION and
EVT_ENTER_WINDOW - but a bit strangely not EVT_LEAVE_WINDOW).

If you can wait few days, I am going to release 2 different (but
almost equivalent) versions of wxAUI written in pure Python, which do
the same things as wxAUI and many others that wxAUI doesn't do. I will
put them in wxPython SVN for the wxPython community to try and
experiment with them: the obvious advantages wrt wxAUI are twofold:

- It's Python, so you/we can tinker them as much as we like to modify
them to suit our needs;
- Patches will be implemented at a faster pace than the current C++
version of wxAUI.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On Tue, Feb 24, 2009 at 12:20 AM, Vlastimil Brom wrote:

Vlastimil Brom wrote:

Hi I am just trying to solve another task in the aui layout of my app
and would like to to ask about the status of caption bars in
AuiManager.
Currently, some longer caption texts aren't fully visible and I'd like
to show them in some way.
Unfortunately I couldn't figure out, whether the caption bars are
somehow programatically accessible (besides setting text or style).
Using the widget inspection tool it seems, that they are part of the
main AUI frame, as its events are triggerd on them (EVT_MOTION and
EVT_ENTER_WINDOW - but a bit strangely not EVT_LEAVE_WINDOW).

I'd like to determine the respective associated pane for the events
triggered on the caption bars; is something like this possible?

When the pane is floating then it is embedded in a AuiFloatingFrame which is a class derived from wx.MiniFrame. It's the mini frame that draws the caption, moves the frame when dragged, etc. and since the caption is not considered part of the client area of the frame[*] then wx doesn't give access to catching events from it, although it can probably be done at least partially with native code and non-client events.

[*] that may vary across platforms as the miniframe doesn't have a native implementation everywhere, so it may be simulated with plain wx code.

I managed to make a popup window with a static text, which copies the
full caption text and displayes it over the (reduced) caption, but
it's rather difficult to call this popup properly (currently I'm
trying the EVT_ENTER_WINDOW of the pane, but this obviously doesn't
work on the children widgets of the panes).
Do I have to bind all single widgets individually, or is there maybe a
more elegant way (or even a better solution to the whole problem with
shortened captions - e.g. setting simple tooltips somehow ...)?

A tooltip would be nice, but I don't think that frame windows will display them. Without being able to get mouse events in the caption area I can only think of two possible approaches, and neither of them is very good IMO.

1. Use an EVT_IDLE handler to (re)set a timer. Doing it from a EVT_IDLE handler will cause it to be restarted every time there is any events in your app. When the timer does expire use wx.GetMousePosition to see if the cursor is currently within the bounds of the active AuiFloatingFrame window, and near the top. If so then use a wx.TipWindow to display a tooltip-like window with your text.

2. You can use a timer to animate the mini frame's title text such that it appears to slide back and forth.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

...

If you can wait few days, I am going to release 2 different (but
almost equivalent) versions of wxAUI written in pure Python, which do
the same things as wxAUI and many others that wxAUI doesn't do. I will
put them in wxPython SVN for the wxPython community to try and
experiment with them: the obvious advantages wrt wxAUI are twofold:

- It's Python, so you/we can tinker them as much as we like to modify
them to suit our needs;
- Patches will be implemented at a faster pace than the current C++
version of wxAUI.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Hi Andrea,
thank you very much for your effort - and first, I'd like to join the
gratulations you already got :slight_smile:
I guess, the full aui implementation in Python would be nice (I am not
hoping, I'd be able to effectively modify the code for something that
complex, but (at least for me) it would surely be more comprehensible,
what's going on ...).

If I may draw your attention to one specific shortcomming in aui, it
would be the issue with destructive resizing of docked panes (unless
it had been fixed somewhere in the original codebase):

http://trac.wxwidgets.org/ticket/4599
http://lists.wxwidgets.org/pipermail/wxpython-users/2008-January/071847.html
currently I am using a variation on the code proposed in the list
above, but it would be nice, if it were fixed in the library.

And, again, many thanks for all your contributions to wxpython!

regards,
Vlasta

···

2009/2/25 Andrea Gavana <andrea.gavana@gmail.com>:

Vlastimil Brom wrote:

...

I'd like to determine the respective associated pane for the events
triggered on the caption bars; is something like this possible?

When the pane is floating then it is embedded in a AuiFloatingFrame which is
a class derived from wx.MiniFrame. It's the mini frame that draws the
caption, moves the frame when dragged, etc. and since the caption is not
considered part of the client area of the frame[*] then wx doesn't give
access to catching events from it, although it can probably be done at least
partially with native code and non-client events.

[*] that may vary across platforms as the miniframe doesn't have a native
implementation everywhere, so it may be simulated with plain wx code.

I managed to make a popup window with a static text, which copies the
full caption text and displayes it over the (reduced) caption, but
it's rather difficult to call this popup properly (currently I'm
trying the EVT_ENTER_WINDOW of the pane, but this obviously doesn't
work on the children widgets of the panes).
Do I have to bind all single widgets individually, or is there maybe a
more elegant way (or even a better solution to the whole problem with
shortened captions - e.g. setting simple tooltips somehow ...)?

A tooltip would be nice, but I don't think that frame windows will display
them. Without being able to get mouse events in the caption area I can only
think of two possible approaches, and neither of them is very good IMO.

1. Use an EVT_IDLE handler to (re)set a timer. Doing it from a EVT_IDLE
handler will cause it to be restarted every time there is any events in your
app. When the timer does expire use wx.GetMousePosition to see if the
cursor is currently within the bounds of the active AuiFloatingFrame window,
and near the top. If so then use a wx.TipWindow to display a tooltip-like
window with your text.

2. You can use a timer to animate the mini frame's title text such that it
appears to slide back and forth.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwidgets.org
http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Hi Robin,
thanks for your suggestions! I'm actually interested in both docked as
well as floating panes (the former are more frequent in this layout).
Unfortunately, I am not able to determine the rectangle of the pane
caption (otherwise the EVT_ENTER_WINDOW event of the aui-frame would
be just fine, as it gets triggered mostly on the pane captions) - the
only way I could think of was to maintain the list of rectangles for
all panes and somehow calculate the position of the caption bar (given
the pane width and caption height -
_mgr.GetArtProvider().GetMetric(wx.aui.AUI_DOCKART_CAPTION_SIZE), this
list would have to be updated with the each rendering of the aui
manager.

Sofar I haven't tried this approach, as it doesn't seem optimal to me;
currently I have all panels and their child widgets bound to the
EVT_ENTER_WINDOW - with a function showing the complete caption via a
PopupWindow - hence it shows more frequently than usual, and not under
the mouse on caption bar, but it isn't realy disturbing.
I'll eventually check the alternatives.

Thanks again,
  Vlasta

···

2009/2/25 Robin Dunn <robin@alldunn.com>:

Hi again,
I just wanted to post the results of further trials on showing the aui
pane captions and ask for opinions or suggestions.
It turned out, that using EVT_ENTER_WINDOW of the AUI frame isn't all
that complicated (or my code is messy enough for this to make a
difference ...:slight_smile:
It is necessary to maintain a list of rectangles of all aui panes -
and to update it on changing the layout.
The tricky part is maybe to infer the coordinates of the caption bar
based on the rectangles of the respective panes.
Furthermore it turned out, that EVT_ENTER_WINDOW is also generated
after discarding the popup window, previously placed over the caption.
I couldn't find a way to prevent it other than using a guarding
variable and resetting it with an arbitrary interval wx.CallLater.

In this version the popups behave more naturaly; however, they are
also called on shorter captions, where they aren't needed, besides
this, while moving from one caption to the neighbour one, no event is
generated as the mouse actualy doesn't enter any new widget; I am not
sure, whether it is important enough to use EVT_MOTION instead. This
way also doesn't work on floating frames, but there are native
tooltips there anyway.

The sample code is attached, I'd really appreciate comments or
suggestions of better approaches. (I also apologise for the coding
style :-), the main objective is to test the usability ...).

Thanks in advance
    Vlasta

#### sample code - wx-aui-popup-caption-sample.py- also attached ###########

#! Python
# -*- coding: utf-8 -*-

import wx
import wx.aui

class PopupInfoText(wx.PopupWindow): # PopupTransientWindow
    """
    wx.PopupWindow for displaying context help/information
    """
    def __init__(self, parent, *args, **kwargs):
        wx.PopupWindow.__init__(self, parent, *args, **kwargs)
        self.info_text = wx.StaticText(self, -1, u"", pos=(2, 2))
        self.discard_timer = wx.CallLater(2000, self.hide_popup)
        self.discard_timer.Stop() # stop in order not to call
hide_popup before actual using
        self.info_text.Bind(wx.EVT_LEFT_UP, self.hide_popup)
        self.should_hide = False # to prevent repeated popups on
EVT_ENTER_WINDOW - popup > frame

    def show_popup_info(self, info_txt="", pos=(0,0), display_duration_ms=2000):
        """
        Shows the popup with given text on given coordinates; check
for self.should_hide to prevent circular popups.
        """
        if self.should_hide:
            self.should_hide = False
            return False
        self.should_hide = False
        self.Show(False)
        self.info_text.SetLabel(info_txt)
        txt_size = self.info_text.GetBestSize()
        self.SetSize((txt_size[0]+5, txt_size[1]+4))
        coord_x, coord_y = pos
        if (self.GetSize()[0] + coord_x) > wx.GetDisplaySize()[0]: #
popup (partly) outside the screen
            coord_x = wx.GetDisplaySize()[0] - self.GetSize()[0] #
align a longer popup with right margin
        if coord_x < 0:
            coord_x = 0 # align with a left margin if the popup is
longer than the screen width # wrapping not implemented
        self.SetPosition((coord_x, coord_y))
        self.Show(True)
        self.discard_timer.Restart(display_duration_ms) # restart for
a new timeout interval after resetting/updating

    def hide_popup(self, evt=None):
        """
        Hides popup after a timeout or by clicking on it (moving the panes etc).
        """
        self.Show(False)
        self.should_hide = True
        self.discard_timer.Stop() # stopping for hiding the popup via mouse
        wx.CallLater(200, self.unset_should_hide) # approx timeout??;
prevent circular calls, reset for next noprmal pane

    def unset_should_hide(self, evt=None):
        """
        Unset the hiding parameter for other than immediate (not
wanted) calls of show_popup_info.
        """
        self.should_hide = False

class AuiFrame(wx.Frame):
    """
    sample frame - aui manager with longer pane captions and
associated popup hints
    """
    def __init__(self, parent, id=-1, title='wx.aui - popup captions',
pos=(10,10), size=(-1, -1), style=wx.DEFAULT_FRAME_STYLE):
        wx.Frame.__init__(self, parent, id, title, pos, size, style)
        self._mgr = wx.aui.AuiManager(self)
        for (pane_nr, pane_pos) in enumerate((wx.BOTTOM, wx.LEFT,
wx.RIGHT, wx.TOP)*4):
            self._mgr.AddPane(self.MakeTextCtrl(str(pane_nr)),
pane_pos, 'some rather longer text of the pane caption nr.
'+str(pane_nr))
        self._mgr.AddPane(self.MakeTextCtrl(),wx.aui.AuiPaneInfo().Center().CloseButton(False).CaptionVisible(False).Name("emptyPanel"))

        self.pop_inf = PopupInfoText(self)
        self.panes_rectangles =
        self.Bind(wx.EVT_ENTER_WINDOW, self.display_caption_popup)
        self.Bind(wx.aui.EVT_AUI_RENDER, self.onRender)
        self._mgr.Update()

    def onRender(self,evt):
        """
        Collect pane rectangles for checking the mouse on pane
captions display_caption_popup; updated on lazout changes.
        """
        self.panes_rectangles = [(pane_info,
pane_info.window.GetRect()) for pane_info in self._mgr.GetAllPanes()]
        evt.Skip()

    def MakeTextCtrl(self, txt='sample text'):
        return wx.TextCtrl(self, -1, txt, style=wx.TE_MULTILINE)

    def display_caption_popup(self, evt):
        """
        Determines the pane based on the mouse position; calls the
popup with its caption on the computed coordinates.
        """
        x_coord, y_coord = evt.GetX(), evt.GetY()
        caption_height =
self._mgr.GetArtProvider().GetMetric(wx.aui.AUI_DOCKART_CAPTION_SIZE)
        sash_thickness =
self._mgr.GetArtProvider().GetMetric(wx.aui.AUI_DOCKART_SASH_SIZE)
        pane_border_size =
self._mgr.GetArtProvider().GetMetric(wx.aui.AUI_DOCKART_PANE_BORDER_SIZE)

        for (pane_info, (x_pos, y_pos, pane_width, pane_height)) in
self.panes_rectangles:
            if (x_pos - sash_thickness - 2 * pane_border_size) <=
x_coord <= (x_pos + pane_width + sash_thickness + 2 *
pane_border_size): # mouse in the same "column" as the pane
                if y_pos >= y_coord >= (y_pos - caption_height -
sash_thickness - 2 * pane_border_size): # panes on the top - no sash
or border above; interval also ok?
                    if pane_info.IsShown(): # check visible panes only
(the hidden ones keep the previous positions)

self.pop_inf.show_popup_info(pane_info.caption,
self.ClientToScreen((x_pos, (y_pos - caption_height))))
                        break

if __name__ == '__main__':
    app = wx.App(redirect=False)
    frm = AuiFrame(None)
    frm.Show()
    app.MainLoop()

wx-aui-popup-caption-sample.py (5.11 KB)

···

2009/2/25 Vlastimil Brom <vlastimil.brom@gmail.com>:

...
I'll eventually check the alternatives.
...