ObjGUI  Check-in [ae315380c1]

Overview
Comment:win32 branch commit
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ae315380c17bd3bf683b4ddc5f2957a0e9ec4594bd3a62c7e4095f668a3d39c1
User & Date: dillonaumiller@gmail.com on 2012-01-05 02:22:08
Other Links: manifest | tags
Context
2012-01-05
14:39
Unbreak Gtk. check-in: 39b3140423 user: js tags: trunk
14:31
Add forgotten copyright. check-in: 82ab8cf0ef user: js tags: trunk
02:22
win32 branch commit check-in: ae315380c1 user: dillonaumiller@gmail.com tags: trunk
Changes

Added .hgignore version [9564fcd29f].













>
>
>
>
>
>
1
2
3
4
5
6
syntax: glob
*.dll
*.so
*.o
*.a
*.exe

Modified headers/OGBox.h from [aa583d8cb5] to [19a668760d].

1
2

3
4
5
6
7
8
9
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>

 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *


>







1
2
3
4
5
6
7
8
9
10
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
17
18
19
20
21
22
23
24













25




26
27
28
29
30
31
32
33
34
35
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#import "OGWidget.h"














@interface OGBox: OGWidget




+ box;
- (void)appendChild: (OGWidget*)child
	     expand: (BOOL)expand
	       fill: (BOOL)fill
	    padding: (float)padding;
- (void)prependChild: (OGWidget*)child
	      expand: (BOOL)expand
		fill: (BOOL)fill
	     padding: (float)padding;
@end








>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>










18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#import "OGWidget.h"

#ifdef OG_W32
typedef struct s_OGBoxChild
{
	HWND  hwnd;
	BOOL  expand;
	BOOL  fill;
	int   padding;
	int   originalSize;
	float currentSize;
	struct s_OGBoxChild *next;
} OGBoxChild;
#endif

@interface OGBox: OGWidget
#ifdef OG_W32
{ OGBoxChild *firstBorn; }
- (void)resizeChildren;
#endif
+ box;
- (void)appendChild: (OGWidget*)child
	     expand: (BOOL)expand
	       fill: (BOOL)fill
	    padding: (float)padding;
- (void)prependChild: (OGWidget*)child
	      expand: (BOOL)expand
		fill: (BOOL)fill
	     padding: (float)padding;
@end

Modified headers/OGComboBox.h from [b779f946c9] to [66411fb990].

1
2

3
4
5
6
7
8
9
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>

 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *


>







1
2
3
4
5
6
7
8
9
10
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
37
38
39
40
41
42
43






44
45
46
47
48
49
@end

@interface OGComboBox: OGWidget
{
	id <OGComboBoxDelegate> delegate;
	id <OGComboBoxDataSource> dataSource;
}







@property (assign) id <OGComboBoxDelegate> delegate;
@property (assign) id <OGComboBoxDataSource> dataSource;

+ comboBox;
@end







>
>
>
>
>
>






38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@end

@interface OGComboBox: OGWidget
{
	id <OGComboBoxDelegate> delegate;
	id <OGComboBoxDataSource> dataSource;
}

#ifdef OG_W32
//unfortunately, the built-in Win32 ListBox stores a pointer to it's parent (for sending selection changed notifications) during CreateWindow().
//it does not update it after a SetParent()... unless we implement a custom ListBox control i don't see a way around this...
- initWithParent : (OGWidget *)parent;
#endif

@property (assign) id <OGComboBoxDelegate> delegate;
@property (assign) id <OGComboBoxDataSource> dataSource;

+ comboBox;
@end

Modified headers/OGWidget.h from [d55653aa53] to [647ac79ffe].

1
2

3
4
5
6
7
8
9
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>

 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *


>







1
2
3
4
5
6
7
8
9
10
/*
 * Copyright (c) 2011, 2012, Jonathan Schleifer <js@webkeks.org>
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
17
18
19
20
21
22
23
24



25
26
27
28
29
30
31
32
33
34



35
36
37
38
39
40

41




 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef OG_GTK
# include <gtk/gtk.h>



#endif

#import <ObjFW/ObjFW.h>

@interface OGWidget: OFObject
{
@public
#ifdef OG_GTK
	GtkWidget *widget;
#endif



}

- (void)show;
- (void)hide;
@end


extern void og_destroy(GtkWidget*, OGWidget*);











|
>
>
>










>
>
>






>

>
>
>
>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef OG_GTK
#i nclude <gtk/gtk.h>
#endif
#ifdef OG_W32
# include <windows.h>
#endif

#import <ObjFW/ObjFW.h>

@interface OGWidget: OFObject
{
@public
#ifdef OG_GTK
	GtkWidget *widget;
#endif
#ifdef OG_W32
	HWND widget;
#endif
}

- (void)show;
- (void)hide;
@end

#ifdef OG_GTK
extern void og_destroy(GtkWidget*, OGWidget*);
#endif
#ifdef OG_W32
extern void og_destroy(HWND widget, OGWidget *object);
#endif

Added win32/Makefile version [2dc76f23f3].

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
PREFIX ?= /usr/local

all : test.exe

%.o : %.m
	gcc -g -DOG_W32 -I../headers -c -o $@ $^ `objfw-config --cppflags --objcflags`

test.exe : OGApplication.o OGWidget.o OGWindow.o OGBox.o OGVBox.o OGHBox.o OGButton.o OGComboBox.o OGComboBoxItem.o test.o
	gcc -mwindows -o test.exe *.o `objfw-config --libs`

clean :
	rm -f *.exe *.o

Added win32/OGApplication.m version [2c830d0590].















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
 
//==================================================================================================================================
// OGApplication.m
//==================================================================================================================================
#import <ObjFW/OFApplication.h> //this seems to be needed for "OF_APPLICATION_DELEGATE"
#import "OGWidget.h"
#import "OGApplication.h"
//==================================================================================================================================
void win32_init(int *argc, char ***argv);
void win32_main();
LRESULT CALLBACK win32_OGWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
//==================================================================================================================================
@interface WndMsgReceiver
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam;
@end
//==================================================================================================================================
OF_APPLICATION_DELEGATE(OGApplication)
extern Class og_application_delegate(void);
//==================================================================================================================================
@implementation OGApplication
//----------------------------------------------------------------------------------------------------------------------------------
+ (void)quit
{
  PostQuitMessage(0);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)applicationDidFinishLaunching
{
  OFAutoreleasePool *pool;
  int *argc;
  char ***argv;

  delegate = [[og_application_delegate() alloc] init];

  [[OFApplication sharedApplication] getArgumentCount: &argc
            andArgumentValues: &argv];
  win32_init(argc, argv);

  pool = [OFAutoreleasePool new];
  [delegate applicationDidFinishLaunching];
  [pool release];

  win32_main();
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)applicationWillTerminate
{
  [delegate applicationWillTerminate];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================
void win32_init(int *argc, char ***argv)
{
  //register a single window class; we'll customize later, as needed
  char *clsName = "OFWidgetClass";
  HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL);
  WNDCLASSEX wcx;
  wcx.cbSize        = sizeof(wcx);
  wcx.style         = CS_VREDRAW | CS_HREDRAW;
  wcx.lpfnWndProc   = (WNDPROC)win32_OGWndProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 0;
  wcx.hInstance     = hInst;
  wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = clsName;
  wcx.hIconSm       = NULL;
  
  RegisterClassEx(&wcx);
  //TODO: although this doesn't ever really fail, we should probably Throw an Exception here...
  //if(!RegisterClassEx(&wcx)) @throw ...;
}
//==================================================================================================================================
void win32_main()
{
  MSG msg; int msgCode;
  while((msgCode = GetMessage(&msg, NULL, 0, 0)) != 0)
  {
    if(msgCode == -1)
      return;
    else
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
}
//==================================================================================================================================
LRESULT CALLBACK win32_OGWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
  void *ptr = (void *)GetWindowLong(hwnd, GWL_USERDATA);
  if(ptr == NULL) return DefWindowProc(hwnd, msg, wparam, lparam); 
  return [(id)ptr MessageReceived : hwnd : msg : wparam : lparam];
}
//==================================================================================================================================

Added win32/OGBox.m version [80155f33e8].





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
 
//==================================================================================================================================
// OGBox.m
//==================================================================================================================================
#include <malloc.h>
#include <windows.h>
#import "OGBox.h"
//==================================================================================================================================
@implementation OGBox
//----------------------------------------------------------------------------------------------------------------------------------
+ box
{
  return [[[self alloc] init] autorelease];
}
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];
  SetWindowLong(widget, GWL_STYLE, WS_CHILD | WS_VISIBLE);
  firstBorn = NULL;

  @try {
    if (isa == [OGBox class])
      @throw [OFNotImplementedException
          exceptionWithClass: isa
              selector: _cmd];
  } @catch (id e) {
    [self release];
    @throw e;
  }

  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)appendChild: (OGWidget*)child
       expand: (BOOL)expand
         fill: (BOOL)fill
      padding: (float)padding
{
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)prependChild: (OGWidget*)child
        expand: (BOOL)expand
    fill: (BOOL)fill
       padding: (float)padding
{
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)resizeChildren
{
}
//----------------------------------------------------------------------------------------------------------------------------------
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam
{
  HWND parent;
  
  switch(msg)
  {
    case WM_COMMAND:
      parent = GetParent(hwnd);
      if(parent != NULL)
        return SendMessage(parent, msg, wparam, lparam);
    break;
  }
  return DefWindowProc(hwnd, msg, wparam, lparam);
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGButton.m version [d076240d64].































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
 
//==================================================================================================================================
// OGButton.m
//==================================================================================================================================
#define BCM_GETIDEALSIZE 0x1601
#import "OGButton.h"
//==================================================================================================================================
@interface OGButton ()
- (void)OG_clicked;
@end
//==================================================================================================================================
typedef void(*CommandHandler)(id,WPARAM);
typedef struct
{
  CommandHandler funct;
  id             object;
} CommandHandlerData;
//----------------------------------------------------------------------------------------------------------------------------------
static void CH_Command(id object, WPARAM wparam)
{
  [object OG_clicked];
}
//==================================================================================================================================
@implementation OGButton
//----------------------------------------------------------------------------------------------------------------------------------
@synthesize delegate;
//----------------------------------------------------------------------------------------------------------------------------------
+ button
{
  return [[[self alloc] init] autorelease];
}
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];
  
  //we're specifying a different class name...
  //so we'll have to discard the default OGWidget HWND...
  DestroyWindow(widget);
  //and create a new one
  widget = NULL;
  HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL);
  widget = CreateWindow("button", "", BS_PUSHBUTTON,
                          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInst, NULL);  
  SetWindowLong(widget, GWL_STYLE, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP);
  //crazy workaround since we don't have control of our WNDPROC for default "button"s
  CommandHandlerData *chd = (CommandHandlerData *)malloc(sizeof(CommandHandlerData));
  chd->funct  = CH_Command;
  chd->object = self;
  //and another workaround because "button" class seems to mess with our GWL_USERDATA storage...
  //SetWindowLong(widget, GWL_USERDATA, (UINT)(chd));
  SetProp(widget, "CommandHandlerData", chd);

  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (OFString*)label
{
  int tlen = GetWindowTextLength(widget);
  char *buff = (char *)malloc(tlen + 1);
  GetWindowText(widget, buff, tlen+1);
  
  OFString *ret = [OFString stringWithUTF8String : buff];
  free(buff);
  return ret;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)setLabel: (OFString*)label
{
  SIZE sz; sz.cx = sz.cy = 0;
  SetWindowText(widget, [label UTF8String]);
  SendMessage(widget, BCM_GETIDEALSIZE, 0, (LPARAM)(&sz));
  //SetWindowPos(widget, NULL, 0, 0, sz.cx, sz.cy, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
  SetWindowPos(widget, NULL, 0, 0, 32, 32, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)OG_clicked
{
  OFAutoreleasePool *pool = [OFAutoreleasePool new];

  if ([delegate respondsToSelector: @selector(buttonWasClicked:)])
        [delegate buttonWasClicked: self];

  [pool release];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGComboBox.m version [3b3750f8b8].



































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGComboBox.m
//==================================================================================================================================
#import "OGComboBox.h"
//==================================================================================================================================
@interface OGComboBox ()
- (void)OG_changed;
@end
//==================================================================================================================================
typedef void(*CommandHandler)(id,WPARAM);
typedef struct
{
  CommandHandler funct;
  id             object;
} CommandHandlerData;
//----------------------------------------------------------------------------------------------------------------------------------
static void CH_Command(id object, WPARAM wparam)
{
  if(HIWORD(wparam) == LBN_SELCHANGE) //selection changed
    [object OG_changed];
}
//==================================================================================================================================
@implementation OGComboBox
//----------------------------------------------------------------------------------------------------------------------------------
@synthesize delegate;
//----------------------------------------------------------------------------------------------------------------------------------
+ comboBox
{
  return [[[self alloc] init] autorelease];
}
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];

  //see [OGButton init] for reasoning here...
  DestroyWindow(widget);
  widget = NULL;
  HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL);
  widget = CreateWindow("LISTBOX", "", LBS_NOINTEGRALHEIGHT,
                          0, 0, 32, 32,
                          NULL, NULL, hInst, NULL);  
  SetWindowLong(widget, GWL_STYLE, LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP);
  CommandHandlerData *chd = (CommandHandlerData *)malloc(sizeof(CommandHandlerData));
  chd->funct  = CH_Command;
  chd->object = self;
  SetProp(widget, "CommandHandlerData", chd);
      
  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- initWithParent : (OGWidget *)parent
{
  self = [super init];

  //see [OGButton init] for reasoning here...
  DestroyWindow(widget);
  widget = NULL;
  HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL);
  widget = CreateWindow("LISTBOX", "", LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | WS_CHILD | WS_VISIBLE,
                          0, 0, 32, 32,
                          parent->widget, NULL, hInst, NULL);  
  CommandHandlerData *chd = (CommandHandlerData *)malloc(sizeof(CommandHandlerData));
  chd->funct  = CH_Command;
  chd->object = self;
  SetProp(widget, "CommandHandlerData", chd);
      
  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (id <OGComboBoxDataSource>)dataSource
{
  return dataSource;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)setDataSource: (id <OGComboBoxDataSource>)dataSource_
{
  OGComboBoxItem* (*itemAtIndex)(id, SEL, OGComboBox*, size_t);

  dataSource = dataSource_;
  itemAtIndex = (OGComboBoxItem*(*)(id, SEL, OGComboBox*, size_t))
      [dataSource methodForSelector: @selector(comboBox:itemAtIndex:)];

  size_t i, size = [dataSource numberOfItemsInComboBox: self];
  for (i = 0; i < size; i++)
  {
    OGComboBoxItem *item = itemAtIndex(dataSource,
        @selector(comboBox:itemAtIndex:), self, i);
    
    SendMessage(widget, LB_ADDSTRING, 0, (WPARAM)[item.label UTF8String]);
  }
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)OG_changed
{
  OFAutoreleasePool *pool = [OFAutoreleasePool new];

  if ([delegate respondsToSelector: @selector(comboBoxWasChanged:)])
    [delegate comboBoxWasChanged: self];

  [pool release];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGComboBoxItem.m version [21d7642f61].























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGComboBoxItem.m
//==================================================================================================================================
#import "OGComboBoxItem.h"
//==================================================================================================================================
@implementation OGComboBoxItem
//----------------------------------------------------------------------------------------------------------------------------------
@synthesize label;
//----------------------------------------------------------------------------------------------------------------------------------
+ comboBoxItemWithLabel: (OFString*)label
{
  return [[[self alloc] initWithLabel: label] autorelease];
}
//----------------------------------------------------------------------------------------------------------------------------------
- initWithLabel: (OFString*)label_
{
  self = [super init];

  @try {
    label = [label_ copy];
  } @catch (id e) {
    [self release];
    @throw e;
  }

  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)dealloc
{
  [label release];

  [super dealloc];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGHBox.m version [e2f8c4d7bd].





















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGHBox.m
//==================================================================================================================================
#include <windows.h>
#import "OGHBox.h"
//==================================================================================================================================
@implementation OGHBox
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];
  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)appendChild: (OGWidget*)child
       expand: (BOOL)expand
         fill: (BOOL)fill
      padding: (float)padding
{
  RECT rc;
  SetParent(child->widget, widget);
  GetWindowRect(child->widget, &rc);
  
  OGBoxChild *newChild   = (OGBoxChild *)malloc(sizeof(OGBoxChild));
  newChild->hwnd         = child->widget;
  newChild->expand       = expand;
  newChild->fill         = fill;
  newChild->padding      = (int)padding;
  newChild->originalSize = (rc.right - rc.left);
  newChild->currentSize  = (float)(newChild->originalSize + (newChild->padding << 1));
  newChild->next         = NULL;
  
  if(firstBorn == NULL)
    firstBorn = newChild;
  else
  {
    OGBoxChild *curr = firstBorn;
    while(curr->next != NULL) curr = curr->next;
    curr->next = newChild;
  }
  
  [self resizeChildren];
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)prependChild: (OGWidget*)child
        expand: (BOOL)expand
    fill: (BOOL)fill
       padding: (float)padding
{
  RECT rc;
  SetParent(child->widget, widget);
  GetWindowRect(child->widget, &rc);
  
  OGBoxChild *newChild   = (OGBoxChild *)malloc(sizeof(OGBoxChild));
  newChild->hwnd         = child->widget;
  newChild->expand       = expand;
  newChild->fill         = fill;
  newChild->padding      = (int)padding;
  newChild->originalSize = (rc.right - rc.left);
  newChild->currentSize  = (float)(newChild->originalSize + (newChild->padding << 1));
  newChild->next         = firstBorn;
  
  firstBorn = newChild;
  
  [self resizeChildren];
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)resizeChildren
{
  RECT rc;
  OGBoxChild *curr;
  
  //get our available size
  GetClientRect(widget, &rc);
  int width  = rc.right;
  int height = rc.bottom;
  
  //get total of childrens' widths
  int childOriginal = 0;
  curr = firstBorn;
  while(curr != NULL)
  {
    childOriginal += (curr->originalSize + (curr->padding << 1));
    curr = curr->next;
  }
  
  //how to divide our extra space
  int extra = width - childOriginal;
  float evenShare = 0.0f;
  
  if(extra <= 0)
  {
    curr = firstBorn;
    while(curr != NULL)
    {
      curr->currentSize = curr->originalSize;
      curr = curr->next;
    }
    if(extra < 0)
    {
      //this will generate a WM_SIZE message, and we'll come back to resizeChildren
      SetWindowPos(widget, NULL, 0, 0, childOriginal, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
      return;
    }
  }
  else
  {
    int sharers = 0;
    curr = firstBorn;
    while(curr != NULL)
    {
      if(curr->expand == YES)
        sharers++;
      curr = curr->next;
    }
    if(sharers > 0)
      evenShare = (float)extra / (float)sharers;
    if(evenShare > 0.0f)
    {
      curr = firstBorn;
      while(curr != NULL)
      {
        if(curr->expand == YES)
          if(curr->fill == YES)
            curr->currentSize = (float)curr->originalSize + evenShare;
        curr = curr->next;
      }
    }
  }
  
  //assign new positions/heights
  float x = 0.0f;
  curr = firstBorn;
  while(curr != NULL)
  {
    x += (float)curr->padding;
    SetWindowPos(curr->hwnd, NULL, (int)x, 0, curr->currentSize, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
    x += (float)curr->currentSize;
    if(curr->fill == NO) if(curr->expand == YES) x += evenShare;
    x += (float)curr->padding;
    curr = curr->next;
  }
}
//----------------------------------------------------------------------------------------------------------------------------------
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam
{
  switch(msg)
  {
    case WM_SIZE:
      [self resizeChildren];
      return DefWindowProc(hwnd, msg, wparam, lparam);
    break;
    
    case WM_SIZING:
      [self resizeChildren];
      return DefWindowProc(hwnd, msg, wparam, lparam);
    break;
  }
  return [(id)super MessageReceived : hwnd : msg : wparam : lparam];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGVBox.m version [8cefd08417].























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGVBox.m
//==================================================================================================================================
#include <windows.h>
#import "OGVBox.h"
//==================================================================================================================================
@implementation OGVBox
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];
  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)appendChild: (OGWidget*)child
       expand: (BOOL)expand
         fill: (BOOL)fill
      padding: (float)padding
{
  RECT rc;
  SetParent(child->widget, widget);
  GetWindowRect(child->widget, &rc);
  
  OGBoxChild *newChild   = (OGBoxChild *)malloc(sizeof(OGBoxChild));
  newChild->hwnd         = child->widget;
  newChild->expand       = expand;
  newChild->fill         = fill;
  newChild->padding      = (int)padding;
  newChild->originalSize = (rc.bottom - rc.top);
  newChild->currentSize  = (float)(newChild->originalSize + (newChild->padding << 1));
  newChild->next         = NULL;
  
  if(firstBorn == NULL)
    firstBorn = newChild;
  else
  {
    OGBoxChild *curr = firstBorn;
    while(curr->next != NULL) curr = curr->next;
    curr->next = newChild;
  }
  
  [self resizeChildren];
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)prependChild: (OGWidget*)child
        expand: (BOOL)expand
    fill: (BOOL)fill
       padding: (float)padding
{
  RECT rc;
  SetParent(child->widget, widget);
  GetWindowRect(child->widget, &rc);
  
  OGBoxChild *newChild   = (OGBoxChild *)malloc(sizeof(OGBoxChild));
  newChild->hwnd         = child->widget;
  newChild->expand       = expand;
  newChild->fill         = fill;
  newChild->padding      = (int)padding;
  newChild->originalSize = (rc.bottom - rc.top);
  newChild->currentSize  = (float)(newChild->originalSize + (newChild->padding << 1));
  newChild->next         = firstBorn;
  
  firstBorn = newChild;
  
  SetParent(child->widget, widget);
  [self resizeChildren];
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)resizeChildren
{
  RECT rc;
  OGBoxChild *curr;
  
  //get our available size
  GetClientRect(widget, &rc);
  int width  = rc.right;
  int height = rc.bottom;
  
  //get total of childrens' heights
  int childOriginal = 0;
  curr = firstBorn;
  while(curr != NULL)
  {
    childOriginal += (curr->originalSize + (curr->padding << 1));
    curr = curr->next;
  }
  
  //how to divide our extra space
  int extra = height - childOriginal;
  float evenShare = 0.0f;
  
  if(extra <= 0)
  {
    curr = firstBorn;
    while(curr != NULL)
    {
      curr->currentSize = curr->originalSize;
      curr = curr->next;
    }
    if(extra < 0)
    {
      //this will generate a WM_SIZE message, and we'll come back to resizeChildren
      SetWindowPos(widget, NULL, 0, 0, width, childOriginal, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
      return;
    }
  }
  else
  {
    int sharers = 0;
    curr = firstBorn;
    while(curr != NULL)
    {
      if(curr->expand == YES)
        sharers++;
      curr = curr->next;
    }
    if(sharers > 0)
      evenShare = (float)extra / (float)sharers;
    if(evenShare > 0.0f)
    {
      curr = firstBorn;
      while(curr != NULL)
      {
        if(curr->expand == YES)
          if(curr->fill == YES)
            curr->currentSize = (float)curr->originalSize + evenShare;
        curr = curr->next;
      }
    }
  }
  
  //assign new positions/heights
  float y = 0;
  curr = firstBorn;
  while(curr != NULL)
  {
    y += (float)curr->padding;
    SetWindowPos(curr->hwnd, NULL, 0, (int)y, width, curr->currentSize, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
    y += (float)curr->currentSize;
    if(curr->fill == NO) if(curr->expand == YES) y += evenShare;
    y += (float)curr->padding;
    curr = curr->next;
  }
}
//----------------------------------------------------------------------------------------------------------------------------------
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam
{
  switch(msg)
  {
    case WM_SIZE:
      [self resizeChildren];
      return DefWindowProc(hwnd, msg, wparam, lparam);
    break;
    
    case WM_SIZING:
      [self resizeChildren];
      return DefWindowProc(hwnd, msg, wparam, lparam);
    break;
  }
  return [(id)super MessageReceived : hwnd : msg : wparam : lparam];
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGWidget.m version [e6393d7b4b].































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGWidget.m
//==================================================================================================================================
#include <windows.h>
#import "OGWidget.h"
//==================================================================================================================================
void og_destroy(HWND widget, OGWidget *object)
{
  if(widget != NULL)
    DestroyWindow(widget);
  [object release];
}
//==================================================================================================================================
@implementation OGWidget
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];
  
  widget = NULL;
  HINSTANCE hInst = (HINSTANCE)GetModuleHandle(NULL);
  widget = CreateWindowEx(WS_EX_LEFT, "OFWidgetClass", "OFWidget", WS_OVERLAPPEDWINDOW,
                          0, 0, 1, 1, NULL, NULL, hInst, NULL);
  SetWindowLong(widget, GWL_USERDATA, (int)self);
  
  @try {
    if (isa == [OGWidget class])
      @throw [OFNotImplementedException
          exceptionWithClass: isa
              selector: @selector(init)];
  } @catch (id e) {
    [self release];
    @throw e;
  }

  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)show
{
  if(widget != NULL)
    ShowWindow(widget, SW_SHOWNORMAL);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)hide
{
  if(widget != NULL)
    ShowWindow(widget, SW_HIDE);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam
{
  return DefWindowProc(hwnd, msg, wparam, lparam);
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/OGWindow.m version [602c7b29cd].





























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

//==================================================================================================================================
// OGWindow.m
//==================================================================================================================================
#include <windows.h>
#import "OGWidget.h"
#import "OGWindow.h"
//==================================================================================================================================
@interface OGWindow ()
- (BOOL)OG_willClose;
@end
//==================================================================================================================================
typedef void(*CommandHandler)(id,WPARAM);
typedef struct
{
  CommandHandler funct;
  id             object;
} CommandHandlerData;
//==================================================================================================================================
static int CALLBACK Resize_EnumChildren(HWND child, LPARAM lparam)
{
  //it appears this is actually EnumAncestorWindows, and not EnumDirectChildWindows
  //so make sure child.parent == use
  HWND parent = (HWND)lparam;
  if(GetParent(child) != parent) return 1;
  
  RECT rc;
  GetClientRect(parent, &rc);
  SetWindowPos(child, NULL, 0, 0, rc.right, rc.bottom,
               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
  return 1;
}
//==================================================================================================================================
@implementation OGWindow
//----------------------------------------------------------------------------------------------------------------------------------
@synthesize delegate;
//----------------------------------------------------------------------------------------------------------------------------------
+ window
{
  return [[[self alloc] init] autorelease];
}
//----------------------------------------------------------------------------------------------------------------------------------
- init
{
  self = [super init];

  SetWindowLong(widget, GWL_EXSTYLE, WS_EX_OVERLAPPEDWINDOW);
  //"event connections" are handled in MessageReceived
  
  [self retain];
  return self;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (OFString*)title
{
  int tlen = GetWindowTextLength(widget);
  char *buff = (char *)malloc(tlen + 1);
  GetWindowText(widget, buff, tlen+1);
  
  OFString *ret = [OFString stringWithUTF8String : buff];
  free(buff);
  return ret;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)setTitle: (OFString*)title
{
  SetWindowText(widget, [title UTF8String]);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (of_point_t)position
{
  RECT rc;
  GetWindowRect(widget, &rc);
  return of_point((int)rc.left, (int)rc.top);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)setPosition: (of_point_t)position
{
  SetWindowPos(widget, NULL, position.x, position.y, 0, 0,
               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (of_dimension_t)dimension
{
  RECT rc;
  GetWindowRect(widget, &rc);
  return of_dimension(rc.right - rc.left, rc.bottom - rc.top);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)setDimension: (of_dimension_t)dimension
{
  SetWindowPos(widget, NULL, 0, 0, dimension.width, dimension.height,
               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (void)addChild: (OGWidget*)child
{
  SetParent(child->widget, widget);
  //act like GTK; we'll assume a single child, and expand it to our size
  RECT rc;
  GetClientRect(widget, &rc);
  SetWindowPos(child->widget, NULL, 0, 0, rc.right, rc.bottom,
               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
//----------------------------------------------------------------------------------------------------------------------------------
- (BOOL)OG_willClose
{
  OFAutoreleasePool *pool = [OFAutoreleasePool new];

  if ([delegate respondsToSelector: @selector(windowWillClose:)])
    return [delegate windowWillClose: self];

  [pool release];
  return YES;
}
//----------------------------------------------------------------------------------------------------------------------------------
- (int)MessageReceived : (HWND)hwnd : (UINT)msg : (WPARAM)wparam : (LPARAM)lparam
{
  HWND ctrlHwnd;
  
  switch(msg)
  {
    case WM_COMMAND:
      //NOTE: TODO: IMPLEMENT: this may need revised later for Menus and Accelerators
      ctrlHwnd = (HWND)lparam;
      CommandHandlerData *chd = (CommandHandlerData *)GetProp(ctrlHwnd, "CommandHandlerData");
      if(chd        == NULL) return DefWindowProc(hwnd, msg, wparam, lparam);
      if(chd->funct == NULL) return DefWindowProc(hwnd, msg, wparam, lparam);
      chd->funct(chd->object, wparam);
      return 0;
    break;
    
    case WM_CLOSE:
      if([self OG_willClose] == YES)
        og_destroy(hwnd, self);
      return 0;
    break;
    
    case WM_SIZE:
      //act like GTK; expand our child(ren) to fit
      EnumChildWindows(widget, Resize_EnumChildren, (LPARAM)widget);
    break;
    
    case WM_SIZING:
      //act like GTK; expand our child(ren) to fit
      EnumChildWindows(widget, Resize_EnumChildren, (LPARAM)widget);
    break;
  }
  return DefWindowProc(hwnd, msg, wparam, lparam);
}
//----------------------------------------------------------------------------------------------------------------------------------
@end
//==================================================================================================================================

Added win32/test.m version [7bc3895fd9].







































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * Copyright (c) 2011, 2012, Dillon Aumiller <dillonaumiller@gmail.com>
 *
 * https://webkeks.org/hg/objgui/
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice is present in all copies.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#import "OGApplication.h"
#import "OGWindow.h"
#import "OGButton.h"
#import "OGHBox.h"
#import "OGVBox.h"
#import "OGComboBox.h"

//i know it's ugly, but it's just for testing...
#include <malloc.h>
@interface TestSource : OFObject <OGComboBoxDataSource>
{
  OGComboBoxItem **items;
}
@end
@implementation TestSource
- init
{
  self = [super init];
  
  items = (OGComboBoxItem **)malloc(sizeof(OGComboBoxItem *) << 2);
  items[0] = [OGComboBoxItem comboBoxItemWithLabel : @"Test Combo Item 0"];
  items[1] = [OGComboBoxItem comboBoxItemWithLabel : @"Test Combo Item 1"];
  items[2] = [OGComboBoxItem comboBoxItemWithLabel : @"Test Combo Item 2"];
  items[3] = [OGComboBoxItem comboBoxItemWithLabel : @"Test Combo Item 3"];
  
  [self retain];
  return self;
}
- (size_t)numberOfItemsInComboBox: (OGComboBox*)comboBox
{
  return 4;
}
- (OGComboBoxItem*)comboBox: (OGComboBox*)comboBox itemAtIndex: (size_t)index
{
  return items[index];
}
@end


@interface Test: OFObject <OGApplicationDelegate, OGWindowDelegate, OGButtonDelegate, OGComboBoxDelegate>
@end

OG_APPLICATION_DELEGATE(Test)

@implementation Test
- (void)applicationDidFinishLaunching
{
  OGWindow *w = [OGWindow window];
  w.title = @"Hallo Welt!";
  w.position = of_point(100, 100);
  w.dimension = of_dimension(600, 400);
  w.delegate = self;

  OGVBox *vbox = [OGVBox box];
  [w addChild: vbox];

  OGHBox *hboxPre = [OGHBox box];
  [vbox appendChild: hboxPre
             expand: YES
               fill: YES
            padding: 0];

  OGButton *b = [OGButton button];
  b.label = @"Klick mich!";
  b.delegate = self;
  [hboxPre appendChild: b
       expand: YES
         fill: YES
      padding: 0];
  
  OGComboBox *cb = [[OGComboBox alloc] initWithParent : hboxPre];
  cb.dataSource  = [[TestSource alloc] init];
  cb.delegate    = self;
  [hboxPre appendChild: cb
                expand: YES
                  fill: YES
               padding: 0];

  OGHBox *hbox = [OGHBox box];
  [vbox appendChild: hbox
       expand: NO
         fill: NO
      padding: 0];

  OGButton *b1 = [OGButton button];
  b1.label = @"Ich";
  [hbox appendChild: b1
       expand: YES
         fill: YES
      padding: 0];

  OGButton *b2 = [OGButton button];
  b2.label = @"mach";
  [hbox appendChild: b2
       expand: YES
         fill: YES
      padding: 0];

  OGButton *b3 = [OGButton button];
  b3.label = @"nix";
  [hbox appendChild: b3
       expand: YES
         fill: YES
      padding: 0];

  [w show];
}

- (BOOL)windowWillClose: (OGWindow*)window
{
  [OGApplication quit];

  return YES;
}

- (void)buttonWasClicked: (OGButton*)button
{
  MessageBox(NULL, "Hallo!", "OGButton says:", MB_OK);
}

- (void)comboBoxWasChanged: (OGComboBox*)comboBox
{
  MessageBox(NULL, "Selected Item Changed", "OGComboBox says:", MB_OK);
}
@end