xref: /haiku/src/tests/servers/app/playground/ObjectWindow.cpp (revision 4dfc2afb5bb408dcbe9fd8121d44449c9a8fc86b)
178c1c29bSStephan Aßmus // main.cpp
278c1c29bSStephan Aßmus 
378c1c29bSStephan Aßmus #include <stdio.h>
478c1c29bSStephan Aßmus #include <stdlib.h>
578c1c29bSStephan Aßmus 
678c1c29bSStephan Aßmus #include <Application.h>
7*4dfc2afbSAxel Dörfler #include <Alert.h>
878c1c29bSStephan Aßmus #include <Box.h>
978c1c29bSStephan Aßmus #include <Button.h>
1078c1c29bSStephan Aßmus #include <CheckBox.h>
1178c1c29bSStephan Aßmus #include <Menu.h>
1278c1c29bSStephan Aßmus #include <MenuBar.h>
1378c1c29bSStephan Aßmus #include <MenuItem.h>
1478c1c29bSStephan Aßmus #include <String.h>
1578c1c29bSStephan Aßmus #include <RadioButton.h>
1678c1c29bSStephan Aßmus #include <TextControl.h>
1778c1c29bSStephan Aßmus #include <TextView.h>
1878c1c29bSStephan Aßmus 
1978c1c29bSStephan Aßmus #include "ObjectView.h"
2078c1c29bSStephan Aßmus #include "States.h"
2178c1c29bSStephan Aßmus 
2278c1c29bSStephan Aßmus #include "ObjectWindow.h"
2378c1c29bSStephan Aßmus 
2478c1c29bSStephan Aßmus enum {
2578c1c29bSStephan Aßmus 	MSG_SET_OBJECT_TYPE		= 'stot',
2678c1c29bSStephan Aßmus 	MSG_SET_FILL_OR_STROKE	= 'stfs',
2778c1c29bSStephan Aßmus 	MSG_SET_COLOR			= 'stcl',
2878c1c29bSStephan Aßmus 	MSG_SET_PEN_SIZE		= 'stps',
2978c1c29bSStephan Aßmus 
3078c1c29bSStephan Aßmus 	MSG_NEW_OBJECT			= 'nobj',
3178c1c29bSStephan Aßmus 
3278c1c29bSStephan Aßmus 	MSG_UNDO				= 'undo',
3378c1c29bSStephan Aßmus 	MSG_REDO				= 'redo',
3478c1c29bSStephan Aßmus 
3578c1c29bSStephan Aßmus 	MSG_CLEAR				= 'clir',
3678c1c29bSStephan Aßmus };
3778c1c29bSStephan Aßmus 
3878c1c29bSStephan Aßmus // constructor
3978c1c29bSStephan Aßmus ObjectWindow::ObjectWindow(BRect frame, const char* name)
4078c1c29bSStephan Aßmus 	: BWindow(frame, name, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS)
4178c1c29bSStephan Aßmus {
4278c1c29bSStephan Aßmus 	BRect b(Bounds());
4378c1c29bSStephan Aßmus 
4478c1c29bSStephan Aßmus 	b.bottom = b.top + 8;
4578c1c29bSStephan Aßmus 	BMenuBar* menuBar = new BMenuBar(b, "menu bar");
4678c1c29bSStephan Aßmus 	AddChild(menuBar);
4778c1c29bSStephan Aßmus 
4878c1c29bSStephan Aßmus 	BMenu* menu = new BMenu("Menus");
4978c1c29bSStephan Aßmus 	menuBar->AddItem(menu);
5078c1c29bSStephan Aßmus 
5178c1c29bSStephan Aßmus 	BMenuItem* menuItem = new BMenuItem("Quit", NULL, 'Q');
5278c1c29bSStephan Aßmus 	menu->AddItem(menuItem);
5378c1c29bSStephan Aßmus 
5478c1c29bSStephan Aßmus 	menuBar->AddItem(new BMenu("don't"));
5578c1c29bSStephan Aßmus 	menuBar->AddItem(new BMenu("work!"));
5678c1c29bSStephan Aßmus 	menuBar->AddItem(new BMenu("(yet)"));
5778c1c29bSStephan Aßmus 
5878c1c29bSStephan Aßmus 	b = Bounds();
5978c1c29bSStephan Aßmus 	b.top = menuBar->Bounds().bottom + 1;
6078c1c29bSStephan Aßmus 	BBox* bg = new BBox(b, "bg box", B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER);
6178c1c29bSStephan Aßmus 
6278c1c29bSStephan Aßmus 	AddChild(bg);
6378c1c29bSStephan Aßmus 	bg->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
6478c1c29bSStephan Aßmus 
6578c1c29bSStephan Aßmus 	b = bg->Bounds();
6678c1c29bSStephan Aßmus 	// object views occupies the right side of the window
6778c1c29bSStephan Aßmus 	b.Set(ceilf((b.left + b.right) / 3.0) + 3.0, b.top + 5.0, b.right - 5.0, b.bottom - 5.0);
6878c1c29bSStephan Aßmus 	fObjectView = new ObjectView(b, "object view", B_FOLLOW_ALL,
6978c1c29bSStephan Aßmus 								 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
7078c1c29bSStephan Aßmus 
7178c1c29bSStephan Aßmus 	bg->AddChild(fObjectView);
7278c1c29bSStephan Aßmus 
7378c1c29bSStephan Aßmus 	b = bg->Bounds();
7478c1c29bSStephan Aßmus 	// controls occupy the left side of the window
7578c1c29bSStephan Aßmus 	b.Set(b.left + 5.0, b.top + 5.0, ceilf((b.left + b.right) / 3.0) - 2.0, b.bottom - 5.0);
7678c1c29bSStephan Aßmus 	BBox* controlGroup = new BBox(b, "controls box", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
7778c1c29bSStephan Aßmus 								  B_WILL_DRAW, B_FANCY_BORDER);
7878c1c29bSStephan Aßmus 
7978c1c29bSStephan Aßmus 	controlGroup->SetLabel("Controls");
8078c1c29bSStephan Aßmus 	bg->AddChild(controlGroup);
8178c1c29bSStephan Aßmus 
8278c1c29bSStephan Aßmus 	b = controlGroup->Bounds();
8378c1c29bSStephan Aßmus 	b.top += 10.0;
8478c1c29bSStephan Aßmus 	b.bottom = b.top + 25.0;
8578c1c29bSStephan Aßmus 	b.InsetBy(5.0, 5.0);
8678c1c29bSStephan Aßmus 
8778c1c29bSStephan Aßmus 	// new button
8878c1c29bSStephan Aßmus 	fNewB = new BButton(b, "new button", "New Object", new BMessage(MSG_NEW_OBJECT));
8978c1c29bSStephan Aßmus 	controlGroup->AddChild(fNewB);
9078c1c29bSStephan Aßmus 
9178c1c29bSStephan Aßmus 	// clear button
9278c1c29bSStephan Aßmus 	b.OffsetBy(0, fNewB->Bounds().Height() + 5.0);
9378c1c29bSStephan Aßmus 	fClearB = new BButton(b, "clear button", "Clear", new BMessage(MSG_CLEAR));
9478c1c29bSStephan Aßmus 	controlGroup->AddChild(fClearB);
9578c1c29bSStephan Aßmus 
9678c1c29bSStephan Aßmus 	// object type radio buttons
9778c1c29bSStephan Aßmus 	BMessage* message;
9878c1c29bSStephan Aßmus 	BRadioButton* radioButton;
9978c1c29bSStephan Aßmus 
10078c1c29bSStephan Aßmus 	b.OffsetBy(0, fClearB->Bounds().Height() + 5.0);
10178c1c29bSStephan Aßmus 	message = new BMessage(MSG_SET_OBJECT_TYPE);
10278c1c29bSStephan Aßmus 	message->AddInt32("type", OBJECT_LINE);
10378c1c29bSStephan Aßmus 	radioButton = new BRadioButton(b, "radio 1", "Line", message);
10478c1c29bSStephan Aßmus 	controlGroup->AddChild(radioButton);
10578c1c29bSStephan Aßmus 
10678c1c29bSStephan Aßmus 	radioButton->SetValue(B_CONTROL_ON);
10778c1c29bSStephan Aßmus 
10878c1c29bSStephan Aßmus 	b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
10978c1c29bSStephan Aßmus 	message = new BMessage(MSG_SET_OBJECT_TYPE);
11078c1c29bSStephan Aßmus 	message->AddInt32("type", OBJECT_RECT);
11178c1c29bSStephan Aßmus 	radioButton = new BRadioButton(b, "radio 2", "Rect", message);
11278c1c29bSStephan Aßmus 	controlGroup->AddChild(radioButton);
11378c1c29bSStephan Aßmus 
11478c1c29bSStephan Aßmus 	b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
11578c1c29bSStephan Aßmus 	message = new BMessage(MSG_SET_OBJECT_TYPE);
11678c1c29bSStephan Aßmus 	message->AddInt32("type", OBJECT_ROUND_RECT);
11778c1c29bSStephan Aßmus 	radioButton = new BRadioButton(b, "radio 3", "Round Rect", message);
11878c1c29bSStephan Aßmus 	controlGroup->AddChild(radioButton);
11978c1c29bSStephan Aßmus 
12078c1c29bSStephan Aßmus 	b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
12178c1c29bSStephan Aßmus 	message = new BMessage(MSG_SET_OBJECT_TYPE);
12278c1c29bSStephan Aßmus 	message->AddInt32("type", OBJECT_ELLIPSE);
12378c1c29bSStephan Aßmus 	radioButton = new BRadioButton(b, "radio 4", "Ellipse", message);
12478c1c29bSStephan Aßmus 	controlGroup->AddChild(radioButton);
12578c1c29bSStephan Aßmus 
12678c1c29bSStephan Aßmus 	// red text control
12778c1c29bSStephan Aßmus 	b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
12878c1c29bSStephan Aßmus 	fRedTC = new BTextControl(b, "red text control", "Red", "",
12978c1c29bSStephan Aßmus 							  new BMessage(MSG_SET_COLOR));
13078c1c29bSStephan Aßmus 	controlGroup->AddChild(fRedTC);
13178c1c29bSStephan Aßmus 
13278c1c29bSStephan Aßmus 	// green text control
13378c1c29bSStephan Aßmus 	b.OffsetBy(0, fRedTC->Bounds().Height() + 5.0);
13478c1c29bSStephan Aßmus 	fGreenTC = new BTextControl(b, "green text control", "Green", "",
13578c1c29bSStephan Aßmus 								new BMessage(MSG_SET_COLOR));
13678c1c29bSStephan Aßmus 	controlGroup->AddChild(fGreenTC);
13778c1c29bSStephan Aßmus 
13878c1c29bSStephan Aßmus 	// blue text control
13978c1c29bSStephan Aßmus 	b.OffsetBy(0, fGreenTC->Bounds().Height() + 5.0);
14078c1c29bSStephan Aßmus 	fBlueTC = new BTextControl(b, "blue text control", "Blue", "",
14178c1c29bSStephan Aßmus 							   new BMessage(MSG_SET_COLOR));
14278c1c29bSStephan Aßmus 	controlGroup->AddChild(fBlueTC);
14378c1c29bSStephan Aßmus 
14478c1c29bSStephan Aßmus 	// alpha text control
14578c1c29bSStephan Aßmus 	b.OffsetBy(0, fBlueTC->Bounds().Height() + 5.0);
14678c1c29bSStephan Aßmus 	fAlphaTC = new BTextControl(b, "alpha text control", "Alpha", "",
14778c1c29bSStephan Aßmus 								new BMessage(MSG_SET_COLOR));
14878c1c29bSStephan Aßmus 	controlGroup->AddChild(fAlphaTC);
14978c1c29bSStephan Aßmus /*
15078c1c29bSStephan Aßmus // TODO: while this block of code works in the Haiku app_server running under R5,
15178c1c29bSStephan Aßmus // it crashes pretty badly under Haiku. I have no idea why this happens, because
15278c1c29bSStephan Aßmus // I was doing the same thing before at other places.
15378c1c29bSStephan Aßmus 	// divide text controls the same
15478c1c29bSStephan Aßmus 	float rWidth = fRedTC->StringWidth(fRedTC->Label());
15578c1c29bSStephan Aßmus 	float gWidth = fGreenTC->StringWidth(fGreenTC->Label());
15678c1c29bSStephan Aßmus 	float bWidth = fBlueTC->StringWidth(fBlueTC->Label());
15778c1c29bSStephan Aßmus 	float aWidth = fAlphaTC->StringWidth(fAlphaTC->Label());
15878c1c29bSStephan Aßmus 
15978c1c29bSStephan Aßmus 	float width = max_c(rWidth, max_c(gWidth, max_c(bWidth, aWidth))) + 10.0;
16078c1c29bSStephan Aßmus 	fRedTC->SetDivider(width);
16178c1c29bSStephan Aßmus 	fGreenTC->SetDivider(width);
16278c1c29bSStephan Aßmus 	fBlueTC->SetDivider(width);
16378c1c29bSStephan Aßmus 	fAlphaTC->SetDivider(width);*/
16478c1c29bSStephan Aßmus 
16578c1c29bSStephan Aßmus 	// fill check box
16678c1c29bSStephan Aßmus 	b.OffsetBy(0, fAlphaTC->Bounds().Height() + 5.0);
16778c1c29bSStephan Aßmus 	fFillCB = new BCheckBox(b, "fill check box", "Fill",
16878c1c29bSStephan Aßmus 							new BMessage(MSG_SET_FILL_OR_STROKE));
16978c1c29bSStephan Aßmus 	controlGroup->AddChild(fFillCB);
17078c1c29bSStephan Aßmus 
17178c1c29bSStephan Aßmus 	// pen size text control
17278c1c29bSStephan Aßmus 	b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
17378c1c29bSStephan Aßmus 	fPenSizeTC = new BTextControl(b, "width text control", "Width", "",
17478c1c29bSStephan Aßmus 								  new BMessage(MSG_SET_PEN_SIZE));
17578c1c29bSStephan Aßmus 	controlGroup->AddChild(fPenSizeTC);
17678c1c29bSStephan Aßmus 
17778c1c29bSStephan Aßmus 	_UpdateControls();
17878c1c29bSStephan Aßmus }
17978c1c29bSStephan Aßmus 
18078c1c29bSStephan Aßmus // destructor
18178c1c29bSStephan Aßmus ObjectWindow::~ObjectWindow()
18278c1c29bSStephan Aßmus {
18378c1c29bSStephan Aßmus }
18478c1c29bSStephan Aßmus 
18578c1c29bSStephan Aßmus // QuitRequested
18678c1c29bSStephan Aßmus bool
18778c1c29bSStephan Aßmus ObjectWindow::QuitRequested()
18878c1c29bSStephan Aßmus {
18978c1c29bSStephan Aßmus 	be_app->PostMessage(B_QUIT_REQUESTED);
19078c1c29bSStephan Aßmus 	return true;
19178c1c29bSStephan Aßmus }
19278c1c29bSStephan Aßmus 
19378c1c29bSStephan Aßmus // MessageReceived
19478c1c29bSStephan Aßmus void
19578c1c29bSStephan Aßmus ObjectWindow::MessageReceived(BMessage* message)
19678c1c29bSStephan Aßmus {
19778c1c29bSStephan Aßmus 	switch (message->what) {
19878c1c29bSStephan Aßmus 		case MSG_SET_OBJECT_TYPE: {
19978c1c29bSStephan Aßmus 			int32 type;
20078c1c29bSStephan Aßmus 			if (message->FindInt32("type", &type) >= B_OK) {
20178c1c29bSStephan Aßmus 				fObjectView->SetObjectType(type);
20278c1c29bSStephan Aßmus 				fFillCB->SetEnabled(type != OBJECT_LINE);
203e803c97cSStephan Aßmus 				if (!fFillCB->IsEnabled())
204e803c97cSStephan Aßmus 					fPenSizeTC->SetEnabled(true);
205e803c97cSStephan Aßmus 				else
206e803c97cSStephan Aßmus 					fPenSizeTC->SetEnabled(fFillCB->Value() == B_CONTROL_OFF);
20778c1c29bSStephan Aßmus 			}
20878c1c29bSStephan Aßmus 			break;
20978c1c29bSStephan Aßmus 		}
21078c1c29bSStephan Aßmus 		case MSG_SET_FILL_OR_STROKE: {
21178c1c29bSStephan Aßmus 			int32 value;
21278c1c29bSStephan Aßmus 			if (message->FindInt32("be:value", &value) >= B_OK) {
21378c1c29bSStephan Aßmus 				fObjectView->SetStateFill(value);
21478c1c29bSStephan Aßmus 				fPenSizeTC->SetEnabled(value == B_CONTROL_OFF);
21578c1c29bSStephan Aßmus 			}
21678c1c29bSStephan Aßmus 			break;
21778c1c29bSStephan Aßmus 		}
21878c1c29bSStephan Aßmus 		case MSG_SET_COLOR:
21978c1c29bSStephan Aßmus 			fObjectView->SetStateColor(_GetColor());
22078c1c29bSStephan Aßmus 			break;
22178c1c29bSStephan Aßmus 		case MSG_OBJECT_COUNT_CHANGED:
22278c1c29bSStephan Aßmus 			fClearB->SetEnabled(fObjectView->CountObjects() > 0);
22378c1c29bSStephan Aßmus 			break;
22478c1c29bSStephan Aßmus 		case MSG_NEW_OBJECT:
22578c1c29bSStephan Aßmus 			fObjectView->SetState(NULL);
22678c1c29bSStephan Aßmus 			break;
227*4dfc2afbSAxel Dörfler 		case MSG_CLEAR: {
228*4dfc2afbSAxel Dörfler 			BAlert *alert = new BAlert("Playground", "Do you really want to clear all drawing objects?", "No", "Yes");
229*4dfc2afbSAxel Dörfler 			if (alert->Go() == 1)
23078c1c29bSStephan Aßmus 				fObjectView->MakeEmpty();
23178c1c29bSStephan Aßmus 			break;
232*4dfc2afbSAxel Dörfler 		}
23378c1c29bSStephan Aßmus 		case MSG_SET_PEN_SIZE:
23478c1c29bSStephan Aßmus 			fObjectView->SetStatePenSize(atof(fPenSizeTC->Text()));
23578c1c29bSStephan Aßmus 			break;
23678c1c29bSStephan Aßmus 		default:
23778c1c29bSStephan Aßmus 			BWindow::MessageReceived(message);
23878c1c29bSStephan Aßmus 	}
23978c1c29bSStephan Aßmus }
24078c1c29bSStephan Aßmus 
24178c1c29bSStephan Aßmus // _UpdateControls
24278c1c29bSStephan Aßmus void
24378c1c29bSStephan Aßmus ObjectWindow::_UpdateControls() const
24478c1c29bSStephan Aßmus {
24578c1c29bSStephan Aßmus 	// update color
24678c1c29bSStephan Aßmus 	rgb_color c = fObjectView->StateColor();
24778c1c29bSStephan Aßmus 	char string[32];
24878c1c29bSStephan Aßmus 
24978c1c29bSStephan Aßmus 	sprintf(string, "%d", c.red);
25078c1c29bSStephan Aßmus 	fRedTC->SetText(string);
25178c1c29bSStephan Aßmus 
25278c1c29bSStephan Aßmus 	sprintf(string, "%d", c.green);
25378c1c29bSStephan Aßmus 	fGreenTC->SetText(string);
25478c1c29bSStephan Aßmus 
25578c1c29bSStephan Aßmus 	sprintf(string, "%d", c.blue);
25678c1c29bSStephan Aßmus 	fBlueTC->SetText(string);
25778c1c29bSStephan Aßmus 
25878c1c29bSStephan Aßmus 	sprintf(string, "%d", c.alpha);
25978c1c29bSStephan Aßmus 	fAlphaTC->SetText(string);
26078c1c29bSStephan Aßmus 
26178c1c29bSStephan Aßmus 
26278c1c29bSStephan Aßmus 	// update buttons
26378c1c29bSStephan Aßmus 	fClearB->SetEnabled(fObjectView->CountObjects() > 0);
26478c1c29bSStephan Aßmus 
26578c1c29bSStephan Aßmus 	fFillCB->SetEnabled(fObjectView->ObjectType() != OBJECT_LINE);
26678c1c29bSStephan Aßmus 
26778c1c29bSStephan Aßmus 	// disable penSize if fill is on
26878c1c29bSStephan Aßmus 	sprintf(string, "%.1f", fObjectView->StatePenSize());
26978c1c29bSStephan Aßmus 	fPenSizeTC->SetText(string);
270e803c97cSStephan Aßmus 	if (!fFillCB->IsEnabled())
271e803c97cSStephan Aßmus 		fPenSizeTC->SetEnabled(true);
272e803c97cSStephan Aßmus 	else
273e803c97cSStephan Aßmus 		fPenSizeTC->SetEnabled(fFillCB->Value() == B_CONTROL_OFF);
27478c1c29bSStephan Aßmus }
27578c1c29bSStephan Aßmus 
27678c1c29bSStephan Aßmus // _GetColor
27778c1c29bSStephan Aßmus rgb_color
27878c1c29bSStephan Aßmus ObjectWindow::_GetColor() const
27978c1c29bSStephan Aßmus {
28078c1c29bSStephan Aßmus 	rgb_color c;
28178c1c29bSStephan Aßmus 	c.red	= max_c(0, min_c(255, atoi(fRedTC->Text())));
28278c1c29bSStephan Aßmus 	c.green	= max_c(0, min_c(255, atoi(fGreenTC->Text())));
28378c1c29bSStephan Aßmus 	c.blue	= max_c(0, min_c(255, atoi(fBlueTC->Text())));
28478c1c29bSStephan Aßmus 	c.alpha	= max_c(0, min_c(255, atoi(fAlphaTC->Text())));
28578c1c29bSStephan Aßmus 
28678c1c29bSStephan Aßmus 	return c;
28778c1c29bSStephan Aßmus }
28878c1c29bSStephan Aßmus 
289