Added beginnings of a generic header view.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31878 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,707 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2009, Stephan Aßmus, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "HeaderView.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <ControlLook.h>
|
||||||
|
#include <LayoutUtils.h>
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderRenderer
|
||||||
|
|
||||||
|
|
||||||
|
HeaderRenderer::~HeaderRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DefaultHeaderRenderer
|
||||||
|
|
||||||
|
|
||||||
|
DefaultHeaderRenderer::DefaultHeaderRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultHeaderRenderer::~DefaultHeaderRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
DefaultHeaderRenderer::HeaderHeight(BView* view, const Header* header)
|
||||||
|
{
|
||||||
|
BVariant value;
|
||||||
|
if (!header->GetValue(value))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (value.Type() == B_STRING_TYPE) {
|
||||||
|
return 15;
|
||||||
|
// TODO:...
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultHeaderRenderer::DrawHeader(BView* view, BRect frame, BRect updateRect,
|
||||||
|
const Header* header, uint32 flags)
|
||||||
|
{
|
||||||
|
printf("DefaultHeaderRenderer::DrawHeader(): frame: (%f, %f) - (%f, %f), header: %p\n",
|
||||||
|
frame.left, frame.top, frame.right, frame.bottom, header);
|
||||||
|
BVariant value;
|
||||||
|
if (!header->GetValue(value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (value.Type() == B_STRING_TYPE) {
|
||||||
|
be_control_look->DrawLabel(view, value.ToString(), frame, updateRect,
|
||||||
|
view->LowColor(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderListener
|
||||||
|
|
||||||
|
|
||||||
|
HeaderListener::~HeaderListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Header
|
||||||
|
|
||||||
|
|
||||||
|
Header::Header(int32 modelIndex)
|
||||||
|
:
|
||||||
|
fWidth(100),
|
||||||
|
fMinWidth(0),
|
||||||
|
fMaxWidth(10000),
|
||||||
|
fPreferredWidth(100),
|
||||||
|
fValue(),
|
||||||
|
fRenderer(NULL),
|
||||||
|
fModelIndex(modelIndex),
|
||||||
|
fResizable(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header::Header(float width, float minWidth, float maxWidth,
|
||||||
|
float preferredWidth, int32 modelIndex)
|
||||||
|
:
|
||||||
|
fWidth(width),
|
||||||
|
fMinWidth(minWidth),
|
||||||
|
fMaxWidth(maxWidth),
|
||||||
|
fPreferredWidth(preferredWidth),
|
||||||
|
fValue(),
|
||||||
|
fRenderer(NULL),
|
||||||
|
fModelIndex(modelIndex),
|
||||||
|
fResizable(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Header::Width() const
|
||||||
|
{
|
||||||
|
return fWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Header::MinWidth() const
|
||||||
|
{
|
||||||
|
return fMinWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Header::MaxWidth() const
|
||||||
|
{
|
||||||
|
return fMaxWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float
|
||||||
|
Header::PreferredWidth() const
|
||||||
|
{
|
||||||
|
return fPreferredWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetWidth(float width)
|
||||||
|
{
|
||||||
|
if (width != fWidth) {
|
||||||
|
fWidth = width;
|
||||||
|
NotifyPropertiesChanged(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetMinWidth(float width)
|
||||||
|
{
|
||||||
|
if (width != fMinWidth) {
|
||||||
|
fMinWidth = width;
|
||||||
|
NotifyPropertiesChanged(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetMaxWidth(float width)
|
||||||
|
{
|
||||||
|
if (width != fMaxWidth) {
|
||||||
|
fMaxWidth = width;
|
||||||
|
NotifyPropertiesChanged(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetPreferredWidth(float width)
|
||||||
|
{
|
||||||
|
if (width != fPreferredWidth) {
|
||||||
|
fPreferredWidth = width;
|
||||||
|
NotifyPropertiesChanged(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Header::IsResizable() const
|
||||||
|
{
|
||||||
|
return fResizable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetResizable(bool resizable)
|
||||||
|
{
|
||||||
|
if (resizable != fResizable) {
|
||||||
|
fResizable = resizable;
|
||||||
|
NotifyPropertiesChanged(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Header::GetValue(BVariant& _value) const
|
||||||
|
{
|
||||||
|
_value = fValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetValue(const BVariant& value)
|
||||||
|
{
|
||||||
|
fValue = value;
|
||||||
|
NotifyPropertiesChanged(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
Header::ModelIndex() const
|
||||||
|
{
|
||||||
|
return fModelIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetModelIndex(int32 index)
|
||||||
|
{
|
||||||
|
if (index != fModelIndex) {
|
||||||
|
fModelIndex = index;
|
||||||
|
NotifyPropertiesChanged(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HeaderRenderer*
|
||||||
|
Header::GetHeaderRenderer() const
|
||||||
|
{
|
||||||
|
return fRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::SetHeaderRenderer(HeaderRenderer* renderer)
|
||||||
|
{
|
||||||
|
if (renderer != fRenderer) {
|
||||||
|
fRenderer = renderer;
|
||||||
|
NotifyPropertiesChanged(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::AddListener(HeaderListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.AddItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::RemoveListener(HeaderListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.RemoveItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::NotifyPropertiesChanged(bool redrawNeeded, bool relayoutNeeded)
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||||
|
HeaderListener* listener = fListeners.ItemAt(i);
|
||||||
|
listener->HeaderPropertiesChanged(this, redrawNeeded, relayoutNeeded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderModelListener
|
||||||
|
|
||||||
|
|
||||||
|
HeaderModelListener::~HeaderModelListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModelListener::HeaderAdded(HeaderModel* model, int32 index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModelListener::HeaderRemoved(HeaderModel* model, int32 index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModelListener::HeaderMoved(HeaderModel* model, int32 fromIndex,
|
||||||
|
int32 toIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderModel
|
||||||
|
|
||||||
|
|
||||||
|
HeaderModel::HeaderModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HeaderModel::~HeaderModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
HeaderModel::CountHeaders() const
|
||||||
|
{
|
||||||
|
return fHeaders.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header*
|
||||||
|
HeaderModel::HeaderAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fHeaders.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
HeaderModel::IndexOfHeader(Header* header) const
|
||||||
|
{
|
||||||
|
return fHeaders.IndexOf(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
HeaderModel::AddHeader(Header* header)
|
||||||
|
{
|
||||||
|
if (!fHeaders.AddItem(header))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NotifyHeaderAdded(fHeaders.CountItems() - 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header*
|
||||||
|
HeaderModel::RemoveHeader(int32 index)
|
||||||
|
{
|
||||||
|
Header* header = fHeaders.RemoveItemAt(index);
|
||||||
|
if (header != NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
NotifyHeaderRemoved(index);
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::RemoveHeader(Header* header)
|
||||||
|
{
|
||||||
|
RemoveHeader(fHeaders.IndexOf(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
HeaderModel::MoveHeader(int32 fromIndex, int32 toIndex)
|
||||||
|
{
|
||||||
|
int32 headerCount = fHeaders.CountItems();
|
||||||
|
if (fromIndex < 0 || fromIndex >= headerCount
|
||||||
|
|| toIndex < 0 || toIndex >= headerCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromIndex == toIndex)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Header* header = fHeaders.RemoveItemAt(fromIndex);
|
||||||
|
fHeaders.AddItem(header, toIndex);
|
||||||
|
// TODO: Might fail.
|
||||||
|
|
||||||
|
NotifyHeaderMoved(fromIndex, toIndex);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::AddListener(HeaderModelListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.AddItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::RemoveListener(HeaderModelListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.RemoveItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::NotifyHeaderAdded(int32 index)
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||||
|
HeaderModelListener* listener = fListeners.ItemAt(i);
|
||||||
|
listener->HeaderAdded(this, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::NotifyHeaderRemoved(int32 index)
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||||
|
HeaderModelListener* listener = fListeners.ItemAt(i);
|
||||||
|
listener->HeaderRemoved(this, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderModel::NotifyHeaderMoved(int32 fromIndex, int32 toIndex)
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||||
|
HeaderModelListener* listener = fListeners.ItemAt(i);
|
||||||
|
listener->HeaderMoved(this, fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderEntry
|
||||||
|
|
||||||
|
|
||||||
|
struct HeaderView::HeaderEntry {
|
||||||
|
Header* header;
|
||||||
|
float position;
|
||||||
|
float width;
|
||||||
|
|
||||||
|
HeaderEntry(Header* header)
|
||||||
|
:
|
||||||
|
header(header)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderView
|
||||||
|
|
||||||
|
|
||||||
|
HeaderView::HeaderView()
|
||||||
|
:
|
||||||
|
BView("header view", B_WILL_DRAW),
|
||||||
|
fModel(NULL),
|
||||||
|
fHeaderEntries(10, true),
|
||||||
|
fLayoutValid(false)
|
||||||
|
{
|
||||||
|
HeaderModel* model = new(std::nothrow) HeaderModel;
|
||||||
|
Reference<HeaderModel> modelReference(model, true);
|
||||||
|
SetModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HeaderView::~HeaderView()
|
||||||
|
{
|
||||||
|
SetModel(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
if (fModel == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ValidateHeadersLayout();
|
||||||
|
|
||||||
|
DefaultHeaderRenderer defaultRenderer;
|
||||||
|
float bottom = Bounds().Height();
|
||||||
|
|
||||||
|
for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++) {
|
||||||
|
if (Header* header = fModel->HeaderAt(i)) {
|
||||||
|
HeaderRenderer* renderer = header->GetHeaderRenderer();
|
||||||
|
if (renderer == NULL)
|
||||||
|
renderer = &defaultRenderer;
|
||||||
|
|
||||||
|
BRect frame(entry->position, 0, entry->position + entry->width - 1,
|
||||||
|
bottom);
|
||||||
|
renderer->DrawHeader(this, frame, updateRect, header, 0);
|
||||||
|
// TODO: flags!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
HeaderView::MinSize()
|
||||||
|
{
|
||||||
|
_ValidateHeadersLayout();
|
||||||
|
|
||||||
|
return BLayoutUtils::ComposeSize(ExplicitMinSize(),
|
||||||
|
BSize(100, fPreferredHeight - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
HeaderView::MaxSize()
|
||||||
|
{
|
||||||
|
_ValidateHeadersLayout();
|
||||||
|
|
||||||
|
return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
|
||||||
|
BSize(B_SIZE_UNLIMITED, fPreferredHeight - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
HeaderView::PreferredSize()
|
||||||
|
{
|
||||||
|
_ValidateHeadersLayout();
|
||||||
|
|
||||||
|
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
|
||||||
|
BSize(fPreferredWidth - 1, fPreferredHeight - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HeaderModel*
|
||||||
|
HeaderView::Model() const
|
||||||
|
{
|
||||||
|
return fModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
HeaderView::SetModel(HeaderModel* model)
|
||||||
|
{
|
||||||
|
if (model == fModel)
|
||||||
|
return B_OK;
|
||||||
|
printf("HeaderView::SetModel(%p)\n", model);
|
||||||
|
|
||||||
|
if (fModel != NULL) {
|
||||||
|
// remove all headers
|
||||||
|
for (int32 i = 0; HeaderEntry* entry = fHeaderEntries.ItemAt(i); i++)
|
||||||
|
{
|
||||||
|
printf(" unsetting entry %p, header: %p\n", entry, entry->header);
|
||||||
|
entry->header->RemoveListener(this);
|
||||||
|
}
|
||||||
|
fHeaderEntries.MakeEmpty();
|
||||||
|
|
||||||
|
fModel->RemoveListener(this);
|
||||||
|
fModel->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
fModel = model;
|
||||||
|
|
||||||
|
if (fModel != NULL) {
|
||||||
|
fModel->AcquireReference();
|
||||||
|
fModel->AddListener(this);
|
||||||
|
|
||||||
|
// create header entries
|
||||||
|
int32 headerCount = fModel->CountHeaders();
|
||||||
|
for (int32 i = 0; i < headerCount; i++) {
|
||||||
|
HeaderEntry* entry = new(std::nothrow) HeaderEntry(
|
||||||
|
fModel->HeaderAt(i));
|
||||||
|
if (entry == NULL || !fHeaderEntries.AddItem(entry)) {
|
||||||
|
delete entry;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->header->AddListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_InvalidateHeadersLayout(0);
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::AddListener(HeaderViewListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.AddItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::RemoveListener(HeaderViewListener* listener)
|
||||||
|
{
|
||||||
|
fListeners.RemoveItem(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::HeaderAdded(HeaderModel* model, int32 index)
|
||||||
|
{
|
||||||
|
if (Header* header = fModel->HeaderAt(index)) {
|
||||||
|
HeaderEntry* entry = new(std::nothrow) HeaderEntry(
|
||||||
|
fModel->HeaderAt(index));
|
||||||
|
printf("HeaderView::HeaderAdded(%p, %ld): header: %p, entry: %p\n", model, index, entry->header, entry);
|
||||||
|
if (entry == NULL || !fHeaderEntries.AddItem(entry)) {
|
||||||
|
delete entry;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
header->AddListener(this);
|
||||||
|
_InvalidateHeadersLayout(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::HeaderRemoved(HeaderModel* model, int32 index)
|
||||||
|
{
|
||||||
|
if (HeaderEntry* entry = fHeaderEntries.RemoveItemAt(index)) {
|
||||||
|
entry->header->RemoveListener(this);
|
||||||
|
_InvalidateHeadersLayout(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::HeaderMoved(HeaderModel* model, int32 fromIndex, int32 toIndex)
|
||||||
|
{
|
||||||
|
_InvalidateHeadersLayout(std::min(fromIndex, toIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::HeaderPropertiesChanged(Header* header, bool redrawNeeded,
|
||||||
|
bool relayoutNeeded)
|
||||||
|
{
|
||||||
|
if (!redrawNeeded && !relayoutNeeded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 index = fModel->IndexOfHeader(header);
|
||||||
|
|
||||||
|
if (relayoutNeeded)
|
||||||
|
_InvalidateHeadersLayout(index);
|
||||||
|
else if (redrawNeeded)
|
||||||
|
_InvalidateHeaders(index, index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::_InvalidateHeadersLayout(int32 firstIndex)
|
||||||
|
{
|
||||||
|
if (!fLayoutValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fLayoutValid = false;
|
||||||
|
InvalidateLayout();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::_InvalidateHeaders(int32 firstIndex, int32 endIndex)
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
// TODO: Be less lazy!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HeaderView::_ValidateHeadersLayout()
|
||||||
|
{
|
||||||
|
if (fLayoutValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DefaultHeaderRenderer defaultRenderer;
|
||||||
|
|
||||||
|
int32 headerCount = fHeaderEntries.CountItems();
|
||||||
|
float position = 0;
|
||||||
|
fPreferredWidth = 0;
|
||||||
|
fPreferredHeight = 0;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < headerCount; i++) {
|
||||||
|
HeaderEntry* entry = fHeaderEntries.ItemAt(i);
|
||||||
|
entry->position = position;
|
||||||
|
if (Header* header = fModel->HeaderAt(i)) {
|
||||||
|
entry->width = header->Width();
|
||||||
|
fPreferredWidth += header->PreferredWidth();
|
||||||
|
} else
|
||||||
|
entry->width = 0;
|
||||||
|
|
||||||
|
position = entry->position + entry->width;
|
||||||
|
|
||||||
|
if (Header* header = fModel->HeaderAt(i)) {
|
||||||
|
HeaderRenderer* renderer = header->GetHeaderRenderer();
|
||||||
|
if (renderer == NULL)
|
||||||
|
renderer = &defaultRenderer;
|
||||||
|
|
||||||
|
float height = renderer->HeaderHeight(this, header);
|
||||||
|
if (height > fPreferredHeight)
|
||||||
|
fPreferredHeight = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fLayoutValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - HeaderViewListener
|
||||||
|
|
||||||
|
|
||||||
|
HeaderViewListener::~HeaderViewListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2009, Stephan Aßmus, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef HEADER_VIEW_H
|
||||||
|
#define HEADER_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <View.h>
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <Referenceable.h>
|
||||||
|
#include <Variant.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Header;
|
||||||
|
class HeaderModel;
|
||||||
|
class HeaderViewListener;
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderRenderer {
|
||||||
|
public:
|
||||||
|
virtual ~HeaderRenderer();
|
||||||
|
|
||||||
|
virtual float HeaderHeight(BView* view, const Header* header)
|
||||||
|
= 0;
|
||||||
|
virtual void DrawHeader(BView* view, BRect frame,
|
||||||
|
BRect updateRect, const Header* header,
|
||||||
|
uint32 flags) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultHeaderRenderer : public HeaderRenderer {
|
||||||
|
public:
|
||||||
|
DefaultHeaderRenderer();
|
||||||
|
virtual ~DefaultHeaderRenderer();
|
||||||
|
|
||||||
|
virtual float HeaderHeight(BView* view, const Header* header);
|
||||||
|
virtual void DrawHeader(BView* view, BRect frame,
|
||||||
|
BRect updateRect, const Header* header,
|
||||||
|
uint32 flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderListener {
|
||||||
|
public:
|
||||||
|
virtual ~HeaderListener();
|
||||||
|
|
||||||
|
virtual void HeaderPropertiesChanged(Header* header,
|
||||||
|
bool redrawNeeded, bool relayoutNeeded) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Header {
|
||||||
|
public:
|
||||||
|
Header(int32 modelIndex = 0);
|
||||||
|
Header(float width, float minWidth,
|
||||||
|
float maxWidth, float preferredWidth,
|
||||||
|
int32 modelIndex = 0);
|
||||||
|
|
||||||
|
float Width() const;
|
||||||
|
float MinWidth() const;
|
||||||
|
float MaxWidth() const;
|
||||||
|
float PreferredWidth() const;
|
||||||
|
|
||||||
|
void SetWidth(float width);
|
||||||
|
void SetMinWidth(float width);
|
||||||
|
void SetMaxWidth(float width);
|
||||||
|
void SetPreferredWidth(float width);
|
||||||
|
|
||||||
|
bool IsResizable() const;
|
||||||
|
void SetResizable(bool resizable);
|
||||||
|
|
||||||
|
bool GetValue(BVariant& _value) const;
|
||||||
|
void SetValue(const BVariant& value);
|
||||||
|
|
||||||
|
int32 ModelIndex() const;
|
||||||
|
void SetModelIndex(int32 index);
|
||||||
|
|
||||||
|
HeaderRenderer* GetHeaderRenderer() const;
|
||||||
|
void SetHeaderRenderer(HeaderRenderer* renderer);
|
||||||
|
|
||||||
|
void AddListener(HeaderListener* listener);
|
||||||
|
void RemoveListener(HeaderListener* listener);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NotifyPropertiesChanged(bool redrawNeeded,
|
||||||
|
bool relayoutNeeded);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BObjectList<HeaderListener> ListenerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float fWidth;
|
||||||
|
float fMinWidth;
|
||||||
|
float fMaxWidth;
|
||||||
|
float fPreferredWidth;
|
||||||
|
BVariant fValue;
|
||||||
|
HeaderRenderer* fRenderer;
|
||||||
|
int32 fModelIndex;
|
||||||
|
bool fResizable;
|
||||||
|
ListenerList fListeners;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderModelListener {
|
||||||
|
public:
|
||||||
|
virtual ~HeaderModelListener();
|
||||||
|
|
||||||
|
virtual void HeaderAdded(HeaderModel* model, int32 index);
|
||||||
|
virtual void HeaderRemoved(HeaderModel* model, int32 index);
|
||||||
|
virtual void HeaderMoved(HeaderModel* model,
|
||||||
|
int32 fromIndex, int32 toIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderModel : public BReferenceable {
|
||||||
|
public:
|
||||||
|
HeaderModel();
|
||||||
|
virtual ~HeaderModel();
|
||||||
|
|
||||||
|
virtual int32 CountHeaders() const;
|
||||||
|
virtual Header* HeaderAt(int32 index) const;
|
||||||
|
virtual int32 IndexOfHeader(Header* header) const;
|
||||||
|
|
||||||
|
virtual bool AddHeader(Header* header);
|
||||||
|
virtual Header* RemoveHeader(int32 index);
|
||||||
|
virtual void RemoveHeader(Header* header);
|
||||||
|
virtual bool MoveHeader(int32 fromIndex, int32 toIndex);
|
||||||
|
|
||||||
|
virtual void AddListener(HeaderModelListener* listener);
|
||||||
|
virtual void RemoveListener(HeaderModelListener* listener);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NotifyHeaderAdded(int32 index);
|
||||||
|
void NotifyHeaderRemoved(int32 index);
|
||||||
|
void NotifyHeaderMoved(int32 fromIndex,
|
||||||
|
int32 toIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BObjectList<Header> HeaderList;
|
||||||
|
typedef BObjectList<HeaderModelListener> ListenerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
HeaderList fHeaders;
|
||||||
|
ListenerList fListeners;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderView : public BView, private HeaderModelListener,
|
||||||
|
private HeaderListener {
|
||||||
|
public:
|
||||||
|
HeaderView();
|
||||||
|
virtual ~HeaderView();
|
||||||
|
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
|
virtual BSize MinSize();
|
||||||
|
virtual BSize MaxSize();
|
||||||
|
virtual BSize PreferredSize();
|
||||||
|
|
||||||
|
HeaderModel* Model() const;
|
||||||
|
status_t SetModel(HeaderModel* model);
|
||||||
|
|
||||||
|
void AddListener(HeaderViewListener* listener);
|
||||||
|
void RemoveListener(HeaderViewListener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct HeaderEntry;
|
||||||
|
|
||||||
|
typedef BObjectList<HeaderEntry> HeaderEntryList;
|
||||||
|
typedef BObjectList<HeaderViewListener> ListenerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// HeaderModelListener
|
||||||
|
virtual void HeaderAdded(HeaderModel* model, int32 index);
|
||||||
|
virtual void HeaderRemoved(HeaderModel* model, int32 index);
|
||||||
|
virtual void HeaderMoved(HeaderModel* model,
|
||||||
|
int32 fromIndex, int32 toIndex);
|
||||||
|
|
||||||
|
// HeaderListener
|
||||||
|
virtual void HeaderPropertiesChanged(Header* header,
|
||||||
|
bool redrawNeeded, bool relayoutNeeded);
|
||||||
|
|
||||||
|
void _InvalidateHeadersLayout(int32 firstIndex);
|
||||||
|
void _InvalidateHeaders(int32 firstIndex,
|
||||||
|
int32 endIndex);
|
||||||
|
void _ValidateHeadersLayout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HeaderModel* fModel;
|
||||||
|
HeaderEntryList fHeaderEntries;
|
||||||
|
float fPreferredWidth;
|
||||||
|
float fPreferredHeight;
|
||||||
|
bool fLayoutValid;
|
||||||
|
ListenerList fListeners;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderViewListener {
|
||||||
|
public:
|
||||||
|
virtual ~HeaderViewListener();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // HEADER_VIEW_H
|
||||||
@@ -5,11 +5,14 @@ UsePrivateSystemHeaders ;
|
|||||||
|
|
||||||
UseHeaders $(HAIKU_DEBUG_ANALYZER_HEADERS) ;
|
UseHeaders $(HAIKU_DEBUG_ANALYZER_HEADERS) ;
|
||||||
|
|
||||||
|
CCFLAGS += -Werror ;
|
||||||
|
C++FLAGS += -Werror ;
|
||||||
|
|
||||||
MergeObject DebugAnalyzer_gui.o
|
MergeObject DebugAnalyzer_gui.o
|
||||||
:
|
:
|
||||||
AbstractGeneralPage.cpp
|
AbstractGeneralPage.cpp
|
||||||
ColorCheckBox.cpp
|
ColorCheckBox.cpp
|
||||||
|
HeaderView.cpp
|
||||||
SubWindow.cpp
|
SubWindow.cpp
|
||||||
SubWindowManager.cpp
|
SubWindowManager.cpp
|
||||||
:
|
:
|
||||||
|
|||||||
Reference in New Issue
Block a user