From be2577e4e650993fe49f18955972e5360840dad2 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Tue, 9 Nov 1999 23:02:41 +0000 Subject: [PATCH] wxSizer patches by Alexander Smishlajev Adds some wxALIGN_* flags to increase ability to position item within its allotted space. Adds wxSHAPED flag that enforces proportional resizing on growable items. Adds a sample and updated documentation. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4461 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/boxsizer.tex | 35 ++--- docs/latex/wx/sizer.tex | 11 +- include/wx/defs.h | 14 +- include/wx/sizer.h | 13 ++ samples/propsize/Makefile.in | 20 +++ samples/propsize/makefile.g95 | 16 +++ samples/propsize/makefile.vc | 17 +++ samples/propsize/mondrian.ico | Bin 0 -> 766 bytes samples/propsize/mondrian.xpm | 44 ++++++ samples/propsize/propsize.cpp | 249 ++++++++++++++++++++++++++++++++++ samples/propsize/propsize.rc | 5 + src/common/sizer.cpp | 58 ++++++-- utils/wxPython/demo/Sizers.py | 94 ++++++++++++- utils/wxPython/lib/grids.py | 24 ++-- utils/wxPython/src/_defs.i | 9 +- 15 files changed, 555 insertions(+), 54 deletions(-) create mode 100644 samples/propsize/Makefile.in create mode 100644 samples/propsize/makefile.g95 create mode 100644 samples/propsize/makefile.vc create mode 100644 samples/propsize/mondrian.ico create mode 100644 samples/propsize/mondrian.xpm create mode 100644 samples/propsize/propsize.cpp create mode 100644 samples/propsize/propsize.rc diff --git a/docs/latex/wx/boxsizer.tex b/docs/latex/wx/boxsizer.tex index f00db53148..42a0cf1104 100644 --- a/docs/latex/wx/boxsizer.tex +++ b/docs/latex/wx/boxsizer.tex @@ -1,6 +1,6 @@ \section{\class{wxBoxSizer}}\label{wxboxsizer} -The basic idea behind a box sizer is that windows will most often be laid out in rather +The basic idea behind a box sizer is that windows will most often be laid out in rather simple basic geomerty, typically in a row or a column or several hierachies of either. As an exmaple, we will construct a dialog that will contain a text field at the top and @@ -21,13 +21,16 @@ when adding a window (or another sizer) to a sizer. It is interpreted as a weight factor, i.e. it can be zero, indicating that the window may not be resized at all, or above zero. If several windows have a value above zero, the value is interpreted relative to the sum of all weight factors of the sizer, so when adding two windows with -a value of 1, they will both get resized equally much and each half as much as the sizer +a value of 1, they will both get resized equally much and each half as much as the sizer owning them. Then what do we do when a column sizer changes its width? This behaviour is -controlled by {\it flags} (the second parameter of the Add() function): Zero or no flag indicates that -the window will get aligned at the left (in a column sizer) and the top (row sizer), whereas -wxALIGN\_RIGHT and wxALIGN\_BOTTOM will do what they say. The item can also be centered -using the wxCENTRE flag (same as wxCENTER) or it can be forced to grow with the sizer (using -the wxGROW flag (same as wxEXPAND)). +controlled by {\it flags} (the second parameter of the Add() function): Zero or no flag +indicates that the window will preserve it's original size, wxGROW flag (same as wxEXPAND) +forces the window to grow with the sizer, and wxSHAPED flag tells the window to change it's +size proportionally, preserving original aspect ratio. When wxGROW flag is not used, +the item can be aligned within available space. wxALIGN\_LEFT, wxALIGN\_TOP, wxALIGN\_RIGHT, +wxALIGN\_BOTTOM, wxALIGN\_CENTER\_HORIZONTAL and wxALIGN\_CENTER\_VERTICAL do what they say. +wxALIGN\_CENTRE (same as wxALIGN\_CENTER) is defined as (wxALIGN\_CENTER\_HORIZONTAL | +wxALIGN\_CENTER\_VERTICAL). Default alignment is wxALIGN\_LEFT | wxALIGN\_TOP. As mentioned above, any window belonging to a sizer may have border, and it can be specified which of the four sides may have this border, using the wxTOP, wxLEFT, wxRIGHT and wxBOTTOM @@ -45,9 +48,9 @@ MyDialog::MyDialog(wxFrame *parent, wxWindowID id, const wxString &title ) : wxDialog( parent, id, title, wxDefaultPosition, wxDefaultSize, wxDIALOG_STYLE | wxRESIZE_BORDER ) { wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); - + // create text ctrl with minimal size 100x60 - topsizer->Add( + topsizer->Add( new wxTextCtrl( this, -1, "My text.", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE), 1, // make vertically stretchable wxEXPAND | // make horizontally stretchable @@ -57,20 +60,20 @@ MyDialog::MyDialog(wxFrame *parent, wxWindowID id, const wxString &title ) : wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL ); button_sizer->Add( - new wxButton( this, wxID_OK, "OK" ), + new wxButton( this, wxID_OK, "OK" ), 0, // make horizontally unstretchable wxALL, // make border all around (implicit top alignment) 10 ); // set border width to 10 button_sizer->Add( - new wxButton( this, wxID_CANCEL, "Cancel" ), + new wxButton( this, wxID_CANCEL, "Cancel" ), 0, // make horizontally unstretchable wxALL, // make border all around (implicit top alignment) 10 ); // set border width to 10 - - topsizer->Add( + + topsizer->Add( button_sizer, - 0, // make vertically unstretchable - wxCENTER ); // no border and centre horizontally + 0, // make vertically unstretchable + wxALIGN_CENTER ); // no border and centre horizontally SetAutoLayout( TRUE ); // tell dialog to use sizer SetSizer( topsizer ); // actually set the sizer @@ -98,7 +101,7 @@ or wxHORIZONTAL for creating either a column sizer or a row sizer. Implements the calculation of a box sizer's dimensions and then sets the size of its its children (calling \helpref{wxWindow::SetSize}{wxwindowsetsize} -if the child is a window). It is used internally only and must not be called +if the child is a window). It is used internally only and must not be called by the users. Documented for information. \membersection{wxBoxSizer::CalcMin}\label{wxboxsizercalcmin} diff --git a/docs/latex/wx/sizer.tex b/docs/latex/wx/sizer.tex index 47e9cf0302..802c70d17d 100644 --- a/docs/latex/wx/sizer.tex +++ b/docs/latex/wx/sizer.tex @@ -1,7 +1,7 @@ \section{\class{wxSizer}}\label{wxsizer} wxSizer is the abstract base class used for laying out subwindows in a window. You -cannot use wxSizer directly; instead, you'll have to use \helpref{wxBoxSizer}{wxboxsizer} +cannot use wxSizer directly; instead, you'll have to use \helpref{wxBoxSizer}{wxboxsizer} or \helpref{wxStaticBoxSizer}{wxstaticboxsizer}. The layout algorithm used by sizers in wxWindows closely related to layout @@ -87,9 +87,12 @@ determine the child window's behaviour if the size of the sizer changes, but - i the {\it option} flag - not in the main orientation, but the respectively other orientation. So if you created a wxBoxSizer with the wxVERTICAL option, these flags will be relevant if the sizer changes its horizontal size. A child may get resized to completely fill out the new size (using -either wxGROW or wxEXPAND), may get centered (wxCENTER or wxCENTRE) or may get aligned to either -side (wxALIGN\_LEFT and wxALIGN\_TOP are set to 0 and thus represent the default, wxALIGN\_RIGHT and -wxALIGN\_BOTTOM have their obvious meaning).} +either wxGROW or wxEXPAND), may get proportionally resized (wxSHAPED), may get centered (wxALIGN\_CENTER +or wxALIGN\_CENTRE) or may get aligned to either side (wxALIGN\_LEFT and wxALIGN\_TOP are set to 0 +and thus represent the default, wxALIGN\_RIGHT and wxALIGN\_BOTTOM have their obvious meaning). +With proportional resize, a child may also be centered in the main orientation using +wxALIGN\_CENTER\_VERTICAL (same as wxALIGN\_CENTRE\_VERTICAL) and wxALIGN\_CENTER\_HORIZONTAL +(same as wxALIGN\_CENTRE\_HORIZONTAL) flags.} \docparam{border}{Determines the border width, if the {\it flag} parameter is set to any border.} diff --git a/include/wx/defs.h b/include/wx/defs.h index 1cf504cb50..8a546d325d 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -695,12 +695,17 @@ enum wxDirection enum wxAlignment { wxALIGN_NOT = 0x0000, - wxALIGN_CENTER = 0x0100, - wxALIGN_CENTRE = wxALIGN_CENTER, + wxALIGN_CENTER_HORIZONTAL = 0x0100, + wxALIGN_CENTRE_HORIZONTAL = wxALIGN_CENTER_HORIZONTAL, wxALIGN_LEFT = wxALIGN_NOT, wxALIGN_TOP = wxALIGN_NOT, wxALIGN_RIGHT = 0x0200, - wxALIGN_BOTTOM = 0x0400 + wxALIGN_BOTTOM = 0x0400, + wxALIGN_CENTER_VERTICAL = 0x0800, + wxALIGN_CENTRE_VERTICAL = wxALIGN_CENTER_VERTICAL, + + wxALIGN_CENTER = (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL), + wxALIGN_CENTRE = wxALIGN_CENTER }; enum wxStretch @@ -708,7 +713,8 @@ enum wxStretch wxSTRETCH_NOT = 0x0000, wxSHRINK = 0x1000, wxGROW = 0x2000, - wxEXPAND = wxGROW + wxEXPAND = wxGROW, + wxSHAPED = 0x4000 }; // ---------------------------------------------------------------------------- diff --git a/include/wx/sizer.h b/include/wx/sizer.h index c94ebfee71..c8e4503f51 100644 --- a/include/wx/sizer.h +++ b/include/wx/sizer.h @@ -56,6 +56,15 @@ public: virtual wxSize CalcMin(); virtual void SetDimension( wxPoint pos, wxSize size ); + void SetRatio( int width, int height ) + // if either of dimensions is zero, ratio is assumed to be 1 + // to avoid "divide by zero" errors + { m_ratio = (width && height) ? ((float) width / (float) height) : 1; } + void SetRatio( wxSize size ) + { m_ratio = (size.x && size.y) ? ((float) size.x / (float) size.y) : 1; } + void SetRatio( float ratio ) { m_ratio = ratio; } + float GetRatio() const { return m_ratio; } + bool IsWindow(); bool IsSizer(); bool IsSpacer(); @@ -81,6 +90,10 @@ protected: int m_option; int m_border; int m_flag; + // als: aspect ratio can always be calculated from m_size, + // but this would cause precision loss when the window + // is shrinked. it is safer to preserve initial value. + float m_ratio; wxObject *m_userData; }; diff --git a/samples/propsize/Makefile.in b/samples/propsize/Makefile.in new file mode 100644 index 0000000000..f889d2842c --- /dev/null +++ b/samples/propsize/Makefile.in @@ -0,0 +1,20 @@ +# +# File: makefile.unx +# Author: Julian Smart +# Created: 1998 +# Updated: +# Copyright: (c) 1998 Julian Smart +# +# "%W% %G%" +# +# Makefile for wxWindows sample (UNIX). + +top_srcdir = @top_srcdir@ +top_builddir = ../.. +program_dir = samples/propsize + +PROGRAM=propsize + +OBJECTS=$(PROGRAM).o + +include ../../src/makeprog.env diff --git a/samples/propsize/makefile.g95 b/samples/propsize/makefile.g95 new file mode 100644 index 0000000000..7a2bd64b3d --- /dev/null +++ b/samples/propsize/makefile.g95 @@ -0,0 +1,16 @@ +# +# File: makefile.g95 +# Author: Julian Smart +# Created: 1999 +# Updated: +# Copyright: (c) Julian Smart, 1999 +# +# Makefile for wxWindows sample (Cygwin/Mingw32). + +WXDIR = ../.. + +TARGET=propsize +OBJECTS = $(TARGET).o + +include $(WXDIR)\src\makeprog.g95 + diff --git a/samples/propsize/makefile.vc b/samples/propsize/makefile.vc new file mode 100644 index 0000000000..c356f69b6f --- /dev/null +++ b/samples/propsize/makefile.vc @@ -0,0 +1,17 @@ +# +# File: makefile.vc +# Author: Julian Smart +# Created: 1999 +# Updated: +# Copyright: (c) Julian Smart +# +# Makefile : Builds sample (VC++, WIN32) +# Use FINAL=1 argument to nmake to build final version with no debug info. + +# Set WXDIR for your system +WXDIR = $(WXWIN) + +PROGRAM=propsize +OBJECTS = $(PROGRAM).obj + +!include $(WXDIR)\src\makeprog.vc diff --git a/samples/propsize/mondrian.ico b/samples/propsize/mondrian.ico new file mode 100644 index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53 GIT binary patch literal 766 zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0ZShow(TRUE); + SetTopWindow(frame); + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; +} + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +// frame constructor +MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) +{ + // set the frame icon + SetIcon(wxICON(mondrian)); + + // create a menu bar + wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF); + + menuFile->Append(Minimal_About, "&About...\tCtrl-A", "Show about dialog"); + menuFile->AppendSeparator(); + menuFile->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar(); + menuBar->Append(menuFile, "&File"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + +#if wxUSE_STATUSBAR + // create a status bar just for fun (by default with 1 pane only) + CreateStatusBar(1); + SetStatusText("Resize the frame to see how controls react"); +#endif // wxUSE_STATUSBAR + +#define AddLine(orient) \ + Add( new wxStaticLine( this, -1, wxDefaultPosition, wxSize(2,2), orient), \ + 0, wxEXPAND) +#define AddButton(label,align) Add( \ + new wxButton( this, -1, label, wxDefaultPosition, wxSize(100,50)), \ + 1, wxSHAPED | align) + + wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); + // top row -- top-aligned + wxBoxSizer *hsizer1 = new wxBoxSizer( wxHORIZONTAL ); + hsizer1->AddButton( "one", wxALIGN_LEFT | wxALIGN_TOP); + hsizer1->AddLine(wxVERTICAL); + hsizer1->AddButton( "two", wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP); + hsizer1->AddLine(wxVERTICAL); + hsizer1->AddButton( "three", wxALIGN_RIGHT | wxALIGN_TOP); + + topsizer->Add(hsizer1, 1, wxEXPAND); + topsizer->AddLine(wxHORIZONTAL); + + wxBoxSizer *hsizer2 = new wxBoxSizer( wxHORIZONTAL ); + hsizer2->AddButton( "four", wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + hsizer2->AddLine(wxVERTICAL); + // sizer that preserves it's shape + wxBoxSizer *vsizer = new wxBoxSizer( wxVERTICAL ); + vsizer->Add( + new wxButton( this, -1, "up", wxDefaultPosition, wxSize(100,25)), \ + 1, wxEXPAND); + vsizer->Add( + new wxButton( this, -1, "down", wxDefaultPosition, wxSize(100,25)), \ + 1, wxEXPAND); + hsizer2->Add(vsizer, 1, wxSHAPED | wxALIGN_CENTER); + hsizer2->AddLine(wxVERTICAL); + hsizer2->AddButton( "six", wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + + topsizer->Add(hsizer2, 1, wxEXPAND); + topsizer->AddLine(wxHORIZONTAL); + + wxBoxSizer *hsizer3 = new wxBoxSizer( wxHORIZONTAL ); + hsizer3->AddButton( "seven", wxALIGN_LEFT | wxALIGN_BOTTOM); + hsizer3->AddLine(wxVERTICAL); + hsizer3->AddButton( "eight", wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM); + hsizer3->AddLine(wxVERTICAL); + // wxEXPAND should have no effect + hsizer3->AddButton( "nine", wxEXPAND | wxALIGN_RIGHT | wxALIGN_BOTTOM); + + topsizer->Add(hsizer3, 1, wxEXPAND); + + // set frame to minimum size + topsizer->Fit( this ); + + // don't allow frame to get smaller than what the sizers tell ye + // topsizer->SetSizeHints( this ); + + SetSizer( topsizer ); + SetAutoLayout( TRUE ); +} + + +// event handlers + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + // TRUE is to force the frame to close + Close(TRUE); +} + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + wxString msg; + msg.Printf( _T("This is the about dialog of proportional sizer test.\n") + _T("Welcome to %s") +#ifdef wxBETA_NUMBER + _T(" (beta %d)!") +#endif // wxBETA_NUMBER + , wxVERSION_STRING +#ifdef wxBETA_NUMBER + , wxBETA_NUMBER +#endif // wxBETA_NUMBER + ); + + wxMessageBox(msg, "About Shaped Sizer", wxOK | wxICON_INFORMATION, this); +} diff --git a/samples/propsize/propsize.rc b/samples/propsize/propsize.rc new file mode 100644 index 0000000000..4e062315d2 --- /dev/null +++ b/samples/propsize/propsize.rc @@ -0,0 +1,5 @@ +mondrian ICON "mondrian.ico" +#include "wx/msw/wx.rc" + +#define MINIMAL_QUIT 1 +#define MINIMAL_ABOUT 102 diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index e412f5a70c..ea20ee7168 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -48,6 +48,8 @@ wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int borde m_minSize.x = width; m_minSize.y = height; + SetRatio(width, height); + // size is set directly m_size = m_minSize; } @@ -64,6 +66,9 @@ wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border, wx // minimal size is the initial size m_minSize = window->GetSize(); + // aspect ratio calculated from initial size + SetRatio(m_minSize); + // size is calculated later // m_size = ... } @@ -79,6 +84,7 @@ wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border, wxOb // minimal size is calculated later // m_minSize = ... + m_ratio = 0; // size is calculated later // m_size = ... @@ -119,7 +125,13 @@ wxSize wxSizerItem::CalcMin() { wxSize ret; if (IsSizer()) + { ret = m_sizer->CalcMin(); + // if we have to preserve aspect ratio _AND_ this is + // the first-time calculation, consider ret to be initial size + if ((m_flag & wxSHAPED) && !m_ratio) SetRatio(ret); + } + /* The minimum size of a window should be the initial size, as saved in m_minSize, not the @@ -163,6 +175,28 @@ void wxSizerItem::SetDimension( wxPoint pos, wxSize size ) { size.y -= m_border; } + if (m_flag & wxSHAPED) { + // adjust aspect ratio + int rwidth = (int) (size.y * m_ratio); + if (rwidth > size.x) { + // fit horizontally + int rheight = (int) (size.x / m_ratio); + // add vertical space + if (m_flag & wxALIGN_CENTER_VERTICAL) + pos.y += (size.y - rheight) / 2; + else if (m_flag & wxALIGN_BOTTOM) + pos.y += (size.y - rheight); + // use reduced dimensions + size.y =rheight; + } else if (rwidth < size.x) { + // add horizontal space + if (m_flag & wxALIGN_CENTER_HORIZONTAL) + pos.x += (size.x - rwidth) / 2; + else if (m_flag & wxALIGN_RIGHT) + pos.x += (size.x - rwidth); + size.x = rwidth; + } + } if (IsSizer()) m_sizer->SetDimension( pos.x, pos.y, size.x, size.y ); @@ -370,12 +404,14 @@ void wxBoxSizer::RecalcSizes() wxPoint child_pos( pt ); wxSize child_size( wxSize( size.x, height) ); - if (item->GetFlag() & wxALIGN_RIGHT) - child_pos.x += m_size.x - size.x; - else if (item->GetFlag() & wxCENTER) - child_pos.x += (m_size.x - size.x) / 2; - else if (item->GetFlag() & wxEXPAND) + if (item->GetFlag() & (wxEXPAND | wxSHAPED)) child_size.x = m_size.x; + else if (item->GetFlag() & wxALIGN_RIGHT) + child_pos.x += m_size.x - size.x; + else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL)) + // XXX wxCENTER is added for backward compatibility; + // wxALIGN_CENTER should be used in new code + child_pos.x += (m_size.x - size.x) / 2; item->SetDimension( child_pos, child_size ); @@ -393,12 +429,14 @@ void wxBoxSizer::RecalcSizes() wxPoint child_pos( pt ); wxSize child_size( wxSize(width, size.y) ); - if (item->GetFlag() & wxALIGN_BOTTOM) - child_pos.y += m_size.y - size.y; - else if (item->GetFlag() & wxCENTER) - child_pos.y += (m_size.y - size.y) / 2; - else if (item->GetFlag() & wxEXPAND) + if (item->GetFlag() & (wxEXPAND | wxSHAPED)) child_size.y = m_size.y; + else if (item->GetFlag() & wxALIGN_BOTTOM) + child_pos.y += m_size.y - size.y; + else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL)) + // XXX wxCENTER is added for backward compatibility; + // wxALIGN_CENTER should be used in new code + child_pos.y += (m_size.y - size.y) / 2; item->SetDimension( child_pos, child_size ); diff --git a/utils/wxPython/demo/Sizers.py b/utils/wxPython/demo/Sizers.py index 0ea2df7807..24545c108d 100644 --- a/utils/wxPython/demo/Sizers.py +++ b/utils/wxPython/demo/Sizers.py @@ -69,7 +69,7 @@ def makeSimpleBox6(win): box = wxBoxSizer(wxHORIZONTAL) box.Add(wxButton(win, 1010, "one"), 1, wxALIGN_TOP) box.Add(wxButton(win, 1010, "two"), 1, wxEXPAND) - box.Add(wxButton(win, 1010, "three"), 1, wxCENTER) + box.Add(wxButton(win, 1010, "three"), 1, wxALIGN_CENTER) box.Add(wxButton(win, 1010, "four"), 1, wxEXPAND) box.Add(wxButton(win, 1010, "five"), 1, wxALIGN_BOTTOM) @@ -93,7 +93,7 @@ def makeSimpleBox8(win): box = wxBoxSizer(wxVERTICAL) box.Add(wxButton(win, 1010, "one"), 0, wxEXPAND) box.Add(0,0, 1) - box.Add(wxButton(win, 1010, "two"), 0, wxCENTER) + box.Add(wxButton(win, 1010, "two"), 0, wxALIGN_CENTER) box.Add(0,0, 1) box.Add(wxButton(win, 1010, "three"), 0, wxEXPAND) box.Add(wxButton(win, 1010, "four"), 0, wxEXPAND) @@ -243,7 +243,7 @@ def makeGrid2(win): (wxButton(win, 1010, 'two'), 0, wxEXPAND), (wxButton(win, 1010, 'three'), 0, wxALIGN_LEFT | wxALIGN_BOTTOM), (wxButton(win, 1010, 'four'), 0, wxEXPAND), - (wxButton(win, 1010, 'five'), 0, wxCENTER), + (wxButton(win, 1010, 'five'), 0, wxALIGN_CENTER), (wxButton(win, 1010, 'six'), 0, wxEXPAND), (box, 0, wxEXPAND | wxALL, 10), (wxButton(win, 1010, 'eight'), 0, wxEXPAND), @@ -276,6 +276,76 @@ def makeGrid3(win): #---------------------------------------------------------------------- +def makeGrid4(win): + bpos = wxDefaultPosition + bsize = wxSize(100, 50) + gs = wxGridSizer(3, 3, 2, 2) # rows, cols, hgap, vgap + + gs.AddMany([ (wxButton(win, 1010, 'one', bpos, bsize), + 0, wxALIGN_TOP | wxALIGN_LEFT ), + (wxButton(win, 1010, 'two', bpos, bsize), + 0, wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL ), + (wxButton(win, 1010, 'three', bpos, bsize), + 0, wxALIGN_TOP | wxALIGN_RIGHT ), + (wxButton(win, 1010, 'four', bpos, bsize), + 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT ), + (wxButton(win, 1010, 'five', bpos, bsize), + 0, wxALIGN_CENTER ), + (wxButton(win, 1010, 'six', bpos, bsize), + 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ), + (wxButton(win, 1010, 'seven', bpos, bsize), + 0, wxALIGN_BOTTOM | wxALIGN_LEFT ), + (wxButton(win, 1010, 'eight', bpos, bsize), + 0, wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL ), + (wxButton(win, 1010, 'nine', bpos, bsize), + 0, wxALIGN_BOTTOM | wxALIGN_RIGHT ), + ]) + + return gs + +#---------------------------------------------------------------------- + +def makeShapes(win): + bpos = wxDefaultPosition + bsize = wxSize(100, 50) + gs = wxGridSizer(3, 3, 2, 2) # rows, cols, hgap, vgap + + gs.AddMany([ (wxButton(win, 1010, 'one', bpos, bsize), + 0, wxSHAPED | wxALIGN_TOP | wxALIGN_LEFT ), + (wxButton(win, 1010, 'two', bpos, bsize), + 0, wxSHAPED | wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL ), + (wxButton(win, 1010, 'three', bpos, bsize), + 0, wxSHAPED | wxALIGN_TOP | wxALIGN_RIGHT ), + (wxButton(win, 1010, 'four', bpos, bsize), + 0, wxSHAPED | wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT ), + (wxButton(win, 1010, 'five', bpos, bsize), + 0, wxSHAPED | wxALIGN_CENTER ), + (wxButton(win, 1010, 'six', bpos, bsize), + 0, wxSHAPED | wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT ), + (wxButton(win, 1010, 'seven', bpos, bsize), + 0, wxSHAPED | wxALIGN_BOTTOM | wxALIGN_LEFT ), + (wxButton(win, 1010, 'eight', bpos, bsize), + 0, wxSHAPED | wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL ), + (wxButton(win, 1010, 'nine', bpos, bsize), + 0, wxSHAPED | wxALIGN_BOTTOM | wxALIGN_RIGHT ), + ]) + + return gs + +#---------------------------------------------------------------------- + +def makeSimpleBoxShaped(win): + box = wxBoxSizer(wxHORIZONTAL) + box.Add(wxButton(win, 1010, "one"), 0, wxEXPAND) + box.Add(wxButton(win, 1010, "two"), 0, wxEXPAND) + box.Add(wxButton(win, 1010, "three"), 0, wxEXPAND) + box.Add(wxButton(win, 1010, "four"), 0, wxEXPAND) + box.Add(wxButton(win, 1010, "five"), 1, wxSHAPED) + + return box + +#---------------------------------------------------------------------- + theTests = [ ("Simple horizontal boxes", makeSimpleBox1, "This is a HORIZONTAL box sizer with four non-stretchable buttons held " @@ -328,7 +398,7 @@ theTests = [ ("", None, ""), ("Simple border sizer", makeSimpleBorder1, - "The wxBorderSizer leaves empty space around its contents. This one " + "The wxBoxSizer can leave empty space around its contents. This one " "gives a border all the way around." ), @@ -380,6 +450,22 @@ theTests = [ "\nThere is also a spacer in the middle cell instead of an actual window." ), + ("Grid with Alignment", makeGrid4, + "New alignment flags allow for the positioning of items in any corner or centered " + "position." + ), + + ("", None, ""), + + ("Proportional resize", makeSimpleBoxShaped, + "Managed items can preserve their original aspect ratio. The last item has the " + "wxSHAPED flag set and will resize proportional to its origingal size." + ), + + ("Proportional resize with Alignments", makeShapes, + "This one shows various alignments as well as proportional resizing for all items." + ), + ] #---------------------------------------------------------------------- diff --git a/utils/wxPython/lib/grids.py b/utils/wxPython/lib/grids.py index d67443e07b..df4d7c9969 100644 --- a/utils/wxPython/lib/grids.py +++ b/utils/wxPython/lib/grids.py @@ -132,22 +132,18 @@ class wxGridSizer(wxPySizer): isz = item.CalcMin() flag = item.GetFlag() - if flag & wxEXPAND: + if flag & wxEXPAND or flag & wxSHAPED: isz = wxSize(w, h) + else: + if flag & wxALIGN_CENTER_HORIZONTAL: + ipt.x = x + (w - isz.width) / 2 + elif flag & wxALIGN_RIGHT: + ipt.x = x + (w - isz.width) - elif flag & wxCENTER: - ipt.x = x + (w - isz.width) / 2 - ipt.y = y + (h - isz.height) / 2 - - if flag & wxALIGN_LEFT: - ipt.x = x - elif flag & wxALIGN_RIGHT: - ipt.x = x + (w - isz.width) - - if flag & wxALIGN_TOP: - ipt.y = y - elif flag & wxALIGN_BOTTOM: - ipt.y = y + (h - isz.height) + if flag & wxALIGN_CENTER_VERTICAL: + ipt.y = y + (h - isz.height) / 2 + elif flag & wxALIGN_BOTTOM: + ipt.y = y + (h - isz.height) item.SetDimension(ipt, isz) diff --git a/utils/wxPython/src/_defs.i b/utils/wxPython/src/_defs.i index 98c6124f09..fbed419f63 100644 --- a/utils/wxPython/src/_defs.i +++ b/utils/wxPython/src/_defs.i @@ -232,11 +232,16 @@ enum { wxCOLOURED, wxFIXED_LENGTH, wxALIGN_LEFT, - wxALIGN_CENTER, - wxALIGN_CENTRE, + wxALIGN_CENTER_HORIZONTAL, + wxALIGN_CENTRE_HORIZONTAL, wxALIGN_RIGHT, wxALIGN_BOTTOM, + wxALIGN_CENTER_VERTICAL, + wxALIGN_CENTRE_VERTICAL, wxALIGN_TOP, + wxALIGN_CENTER, + wxALIGN_CENTRE, + wxSHAPED, wxLB_NEEDED_SB, wxLB_ALWAYS_SB, wxLB_SORT,