I am in the process of adding some features to ButtonPanel (as Robin has renamed FancyButtonPanel), which were on Robin's wish list. Basically they are:
Adding toggle support to the buttons (done);
Possibility to draw text below the bitmap buttons (done);
Using (when available) bitmaps for the “Normal”, “Pressed”, “Hover”, “Toggled”, “Disabled” state of a button (done);
Implementing programmer’s defined “custom” states for a button with associated bitmap (almost done);
Moving the gradient drawing inside EVT_ERASE_BACKGROUND so as to give the programmer a way to override it (it seems impossible to me, EVT_ERASE_BACKGROUND does not allow me to do anything except calling “pass” when I use wx.BufferedPaintDC in the OnPaint. It works with wx.PaintDC but it flickers like mad);
Possibility to add stretchable spacers between buttons that allows you to align buttons almost in every way you wish (no idea on how to do it);
Adding support of wx.Control inside ButtonPanel (no idea on how to do it);
5 and 6 are particularly hostile to me because:
I can not use sizers (the buttons are not real controls, just images painted during OnPaint);
The combination of ButtonPanel text, possible stretchable spacers, controls and owner-drawn buttons is driving me crazy. I can’t even start to think about a layout strategy, let’s skip the actual coding
The layout is complicated by the fact that if you shrink the ButtonPanel window, the buttons/controls that can not fit into it should be hidden/not drawn.
This is how ButtonPanel looks like right now (disabled bitmap, toggle functionality, text under bitmaps):
4) Moving the gradient drawing inside EVT_ERASE_BACKGROUND so as to give the programmer a way to override it (it seems impossible to me, EVT_ERASE_BACKGROUND does not allow me to do anything *except* calling "pass" when I use wx.BufferedPaintDC in the OnPaint. It works with wx.PaintDC but it flickers like mad);
Yep, I forgot that it doesn't play nice with buffered DCs when I suggested the change. So I would instead leave the empty EVT_ERASE_BACKGROUND handler but split up the paint handler so parts of it can be overridden in a derived class.
5) Possibility to add stretchable spacers between buttons that allows you to align buttons almost in every way you wish (no idea on how to do it);
6) Adding support of wx.Control inside ButtonPanel (no idea on how to do it);
5 and 6 are particularly hostile to me because:
1) I can not use sizers (the buttons are not real controls, just images painted during OnPaint);
Actually, I just realized that you can use a sizer. When you add an item to a sizer you get a wx.SizerItem returned to you, even when you add a spacer. That wx.SizerItem has methods that will give you the rectangle that the item occupies, so you can add a spacer of the right size for each of the things that are not real controls (the buttons and also the main text label for example) and then in the EVT_PAINT handler access their sizer item to figure out where to draw the item. (You could save a reference to the sizer item in the ButtonInfo for example.)
2) The combination of ButtonPanel text, possible stretchable spacers, controls and owner-drawn buttons is driving me crazy. I can't even start to think about a layout strategy, let's skip the actual coding
This problem goes away with a sizer.
3) The layout is complicated by the fact that if you shrink the ButtonPanel window, the buttons/controls that can not fit into it should be hidden/not drawn.
But this becomes more tricky. It's definitely a nice professional looking feature and I would hate to loose it. To go the sizer route you would probably have to add code to the EVT_SIZE handler that tests if the size is too narrow and rebuilds the sizer if needed, or you could keep the original sizer but change the size of the spacers to (0,0) or Hide() the controls that need to dissapear, Don't forget to still call sizer.Layout() from OnSize since you are overriding the default autosize behavior.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
I am looking forward to your control, as i wanted to have something that could act as a “history panel” … In GTK in the file browser they show something like;
[home] [jorg] [somedir]
···
dir contents
You can click on the jorg button and it will quickly change the dir. In my wiki project I wanted to emulate the same behaviour, by remembering the pages one visited in a history panel. Your buttonpanel can function as something like that.
A small question, can your button panel handle buttons of variying width?
Possibility to add stretchable spacers between buttons that allows you to align buttons almost in every way you wish (no idea on how to do it);
Well why don’t you derive the fancy buttons from a class that is derived from e.g. wxPanel or wxControl ? That is how I did it with wxCaptionBar in the wxFoldPanel component. Every button can report the size it needs to the sizer by GetBestSize, this way the panel can hold sizers. My solution would be;
the fancy background would be a wxPanel
One sizer can be assigned to it, either H sizer or V sizer (using a V sizer would allow buttons on the side)
The sizer contains the controls that are the fancy buttons
If the sizer is set to wxALIGN_LEFT it will allign on the left, wxALIGN_RIGHT it will be aligned on the right etc.
Adding support of wx.Control inside ButtonPanel (no idea on how to do it);
That would be possible when your group of controls in your fancy button panel would become wxWindow derived controls (you are basically half way there when your custom drawn buttons become wxControls / wxWindows) if you add something else to the list, the sizer would be able to pick them up as extra controls.
A small question, can your button panel handle buttons of variying width?
Yes, this is how it works right now. Every button in ButtonPanel can
have its own with (calculated with GetBestSize and a lot of tricky
things).
> 5) Possibility to add stretchable spacers between buttons that allows you
to align buttons almost in every way you wish (no idea on how to do it);
Well why don't you derive the fancy buttons from a class that is derived
from e.g. wxPanel or wxControl ? That is how I did it with wxCaptionBar in
the wxFoldPanel component. Every button can report the size it needs to the
sizer by GetBestSize, this way the panel can hold sizers. My solution would
be;
the fancy background would be a wxPanel
One sizer can be assigned to it, either H sizer or V sizer (using a V sizer
would allow buttons on the side)
The sizer contains the controls that are the fancy buttons
If the sizer is set to wxALIGN_LEFT it will allign on the left,
wxALIGN_RIGHT it will be aligned on the right etc.
It seems I can not do that:
Well why don't you derive the fancy buttons from a class that is derived
from e.g. wxPanel or wxControl?
I thought about this approach: but when I paint the ButtonPanel
background using gradient colours, wxPanel or wxControl inside
ButtonPanel will not be painted transparent. So I will get the
gradient background with an ugly grey colour for the buttons. The aim
of ButtonPanel was to keep the gradient shading behind the images
(that are drawn using transparent PNGs). I am not sure I can use your
approach in this way, unless I am missing something. If you have any
suggestion about this, please let me know (also snippets of code
).
Yes, this is how it works right now. Every button in ButtonPanel can
have its own with (calculated with GetBestSize and a lot of tricky
things).
Thanks! That would be great at least I know your component can be used as a base for my history panel
I thought about this approach: but when I paint the ButtonPanel
background using gradient colours, wxPanel or wxControl inside
ButtonPanel will not be painted transparent. So I will get the
gradient background with an ugly grey colour for the buttons. The aim
of ButtonPanel was to keep the gradient shading behind the images
(that are drawn using transparent PNGs). I am not sure I can use your
approach in this way, unless I am missing something. If you have any
suggestion about this, please let me know (also snippets of code
Ohh ok I understand. Well on wxTreeMultiCtrl what I did was matching the background color with the main control so that they would look more embedded. The problem is the contradiction wxWidgets brings along. On one side you want to be compliant with the native look and feel, on the other hand you want to be very fancy with grandient backgrounds. One thing I could think of, is writing your own code that deals with the WIN32 api directly (is that possible from wxPython?) and set the background color to transparent. I know it is possible as in Delphi I can also set this option and my buttons / checkboxes are transparent. But this is ofcourse cumbersome. You will have to write C++ code or Win32 API through python, and then it’s really the question is it worth the effort…
Ohh ok I understand. Well on wxTreeMultiCtrl what I did was matching the
background color with the main control so that they would look more
embedded. The problem is the contradiction wxWidgets brings along. On one
side you want to be compliant with the native look and feel, on the other
hand you want to be very fancy with grandient backgrounds. One thing I could
think of, is writing your own code that deals with the WIN32 api directly
(is that possible from wxPython?)
No, I don't think is possible. I had big troubles with PyAUI in
writing win32 api calls for the transparent hint windows, and I had to
use win32api on Windows and ctypes on Mac. Nothing could be done for
GTK. You can do what you said but then your code will work only on
Windows (if you use win32api). To adapt it to other platforms (if even
supported) would be a mess.
I am progressing however, I have a nice panel in which you can add
button, spacers, flexible spacers, controls; all of them are laying
out nicely and, when there is not enough room for an item in
ButtonPanel, it is hidden. It starts to look quite professional
I am doing all the work on a horizontal ButtonPanel bar, but once I
finish this (it won't take long, I am just checking if everything
works ok and adding some whistles and bells) I will add support also
for vertical ButtonPanel.
Andrea.
"Imagination Is The Only Weapon In The War Against Reality."