Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

[wxpython-users] caption bars of the panes in wx AuiManager() - accesibility, events?

65 views
Skip to first unread message

Vlastimil Brom

unread,
Feb 23, 2009, 7:20:03 PM2/23/09
to wxpytho...@lists.wxwidgets.org
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

Andrea Gavana

unread,
Feb 24, 2009, 6:41:14 PM2/24/09
to wxpytho...@lists.wxwidgets.org
Hi Vlasta,

On Tue, Feb 24, 2009 at 12:20 AM, 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).

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/

Robin Dunn

unread,
Feb 24, 2009, 9:52:05 PM2/24/09
to wxpytho...@lists.wxwidgets.org
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!

Vlastimil Brom

unread,
Feb 25, 2009, 3:09:10 PM2/25/09
to wxpytho...@lists.wxwidgets.org
2009/2/25 Robin Dunn <ro...@alldunn.com>:
> Vlastimil Brom wrote:
...
> _______________________________________________
> wxpython-users mailing list
> wxpytho...@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

Vlastimil Brom

unread,
Feb 25, 2009, 2:15:11 PM2/25/09
to wxpytho...@lists.wxwidgets.org
2009/2/25 Andrea Gavana <andrea...@gmail.com>:
...

>
> 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
> wxpytho...@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 :-)
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

Vlastimil Brom

unread,
Feb 27, 2009, 3:55:37 PM2/27/09
to wxpytho...@lists.wxwidgets.org
2009/2/25 Vlastimil Brom <vlastim...@gmail.com>:
>...

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

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 ...:-)
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
Reply all
Reply to author
Forward
0 new messages