Playground is now a little drawing app. Fully functional under Haiku, but with some strange defects in arc calculation within AGG.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12702 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4a95e83357
commit
78c1c29baf
@ -2,6 +2,6 @@ SubDir OBOS_TOP src tests servers app ;
|
||||
|
||||
SubInclude OBOS_TOP src tests servers app copy_bits ;
|
||||
SubInclude OBOS_TOP src tests servers app painter ;
|
||||
SubInclude OBOS_TOP src tests servers app playground ;
|
||||
SubInclude OBOS_TOP src tests servers app scrolling ;
|
||||
SubInclude OBOS_TOP src tests servers app textview ;
|
||||
SubInclude OBOS_TOP src tests servers app playground ;
|
||||
|
@ -3,8 +3,11 @@ SubDir OBOS_TOP src tests servers app playground ;
|
||||
UseHeaders [ FDirName os app ] ;
|
||||
UseHeaders [ FDirName os interface ] ;
|
||||
|
||||
SimpleTest Playground :
|
||||
App Playground :
|
||||
main.cpp
|
||||
ObjectView.cpp
|
||||
ObjectWindow.cpp
|
||||
States.cpp
|
||||
;
|
||||
|
||||
if ( $(TARGET_PLATFORM) = haiku ) {
|
||||
|
228
src/tests/servers/app/playground/ObjectView.cpp
Normal file
228
src/tests/servers/app/playground/ObjectView.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
// ObjectView.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Message.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "States.h"
|
||||
|
||||
#include "ObjectView.h"
|
||||
|
||||
// constructor
|
||||
ObjectView::ObjectView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags)
|
||||
: BView(frame, name, resizeFlags, flags | B_FRAME_EVENTS),
|
||||
fState(NULL),
|
||||
fObjectType(OBJECT_LINE),
|
||||
fStateList(20),
|
||||
fColor((rgb_color){ 0, 80, 255, 100 }),
|
||||
fFill(false),
|
||||
fPenSize(10.0)
|
||||
{
|
||||
rgb_color bg = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT);
|
||||
SetViewColor(bg);
|
||||
SetLowColor(bg);
|
||||
}
|
||||
|
||||
// AttachedToWindow
|
||||
void
|
||||
ObjectView::AttachedToWindow()
|
||||
{
|
||||
}
|
||||
|
||||
// Draw
|
||||
void
|
||||
ObjectView::Draw(BRect updateRect)
|
||||
{
|
||||
rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT);
|
||||
rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT);
|
||||
|
||||
BRect r(Bounds());
|
||||
|
||||
BeginLineArray(4);
|
||||
AddLine(BPoint(r.left, r.top),
|
||||
BPoint(r.right, r.top), shadow);
|
||||
AddLine(BPoint(r.right, r.top + 1),
|
||||
BPoint(r.right, r.bottom), light);
|
||||
AddLine(BPoint(r.right - 1, r.bottom),
|
||||
BPoint(r.left, r.bottom), light);
|
||||
AddLine(BPoint(r.left, r.bottom - 1),
|
||||
BPoint(r.left, r.top + 1), shadow);
|
||||
EndLineArray();
|
||||
|
||||
SetHighColor(255, 0, 0, 128);
|
||||
|
||||
const char* message = "Click and drag";
|
||||
float width = StringWidth(message);
|
||||
BPoint p(r.left + r.Width() / 2.0 - width / 2.0,
|
||||
r.top + r.Height() / 2.0);
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
message = "to draw an object!";
|
||||
width = StringWidth(message);
|
||||
p.x = r.left + r.Width() / 2.0 - width / 2.0;
|
||||
p.y += 20;
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
|
||||
state->Draw(this);
|
||||
|
||||
// TODO: this should not be necessary with proper state stack
|
||||
// (a new state is pushed before Draw() is called)
|
||||
SetPenSize(1.0);
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
ObjectView::MouseDown(BPoint where)
|
||||
{
|
||||
if (!fState)
|
||||
SetState(State::StateFor(fObjectType, fColor, fFill, fPenSize));
|
||||
|
||||
if (fState) {
|
||||
Invalidate(fState->Bounds());
|
||||
fState->MouseDown(where);
|
||||
Invalidate(fState->Bounds());
|
||||
}
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
ObjectView::MouseUp(BPoint where)
|
||||
{
|
||||
if (fState) {
|
||||
fState->MouseUp(where);
|
||||
}
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
ObjectView::MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage)
|
||||
{
|
||||
if (fState && fState->IsTracking()) {
|
||||
BRect before = fState->Bounds();
|
||||
|
||||
fState->MouseMoved(where);
|
||||
|
||||
BRect after = fState->Bounds();
|
||||
BRect invalid(before | after);
|
||||
Invalidate(invalid);
|
||||
}
|
||||
}
|
||||
|
||||
// SetState
|
||||
void
|
||||
ObjectView::SetState(State* state)
|
||||
{
|
||||
fState = state;
|
||||
|
||||
if (fState) {
|
||||
Invalidate(fState->Bounds());
|
||||
AddObject(fState);
|
||||
}
|
||||
}
|
||||
|
||||
// SetObjectType
|
||||
void
|
||||
ObjectView::SetObjectType(int32 type)
|
||||
{
|
||||
if (type != fObjectType) {
|
||||
fObjectType = type;
|
||||
SetState(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// AddObject
|
||||
void
|
||||
ObjectView::AddObject(State* state)
|
||||
{
|
||||
if (state) {
|
||||
fStateList.AddItem((void*)state);
|
||||
Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
// CountObjects
|
||||
int32
|
||||
ObjectView::CountObjects() const
|
||||
{
|
||||
return fStateList.CountItems();
|
||||
}
|
||||
|
||||
// MakeEmpty
|
||||
void
|
||||
ObjectView::MakeEmpty()
|
||||
{
|
||||
for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
|
||||
delete state;
|
||||
fStateList.MakeEmpty();
|
||||
|
||||
Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
|
||||
|
||||
fState = NULL;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
// SetStateColor
|
||||
void
|
||||
ObjectView::SetStateColor(rgb_color color)
|
||||
{
|
||||
if (color.red != fColor.red ||
|
||||
color.green != fColor.green ||
|
||||
color.blue != fColor.blue ||
|
||||
color.alpha != fColor.alpha) {
|
||||
|
||||
fColor = color;
|
||||
|
||||
if (fState) {
|
||||
fState->SetColor(fColor);
|
||||
Invalidate(fState->Bounds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetStateFill
|
||||
void
|
||||
ObjectView::SetStateFill(bool fill)
|
||||
{
|
||||
if (fFill != fill) {
|
||||
fFill = fill;
|
||||
|
||||
if (fState) {
|
||||
BRect before = fState->Bounds();
|
||||
|
||||
fState->SetFill(fill);
|
||||
|
||||
BRect after = fState->Bounds();
|
||||
BRect invalid(before | after);
|
||||
Invalidate(invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetStatePenSize
|
||||
void
|
||||
ObjectView::SetStatePenSize(float penSize)
|
||||
{
|
||||
if (fPenSize != penSize) {
|
||||
fPenSize = penSize;
|
||||
|
||||
if (fState) {
|
||||
BRect before = fState->Bounds();
|
||||
|
||||
fState->SetPenSize(penSize);
|
||||
|
||||
BRect after = fState->Bounds();
|
||||
BRect invalid(before | after);
|
||||
Invalidate(invalid);
|
||||
}
|
||||
}
|
||||
}
|
64
src/tests/servers/app/playground/ObjectView.h
Normal file
64
src/tests/servers/app/playground/ObjectView.h
Normal file
@ -0,0 +1,64 @@
|
||||
// ObjectView.h
|
||||
|
||||
#ifndef OBJECT_VIEW_H
|
||||
#define OBJECT_VIEW_H
|
||||
|
||||
#include <List.h>
|
||||
#include <View.h>
|
||||
|
||||
class State;
|
||||
|
||||
enum {
|
||||
MSG_OBJECT_COUNT_CHANGED = 'obcc',
|
||||
};
|
||||
|
||||
class ObjectView : public BView {
|
||||
public:
|
||||
ObjectView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags);
|
||||
|
||||
// BView
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
|
||||
// ObjectView
|
||||
void SetState(State* state);
|
||||
|
||||
void SetObjectType(int32 type);
|
||||
int32 ObjectType() const
|
||||
{ return fObjectType; }
|
||||
|
||||
void AddObject(State* state);
|
||||
int32 CountObjects() const;
|
||||
void MakeEmpty();
|
||||
|
||||
void SetStateColor(rgb_color color);
|
||||
rgb_color StateColor() const
|
||||
{ return fColor; }
|
||||
|
||||
void SetStateFill(bool fill);
|
||||
bool StateFill() const
|
||||
{ return fFill; }
|
||||
|
||||
void SetStatePenSize(float penSize);
|
||||
float StatePenSize() const
|
||||
{ return fPenSize; }
|
||||
|
||||
private:
|
||||
State* fState;
|
||||
int32 fObjectType;
|
||||
|
||||
BList fStateList;
|
||||
|
||||
rgb_color fColor;
|
||||
bool fFill;
|
||||
float fPenSize;
|
||||
};
|
||||
|
||||
#endif // OBJECT_VIEW_H
|
277
src/tests/servers/app/playground/ObjectWindow.cpp
Normal file
277
src/tests/servers/app/playground/ObjectWindow.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
// main.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <CheckBox.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <String.h>
|
||||
#include <RadioButton.h>
|
||||
#include <TextControl.h>
|
||||
#include <TextView.h>
|
||||
|
||||
#include "ObjectView.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "ObjectWindow.h"
|
||||
|
||||
enum {
|
||||
MSG_SET_OBJECT_TYPE = 'stot',
|
||||
MSG_SET_FILL_OR_STROKE = 'stfs',
|
||||
MSG_SET_COLOR = 'stcl',
|
||||
MSG_SET_PEN_SIZE = 'stps',
|
||||
|
||||
MSG_NEW_OBJECT = 'nobj',
|
||||
|
||||
MSG_UNDO = 'undo',
|
||||
MSG_REDO = 'redo',
|
||||
|
||||
MSG_CLEAR = 'clir',
|
||||
};
|
||||
|
||||
// constructor
|
||||
ObjectWindow::ObjectWindow(BRect frame, const char* name)
|
||||
: BWindow(frame, name, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS)
|
||||
{
|
||||
BRect b(Bounds());
|
||||
|
||||
b.bottom = b.top + 8;
|
||||
BMenuBar* menuBar = new BMenuBar(b, "menu bar");
|
||||
AddChild(menuBar);
|
||||
|
||||
BMenu* menu = new BMenu("Menus");
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
BMenuItem* menuItem = new BMenuItem("Quit", NULL, 'Q');
|
||||
menu->AddItem(menuItem);
|
||||
|
||||
menuBar->AddItem(new BMenu("don't"));
|
||||
menuBar->AddItem(new BMenu("work!"));
|
||||
menuBar->AddItem(new BMenu("(yet)"));
|
||||
|
||||
b = Bounds();
|
||||
b.top = menuBar->Bounds().bottom + 1;
|
||||
BBox* bg = new BBox(b, "bg box", B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER);
|
||||
|
||||
AddChild(bg);
|
||||
bg->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
b = bg->Bounds();
|
||||
// object views occupies the right side of the window
|
||||
b.Set(ceilf((b.left + b.right) / 3.0) + 3.0, b.top + 5.0, b.right - 5.0, b.bottom - 5.0);
|
||||
fObjectView = new ObjectView(b, "object view", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
|
||||
bg->AddChild(fObjectView);
|
||||
|
||||
b = bg->Bounds();
|
||||
// controls occupy the left side of the window
|
||||
b.Set(b.left + 5.0, b.top + 5.0, ceilf((b.left + b.right) / 3.0) - 2.0, b.bottom - 5.0);
|
||||
BBox* controlGroup = new BBox(b, "controls box", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
|
||||
B_WILL_DRAW, B_FANCY_BORDER);
|
||||
|
||||
controlGroup->SetLabel("Controls");
|
||||
bg->AddChild(controlGroup);
|
||||
|
||||
b = controlGroup->Bounds();
|
||||
b.top += 10.0;
|
||||
b.bottom = b.top + 25.0;
|
||||
b.InsetBy(5.0, 5.0);
|
||||
|
||||
// new button
|
||||
fNewB = new BButton(b, "new button", "New Object", new BMessage(MSG_NEW_OBJECT));
|
||||
controlGroup->AddChild(fNewB);
|
||||
|
||||
// clear button
|
||||
b.OffsetBy(0, fNewB->Bounds().Height() + 5.0);
|
||||
fClearB = new BButton(b, "clear button", "Clear", new BMessage(MSG_CLEAR));
|
||||
controlGroup->AddChild(fClearB);
|
||||
|
||||
// object type radio buttons
|
||||
BMessage* message;
|
||||
BRadioButton* radioButton;
|
||||
|
||||
b.OffsetBy(0, fClearB->Bounds().Height() + 5.0);
|
||||
message = new BMessage(MSG_SET_OBJECT_TYPE);
|
||||
message->AddInt32("type", OBJECT_LINE);
|
||||
radioButton = new BRadioButton(b, "radio 1", "Line", message);
|
||||
controlGroup->AddChild(radioButton);
|
||||
|
||||
radioButton->SetValue(B_CONTROL_ON);
|
||||
|
||||
b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
|
||||
message = new BMessage(MSG_SET_OBJECT_TYPE);
|
||||
message->AddInt32("type", OBJECT_RECT);
|
||||
radioButton = new BRadioButton(b, "radio 2", "Rect", message);
|
||||
controlGroup->AddChild(radioButton);
|
||||
|
||||
b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
|
||||
message = new BMessage(MSG_SET_OBJECT_TYPE);
|
||||
message->AddInt32("type", OBJECT_ROUND_RECT);
|
||||
radioButton = new BRadioButton(b, "radio 3", "Round Rect", message);
|
||||
controlGroup->AddChild(radioButton);
|
||||
|
||||
b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
|
||||
message = new BMessage(MSG_SET_OBJECT_TYPE);
|
||||
message->AddInt32("type", OBJECT_ELLIPSE);
|
||||
radioButton = new BRadioButton(b, "radio 4", "Ellipse", message);
|
||||
controlGroup->AddChild(radioButton);
|
||||
|
||||
// red text control
|
||||
b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
|
||||
fRedTC = new BTextControl(b, "red text control", "Red", "",
|
||||
new BMessage(MSG_SET_COLOR));
|
||||
controlGroup->AddChild(fRedTC);
|
||||
|
||||
// green text control
|
||||
b.OffsetBy(0, fRedTC->Bounds().Height() + 5.0);
|
||||
fGreenTC = new BTextControl(b, "green text control", "Green", "",
|
||||
new BMessage(MSG_SET_COLOR));
|
||||
controlGroup->AddChild(fGreenTC);
|
||||
|
||||
// blue text control
|
||||
b.OffsetBy(0, fGreenTC->Bounds().Height() + 5.0);
|
||||
fBlueTC = new BTextControl(b, "blue text control", "Blue", "",
|
||||
new BMessage(MSG_SET_COLOR));
|
||||
controlGroup->AddChild(fBlueTC);
|
||||
|
||||
// alpha text control
|
||||
b.OffsetBy(0, fBlueTC->Bounds().Height() + 5.0);
|
||||
fAlphaTC = new BTextControl(b, "alpha text control", "Alpha", "",
|
||||
new BMessage(MSG_SET_COLOR));
|
||||
controlGroup->AddChild(fAlphaTC);
|
||||
/*
|
||||
// TODO: while this block of code works in the Haiku app_server running under R5,
|
||||
// it crashes pretty badly under Haiku. I have no idea why this happens, because
|
||||
// I was doing the same thing before at other places.
|
||||
// divide text controls the same
|
||||
float rWidth = fRedTC->StringWidth(fRedTC->Label());
|
||||
float gWidth = fGreenTC->StringWidth(fGreenTC->Label());
|
||||
float bWidth = fBlueTC->StringWidth(fBlueTC->Label());
|
||||
float aWidth = fAlphaTC->StringWidth(fAlphaTC->Label());
|
||||
|
||||
float width = max_c(rWidth, max_c(gWidth, max_c(bWidth, aWidth))) + 10.0;
|
||||
fRedTC->SetDivider(width);
|
||||
fGreenTC->SetDivider(width);
|
||||
fBlueTC->SetDivider(width);
|
||||
fAlphaTC->SetDivider(width);*/
|
||||
|
||||
// fill check box
|
||||
b.OffsetBy(0, fAlphaTC->Bounds().Height() + 5.0);
|
||||
fFillCB = new BCheckBox(b, "fill check box", "Fill",
|
||||
new BMessage(MSG_SET_FILL_OR_STROKE));
|
||||
controlGroup->AddChild(fFillCB);
|
||||
|
||||
// pen size text control
|
||||
b.OffsetBy(0, radioButton->Bounds().Height() + 5.0);
|
||||
fPenSizeTC = new BTextControl(b, "width text control", "Width", "",
|
||||
new BMessage(MSG_SET_PEN_SIZE));
|
||||
controlGroup->AddChild(fPenSizeTC);
|
||||
|
||||
_UpdateControls();
|
||||
}
|
||||
|
||||
// destructor
|
||||
ObjectWindow::~ObjectWindow()
|
||||
{
|
||||
}
|
||||
|
||||
// QuitRequested
|
||||
bool
|
||||
ObjectWindow::QuitRequested()
|
||||
{
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
ObjectWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_SET_OBJECT_TYPE: {
|
||||
int32 type;
|
||||
if (message->FindInt32("type", &type) >= B_OK) {
|
||||
fObjectView->SetObjectType(type);
|
||||
fFillCB->SetEnabled(type != OBJECT_LINE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_FILL_OR_STROKE: {
|
||||
int32 value;
|
||||
if (message->FindInt32("be:value", &value) >= B_OK) {
|
||||
fObjectView->SetStateFill(value);
|
||||
fPenSizeTC->SetEnabled(value == B_CONTROL_OFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_SET_COLOR:
|
||||
fObjectView->SetStateColor(_GetColor());
|
||||
break;
|
||||
case MSG_OBJECT_COUNT_CHANGED:
|
||||
fClearB->SetEnabled(fObjectView->CountObjects() > 0);
|
||||
break;
|
||||
case MSG_NEW_OBJECT:
|
||||
fObjectView->SetState(NULL);
|
||||
break;
|
||||
case MSG_CLEAR:
|
||||
fObjectView->MakeEmpty();
|
||||
break;
|
||||
case MSG_SET_PEN_SIZE:
|
||||
fObjectView->SetStatePenSize(atof(fPenSizeTC->Text()));
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
// _UpdateControls
|
||||
void
|
||||
ObjectWindow::_UpdateControls() const
|
||||
{
|
||||
// update color
|
||||
rgb_color c = fObjectView->StateColor();
|
||||
char string[32];
|
||||
|
||||
sprintf(string, "%d", c.red);
|
||||
fRedTC->SetText(string);
|
||||
|
||||
sprintf(string, "%d", c.green);
|
||||
fGreenTC->SetText(string);
|
||||
|
||||
sprintf(string, "%d", c.blue);
|
||||
fBlueTC->SetText(string);
|
||||
|
||||
sprintf(string, "%d", c.alpha);
|
||||
fAlphaTC->SetText(string);
|
||||
|
||||
|
||||
// update buttons
|
||||
fClearB->SetEnabled(fObjectView->CountObjects() > 0);
|
||||
|
||||
fFillCB->SetEnabled(fObjectView->ObjectType() != OBJECT_LINE);
|
||||
|
||||
// disable penSize if fill is on
|
||||
sprintf(string, "%.1f", fObjectView->StatePenSize());
|
||||
fPenSizeTC->SetText(string);
|
||||
fPenSizeTC->SetEnabled(!fFillCB->IsEnabled());
|
||||
}
|
||||
|
||||
// _GetColor
|
||||
rgb_color
|
||||
ObjectWindow::_GetColor() const
|
||||
{
|
||||
rgb_color c;
|
||||
c.red = max_c(0, min_c(255, atoi(fRedTC->Text())));
|
||||
c.green = max_c(0, min_c(255, atoi(fGreenTC->Text())));
|
||||
c.blue = max_c(0, min_c(255, atoi(fBlueTC->Text())));
|
||||
c.alpha = max_c(0, min_c(255, atoi(fAlphaTC->Text())));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
48
src/tests/servers/app/playground/ObjectWindow.h
Normal file
48
src/tests/servers/app/playground/ObjectWindow.h
Normal file
@ -0,0 +1,48 @@
|
||||
// ObjectWindow.h
|
||||
|
||||
#ifndef OBJECT_WINDOW_H
|
||||
#define OBJECT_WINDOW_H
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
/*
|
||||
class Box;
|
||||
class Button;
|
||||
class CheckBox;
|
||||
class Menu;
|
||||
class MenuBar;
|
||||
class RadioButton;
|
||||
class TextView;*/
|
||||
class BButton;
|
||||
class BCheckBox;
|
||||
class BTextControl;
|
||||
class ObjectView;
|
||||
|
||||
class ObjectWindow : public BWindow {
|
||||
public:
|
||||
ObjectWindow(BRect frame, const char* name);
|
||||
virtual ~ObjectWindow();
|
||||
|
||||
virtual bool QuitRequested();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _UpdateControls() const;
|
||||
rgb_color _GetColor() const;
|
||||
|
||||
ObjectView* fObjectView;
|
||||
|
||||
BButton* fNewB;
|
||||
BButton* fClearB;
|
||||
|
||||
BTextControl* fRedTC;
|
||||
BTextControl* fGreenTC;
|
||||
BTextControl* fBlueTC;
|
||||
BTextControl* fAlphaTC;
|
||||
|
||||
BCheckBox* fFillCB;
|
||||
BTextControl* fPenSizeTC;
|
||||
};
|
||||
|
||||
#endif // OBJECT_WINDOW_H
|
194
src/tests/servers/app/playground/States.cpp
Normal file
194
src/tests/servers/app/playground/States.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
// States.cpp
|
||||
|
||||
#include <View.h>
|
||||
|
||||
#include "States.h"
|
||||
|
||||
// constructor
|
||||
State::State(rgb_color color, bool fill, float penSize)
|
||||
: fValid(false),
|
||||
fTracking(false),
|
||||
fTrackingStart(-1.0, -1.0),
|
||||
fLastMousePos(-1.0, -1.0),
|
||||
fColor(color),
|
||||
fFill(fill),
|
||||
fPenSize(penSize)
|
||||
{
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
State::MouseDown(BPoint where)
|
||||
{
|
||||
fTracking = true;
|
||||
fTrackingStart = fLastMousePos = where;
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
State::MouseUp(BPoint where)
|
||||
{
|
||||
fTracking = false;
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
State::MouseMoved(BPoint where)
|
||||
{
|
||||
if (fTracking) {
|
||||
fLastMousePos = where;
|
||||
fValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// SetColor
|
||||
void
|
||||
State::SetColor(rgb_color color)
|
||||
{
|
||||
fColor = color;
|
||||
}
|
||||
|
||||
// SetFill
|
||||
void
|
||||
State::SetFill(bool fill)
|
||||
{
|
||||
fFill = fill;
|
||||
}
|
||||
|
||||
// SetPenSize
|
||||
void
|
||||
State::SetPenSize(float penSize)
|
||||
{
|
||||
fPenSize = penSize;
|
||||
}
|
||||
|
||||
// Bounds
|
||||
BRect
|
||||
State::Bounds() const
|
||||
{
|
||||
if (fValid) {
|
||||
BRect r = _ValidRect();
|
||||
if (!fFill) {
|
||||
float inset = -ceilf(fPenSize / 2.0);
|
||||
r.InsetBy(inset, inset);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return BRect(0.0, 0.0, -1.0, -1.0);
|
||||
}
|
||||
|
||||
// _ValidRect
|
||||
BRect
|
||||
State::_ValidRect() const
|
||||
{
|
||||
return BRect(min_c(fTrackingStart.x, fLastMousePos.x),
|
||||
min_c(fTrackingStart.y, fLastMousePos.y),
|
||||
max_c(fTrackingStart.x, fLastMousePos.x),
|
||||
max_c(fTrackingStart.y, fLastMousePos.y));
|
||||
}
|
||||
|
||||
// LineState
|
||||
class LineState : public State {
|
||||
public:
|
||||
LineState(rgb_color color, bool fill, float penSize)
|
||||
: State(color, fill, penSize) {}
|
||||
|
||||
virtual BRect Bounds() const
|
||||
{
|
||||
if (fValid) {
|
||||
BRect r = _ValidRect();
|
||||
r.InsetBy(-fPenSize, -fPenSize);
|
||||
return r;
|
||||
}
|
||||
return BRect(0.0, 0.0, -1.0, -1.0);
|
||||
}
|
||||
virtual void Draw(BView* view) const
|
||||
{
|
||||
if (fValid) {
|
||||
view->SetHighColor(fColor);
|
||||
view->SetPenSize(fPenSize);
|
||||
view->StrokeLine(fTrackingStart, fLastMousePos);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// RectState
|
||||
class RectState : public State {
|
||||
public:
|
||||
RectState(rgb_color color, bool fill, float penSize)
|
||||
: State(color, fill, penSize) {}
|
||||
|
||||
virtual void Draw(BView* view) const
|
||||
{
|
||||
if (fValid) {
|
||||
view->SetHighColor(fColor);
|
||||
if (fFill)
|
||||
view->FillRect(_ValidRect());
|
||||
else {
|
||||
view->SetPenSize(fPenSize);
|
||||
view->StrokeRect(_ValidRect());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// RoundRectState
|
||||
class RoundRectState : public State {
|
||||
public:
|
||||
RoundRectState(rgb_color color, bool fill, float penSize)
|
||||
: State(color, fill, penSize) {}
|
||||
|
||||
virtual void Draw(BView* view) const
|
||||
{
|
||||
if (fValid) {
|
||||
view->SetHighColor(fColor);
|
||||
BRect r = _ValidRect();
|
||||
float radius = min_c(r.Width() / 4.0, r.Height() / 4.0);
|
||||
if (fFill)
|
||||
view->FillRoundRect(r, radius, radius);
|
||||
else {
|
||||
view->SetPenSize(fPenSize);
|
||||
view->StrokeRoundRect(r, radius, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// EllipseState
|
||||
class EllipseState : public State {
|
||||
public:
|
||||
EllipseState(rgb_color color, bool fill, float penSize)
|
||||
: State(color, fill, penSize) {}
|
||||
|
||||
virtual void Draw(BView* view) const
|
||||
{
|
||||
if (fValid) {
|
||||
view->SetHighColor(fColor);
|
||||
if (fFill)
|
||||
view->FillEllipse(_ValidRect());
|
||||
else {
|
||||
view->SetPenSize(fPenSize);
|
||||
view->StrokeEllipse(_ValidRect());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// StateFor
|
||||
State*
|
||||
State::StateFor(int32 objectType, rgb_color color, bool fill, float penSize)
|
||||
{
|
||||
switch (objectType) {
|
||||
case OBJECT_LINE:
|
||||
return new LineState(color, fill, penSize);
|
||||
case OBJECT_RECT:
|
||||
return new RectState(color, fill, penSize);
|
||||
case OBJECT_ROUND_RECT:
|
||||
return new RoundRectState(color, fill, penSize);
|
||||
case OBJECT_ELLIPSE:
|
||||
return new EllipseState(color, fill, penSize);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
56
src/tests/servers/app/playground/States.h
Normal file
56
src/tests/servers/app/playground/States.h
Normal file
@ -0,0 +1,56 @@
|
||||
// States.h
|
||||
|
||||
#ifndef STATES_H
|
||||
#define STATES_H
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
#include <Point.h>
|
||||
|
||||
class BView;
|
||||
|
||||
enum {
|
||||
OBJECT_LINE = 0,
|
||||
OBJECT_RECT,
|
||||
OBJECT_ROUND_RECT,
|
||||
OBJECT_ELLIPSE,
|
||||
OBJECT_TRIANGLE,
|
||||
OBJECT_SHAPE,
|
||||
};
|
||||
|
||||
class State {
|
||||
public:
|
||||
State(rgb_color color,
|
||||
bool fill, float penSize);
|
||||
|
||||
void MouseDown(BPoint where);
|
||||
void MouseUp(BPoint where);
|
||||
void MouseMoved(BPoint where);
|
||||
bool IsTracking() const
|
||||
{ return fTracking; }
|
||||
|
||||
void SetColor(rgb_color color);
|
||||
void SetFill(bool fill);
|
||||
void SetPenSize(float penSize);
|
||||
|
||||
virtual BRect Bounds() const;
|
||||
virtual void Draw(BView* view) const = 0;
|
||||
|
||||
static State* StateFor(int32 objectType,
|
||||
rgb_color color,
|
||||
bool fill, float penSize);
|
||||
|
||||
protected:
|
||||
BRect _ValidRect() const;
|
||||
|
||||
bool fValid;
|
||||
|
||||
bool fTracking;
|
||||
BPoint fTrackingStart;
|
||||
BPoint fLastMousePos;
|
||||
|
||||
rgb_color fColor;
|
||||
bool fFill;
|
||||
float fPenSize;
|
||||
};
|
||||
|
||||
#endif // STATES_H
|
@ -1,287 +1,17 @@
|
||||
// main.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <CheckBox.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <String.h>
|
||||
#include <RadioButton.h>
|
||||
#include <TextControl.h>
|
||||
#include <TextView.h>
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
|
||||
class HelloView : public BView {
|
||||
public:
|
||||
HelloView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags);
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void FrameMoved(BPoint were);
|
||||
virtual void FrameResized(float width, float height);
|
||||
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
private:
|
||||
bool fTracking;
|
||||
BPoint fTrackingStart;
|
||||
BPoint fLastMousePos;
|
||||
};
|
||||
|
||||
// constructor
|
||||
HelloView::HelloView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags)
|
||||
: BView(frame, name, resizeFlags, flags | B_FRAME_EVENTS),
|
||||
fTracking(false),
|
||||
fTrackingStart(-1.0, -1.0),
|
||||
fLastMousePos(-1.0, -1.0)
|
||||
{
|
||||
// TODO: Find bug: this influences StringWidth(), but the font is not used
|
||||
// SetFontSize(9);
|
||||
rgb_color bg = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT);
|
||||
SetViewColor(bg);
|
||||
SetLowColor(bg);
|
||||
|
||||
BFont font;
|
||||
GetFont(&font);
|
||||
BString string("ß amM öo\t");
|
||||
int32 charCount = string.CountChars();
|
||||
float* escapements = new float[charCount];
|
||||
escapement_delta dummy;
|
||||
dummy.space = 0.0;
|
||||
dummy.nonspace = 0.0;
|
||||
font.GetEscapements(string.String(), charCount, &dummy, escapements);
|
||||
for (int32 i = 0; i < charCount; i++)
|
||||
printf("escapement: %.3f\n", escapements[i]);
|
||||
delete[] escapements;
|
||||
}
|
||||
|
||||
// AttachedToWindow
|
||||
void
|
||||
HelloView::AttachedToWindow()
|
||||
{
|
||||
}
|
||||
|
||||
// Draw
|
||||
void
|
||||
HelloView::Draw(BRect updateRect)
|
||||
{
|
||||
rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT);
|
||||
rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT);
|
||||
|
||||
BRect r(Bounds());
|
||||
|
||||
BeginLineArray(4);
|
||||
AddLine(BPoint(r.left, r.top),
|
||||
BPoint(r.right, r.top), shadow);
|
||||
AddLine(BPoint(r.right, r.top + 1),
|
||||
BPoint(r.right, r.bottom), light);
|
||||
AddLine(BPoint(r.right - 1, r.bottom),
|
||||
BPoint(r.left, r.bottom), light);
|
||||
AddLine(BPoint(r.left, r.bottom - 1),
|
||||
BPoint(r.left, r.top + 1), shadow);
|
||||
EndLineArray();
|
||||
|
||||
SetHighColor(255, 0, 0, 128);
|
||||
|
||||
const char* message = "Click and drag";
|
||||
float width = StringWidth(message);
|
||||
BPoint p(r.left + r.Width() / 2.0 - width / 2.0,
|
||||
r.top + r.Height() / 2.0);
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
message = "to draw a line!";
|
||||
width = StringWidth(message);
|
||||
p.x = r.left + r.Width() / 2.0 - width / 2.0;
|
||||
p.y += 20;
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
// SetDrawingMode(B_OP_OVER);
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
SetPenSize(10.0);
|
||||
SetHighColor(0, 80, 255, 100);
|
||||
StrokeLine(fTrackingStart, fLastMousePos);
|
||||
// TODO: this should not be necessary with proper state stack
|
||||
// (a new state is pushed before Draw() is called)
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
}
|
||||
|
||||
// FrameMoved
|
||||
void
|
||||
HelloView::FrameMoved(BPoint were)
|
||||
{
|
||||
printf("HelloView::FrameMoved()\n");
|
||||
if (Window()) {
|
||||
Window()->CurrentMessage()->PrintToStream();
|
||||
}
|
||||
}
|
||||
|
||||
// FrameResized
|
||||
void
|
||||
HelloView::FrameResized(float width, float height)
|
||||
{
|
||||
printf("HelloView::FrameResized()\n");
|
||||
if (Window()) {
|
||||
Window()->CurrentMessage()->PrintToStream();
|
||||
}
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
HelloView::MouseDown(BPoint where)
|
||||
{
|
||||
fTracking = true;
|
||||
fTrackingStart = fLastMousePos = where;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
HelloView::MouseUp(BPoint where)
|
||||
{
|
||||
fTracking = false;
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
HelloView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
|
||||
{
|
||||
if (fTracking) {
|
||||
BRect invalidBefore(min_c(fTrackingStart.x, fLastMousePos.x),
|
||||
min_c(fTrackingStart.y, fLastMousePos.y),
|
||||
max_c(fTrackingStart.x, fLastMousePos.x),
|
||||
max_c(fTrackingStart.y, fLastMousePos.y));
|
||||
fLastMousePos = where;
|
||||
BRect invalidAfter(min_c(fTrackingStart.x, fLastMousePos.x),
|
||||
min_c(fTrackingStart.y, fLastMousePos.y),
|
||||
max_c(fTrackingStart.x, fLastMousePos.x),
|
||||
max_c(fTrackingStart.y, fLastMousePos.y));
|
||||
BRect invalid(invalidBefore | invalidAfter);
|
||||
invalid.InsetBy(-10.0, -10.0);
|
||||
Invalidate(invalid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// show_window
|
||||
void
|
||||
show_window(BRect frame, const char* name)
|
||||
{
|
||||
// BRect f(0, 0, frame.Width(), frame.Height());
|
||||
BRect f(frame);
|
||||
BWindow* window = new BWindow(f, name,
|
||||
B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
BRect b(window->Bounds());
|
||||
|
||||
b.bottom = b.top + 8;
|
||||
BMenuBar* menuBar = new BMenuBar(b, "menu bar");
|
||||
window->AddChild(menuBar);
|
||||
|
||||
BMenu* menu = new BMenu("Menus");
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
BMenuItem* menuItem = new BMenuItem("Quit", NULL, 'Q');
|
||||
menu->AddItem(menuItem);
|
||||
|
||||
menuBar->AddItem(new BMenu("don't"));
|
||||
menuBar->AddItem(new BMenu("work!"));
|
||||
menuBar->AddItem(new BMenu("(yet)"));
|
||||
|
||||
b = window->Bounds();
|
||||
b.top = menuBar->Bounds().bottom + 1;
|
||||
BBox* bg = new BBox(b, "box", B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER);
|
||||
|
||||
window->AddChild(bg);
|
||||
|
||||
b = bg->Bounds();
|
||||
// occupy the right side of the window
|
||||
b.Set((b.left + b.right) / 2.0 + 3.0, b.top + 5.0, b.right - 5.0, b.bottom - 5.0);
|
||||
BView* view = new HelloView(b, "hello view", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
|
||||
bg->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
bg->AddChild(view);
|
||||
|
||||
b = bg->Bounds();
|
||||
// occupy the left side of the window
|
||||
b.Set(b.left + 5.0, b.top + 5.0, (b.left + b.right) / 2.0 - 2.0, b.bottom - 5.0);
|
||||
BBox* controlGroup = new BBox(b, "controls box", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
|
||||
B_WILL_DRAW, B_FANCY_BORDER);
|
||||
|
||||
controlGroup->SetLabel("Controls");
|
||||
bg->AddChild(controlGroup);
|
||||
|
||||
b = controlGroup->Bounds();
|
||||
b.top += 15.0;
|
||||
b.bottom = b.top + 25.0;
|
||||
b.InsetBy(5.0, 5.0);
|
||||
BRadioButton* radioButton1 = new BRadioButton(b, "radio 1", "Choice One", NULL);
|
||||
controlGroup->AddChild(radioButton1);
|
||||
|
||||
b.OffsetBy(0, radioButton1->Bounds().Height() + 5.0);
|
||||
BRadioButton* radioButton2 = new BRadioButton(b, "radio 2", "Choice Two", NULL);
|
||||
controlGroup->AddChild(radioButton2);
|
||||
|
||||
b.OffsetBy(0, radioButton2->Bounds().Height() + 5.0);
|
||||
BRadioButton* radioButton3 = new BRadioButton(b, "radio 3", "Choice Three", NULL);
|
||||
controlGroup->AddChild(radioButton3);
|
||||
|
||||
radioButton1->SetValue(B_CONTROL_ON);
|
||||
|
||||
// button
|
||||
b.OffsetBy(0, radioButton3->Bounds().Height() + 5.0);
|
||||
BButton* button = new BButton(b, "button", "Button", NULL);
|
||||
controlGroup->AddChild(button);
|
||||
|
||||
// text control
|
||||
b.OffsetBy(0, button->Bounds().Height() + 5.0);
|
||||
BTextControl* textControl = new BTextControl(b, "text control", "Text", "<enter text here>", NULL);
|
||||
textControl->SetDivider(textControl->StringWidth(textControl->Label()) + 10.0);
|
||||
controlGroup->AddChild(textControl);
|
||||
|
||||
/* BRect textRect(b);
|
||||
textRect.OffsetTo(0.0, 0.0);
|
||||
BTextView* textView = new BTextView(b, "text view", textRect,
|
||||
B_FOLLOW_ALL, B_WILL_DRAW);
|
||||
view->AddChild(textView);
|
||||
textView->SetText("This is a BTextView.");
|
||||
textView->MakeFocus(true);*/
|
||||
|
||||
// check box
|
||||
b.OffsetBy(0, textControl->Bounds().Height() + 5.0);
|
||||
BCheckBox* checkBox = new BCheckBox(b, "check box", "CheckBox", NULL);
|
||||
controlGroup->AddChild(checkBox);
|
||||
|
||||
// window->MoveTo(frame.left, frame.top);
|
||||
window->Show();
|
||||
}
|
||||
#include "ObjectWindow.h"
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
BApplication* app = new BApplication("application/x.vnd-Haiku.windows_test");
|
||||
BApplication* app = new BApplication("application/x.vnd-Haiku.Objects");
|
||||
|
||||
BRect frame(80.0, 100.0, 450.0, 400.0);
|
||||
show_window(frame, "Playground");
|
||||
|
||||
// frame.Set(50.0, 50.0, 200.0, 250.0);
|
||||
// show_window(frame, "Window #2");
|
||||
BRect frame(50.0, 50.0, 450.0, 430.0);
|
||||
(new ObjectWindow(frame, "Playground"))->Show();
|
||||
|
||||
app->Run();
|
||||
|
||||
|
@ -4,4 +4,4 @@
|
||||
sleep 1s
|
||||
../../../../../distro/x86.R1/beos/system/servers/obos_registrar &
|
||||
sleep 1s
|
||||
../../../../../tests/servers/app/playground/Playground
|
||||
../../../../../distro/x86.R1/beos/apps/Playground
|
||||
|
Loading…
Reference in New Issue
Block a user