Added support for resizing headers.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34559 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-08 17:04:19 +00:00
parent 8f70123737
commit c5c5949618
2 changed files with 246 additions and 9 deletions
+236 -7
View File
@@ -14,6 +14,7 @@
#include <ControlLook.h>
#include <LayoutUtils.h>
#include <Looper.h>
// #pragma mark - HeaderRenderer
@@ -539,22 +540,178 @@ struct HeaderView::HeaderEntry {
};
// #pragma mark - HeaderEntry
// #pragma mark - States
class HeaderView::DragState {
class HeaderView::State {
public:
virtual ~DragState()
State(HeaderView* parent)
:
fParent(parent)
{
}
virtual void MouseDown(BPoint where) = 0;
virtual void DragTo(BPoint where) = 0;
virtual void MouseUp();
virtual ~State()
{
}
virtual void Entering(State* previousState)
{
}
virtual void Leaving(State* nextState)
{
}
virtual void MouseDown(BPoint where, uint32 buttons, uint32 modifiers)
{
}
virtual void MouseUp(BPoint where, uint32 buttons, uint32 modifiers)
{
}
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
}
protected:
HeaderView* fParent;
};
class HeaderView::DefaultState : public State {
public:
DefaultState(HeaderView* parent);
virtual void MouseDown(BPoint where, uint32 buttons,
uint32 modifiers);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
};
class HeaderView::ResizeState : public State {
public:
virtual void Entering(State* previousState);
virtual void Leaving(State* nextState);
ResizeState(HeaderView* parent,
int32 headerIndex, BPoint startPoint);
virtual void MouseUp(BPoint where, uint32 buttons,
uint32 modifiers);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
private:
Header* fHeader;
float fStartX;
float fStartWidth;
};
// #pragma mark - DefaultState
HeaderView::DefaultState::DefaultState(HeaderView* parent)
:
State(parent)
{
}
void
HeaderView::DefaultState::MouseDown(BPoint where, uint32 buttons,
uint32 modifiers)
{
HeaderModel* model = fParent->Model();
if (model == NULL)
return;
if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0)
return;
int32 headerIndex = fParent->HeaderIndexAt(where);
if (headerIndex < 0) {
int32 headerCount = model->CountHeaders();
if (headerCount == 0)
return;
headerIndex = headerCount - 1;
}
// Check whether the mouse is close to the left or the right side of the
// header.
BRect headerFrame = fParent->HeaderFrame(headerIndex);
if (fabs(headerFrame.left - where.x) <= 3) {
if (headerIndex == 0)
return;
headerIndex--;
} else if (fabs(headerFrame.right + 1 - where.x) > 3)
return;
// start resizing the header
fParent->_SwitchState(new ResizeState(fParent, headerIndex, where));
}
void
HeaderView::DefaultState::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
}
// #pragma mark - ResizeState
void
HeaderView::ResizeState::Entering(State* previousState)
{
fParent->SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
}
void
HeaderView::ResizeState::Leaving(State* nextState)
{
fParent->SetEventMask(0, 0);
}
HeaderView::ResizeState::ResizeState(HeaderView* parent, int32 headerIndex,
BPoint startPoint)
:
State(parent),
fHeader(parent->Model()->HeaderAt(headerIndex)),
fStartX(startPoint.x),
fStartWidth(fHeader->Width())
{
}
void
HeaderView::ResizeState::MouseUp(BPoint where, uint32 buttons,
uint32 modifiers)
{
if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0)
fParent->_SwitchState(NULL);
}
void
HeaderView::ResizeState::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
float width = fStartWidth + where.x - fStartX;
width = std::max(width, fHeader->MinWidth());
width = std::min(width, fHeader->MaxWidth());
fHeader->SetWidth(width);
}
// #pragma mark - HeaderView
@@ -563,7 +720,9 @@ HeaderView::HeaderView()
BView("header view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fModel(NULL),
fHeaderEntries(10, true),
fLayoutValid(false)
fLayoutValid(false),
fDefaultState(new DefaultState(this)),
fState(fDefaultState)
{
HeaderModel* model = new(std::nothrow) HeaderModel;
Reference<HeaderModel> modelReference(model, true);
@@ -576,6 +735,9 @@ HeaderView::HeaderView()
HeaderView::~HeaderView()
{
SetModel(NULL);
_SwitchState(NULL);
delete fDefaultState;
}
@@ -652,12 +814,32 @@ HeaderView::Model() const
void
HeaderView::MouseDown(BPoint where)
{
// get buttons and modifiers
BMessage* message = Looper()->CurrentMessage();
int32 buttons;
if (message == NULL || message->FindInt32("buttons", &buttons) != B_OK)
buttons = 0;
int32 modifiers;
if (message == NULL || message->FindInt32("modifiers", &modifiers) != B_OK)
modifiers = 0;
fState->MouseDown(where, buttons, modifiers);
}
void
HeaderView::MouseUp(BPoint where)
{
// get buttons and modifiers
BMessage* message = Looper()->CurrentMessage();
int32 buttons;
if (message == NULL || message->FindInt32("buttons", &buttons) != B_OK)
buttons = 0;
int32 modifiers;
if (message == NULL || message->FindInt32("modifiers", &modifiers) != B_OK)
modifiers = 0;
fState->MouseUp(where, buttons, modifiers);
}
@@ -665,6 +847,7 @@ void
HeaderView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
fState->MouseMoved(where, transit, dragMessage);
}
@@ -674,6 +857,8 @@ HeaderView::SetModel(HeaderModel* model)
if (model == fModel)
return B_OK;
_SwitchState(NULL);
if (fModel != NULL) {
// remove all headers
for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++)
@@ -711,6 +896,34 @@ HeaderView::SetModel(HeaderModel* model)
}
BRect
HeaderView::HeaderFrame(int32 index) const
{
float bottom = Bounds().Height();
if (HeaderEntry* entry = fHeaderEntries.ItemAt(index)) {
return BRect(entry->position, 0, entry->position + entry->width - 1,
bottom);
}
return BRect();
}
int32
HeaderView::HeaderIndexAt(BPoint point) const
{
float x = point.x;
for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++) {
if (x >= entry->position && x < entry->position + entry->width)
return i;
}
return -1;
}
void
HeaderView::AddListener(HeaderViewListener* listener)
{
@@ -863,6 +1076,22 @@ HeaderView::_ValidateHeadersLayout()
}
void
HeaderView::_SwitchState(State* newState)
{
if (newState == NULL)
newState = fDefaultState;
fState->Leaving(newState);
newState->Entering(fState);
if (fState != fDefaultState)
delete fState;
fState = newState;
}
// #pragma mark - HeaderViewListener
+10 -2
View File
@@ -178,6 +178,9 @@ public:
HeaderModel* Model() const;
status_t SetModel(HeaderModel* model);
BRect HeaderFrame(int32 index) const;
int32 HeaderIndexAt(BPoint point) const;
void AddListener(HeaderViewListener* listener);
void RemoveListener(HeaderViewListener* listener);
@@ -187,7 +190,9 @@ private:
typedef BObjectList<HeaderEntry> HeaderEntryList;
typedef BObjectList<HeaderViewListener> ListenerList;
class DragState;
class State;
class DefaultState;
class ResizeState;
private:
// HeaderModelListener
@@ -209,6 +214,8 @@ private:
int32 endIndex);
void _ValidateHeadersLayout();
void _SwitchState(State* newState);
private:
HeaderModel* fModel;
HeaderEntryList fHeaderEntries;
@@ -216,7 +223,8 @@ private:
float fPreferredHeight;
bool fLayoutValid;
ListenerList fListeners;
DragState* fDragState;
State* fDefaultState;
State* fState;
};