2015-08-30 17:38:22 -05:00
// 16 may 2015
2016-04-22 21:20:02 -05:00
# include "uipriv_windows.hpp"
2015-08-30 17:38:22 -05:00
struct uiGroup {
uiWindowsControl c ;
HWND hwnd ;
struct child * child ;
int margined ;
} ;
static void onDestroy ( uiGroup * ) ;
uiWindowsDefineControlWithOnDestroy (
uiGroup , // type name
uiGroupType , // type function
2016-04-23 15:52:53 -05:00
onDestroy ( me ) ; // on destroy
2015-08-30 17:38:22 -05:00
)
static void onDestroy ( uiGroup * g )
{
if ( g - > child ! = NULL )
childDestroy ( g - > child ) ;
}
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
# define groupXMargin 6
# define groupYMarginTop 11 /* note this value /includes the groupbox label */
# define groupYMarginBottom 7
// unfortunately because the client area of a groupbox includes the frame and caption text, we have to apply some margins ourselves, even if we don't want "any"
// these were deduced by hand based on the standard DLU conversions; the X and Y top margins are the width and height, respectively, of one character cell
// they can be fine-tuned later
# define groupUnmarginedXMargin 4
# define groupUnmarginedYMarginTop 8
# define groupUnmarginedYMarginBottom 3
2015-08-31 16:50:23 -05:00
static void minimumSize ( uiWindowsControl * c , uiWindowsSizing * d , intmax_t * width , intmax_t * height )
2015-08-30 17:38:22 -05:00
{
uiGroup * g = uiGroup ( c ) ;
* width = 0 ;
* height = 0 ;
if ( g - > child ! = NULL )
childMinimumSize ( g - > child , d , width , height ) ;
if ( g - > margined ) {
* width + = 2 * uiWindowsDlgUnitsToX ( groupXMargin , d - > BaseX ) ;
* height + = uiWindowsDlgUnitsToY ( groupYMarginTop , d - > BaseY ) + uiWindowsDlgUnitsToY ( groupYMarginBottom , d - > BaseY ) ;
} else {
* width + = 2 * uiWindowsDlgUnitsToX ( groupUnmarginedXMargin , d - > BaseX ) ;
* height + = uiWindowsDlgUnitsToY ( groupUnmarginedYMarginTop , d - > BaseY ) + uiWindowsDlgUnitsToY ( groupUnmarginedYMarginBottom , d - > BaseY ) ;
}
}
2015-08-31 16:50:23 -05:00
static void groupRelayout ( uiWindowsControl * c , intmax_t x , intmax_t y , intmax_t width , intmax_t height )
2015-08-30 17:38:22 -05:00
{
2015-08-31 16:50:23 -05:00
uiGroup * g = uiGroup ( c ) ;
uiWindowsSizing * d ;
2015-08-30 17:38:22 -05:00
2016-04-23 21:23:07 -05:00
uiWindowsEnsureMoveWindowDuringResize ( g - > hwnd , x , y , width , height ) ;
2015-08-30 17:38:22 -05:00
if ( g - > child = = NULL )
return ;
2015-09-01 06:21:18 -05:00
d = uiWindowsNewSizing ( g - > hwnd ) ;
2015-09-02 20:29:16 -05:00
x = 0 ; // make relative to the top-left corner of the groupbox
y = 0 ;
2015-08-30 17:38:22 -05:00
if ( g - > margined ) {
x + = uiWindowsDlgUnitsToX ( groupXMargin , d - > BaseX ) ;
y + = uiWindowsDlgUnitsToY ( groupYMarginTop , d - > BaseY ) ;
width - = 2 * uiWindowsDlgUnitsToX ( groupXMargin , d - > BaseX ) ;
height - = uiWindowsDlgUnitsToY ( groupYMarginTop , d - > BaseY ) + uiWindowsDlgUnitsToY ( groupYMarginBottom , d - > BaseY ) ;
} else {
x + = uiWindowsDlgUnitsToX ( groupUnmarginedXMargin , d - > BaseX ) ;
y + = uiWindowsDlgUnitsToY ( groupUnmarginedYMarginTop , d - > BaseY ) ;
width - = 2 * uiWindowsDlgUnitsToX ( groupUnmarginedXMargin , d - > BaseX ) ;
height - = uiWindowsDlgUnitsToY ( groupUnmarginedYMarginTop , d - > BaseY ) + uiWindowsDlgUnitsToY ( groupUnmarginedYMarginBottom , d - > BaseY ) ;
}
uiWindowsFreeSizing ( d ) ;
childRelayout ( g - > child , x , y , width , height ) ;
}
static void groupContainerUpdateState ( uiControl * c )
{
uiGroup * g = uiGroup ( c ) ;
if ( g - > child ! = NULL )
childUpdateState ( g - > child ) ;
}
2015-09-02 11:59:57 -05:00
static void groupArrangeChildrenControlIDsZOrder ( uiWindowsControl * c )
{
uiGroup * g = uiGroup ( c ) ;
if ( g - > child ! = NULL )
childSetSoleControlID ( g - > child ) ;
}
2015-08-30 17:38:22 -05:00
char * uiGroupTitle ( uiGroup * g )
{
2016-04-22 19:04:30 -05:00
return uiWindowsWindowText ( g - > hwnd ) ;
2015-08-30 17:38:22 -05:00
}
void uiGroupSetTitle ( uiGroup * g , const char * text )
{
2016-04-22 19:04:30 -05:00
uiWindowsSetWindowText ( g - > hwnd , text ) ;
2015-08-30 17:38:22 -05:00
// changing the text might necessitate a change in the groupbox's size
2015-09-01 06:21:18 -05:00
uiWindowsControlQueueRelayout ( uiWindowsControl ( g ) ) ;
2015-08-30 17:38:22 -05:00
}
void uiGroupSetChild ( uiGroup * g , uiControl * child )
{
if ( g - > child ! = NULL )
childRemove ( g - > child ) ;
g - > child = newChild ( child , uiControl ( g ) , g - > hwnd ) ;
2015-09-02 08:18:49 -05:00
if ( g - > child ! = NULL ) {
childSetSoleControlID ( g - > child ) ;
2015-09-01 06:21:18 -05:00
uiWindowsControlQueueRelayout ( uiWindowsControl ( g ) ) ;
2015-09-02 08:18:49 -05:00
}
2015-08-30 17:38:22 -05:00
}
int uiGroupMargined ( uiGroup * g )
{
return g - > margined ;
}
void uiGroupSetMargined ( uiGroup * g , int margined )
{
g - > margined = margined ;
2015-09-01 06:21:18 -05:00
uiWindowsControlQueueRelayout ( uiWindowsControl ( g ) ) ;
2015-08-30 17:38:22 -05:00
}
2015-09-01 15:10:29 -05:00
static LRESULT CALLBACK groupSubProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam , UINT_PTR uIdSubclass , DWORD_PTR dwRefData )
{
LRESULT lResult ;
if ( handleParentMessages ( hwnd , uMsg , wParam , lParam , & lResult ) ! = FALSE )
return lResult ;
switch ( uMsg ) {
case WM_NCDESTROY :
if ( RemoveWindowSubclass ( hwnd , groupSubProc , uIdSubclass ) = = FALSE )
2016-04-22 21:20:02 -05:00
logLastError ( L " error removing groupbox subclass " ) ;
2015-09-01 15:10:29 -05:00
break ;
}
return DefSubclassProc ( hwnd , uMsg , wParam , lParam ) ;
}
2015-08-30 17:38:22 -05:00
uiGroup * uiNewGroup ( const char * text )
{
uiGroup * g ;
WCHAR * wtext ;
g = ( uiGroup * ) uiNewControl ( uiGroupType ( ) ) ;
wtext = toUTF16 ( text ) ;
2015-08-31 11:33:44 -05:00
g - > hwnd = uiWindowsEnsureCreateControlHWND ( WS_EX_CONTROLPARENT ,
2015-08-30 17:38:22 -05:00
L " button " , wtext ,
BS_GROUPBOX ,
hInstance , NULL ,
TRUE ) ;
uiFree ( wtext ) ;
2015-09-01 15:10:29 -05:00
if ( SetWindowSubclass ( g - > hwnd , groupSubProc , 0 , ( DWORD_PTR ) g ) = = FALSE )
2016-04-22 21:20:02 -05:00
logLastError ( L " error subclassing groupbox to handle parent messages " ) ;
2015-08-30 17:38:22 -05:00
uiWindowsFinishNewControl ( g , uiGroup ) ;
uiControl ( g ) - > ContainerUpdateState = groupContainerUpdateState ;
2015-08-31 16:50:23 -05:00
uiWindowsControl ( g ) - > Relayout = groupRelayout ;
2015-09-02 11:59:57 -05:00
uiWindowsControl ( g ) - > ArrangeChildrenControlIDsZOrder = groupArrangeChildrenControlIDsZOrder ;
2015-08-30 17:38:22 -05:00
return g ;
}