* the path list view shows check boxes now when a shape is selected,

the marked paths are used in the shape
* a new path is auto-selected
* deselecting a shape still sends the selection message
* PathSource does not call agg::path_storage::start_new_path() for
  each subpath... a move_to() is sufficient and makes sure the
  subpaths are rendered even :-)
* updated NOTES
* moved IconView into gui subfolder


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18021 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-07-04 00:04:50 +00:00
parent 98662fad6d
commit 9b4fa889fd
8 changed files with 325 additions and 25 deletions

View File

@ -45,6 +45,7 @@ enum {
MSG_NEW_PATH = 'nwvp',
MSG_PATH_SELECTED = 'vpsl',
MSG_SHAPE_SELECTED = 'spsl',
};
// constructor
@ -100,6 +101,13 @@ case MSG_PATH_SELECTED: {
}
break;
}
case MSG_SHAPE_SELECTED: {
Shape* shape;
if (message->FindPointer("shape", (void**)&shape) < B_OK)
shape = NULL;
fPathListView->SetCurrentShape(shape);
break;
}
default:
BWindow::MessageReceived(message);
@ -291,7 +299,8 @@ MainWindow::_CreateGUI(BRect bounds)
new BMessage(MSG_PATH_SELECTED), this);
bounds.OffsetBy(bounds.Width() + 6 + B_V_SCROLL_BAR_WIDTH, 0);
fShapeListView = new ShapeListView(bounds, "shape list view");
fShapeListView = new ShapeListView(bounds, "shape list view",
new BMessage(MSG_SHAPE_SELECTED), this);
bg->AddChild(fSwatchGroup);

View File

@ -15,21 +15,33 @@
different paths showing at the same time...
* solve the problem of individual gradient transformation per shape
-> introduce "StyleInstance", a Shape would not reference a Style
directly but via a StyleInstance... this object can have additional
information like the gradient transformation
* IconRenderer should construct a separate StyleManager and append
the styles in the order of shapes, also adding styles multiple
times, if two or more shapes use the same style (the compound shape
rendering uses the style index for z ordering)
rendering uses the style index for z ordering) [done]
* add more functionality to Transformer/VertexSource interface:
- (inverse) Transformation
- Cloning
* add more powerful listener interface to Shape
(TransformerAdded()/Removed()...)
* implement commands for the newly added editing features
--------- user interface
* list of global vector paths
* list of global vector paths [done]
* list of shapes
* list of shapes [done]
* list of paths used by shape, but it could also be done such that
used paths are marked in the global list when a shape is selected
used paths are marked in the global list when a shape is selected [done]
* list of transformers attached to the selected shape
@ -40,12 +52,12 @@
* 192 "built-in" (pre-defined) style definitions
* up to 64 additional style definitions per document
* referencing of fill style by uint8 id
* solid colors and different types of gradients
* uint8 precision for coordinates on a 64x64 virtual pixel grid
(* removal (freezing) of transformations at export time
not sure about this one, it would remove the possiblity
to store vector path only once for referenced objects)
* referencing of fill style by uint8 id
* IFF type chunk format

View File

@ -18,16 +18,25 @@
#include "VectorPath.h"
#include "Observer.h"
#include "Shape.h"
#include "ShapeContainer.h"
#include "Selection.h"
static const float kMarkWidth = 14.0;
static const float kBorderOffset = 3.0;
static const float kTextOffset = 4.0;
class PathListItem : public SimpleItem,
public Observer {
public:
PathListItem(VectorPath* p,
PathListView* listView)
PathListView* listView,
bool markEnabled)
: SimpleItem(""),
path(NULL),
fListView(listView)
fListView(listView),
fMarkEnabled(markEnabled),
fMarked(false)
{
SetPath(p);
}
@ -37,11 +46,63 @@ class PathListItem : public SimpleItem,
SetPath(NULL);
}
// SimpleItem interface
virtual void Draw(BView* owner, BRect itemFrame, uint32 flags)
{
SimpleItem::DrawBackground(owner, itemFrame, flags);
// text
owner->SetHighColor(0, 0, 0, 255);
font_height fh;
owner->GetFontHeight(&fh);
BString truncatedString(Text());
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
itemFrame.Width()
- kBorderOffset
- kMarkWidth
- kTextOffset
- kBorderOffset);
float height = itemFrame.Height();
float textHeight = fh.ascent + fh.descent;
BPoint pos;
pos.x = itemFrame.left
+ kBorderOffset + kMarkWidth + kTextOffset;
pos.y = itemFrame.top
+ ceilf((height - textHeight) / 2.0 + fh.ascent);
owner->DrawString(truncatedString.String(), pos);
if (!fMarkEnabled)
return;
// mark
BRect markRect = itemFrame;
markRect.left += kBorderOffset;
markRect.right = markRect.left + kMarkWidth;
markRect.top = (markRect.top + markRect.bottom - kMarkWidth) / 2.0;
markRect.bottom = markRect.top + kMarkWidth;
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_1_TINT));
owner->StrokeRect(markRect);
markRect.InsetBy(1, 1);
owner->SetHighColor(tint_color(owner->LowColor(), 1.04));
owner->FillRect(markRect);
if (fMarked) {
markRect.InsetBy(2, 2);
owner->SetHighColor(tint_color(owner->LowColor(),
B_DARKEN_4_TINT));
owner->SetPenSize(2);
owner->StrokeLine(markRect.LeftTop(), markRect.RightBottom());
owner->StrokeLine(markRect.LeftBottom(), markRect.RightTop());
owner->SetPenSize(1);
}
}
// Observer interface
virtual void ObjectChanged(const Observable* object)
{
UpdateText();
}
// PathListItem
void SetPath(VectorPath* p)
{
if (p == path)
@ -63,17 +124,92 @@ class PathListItem : public SimpleItem,
void UpdateText()
{
SetText(path->Name());
// :-/
if (fListView->LockLooper()) {
fListView->InvalidateItem(
fListView->IndexOf(this));
fListView->UnlockLooper();
}
Invalidate();
}
void SetMarkEnabled(bool enabled)
{
if (fMarkEnabled == enabled)
return;
fMarkEnabled = enabled;
Invalidate();
}
void SetMarked(bool marked)
{
if (fMarked == marked)
return;
fMarked = marked;
Invalidate();
}
void Invalidate()
{
// :-/
if (fListView->LockLooper()) {
fListView->InvalidateItem(
fListView->IndexOf(this));
fListView->UnlockLooper();
}
}
VectorPath* path;
private:
PathListView* fListView;
bool fMarkEnabled;
bool fMarked;
};
class ShapePathListener : public PathContainerListener,
public ShapeContainerListener {
public:
ShapePathListener(PathListView* listView)
: fListView(listView),
fShape(NULL)
{
}
virtual ~ShapePathListener()
{
SetShape(NULL);
}
virtual void PathAdded(VectorPath* path)
{
fListView->_SetPathMarked(path, true);
}
virtual void PathRemoved(VectorPath* path)
{
fListView->_SetPathMarked(path, false);
}
virtual void ShapeAdded(Shape* shape, int32 index) {}
virtual void ShapeRemoved(Shape* shape)
{
fListView->SetCurrentShape(NULL);
}
void SetShape(Shape* shape)
{
if (fShape == shape)
return;
if (fShape)
fShape->Paths()->RemoveListener(this);
fShape = shape;
if (fShape)
fShape->Paths()->AddListener(this);
}
Shape* CurrentShape() const
{
return fShape;
}
private:
PathListView* fListView;
Shape* fShape;
};
// #pragma mark -
@ -86,7 +222,12 @@ PathListView::PathListView(BRect frame,
NULL, B_SINGLE_SELECTION_LIST),
fMessage(message),
fPathContainer(NULL),
fSelection(NULL)
fShapeContainer(NULL),
fSelection(NULL),
fCommandStack(NULL),
fCurrentShape(NULL),
fShapePathListener(new ShapePathListener(this))
{
SetTarget(target);
}
@ -99,6 +240,11 @@ PathListView::~PathListView()
if (fPathContainer)
fPathContainer->RemoveListener(this);
if (fShapeContainer)
fShapeContainer->RemoveListener(fShapePathListener);
delete fShapePathListener;
}
// SelectionChanged
@ -125,6 +271,49 @@ PathListView::SelectionChanged()
// fSelection->DeselectAll();
}
// MouseDown
void
PathListView::MouseDown(BPoint where)
{
if (!fCurrentShape) {
SimpleListView::MouseDown(where);
return;
}
bool handled = false;
int32 index = IndexOf(where);
PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(index));
if (item) {
BRect itemFrame(ItemFrame(index));
itemFrame.right = itemFrame.left
+ kBorderOffset + kMarkWidth
+ kTextOffset / 2.0;
VectorPath* path = item->path;
if (itemFrame.Contains(where)) {
// add or remove the path to the shape
// TODO: code these commands...
// Command* command;
// if (fCurrentShape->Paths()->HasPath(path)) {
// command = new RemovePathFromShapeCommand(
// fCurrentShape, path);
// } else {
// command = new AddPathToShapeCommand(
// fCurrentShape, path);
// }
// fCommandStack->Perform(command);
if (fCurrentShape->Paths()->HasPath(path)) {
fCurrentShape->Paths()->RemovePath(path);
} else {
fCurrentShape->Paths()->AddPath(path);
}
handled = true;
}
}
if (!handled)
SimpleListView::MouseDown(where);
}
// MessageReceived
void
PathListView::MessageReceived(BMessage* message)
@ -176,7 +365,8 @@ PathListView::CloneItem(int32 index) const
{
if (PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(index))) {
return new PathListItem(item->path,
const_cast<PathListView*>(this));
const_cast<PathListView*>(this),
fCurrentShape != NULL);
}
return NULL;
}
@ -196,7 +386,8 @@ PathListView::PathAdded(VectorPath* path)
// NOTE: shapes are always added at the end
// of the list, so the sorting is synced...
_AddPath(path);
if (_AddPath(path))
Select(CountItems() - 1);
UnlockLooper();
}
@ -251,6 +442,23 @@ PathListView::SetPathContainer(PathContainer* container)
// fPathContainer->ReadUnlock();
}
// SetShapeContainer
void
PathListView::SetShapeContainer(ShapeContainer* container)
{
if (fShapeContainer == container)
return;
// detach from old container
if (fShapeContainer)
fShapeContainer->RemoveListener(fShapePathListener);
fShapeContainer = container;
if (fShapeContainer)
fShapeContainer->AddListener(fShapePathListener);
}
// SetSelection
void
PathListView::SetSelection(Selection* selection)
@ -258,6 +466,19 @@ PathListView::SetSelection(Selection* selection)
fSelection = selection;
}
// SetCurrentShape
void
PathListView::SetCurrentShape(Shape* shape)
{
if (fCurrentShape == shape)
return;
fCurrentShape = shape;
fShapePathListener->SetShape(shape);
_UpdateMarks();
}
// #pragma mark -
// _AddPath
@ -265,7 +486,7 @@ bool
PathListView::_AddPath(VectorPath* path)
{
if (path)
return AddItem(new PathListItem(path, this));
return AddItem(new PathListItem(path, this, fCurrentShape != NULL));
return false;
}
@ -306,3 +527,41 @@ PathListView::_MakeEmpty()
delete RemoveItem(i);
}
// #pragma mark -
// _UpdateMarks
void
PathListView::_UpdateMarks()
{
int32 count = CountItems();
if (fCurrentShape) {
// enable display of marks and mark items whoes
// path is contained in fCurrentShape
for (int32 i = 0; i < count; i++) {
PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(i));
if (!item)
continue;
item->SetMarkEnabled(true);
item->SetMarked(fCurrentShape->Paths()->HasPath(item->path));
}
} else {
// disable display of marks
for (int32 i = 0; i < count; i++) {
PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(i));
if (!item)
continue;
item->SetMarkEnabled(false);
}
}
Invalidate();
}
// _SetPathMarked
void
PathListView::_SetPathMarked(VectorPath* path, bool marked)
{
if (PathListItem* item = _ItemForPath(path)) {
item->SetMarked(marked);
}
}

View File

@ -12,9 +12,13 @@
#include "ListViews.h"
#include "PathContainer.h"
class CommandStack;
class VectorPath;
class PathListItem;
class Selection;
class Shape;
class ShapeContainer;
class ShapePathListener;
class PathListView : public SimpleListView,
public PathContainerListener {
@ -28,6 +32,7 @@ class PathListView : public SimpleListView,
// SimpleListView interface
virtual void SelectionChanged();
virtual void MouseDown(BPoint where);
virtual void MessageReceived(BMessage* message);
virtual void MakeDragMessage(BMessage* message) const;
@ -48,8 +53,13 @@ class PathListView : public SimpleListView,
// PathListView
void SetPathContainer(PathContainer* container);
void SetShapeContainer(ShapeContainer* container);
void SetSelection(Selection* selection);
void SetCurrentShape(Shape* shape);
Shape* CurrentShape() const
{ return fCurrentShape; }
private:
bool _AddPath(VectorPath* path);
bool _RemovePath(VectorPath* path);
@ -57,10 +67,22 @@ class PathListView : public SimpleListView,
PathListItem* _ItemForPath(VectorPath* path) const;
void _MakeEmpty();
friend class ShapePathListener;
void _UpdateMarks();
void _SetPathMarked(VectorPath* path, bool marked);
BMessage* fMessage;
PathContainer* fPathContainer;
ShapeContainer* fShapeContainer;
Selection* fSelection;
CommandStack* fCommandStack;
Shape* fCurrentShape;
// those path items will be marked that
// are referenced by this shape
ShapePathListener* fShapePathListener;
};
#endif // PATH_LIST_VIEW_H

View File

@ -120,9 +120,9 @@ ShapeListView::SelectionChanged()
// TODO: single selection versus multiple selection
ShapeListItem* item = dynamic_cast<ShapeListItem*>(ItemAt(CurrentSelection(0)));
if (item && fMessage) {
if (fMessage) {
BMessage message(*fMessage);
message.AddPointer("shape", (void*)item->shape);
message.AddPointer("shape", item ? (void*)item->shape : NULL);
Invoke(&message);
}

View File

@ -44,11 +44,9 @@ void
PathSource::Update()
{
fAGGPath.remove_all();
int32 count = fPaths->CountPaths();
for (int32 i = 0; i < count; i++) {
VectorPath* path = fPaths->PathAtFast(i);
fAGGPath.start_new_path();
path->GetAGGPathStorage(fAGGPath);
}
for (int32 i = 0; i < count; i++)
fPaths->PathAtFast(i)->GetAGGPathStorage(fAGGPath);
}