Implemented some support for moving and reziving Layers. It works too. :-)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12701 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adi Oanca
2005-05-17 17:24:50 +00:00
parent e3c6cec42e
commit 4a95e83357
6 changed files with 469 additions and 267 deletions
Binary file not shown.
+426 -258
View File
@@ -1,258 +1,426 @@
#include <OS.h> #include <OS.h>
#include <View.h> #include <Region.h>
#include <Window.h> #include <Rect.h>
#include <Looper.h> #include <stdio.h>
#include <Region.h> #include <strings.h>
#include <Rect.h>
#include <stdio.h> #include <Window.h>
#include <strings.h>
#include "Layer.h"
#include "Layer.h" #include "MyView.h"
extern BWindow* wind; extern BWindow* wind;
Layer::Layer(BRect frame, const char* name, uint32 rm, rgb_color c) Layer::Layer(BRect frame, const char* name, uint32 rm, rgb_color c)
{ {
fFrame = frame; fFrame = frame;
fRM = rm; fOrigin.Set(0.0f, 0.0f);
fColor = c; fResizeMode = rm;
fColor = c;
fBottom = NULL;
fUpper = NULL; fBottom = NULL;
fLower = NULL; fUpper = NULL;
fTop = NULL; fLower = NULL;
fParent = NULL; fTop = NULL;
fView = NULL; fParent = NULL;
fView = NULL;
strcpy(fName, name);
} strcpy(fName, name);
}
Layer::~Layer()
{ Layer::~Layer()
Layer *c = fBottom; {
Layer *toast; Layer *c = fBottom;
while (c) Layer *toast;
{ while (c)
toast = c; {
c = c->fUpper; toast = c;
delete toast; c = c->fUpper;
} delete toast;
} }
}
void Layer::ConvertToScreen2(BRect* rect)
{ void Layer::ConvertToScreen2(BRect* rect)
BView *view = GetRootLayer(); {
if (view) MyView *view = GetRootLayer();
if (fParent) if (view)
{ if (fParent)
rect->Set( rect->left + fFrame.left, {
rect->top + fFrame. top, rect->Set( rect->left + fFrame.left,
rect->right + fFrame.left, rect->top + fFrame. top,
rect->bottom + fFrame.top); rect->right + fFrame.left,
rect->bottom + fFrame.top);
fParent->ConvertToScreen2(rect);
} fParent->ConvertToScreen2(rect);
} }
}
BView* Layer::GetRootLayer() const
{ MyView* Layer::GetRootLayer() const
if (fView) {
return fView; if (fView)
else return fView;
if (fParent) else
return fParent->GetRootLayer(); if (fParent)
else return fParent->GetRootLayer();
return NULL; else
} return NULL;
}
Layer* Layer::VirtualBottomChild() const
{ Layer* Layer::VirtualBottomChild() const
return fBottom; {
} return fBottom;
}
Layer* Layer::VirtualTopChild() const
{ Layer* Layer::VirtualTopChild() const
return fTop; {
} return fTop;
}
Layer* Layer::VirtualUpperSibling() const
{ Layer* Layer::VirtualUpperSibling() const
return fUpper; {
} return fUpper;
}
Layer* Layer::VirtualLowerSibling() const
{ Layer* Layer::VirtualLowerSibling() const
return fLower; {
} return fLower;
}
void Layer::AddLayer(Layer* layer)
{ void Layer::AddLayer(Layer* layer)
if( layer->fParent != NULL ) {
{ if( layer->fParent != NULL )
printf("ERROR: Layer already has a parent\n"); {
return; printf("ERROR: Layer already has a parent\n");
} return;
}
layer->fParent = this;
layer->fParent = this;
if (!fBottom)
{ if (!fBottom)
fBottom = layer; {
fTop = layer; fBottom = layer;
return; fTop = layer;
} return;
fBottom->fLower = layer; }
layer->fUpper = fBottom; fBottom->fLower = layer;
fBottom = layer; layer->fUpper = fBottom;
} fBottom = layer;
}
bool Layer::RemLayer(Layer* layer)
{ bool Layer::RemLayer(Layer* layer)
if(!layer->fParent || layer->fParent != this) {
{ if(!layer->fParent || layer->fParent != this)
printf("ERROR: Rem: Layer doesn't have a fParent or !=this\n"); {
return false; printf("ERROR: Rem: Layer doesn't have a fParent or !=this\n");
} return false;
}
layer->fParent = NULL;
layer->fParent = NULL;
if(fTop == layer)
fTop = layer->fLower; if(fTop == layer)
fTop = layer->fLower;
if(fBottom == layer )
fBottom = layer->fUpper; if(fBottom == layer )
fBottom = layer->fUpper;
if(layer->fUpper != NULL)
layer->fUpper->fLower = layer->fLower; if(layer->fUpper != NULL)
layer->fUpper->fLower = layer->fLower;
if(layer->fLower != NULL)
layer->fLower->fUpper = layer->fUpper; if(layer->fLower != NULL)
layer->fLower->fUpper = layer->fUpper;
layer->fUpper = NULL;
layer->fLower = NULL; layer->fUpper = NULL;
layer->fLower = NULL;
layer->clear_visible_regions();
layer->clear_visible_regions();
return true;
} return true;
}
void Layer::set_user_regions(BRegion &reg)
{ bool Layer::IsVisuallyHidden() const
// OPT: maybe we should have all these cached in a 'fFull' member {
// TODO: implement
// 1) set to frame in screen coords return false;
// BRect screenFrame(fFrame); }
BRect screenFrame(Bounds());
ConvertToScreen2(&screenFrame); void Layer::resize_layer_frame_by(float x, float y)
reg.Set(screenFrame); {
uint16 rm = fResizeMode & 0x0000FFFF;
// 2) intersect with screen region BRect newFrame = fFrame;
// TODO: remove locking when for real float dx, dy;
wind->Lock();
printf("Adi: RL: %p\n", wind); if ((rm & 0x000FU) == _VIEW_LEFT_)
printf("Adi: RL: %s\n", wind->Name()); {
BRegion screenReg(GetRootLayer()->Bounds()); newFrame.left += 0.0f;
wind->Unlock(); newFrame.right += x;
reg.IntersectWith(&screenReg); }
else if ((rm & 0x000FU) == _VIEW_RIGHT_)
// TODO: you MUST at some point uncomment this block! {
/* newFrame.left += x;
// 3) impose user constrained regions newFrame.right += x;
LayerData *stackData = fLayerData; }
while (stackData) else if ((rm & 0x000FU) == _VIEW_CENTER_)
{ {
// transform in screen coords newFrame.left += x/2;
BRegion screenReg(stackData->ClippingRegion()); newFrame.right += x/2;
ConvertToScreen2(&screenReg); }
reg.IntersectWith(&screenReg);
stackData = stackData->prevState; if ((rm & 0x00F0U) == _VIEW_TOP_)
} {
*/ newFrame.top += 0.0f;
} newFrame.bottom += y;
}
void Layer::RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom) else if ((rm & 0x00F0U) == _VIEW_BOTTOM_)
{ {
BRegion localVisible(fFullVisible); newFrame.top += y;
localVisible.IntersectWith(&invalid); newFrame.bottom += y;
rebuild_visible_regions(invalid, localVisible, startFrom); }
} else if ((rm & 0x00F0U) == _VIEW_CENTER_)
{
void Layer::rebuild_visible_regions(const BRegion &invalid, newFrame.top += y/2;
const BRegion &parentLocalVisible, newFrame.bottom += y/2;
const Layer *startFrom) }
{
bool fullRebuild = false; dx = newFrame.Width() - fFrame.Width();
// intersect maximum wanted region with the invalid region dy = newFrame.Height() - fFrame.Height();
BRegion common;
set_user_regions(common); fFrame = newFrame;
common.IntersectWith(&invalid);
// if the resulted region is not valid, this layer is not in the catchment area for (Layer *lay = VirtualBottomChild(); lay ; lay = VirtualUpperSibling())
// of the region being invalidated {
if (!common.Frame().IsValid()) lay->resize_layer_frame_by(dx, dy);
return; }
}
// now intersect with parent's visible part of the region that was/is invalidated
common.IntersectWith(&parentLocalVisible); void Layer::ResizeBy(float dx, float dy)
//printf("\t%s: For this layer we invalidate:\n", fName); {
//common.PrintToStream(); // TODO: add support for B_FULL_UPDATE_ON_RESIZE
if (common.Frame().IsValid()) // TODO: center and right alligned view must be full redrawn
{
// we have something to include to our fullVisible. It may already be in fFrame.Set(fFrame.left, fFrame.top, fFrame.right+dx, fFrame.bottom+dy);
// there, but we'll never know.
fFullVisible.Include(&common); // resize children using their resize_mask.
} for (Layer *lay = fParent->VirtualBottomChild();
else lay; lay = fParent->VirtualUpperSibling())
{ lay->resize_layer_frame_by(dx, dy);
// this layer is in the catchment area of the region being invalidated,
// yet it will have no new visible area attached to it. It means if (!IsVisuallyHidden() && GetRootLayer())
// this layer was overshaddowed by those above it and any visible area {
// that it may have common with the region being invalidated, must be BRegion oldFullVisible(fFullVisible);
// excluded from it's fFullVisible and fVisible regions.
fFullVisible.Exclude(&invalid); // we'll invalidate the old position and the new, maxmial, one (bounds in screen coords).
fVisible.Exclude(&invalid); BRegion invalid(fFullVisible);
// we don't return here becase we want the same thing to happen to all BRect r(Bounds());
// our children. ConvertToScreen2(&r);
invalid.Include(r);
// Don't worry about the last line from this method, it will do nothing -
// common is invalid. Same goes for the last one in the 'for' statement below. clear_visible_regions();
}
fParent->RebuildVisibleRegions(invalid, this);
for (Layer *lay = VirtualBottomChild(); lay ; lay = VirtualUpperSibling())
{ // done rebuilding regions, now redraw regions that became visible
if (lay == startFrom)
fullRebuild = true; // what's invalid, are the differences between to old and the new fullVisible region
// 1) in case we grow.
if (fullRebuild) BRegion redrawReg(fFullVisible);
lay->rebuild_visible_regions(invalid, common, lay->VirtualBottomChild()); redrawReg.Exclude(&oldFullVisible);
// 2) in case we shrink
common.Exclude(&lay->fFullVisible); BRegion redrawReg2(oldFullVisible);
fVisible.Exclude(&lay->fFullVisible); redrawReg2.Exclude(&fFullVisible);
} // 3) combine.
redrawReg.Include(&redrawReg2);
// the visible region of this layer is what left after all its children took
// what they could. // add redrawReg to our RootLayer's redraw region.
fVisible.Include(&common); GetRootLayer()->fRedrawReg.Include(&redrawReg);
} GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
}
void Layer::clear_visible_regions()
{ // call hook function
fVisible.MakeEmpty(); if (dx != 0.0f || dy != 0.0f)
fFullVisible.MakeEmpty(); ResizedByHook(dx, dy);
Layer *child = fBottom; }
while (child)
{ void Layer::MoveBy(float dx, float dy)
child->clear_visible_regions(); {
child = child->fUpper; fFrame.Set(fFrame.left+dx, fFrame.top+dy, fFrame.right+dx, fFrame.bottom+dy);
}
} if (!IsVisuallyHidden() && GetRootLayer())
{
void Layer::PrintToStream() const BRegion oldFullVisible(fFullVisible);
{
printf("-> %s\n", fName); // we'll invalidate the old position and the new, maxmial, one (bounds in screen coords).
Layer *child = VirtualBottomChild(); BRegion invalid(fFullVisible);
while(child) BRect r(Bounds());
{ ConvertToScreen2(&r);
child->PrintToStream(); invalid.Include(r);
child = child->VirtualUpperSibling();
} clear_visible_regions();
}
fParent->RebuildVisibleRegions(invalid, this);
// done rebuilding regions, now copy common parts and redraw regions that became visible
// include the actual and the old fullVisible regions. later, we'll exclude the common parts.
BRegion redrawReg(fFullVisible);
redrawReg.Include(&oldFullVisible);
// offset to layer's new location so that we can calculate the common region.
oldFullVisible.OffsetBy(dx, dy);
// finally we have the region that needs to be redrawn.
redrawReg.Exclude(&oldFullVisible);
// by intersecting the old fullVisible offseted to layer's new location, with the current
// fullVisible, we'll have the common region which can be copied using HW acceleration.
oldFullVisible.IntersectWith(&fFullVisible);
// offset back and instruct the HW to do the actual copying.
oldFullVisible.OffsetBy(-dx, -dy);
// TODO: HACK this!
// GetDisplayDriver()->CopyRegion(&oldFullVisible, dx, dy);
// add redrawReg to our RootLayer's redraw region.
GetRootLayer()->fRedrawReg.Include(&redrawReg);
GetRootLayer()->RequestRedraw(); // TODO: what if we pass (fParent, startFromTHIS, &redrawReg)?
}
// call hook function
if (dx != 0.0f || dy != 0.0f)
MovedByHook(dx, dy);
}
void Layer::ScrollBy(float dx, float dy)
{
fOrigin.Set(fOrigin.x + dx, fOrigin.y + dy);
if (!IsVisuallyHidden() && GetRootLayer())
{
clear_visible_regions();
RebuildVisibleRegions(fFullVisible, VirtualBottomChild());
// TODO: continue
}
if (dx != 0.0f || dy != 0.0f)
ScrolledByHook(dx, dy);
}
void Layer::set_user_regions(BRegion &reg)
{
// OPT: maybe we should have all these cached in a 'fFull' member
// 1) set to frame in screen coords
// BRect screenFrame(fFrame);
BRect screenFrame(Bounds());
ConvertToScreen2(&screenFrame);
reg.Set(screenFrame);
// 2) intersect with screen region
// TODO: remove locking when for real
wind->Lock();
BRegion screenReg(GetRootLayer()->Bounds());
wind->Unlock();
reg.IntersectWith(&screenReg);
// TODO: you MUST at some point uncomment this block!
/*
// 3) impose user constrained regions
LayerData *stackData = fLayerData;
while (stackData)
{
// transform in screen coords
BRegion screenReg(stackData->ClippingRegion());
ConvertToScreen2(&screenReg);
reg.IntersectWith(&screenReg);
stackData = stackData->prevState;
}
*/
}
void Layer::RebuildVisibleRegions(const BRegion &invalid, const Layer *startFrom)
{
BRegion localVisible(fFullVisible);
localVisible.IntersectWith(&invalid);
rebuild_visible_regions(invalid, localVisible, startFrom);
}
void Layer::rebuild_visible_regions(const BRegion &invalid,
const BRegion &parentLocalVisible,
const Layer *startFrom)
{
bool fullRebuild = false;
// intersect maximum wanted region with the invalid region
BRegion common;
set_user_regions(common);
common.IntersectWith(&invalid);
// if the resulted region is not valid, this layer is not in the catchment area
// of the region being invalidated
if (!common.Frame().IsValid())
return;
// now intersect with parent's visible part of the region that was/is invalidated
common.IntersectWith(&parentLocalVisible);
if (common.Frame().IsValid())
{
// we have something to include to our fullVisible. It may already be in
// there, but we'll never know.
fFullVisible.Include(&common);
}
else
{
// this layer is in the catchment area of the region being invalidated,
// yet it will have no new visible area attached to it. It means
// this layer was overshaddowed by those above it and any visible area
// that it may have common with the region being invalidated, must be
// excluded from it's fFullVisible and fVisible regions.
fFullVisible.Exclude(&invalid);
fVisible.Exclude(&invalid);
// we don't return here becase we want the same thing to happen to all
// our children.
// Don't worry about the last line from this method, it will do nothing -
// common is invalid. Same goes for the last one in the 'for' statement below.
}
for (Layer *lay = VirtualBottomChild(); lay ; lay = VirtualUpperSibling())
{
if (lay == startFrom)
fullRebuild = true;
if (fullRebuild)
lay->rebuild_visible_regions(invalid, common, lay->VirtualBottomChild());
common.Exclude(&lay->fFullVisible);
fVisible.Exclude(&lay->fFullVisible);
}
// the visible region of this layer is what left after all its children took
// what they could.
fVisible.Include(&common);
}
void Layer::clear_visible_regions()
{
fVisible.MakeEmpty();
fFullVisible.MakeEmpty();
Layer *child = VirtualBottomChild();
while (child)
{
child->clear_visible_regions();
child = child->VirtualUpperSibling();
}
}
void Layer::PrintToStream() const
{
printf("-> %s\n", fName);
Layer *child = VirtualBottomChild();
while(child)
{
child->PrintToStream();
child = child->VirtualUpperSibling();
}
}
+17 -6
View File
@@ -3,7 +3,7 @@
#include <Rect.h> #include <Rect.h>
#include <GraphicsDefs.h> #include <GraphicsDefs.h>
class BView; class MyView;
class Layer class Layer
{ {
@@ -14,6 +14,14 @@ public:
void AddLayer(Layer* layer); void AddLayer(Layer* layer);
bool RemLayer(Layer* layer); bool RemLayer(Layer* layer);
void MoveBy(float dx, float dy);
void ResizeBy(float dx, float dy);
void ScrollBy(float dx, float dy);
virtual void MovedByHook(float dx, float dy) { }
virtual void ResizedByHook(float dx, float dy) { }
virtual void ScrolledByHook(float dx, float dy) { }
Layer* VirtualBottomChild() const; Layer* VirtualBottomChild() const;
Layer* VirtualTopChild() const; Layer* VirtualTopChild() const;
Layer* VirtualUpperSibling() const; Layer* VirtualUpperSibling() const;
@@ -22,15 +30,16 @@ public:
void RebuildVisibleRegions( const BRegion &invalid, void RebuildVisibleRegions( const BRegion &invalid,
const Layer *startFrom); const Layer *startFrom);
void ConvertToScreen2(BRect* rect); void ConvertToScreen2(BRect* rect);
BView* GetRootLayer() const; MyView* GetRootLayer() const;
void SetRootLayer(BView* view) { fView = view; } void SetRootLayer(MyView* view) { fView = view; }
bool IsVisuallyHidden() const;
BRegion* Visible() { return &fVisible; } BRegion* Visible() { return &fVisible; }
BRegion* FullVisible() { return &fFullVisible; } BRegion* FullVisible() { return &fFullVisible; }
BRect Frame() const { return fFrame; } BRect Frame() const { return fFrame; }
BRect Bounds() const { BRect r(fFrame); BRect Bounds() const { BRect r(fFrame);
r.OffsetTo(0,0); r.OffsetTo(fOrigin);
return r; } return r; }
const char* Name() const { return fName; } const char* Name() const { return fName; }
Layer* Parent() const { return fParent; } Layer* Parent() const { return fParent; }
@@ -44,13 +53,15 @@ public:
private: private:
void set_user_regions(BRegion &reg); void set_user_regions(BRegion &reg);
void clear_visible_regions(); void clear_visible_regions();
void resize_layer_frame_by(float x, float y);
char fName[50]; char fName[50];
BRegion fVisible; BRegion fVisible;
BRegion fFullVisible; BRegion fFullVisible;
BRect fFrame; BRect fFrame;
uint32 fRM; BPoint fOrigin;
uint32 fResizeMode;
rgb_color fColor; rgb_color fColor;
Layer* fBottom; Layer* fBottom;
@@ -59,5 +70,5 @@ private:
Layer* fTop; Layer* fTop;
Layer* fParent; Layer* fParent;
BView* fView; MyView* fView;
}; };
@@ -1,11 +1,14 @@
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <Window.h>
#include <stdio.h> #include <stdio.h>
#include "MyView.h" #include "MyView.h"
#include "Layer.h" #include "Layer.h"
extern BWindow *wind;
MyView::MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) MyView::MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
: BView(frame, name, resizingMode, flags) : BView(frame, name, resizingMode, flags)
{ {
@@ -45,6 +48,14 @@ Layer* MyView::FindLayer(Layer *lay, const char *bytes) const
return NULL; return NULL;
} }
void MyView::RequestRedraw()
{
// TODO: implement
wind->Lock();
Invalidate();
wind->Unlock();
}
void MyView::Draw(BRect area) void MyView::Draw(BRect area)
{ {
DrawSubTree(topLayer); DrawSubTree(topLayer);
+5 -1
View File
@@ -1,5 +1,6 @@
#include <OS.h> #include <OS.h>
#include <View.h> #include <View.h>
#include <Region.h>
class Layer; class Layer;
@@ -9,11 +10,14 @@ public:
MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags); MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags);
virtual ~MyView(); virtual ~MyView();
virtual void Draw(BRect area); virtual void Draw(BRect area);
void RequestRedraw();
Layer* FindLayer(Layer *lay, const char *bytes) const; Layer* FindLayer(Layer *lay, const char *bytes) const;
Layer *topLayer; Layer *topLayer;
BRegion fRedrawReg;
private: private:
void DrawSubTree(Layer* lay); void DrawSubTree(Layer* lay);
}; };
+10 -2
View File
@@ -80,7 +80,7 @@ bool clsMainWindow::QuitRequested()
void clsMainWindow::test1() void clsMainWindow::test1()
{ {
Layer *topLayer = fView->topLayer; Layer *topLayer = fView->topLayer;
Layer *parent; // Layer *parent;
rgb_color c; rgb_color c;
BRect temp; BRect temp;
@@ -110,7 +110,7 @@ void clsMainWindow::test1()
wind->Lock(); wind->Lock();
fView->Invalidate(); fView->Invalidate();
wind->Unlock(); wind->Unlock();
/*
snooze(2000000); snooze(2000000);
temp = lay2->Bounds(); temp = lay2->Bounds();
@@ -125,6 +125,14 @@ void clsMainWindow::test1()
wind->Lock(); wind->Lock();
fView->Invalidate(); fView->Invalidate();
wind->Unlock(); wind->Unlock();
*/
snooze(2000000);
lay2->MoveBy(25,35);
snooze(2000000);
lay2->ResizeBy(45,55);
} }