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 (5.11 KB)
···
2009/2/25 Vlastimil Brom <vlastimil.brom@gmail.com>:
...
I'll eventually check the alternatives.
...