* work in progress on GUI classes

- added IconView which just uses an IconRenderer to display a preview
    of the icon at a certain size
  - PathListView and ShapeListView (very much work in progress)
* actually had the gamma correction applied in the wrong direction...
  now the anti-aliasing looks as smooth as planned
* added SetName() and Name() to Shape and VectorPath... will be in a
  common base class later on


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17988 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-06-30 21:39:18 +00:00
parent deca617c6b
commit cfda5dd75b
17 changed files with 1324 additions and 204 deletions
+99
View File
@@ -0,0 +1,99 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "IconView.h"
#include <Bitmap.h>
#include "ui_defines.h"
#include "IconRenderer.h"
// constructor
IconView::IconView(BRect frame, const char* name)
: BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
fBitmap(new BBitmap(frame.OffsetToCopy(B_ORIGIN), 0, B_RGB32)),
fIcon(NULL),
fRenderer(new IconRenderer(fBitmap)),
fDirtyIconArea(fBitmap->Bounds()),
fScale((frame.Width() + 1.0) / 64.0)
{
fRenderer->SetScale(fScale);
}
// destructor
IconView::~IconView()
{
SetIcon(NULL);
delete fRenderer;
delete fBitmap;
}
// #pragma mark -
// AttachedToWindow
void
IconView::AttachedToWindow()
{
SetViewColor(B_TRANSPARENT_COLOR);
}
// Draw
void
IconView::Draw(BRect updateRect)
{
if (fDirtyIconArea.IsValid()) {
fRenderer->Render(fDirtyIconArea);
fDirtyIconArea.Set(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
}
// icon
DrawBitmap(fBitmap, B_ORIGIN);
}
// #pragma mark -
// AreaInvalidated
void
IconView::AreaInvalidated(const BRect& area)
{
BRect scaledArea(area);
scaledArea.left *= fScale;
scaledArea.top *= fScale;
scaledArea.right *= fScale;
scaledArea.bottom *= fScale;
if (fDirtyIconArea.Contains(scaledArea))
return;
fDirtyIconArea = fDirtyIconArea | scaledArea;
Invalidate(scaledArea);
}
// #pragma mark -
// SetIcon
void
IconView::SetIcon(Icon* icon)
{
if (fIcon == icon)
return;
if (fIcon)
fIcon->RemoveListener(this);
fIcon = icon;
fRenderer->SetIcon(icon);
if (fIcon)
fIcon->AddListener(this);
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef ICON_VIEW_H
#define ICON_VIEW_H
#include <View.h>
#include "Icon.h"
class BBitmap;
class IconRenderer;
class IconView : public BView,
public IconListener {
public:
IconView(BRect frame, const char* name);
virtual ~IconView();
// BView interface
virtual void AttachedToWindow();
virtual void Draw(BRect updateRect);
// IconListener interface
virtual void AreaInvalidated(const BRect& area);
// IconView
void SetIcon(Icon* icon);
private:
BBitmap* fBitmap;
Icon* fIcon;
IconRenderer* fRenderer;
BRect fDirtyIconArea;
double fScale;
};
#endif // ICON_VIEW_H
+5
View File
@@ -41,10 +41,12 @@ Application Icon-O-Matic :
# generic/command # generic/command
Command.cpp Command.cpp
CommandStack.cpp CommandStack.cpp
# generic/selection
Selectable.cpp Selectable.cpp
Selection.cpp Selection.cpp
# generic/gui # generic/gui
Group.cpp Group.cpp
ListViews.cpp
SwatchView.cpp SwatchView.cpp
# generic/gui/panel # generic/gui/panel
Panel.cpp Panel.cpp
@@ -70,6 +72,8 @@ Application Icon-O-Matic :
support.cpp support.cpp
support_ui.cpp support_ui.cpp
# gui # gui
PathListView.cpp
ShapeListView.cpp
SwatchGroup.cpp SwatchGroup.cpp
# gradient # gradient
Gradient.cpp Gradient.cpp
@@ -98,6 +102,7 @@ Application Icon-O-Matic :
# #
CanvasView.cpp CanvasView.cpp
IconEditorApp.cpp IconEditorApp.cpp
IconView.cpp
main.cpp main.cpp
MainWindow.cpp MainWindow.cpp
: be libagg.a : be libagg.a
+69 -2
View File
@@ -11,10 +11,14 @@
#include <stdio.h> #include <stdio.h>
#include <Message.h> #include <Message.h>
#include <ScrollView.h>
#include "Document.h" #include "Document.h"
#include "CanvasView.h" #include "CanvasView.h"
#include "IconEditorApp.h" #include "IconEditorApp.h"
#include "IconView.h"
#include "PathListView.h"
#include "ShapeListView.h"
#include "SwatchGroup.h" #include "SwatchGroup.h"
// TODO: just for testing // TODO: just for testing
@@ -25,6 +29,7 @@
#include "PathManipulator.h" #include "PathManipulator.h"
#include "Shape.h" #include "Shape.h"
#include "ShapeContainer.h" #include "ShapeContainer.h"
#include "ShapeListView.h"
#include "StrokeTransformer.h" #include "StrokeTransformer.h"
#include "Style.h" #include "Style.h"
#include "StyleManager.h" #include "StyleManager.h"
@@ -36,8 +41,7 @@ MainWindow::MainWindow(IconEditorApp* app, Document* document)
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS), B_ASYNCHRONOUS_CONTROLS),
fApp(app), fApp(app),
fDocument(document), fDocument(document)
fCanvasView(NULL)
{ {
_Init(); _Init();
} }
@@ -87,6 +91,19 @@ MainWindow::_Init()
// fCanvasView->SetSelection(fDocument->Selection()); // fCanvasView->SetSelection(fDocument->Selection());
fCanvasView->SetIcon(fDocument->Icon()); fCanvasView->SetIcon(fDocument->Icon());
fPathListView->SetPathContainer(fDocument->Icon()->Paths());
// fPathListView->SetCommandStack(fDocument->CommandStack());
// fPathListView->SetSelection(fDocument->Selection());
fShapeListView->SetShapeContainer(fDocument->Icon()->Shapes());
// fShapeListView->SetCommandStack(fDocument->CommandStack());
// fShapeListView->SetSelection(fDocument->Selection());
fIconPreview16->SetIcon(fDocument->Icon());
fIconPreview32->SetIcon(fDocument->Icon());
// fIconPreview48->SetIcon(fDocument->Icon());
fIconPreview64->SetIcon(fDocument->Icon());
// TODO: for testing only: // TODO: for testing only:
MultipleManipulatorState* state = new MultipleManipulatorState(fCanvasView); MultipleManipulatorState* state = new MultipleManipulatorState(fCanvasView);
fCanvasView->SetState(state); fCanvasView->SetState(state);
@@ -112,6 +129,7 @@ MainWindow::_Init()
Shape* shape = new Shape(style2); Shape* shape = new Shape(style2);
shape->Paths()->AddPath(path); shape->Paths()->AddPath(path);
shape->SetName("Gradient");
fDocument->Icon()->Shapes()->AddShape(shape); fDocument->Icon()->Shapes()->AddShape(shape);
shape = new Shape(style1); shape = new Shape(style1);
@@ -121,6 +139,7 @@ MainWindow::_Init()
transformer->width(5.0); transformer->width(5.0);
shape->AppendTransformer(transformer); shape->AppendTransformer(transformer);
shape->SetName("Outline");
fDocument->Icon()->Shapes()->AddShape(shape); fDocument->Icon()->Shapes()->AddShape(shape);
Style* style3 = new Style(); Style* style3 = new Style();
@@ -137,6 +156,7 @@ MainWindow::_Init()
*transformer2 *= agg::trans_affine_scaling(0.8, 0.6); *transformer2 *= agg::trans_affine_scaling(0.8, 0.6);
shape->AppendTransformer(transformer2); shape->AppendTransformer(transformer2);
shape->SetName("Transformed");
fDocument->Icon()->Shapes()->AddShape(shape); fDocument->Icon()->Shapes()->AddShape(shape);
PathManipulator* pathManipulator = new PathManipulator(path); PathManipulator* pathManipulator = new PathManipulator(path);
@@ -157,7 +177,54 @@ MainWindow::_CreateGUI(BRect bounds)
fCanvasView = new CanvasView(bounds); fCanvasView = new CanvasView(bounds);
bounds.left = fSwatchGroup->Frame().right + 5;
bounds.top = fSwatchGroup->Frame().top + 5;
bounds.right = bounds.left + 15;
bounds.bottom = bounds.top + 15;
fIconPreview16 = new IconView(bounds, "icon preview 16");
bounds.OffsetBy(bounds.Width() + 6, 0);
bounds.right = bounds.left + 31;
bounds.bottom = bounds.top + 31;
fIconPreview32 = new IconView(bounds, "icon preview 32");
// bounds.OffsetBy(bounds.Width() + 6, 0);
// bounds.right = bounds.left + 47;
// bounds.bottom = bounds.top + 47;
// fIconPreview48 = new IconView(bounds, "icon preview 48");
bounds.OffsetBy(bounds.Width() + 6, 0);
bounds.right = bounds.left + 63;
bounds.bottom = bounds.top + 63;
fIconPreview64 = new IconView(bounds, "icon preview 64");
bounds.OffsetBy(bounds.Width() + 6, 0);
bounds.right = bounds.left + 100;
bounds.bottom = fCanvasView->Frame().top - 5.0;
fPathListView = new PathListView(bounds, "path list view");
bounds.OffsetBy(bounds.Width() + 6 + B_V_SCROLL_BAR_WIDTH, 0);
fShapeListView = new ShapeListView(bounds, "shape list view");
bg->AddChild(fSwatchGroup); bg->AddChild(fSwatchGroup);
bg->AddChild(fIconPreview16);
bg->AddChild(fIconPreview32);
// bg->AddChild(fIconPreview48);
bg->AddChild(fIconPreview64);
bg->AddChild(new BScrollView("path list scroll view",
fPathListView,
B_FOLLOW_LEFT | B_FOLLOW_TOP,
0, false, true,
B_NO_BORDER));
bg->AddChild(new BScrollView("shape list scroll view",
fShapeListView,
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
0, false, true,
B_NO_BORDER));
bg->AddChild(fCanvasView); bg->AddChild(fCanvasView);
return bg; return bg;
+11
View File
@@ -14,6 +14,9 @@
class CanvasView; class CanvasView;
class Document; class Document;
class IconEditorApp; class IconEditorApp;
class IconView;
class PathListView;
class ShapeListView;
class SwatchGroup; class SwatchGroup;
class ViewState; class ViewState;
@@ -36,6 +39,14 @@ class MainWindow : public BWindow {
CanvasView* fCanvasView; CanvasView* fCanvasView;
SwatchGroup* fSwatchGroup; SwatchGroup* fSwatchGroup;
IconView* fIconPreview16;
IconView* fIconPreview32;
IconView* fIconPreview48;
IconView* fIconPreview64;
PathListView* fPathListView;
ShapeListView* fShapeListView;
// TODO: for testing only... // TODO: for testing only...
ViewState* fState; ViewState* fState;
}; };
@@ -103,6 +103,7 @@ StyleHandler::generate_span(agg::rgba8* span, int x, int y,
agg::trans_affine transformation; agg::trans_affine transformation;
// TODO: construct the gradient transformation here // TODO: construct the gradient transformation here
// remember to invert() it!
switch (gradient->Type()) { switch (gradient->Type()) {
case GRADIENT_LINEAR: { case GRADIENT_LINEAR: {
@@ -191,7 +192,9 @@ IconRenderer::IconRenderer(BBitmap* bitmap)
fBinaryScanline(), fBinaryScanline(),
fSpanAllocator(), fSpanAllocator(),
fRasterizer() fRasterizer(),
fGlobalTransform()
{ {
// attach rendering buffer to bitmap // attach rendering buffer to bitmap
fRenderingBuffer.attach((uint8*)bitmap->Bits(), fRenderingBuffer.attach((uint8*)bitmap->Bits(),
@@ -230,6 +233,14 @@ IconRenderer::Render(const BRect& area)
_Render(fBitmap->Bounds() & area); _Render(fBitmap->Bounds() & area);
} }
//SetScale
void
IconRenderer::SetScale(double scale)
{
fGlobalTransform.reset();
fGlobalTransform.multiply(agg::trans_affine_scaling(scale));
}
// #pragma mark - // #pragma mark -
// _Render // _Render
@@ -247,17 +258,23 @@ IconRenderer::_Render(const BRect& r)
(int)ceilf(r.bottom)); (int)ceilf(r.bottom));
fRasterizer.reset(); fRasterizer.reset();
// iterate over shapes in icon and // iterate over the shapes in the icon,
// add the vector paths to the rasterizer // add the vector paths to the rasterizer
// and associate the shapes style // and associate each shapes style
int32 shapeCount = fIcon->Shapes()->CountShapes(); int32 shapeCount = fIcon->Shapes()->CountShapes();
for (int32 s = 0; s < shapeCount; s++) { for (int32 i = 0; i < shapeCount; i++) {
Shape* shape = fIcon->Shapes()->ShapeAtFast(s); Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
int32 styleIndex = fStyles->IndexOf(shape->Style()); int32 styleIndex = fStyles->IndexOf(shape->Style());
fRasterizer.styles(styleIndex, -1); fRasterizer.styles(styleIndex, -1);
if (fGlobalTransform.is_identity()) {
fRasterizer.add_path(shape->VertexSource()); fRasterizer.add_path(shape->VertexSource());
} else {
agg::conv_transform<VertexSource, Transformation>
scaledPath(shape->VertexSource(), fGlobalTransform);
fRasterizer.add_path(scaledPath);
}
} }
StyleHandler styleHandler(fStyles, fGammaTable); StyleHandler styleHandler(fStyles, fGammaTable);
@@ -269,6 +286,7 @@ IconRenderer::_Render(const BRect& r)
fSpanAllocator, fSpanAllocator,
styleHandler); styleHandler);
fPixelFormat.apply_gamma_dir(fGammaTable); if (fGammaTable.gamma() != 1.0)
fPixelFormat.apply_gamma_inv(fGammaTable);
} }
+13 -6
View File
@@ -10,13 +10,14 @@
#define ICON_RENDERER_H #define ICON_RENDERER_H
#include "agg_gamma_lut.h" #include "agg_gamma_lut.h"
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_compound_aa.h"
#include "agg_scanline_u.h"
#include "agg_scanline_bin.h"
#include "agg_renderer_scanline.h"
#include "agg_span_allocator.h"
#include "agg_pixfmt_rgba.h" #include "agg_pixfmt_rgba.h"
#include "agg_rasterizer_compound_aa.h"
#include "agg_rendering_buffer.h"
#include "agg_renderer_scanline.h"
#include "agg_scanline_bin.h"
#include "agg_scanline_u.h"
#include "agg_span_allocator.h"
#include "agg_trans_affine.h"
class BBitmap; class BBitmap;
class Icon; class Icon;
@@ -37,6 +38,8 @@ typedef agg::span_allocator<agg::rgba8> SpanAllocator;
typedef agg::rasterizer_compound_aa typedef agg::rasterizer_compound_aa
<agg::rasterizer_sl_clip_dbl> CompoundRasterizer; <agg::rasterizer_sl_clip_dbl> CompoundRasterizer;
typedef agg::trans_affine Transformation;
class IconRenderer { class IconRenderer {
public: public:
IconRenderer(BBitmap* bitmap); IconRenderer(BBitmap* bitmap);
@@ -47,6 +50,8 @@ class IconRenderer {
void Render(); void Render();
void Render(const BRect& area); void Render(const BRect& area);
void SetScale(double scale);
private: private:
void _Render(const BRect& area); void _Render(const BRect& area);
@@ -67,6 +72,8 @@ class IconRenderer {
SpanAllocator fSpanAllocator; SpanAllocator fSpanAllocator;
CompoundRasterizer fRasterizer; CompoundRasterizer fRasterizer;
Transformation fGlobalTransform;
}; };
#endif // ICON_RENDERER_H #endif // ICON_RENDERER_H
+16 -21
View File
@@ -240,7 +240,8 @@ DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
} }
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true); BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
if (dragBitmap && dragBitmap->IsValid()) { if (dragBitmap && dragBitmap->IsValid()) {
if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) { if (BView *v = new BView(dragBitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW)) {
dragBitmap->AddChild(v); dragBitmap->AddChild(v);
dragBitmap->Lock(); dragBitmap->Lock();
BRect itemBounds(dragRect) ; BRect itemBounds(dragRect) ;
@@ -628,27 +629,23 @@ DragSortableListView::MoveItems( BList& items, int32 index )
// removal // removal
BList removedItems; BList removedItems;
int32 count = items.CountItems(); int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ ) for (int32 i = 0; i < count; i++) {
{
BListItem* item = (BListItem*)items.ItemAt(i); BListItem* item = (BListItem*)items.ItemAt(i);
int32 removeIndex = IndexOf(item); int32 removeIndex = IndexOf(item);
if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) ) if (RemoveItem(item) && removedItems.AddItem((void*)item)) {
{
if (removeIndex < index) if (removeIndex < index)
index--; index--;
} }
// else ??? -> blow up // else ??? -> blow up
} }
for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ ) for (int32 i = 0;
{ BListItem* item = (BListItem*)removedItems.ItemAt(i); i++) {
if ( AddItem( item, index ) ) if (AddItem(item, index)) {
{
// after we're done, the newly inserted items will be selected // after we're done, the newly inserted items will be selected
Select(index, true); Select(index, true);
// next items will be inserted after this one // next items will be inserted after this one
index++; index++;
} } else
else
delete item; delete item;
} }
} }
@@ -664,22 +661,19 @@ DragSortableListView::CopyItems( BList& items, int32 index )
// need to be cloned // need to be cloned
BList clonedItems; BList clonedItems;
int32 count = items.CountItems(); int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ ) for (int32 i = 0; i < count; i++) {
{
BListItem* item = CloneItem(IndexOf((BListItem*)items.ItemAt(i))); BListItem* item = CloneItem(IndexOf((BListItem*)items.ItemAt(i)));
if (item && !clonedItems.AddItem((void*)item)) if (item && !clonedItems.AddItem((void*)item))
delete item; delete item;
} }
for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ ) for (int32 i = 0;
{ BListItem* item = (BListItem*)clonedItems.ItemAt(i); i++) {
if ( AddItem( item, index ) ) if (AddItem(item, index)) {
{
// after we're done, the newly inserted items will be selected // after we're done, the newly inserted items will be selected
Select(index, true); Select(index, true);
// next items will be inserted after this one // next items will be inserted after this one
index++; index++;
} } else
else
delete item; delete item;
} }
} }
@@ -689,8 +683,7 @@ void
DragSortableListView::RemoveItemList(BList& items) DragSortableListView::RemoveItemList(BList& items)
{ {
int32 count = items.CountItems(); int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ ) for (int32 i = 0; i < count; i++) {
{
BListItem* item = (BListItem*)items.ItemAt(i); BListItem* item = (BListItem*)items.ItemAt(i);
if (RemoveItem(item)) if (RemoveItem(item))
delete item; delete item;
@@ -827,6 +820,7 @@ SimpleListView::~SimpleListView()
delete fSelectionChangeMessage; delete fSelectionChangeMessage;
} }
#ifdef LIB_LAYOUT
// layoutprefs // layoutprefs
minimax minimax
SimpleListView::layoutprefs() SimpleListView::layoutprefs()
@@ -847,6 +841,7 @@ SimpleListView::layout(BRect frame)
ResizeTo(frame.Width(), frame.Height()); ResizeTo(frame.Width(), frame.Height());
return Frame(); return Frame();
} }
#endif // LIB_LAYOUT
// MessageReceived // MessageReceived
void void
@@ -13,7 +13,9 @@
#include <ListView.h> #include <ListView.h>
#include <Message.h> #include <Message.h>
#ifdef LIB_LAYOUT
# include <layout.h> # include <layout.h>
#endif
#include "MouseWheelFilter.h" #include "MouseWheelFilter.h"
@@ -148,7 +150,11 @@ class DragSortableListView : public MouseWheelTarget,
}; };
// SimpleListView // SimpleListView
class SimpleListView : public MView, public DragSortableListView { class SimpleListView :
#ifdef LIB_LAYOUT
public MView,
#endif
public DragSortableListView {
public: public:
SimpleListView(BRect frame, SimpleListView(BRect frame,
BMessage* selectionChangeMessage = NULL); BMessage* selectionChangeMessage = NULL);
@@ -164,10 +170,11 @@ class SimpleListView : public MView, public DragSortableListView {
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE); | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE);
~SimpleListView(); ~SimpleListView();
#ifdef LIB_LAYOUT
// MView // MView
virtual minimax layoutprefs(); virtual minimax layoutprefs();
virtual BRect layout(BRect frame); virtual BRect layout(BRect frame);
#endif
// BListView // BListView
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void SelectionChanged(); virtual void SelectionChanged();
+308
View File
@@ -0,0 +1,308 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "PathListView.h"
#include <stdio.h>
#include <Application.h>
#include <ListItem.h>
#include <Message.h>
#include <Mime.h>
#include <Window.h>
#include "VectorPath.h"
#include "Observer.h"
#include "Selection.h"
class PathListItem : public SimpleItem,
public Observer {
public:
PathListItem(VectorPath* p,
PathListView* listView)
: SimpleItem(""),
path(NULL),
fListView(listView)
{
SetPath(p);
}
virtual ~PathListItem()
{
SetPath(NULL);
}
virtual void ObjectChanged(const Observable* object)
{
UpdateText();
}
void SetPath(VectorPath* p)
{
if (p == path)
return;
if (path) {
path->RemoveObserver(this);
path->Release();
}
path = p;
if (path) {
path->Acquire();
path->AddObserver(this);
UpdateText();
}
}
void UpdateText()
{
SetText(path->Name());
// :-/
if (fListView->LockLooper()) {
fListView->InvalidateItem(
fListView->IndexOf(this));
fListView->UnlockLooper();
}
}
VectorPath* path;
private:
PathListView* fListView;
};
// #pragma mark -
// constructor
PathListView::PathListView(BRect frame,
const char* name,
BMessage* message, BHandler* target)
: SimpleListView(frame, name,
NULL, B_SINGLE_SELECTION_LIST),
fMessage(message),
fPathContainer(NULL),
fSelection(NULL)
{
SetTarget(target);
}
// destructor
PathListView::~PathListView()
{
_MakeEmpty();
delete fMessage;
if (fPathContainer)
fPathContainer->RemoveListener(this);
}
// SelectionChanged
void
PathListView::SelectionChanged()
{
// NOTE: single selection list
PathListItem* item
= dynamic_cast<PathListItem*>(ItemAt(CurrentSelection(0)));
if (item && fMessage) {
BMessage message(*fMessage);
message.AddPointer("path", (void*)item->path);
Invoke(&message);
}
// modify global Selection
if (!fSelection)
return;
// if (item)
// fSelection->Select(item->path);
// else
// fSelection->DeselectAll();
}
// MessageReceived
void
PathListView::MessageReceived(BMessage* message)
{
SimpleListView::MessageReceived(message);
}
// MakeDragMessage
void
PathListView::MakeDragMessage(BMessage* message) const
{
}
// AcceptDragMessage
bool
PathListView::AcceptDragMessage(const BMessage* message) const
{
return false;
}
// SetDropTargetRect
void
PathListView::SetDropTargetRect(const BMessage* message, BPoint where)
{
}
// MoveItems
void
PathListView::MoveItems(BList& items, int32 toIndex)
{
}
// CopyItems
void
PathListView::CopyItems(BList& items, int32 toIndex)
{
}
// RemoveItemList
void
PathListView::RemoveItemList(BList& indices)
{
// TODO: allow removing items
}
// CloneItem
BListItem*
PathListView::CloneItem(int32 index) const
{
if (PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(index))) {
return new PathListItem(item->path,
const_cast<PathListView*>(this));
}
return NULL;
}
// #pragma mark -
// PathAdded
void
PathListView::PathAdded(VectorPath* path)
{
// NOTE: we are in the thread that messed with the
// ShapeContainer, so no need to lock the
// container, when this is changed to asynchronous
// notifications, then it would need to be read-locked!
if (!LockLooper())
return;
// NOTE: shapes are always added at the end
// of the list, so the sorting is synced...
_AddPath(path);
UnlockLooper();
}
// PathRemoved
void
PathListView::PathRemoved(VectorPath* path)
{
// NOTE: we are in the thread that messed with the
// ShapeContainer, so no need to lock the
// container, when this is changed to asynchronous
// notifications, then it would need to be read-locked!
if (!LockLooper())
return;
// NOTE: we're only interested in VectorPath objects
_RemovePath(path);
UnlockLooper();
}
// #pragma mark -
// SetPathContainer
void
PathListView::SetPathContainer(PathContainer* container)
{
if (fPathContainer == container)
return;
// detach from old container
if (fPathContainer)
fPathContainer->RemoveListener(this);
_MakeEmpty();
fPathContainer = container;
if (!fPathContainer)
return;
fPathContainer->AddListener(this);
// sync
// if (!fPathContainer->ReadLock())
// return;
int32 count = fPathContainer->CountPaths();
for (int32 i = 0; i < count; i++)
_AddPath(fPathContainer->PathAtFast(i));
// fPathContainer->ReadUnlock();
}
// SetSelection
void
PathListView::SetSelection(Selection* selection)
{
fSelection = selection;
}
// #pragma mark -
// _AddPath
bool
PathListView::_AddPath(VectorPath* path)
{
if (path)
return AddItem(new PathListItem(path, this));
return false;
}
// _RemovePath
bool
PathListView::_RemovePath(VectorPath* path)
{
PathListItem* item = _ItemForPath(path);
if (item && RemoveItem(item)) {
delete item;
return true;
}
return false;
}
// _ItemForPath
PathListItem*
PathListView::_ItemForPath(VectorPath* path) const
{
for (int32 i = 0;
PathListItem* item = dynamic_cast<PathListItem*>(ItemAt(i));
i++) {
if (item->path == path)
return item;
}
return NULL;
}
// _MakeEmpty
void
PathListView::_MakeEmpty()
{
// NOTE: BListView::MakeEmpty() uses ScrollTo()
// for which the object needs to be attached to
// a BWindow.... :-(
int32 count = CountItems();
for (int32 i = count - 1; i >= 0; i--)
delete RemoveItem(i);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef PATH_LIST_VIEW_H
#define PATH_LIST_VIEW_H
#include "ListViews.h"
#include "PathContainer.h"
class VectorPath;
class PathListItem;
class Selection;
class PathListView : public SimpleListView,
public PathContainerListener {
public:
PathListView(BRect frame,
const char* name,
BMessage* selectionMessage = NULL,
BHandler* target = NULL);
virtual ~PathListView();
// SimpleListView interface
virtual void SelectionChanged();
virtual void MessageReceived(BMessage* message);
virtual void MakeDragMessage(BMessage* message) const;
virtual bool AcceptDragMessage(const BMessage* message) const;
virtual void SetDropTargetRect(const BMessage* message,
BPoint where);
virtual void MoveItems(BList& items, int32 toIndex);
virtual void CopyItems(BList& items, int32 toIndex);
virtual void RemoveItemList(BList& indices);
virtual BListItem* CloneItem(int32 atIndex) const;
// ShapeContainerListener interface
virtual void PathAdded(VectorPath* path);
virtual void PathRemoved(VectorPath* path);
// PathListView
void SetPathContainer(PathContainer* container);
void SetSelection(Selection* selection);
private:
bool _AddPath(VectorPath* path);
bool _RemovePath(VectorPath* path);
PathListItem* _ItemForPath(VectorPath* path) const;
void _MakeEmpty();
BMessage* fMessage;
PathContainer* fPathContainer;
Selection* fSelection;
};
#endif // PATH_LIST_VIEW_H
+340
View File
@@ -0,0 +1,340 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#include "ShapeListView.h"
#include <stdio.h>
#include <Application.h>
#include <ListItem.h>
#include <Message.h>
#include <Mime.h>
#include <Window.h>
#include "Shape.h"
#include "Observer.h"
#include "Selection.h"
class ShapeListItem : public SimpleItem,
public Observer {
public:
ShapeListItem(Shape* s,
ShapeListView* listView)
: SimpleItem(""),
shape(NULL),
fListView(listView)
{
SetClip(s);
}
virtual ~ShapeListItem()
{
SetClip(NULL);
}
virtual void ObjectChanged(const Observable* object)
{
UpdateText();
}
void SetClip(Shape* s)
{
if (s == shape)
return;
if (shape) {
shape->RemoveObserver(this);
shape->Release();
}
shape = s;
if (shape) {
shape->Acquire();
shape->AddObserver(this);
UpdateText();
}
}
void UpdateText()
{
SetText(shape->Name());
// :-/
if (fListView->LockLooper()) {
fListView->InvalidateItem(
fListView->IndexOf(this));
fListView->UnlockLooper();
}
}
Shape* shape;
private:
ShapeListView* fListView;
};
// #pragma mark -
enum {
MSG_DRAG_SHAPE = 'drgs',
};
// constructor
ShapeListView::ShapeListView(BRect frame,
const char* name,
BMessage* message, BHandler* target)
: SimpleListView(frame, name,
NULL, B_MULTIPLE_SELECTION_LIST),
fMessage(message),
fShapeContainer(NULL),
fSelection(NULL)
{
SetDragCommand(MSG_DRAG_SHAPE);
SetTarget(target);
}
// destructor
ShapeListView::~ShapeListView()
{
_MakeEmpty();
delete fMessage;
if (fShapeContainer)
fShapeContainer->RemoveListener(this);
}
// SelectionChanged
void
ShapeListView::SelectionChanged()
{
// TODO: single selection versus multiple selection
ShapeListItem* item = dynamic_cast<ShapeListItem*>(ItemAt(CurrentSelection(0)));
if (item && fMessage) {
BMessage message(*fMessage);
message.AddPointer("shape", (void*)item->shape);
Invoke(&message);
}
// modify global Selection
if (!fSelection)
return;
if (item)
fSelection->Select(item->shape);
else
fSelection->DeselectAll();
}
// MessageReceived
void
ShapeListView::MessageReceived(BMessage* message)
{
SimpleListView::MessageReceived(message);
}
// MakeDragMessage
void
ShapeListView::MakeDragMessage(BMessage* message) const
{
SimpleListView::MakeDragMessage(message);
message->AddPointer("container", fShapeContainer);
int32 count = CountItems();
for (int32 i = 0; i < count; i++) {
ShapeListItem* item = dynamic_cast<ShapeListItem*>(ItemAt(CurrentSelection(i)));
if (item) {
message->AddPointer("shape", (void*)item->shape);
} else
break;
}
// message->AddInt32("be:actions", B_COPY_TARGET);
// message->AddInt32("be:actions", B_TRASH_TARGET);
//
// message->AddString("be:types", B_FILE_MIME_TYPE);
//// message->AddString("be:filetypes", "");
//// message->AddString("be:type_descriptions", "");
//
// message->AddString("be:clip_name", item->shape->Name());
//
// message->AddString("be:originator", "Icon-O-Matic");
// message->AddPointer("be:originator_data", (void*)item->shape);
}
// AcceptDragMessage
bool
ShapeListView::AcceptDragMessage(const BMessage* message) const
{
return SimpleListView::AcceptDragMessage(message);
}
// SetDropTargetRect
void
ShapeListView::SetDropTargetRect(const BMessage* message, BPoint where)
{
SimpleListView::SetDropTargetRect(message, where);
}
// MoveItems
void
ShapeListView::MoveItems(BList& items, int32 toIndex)
{
SimpleListView::MoveItems(items, toIndex);
}
// CopyItems
void
ShapeListView::CopyItems(BList& items, int32 toIndex)
{
MoveItems(items, toIndex);
// copy operation not allowed -> ?!?
// TODO: what about clips that reference the same file but
// with different "in/out points"
}
// RemoveItemList
void
ShapeListView::RemoveItemList(BList& indices)
{
// TODO: allow removing items
}
// CloneItem
BListItem*
ShapeListView::CloneItem(int32 index) const
{
if (ShapeListItem* item = dynamic_cast<ShapeListItem*>(ItemAt(index))) {
return new ShapeListItem(item->shape,
const_cast<ShapeListView*>(this));
}
return NULL;
}
// #pragma mark -
// ShapeAdded
void
ShapeListView::ShapeAdded(Shape* shape)
{
// NOTE: we are in the thread that messed with the
// ShapeContainer, so no need to lock the
// container, when this is changed to asynchronous
// notifications, then it would need to be read-locked!
if (!LockLooper())
return;
// NOTE: shapes are always added at the end
// of the list, so the sorting is synced...
_AddShape(shape);
UnlockLooper();
}
// ShapeRemoved
void
ShapeListView::ShapeRemoved(Shape* shape)
{
// NOTE: we are in the thread that messed with the
// ShapeContainer, so no need to lock the
// container, when this is changed to asynchronous
// notifications, then it would need to be read-locked!
if (!LockLooper())
return;
// NOTE: we're only interested in Shape objects
_RemoveShape(shape);
UnlockLooper();
}
// #pragma mark -
// SetShapeContainer
void
ShapeListView::SetShapeContainer(ShapeContainer* container)
{
if (fShapeContainer == container)
return;
// detach from old container
if (fShapeContainer)
fShapeContainer->RemoveListener(this);
_MakeEmpty();
fShapeContainer = container;
if (!fShapeContainer)
return;
fShapeContainer->AddListener(this);
// sync
// if (!fShapeContainer->ReadLock())
// return;
int32 count = fShapeContainer->CountShapes();
for (int32 i = 0; i < count; i++)
_AddShape(fShapeContainer->ShapeAtFast(i));
// fShapeContainer->ReadUnlock();
}
// SetSelection
void
ShapeListView::SetSelection(Selection* selection)
{
fSelection = selection;
}
// #pragma mark -
// _AddShape
bool
ShapeListView::_AddShape(Shape* shape)
{
if (shape)
return AddItem(new ShapeListItem(shape, this));
return false;
}
// _RemoveShape
bool
ShapeListView::_RemoveShape(Shape* shape)
{
ShapeListItem* item = _ItemForShape(shape);
if (item && RemoveItem(item)) {
delete item;
return true;
}
return false;
}
// _ItemForShape
ShapeListItem*
ShapeListView::_ItemForShape(Shape* shape) const
{
for (int32 i = 0;
ShapeListItem* item = dynamic_cast<ShapeListItem*>(ItemAt(i));
i++) {
if (item->shape == shape)
return item;
}
return NULL;
}
// _MakeEmpty
void
ShapeListView::_MakeEmpty()
{
// NOTE: BListView::MakeEmpty() uses ScrollTo()
// for which the object needs to be attached to
// a BWindow.... :-(
int32 count = CountItems();
for (int32 i = count - 1; i >= 0; i--)
delete RemoveItem(i);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
#ifndef SHAPE_LIST_VIEW_H
#define SHAPE_LIST_VIEW_H
#include "ListViews.h"
#include "ShapeContainer.h"
class Shape;
class ShapeListItem;
class Selection;
class ShapeListView : public SimpleListView,
public ShapeContainerListener {
public:
ShapeListView(BRect frame,
const char* name,
BMessage* selectionMessage = NULL,
BHandler* target = NULL);
virtual ~ShapeListView();
// SimpleListView interface
virtual void SelectionChanged();
virtual void MessageReceived(BMessage* message);
virtual void MakeDragMessage(BMessage* message) const;
virtual bool AcceptDragMessage(const BMessage* message) const;
virtual void SetDropTargetRect(const BMessage* message,
BPoint where);
virtual void MoveItems(BList& items, int32 toIndex);
virtual void CopyItems(BList& items, int32 toIndex);
virtual void RemoveItemList(BList& indices);
virtual BListItem* CloneItem(int32 atIndex) const;
// ShapeContainerListener interface
virtual void ShapeAdded(Shape* shape);
virtual void ShapeRemoved(Shape* shape);
// ShapeListView
void SetShapeContainer(ShapeContainer* container);
void SetSelection(Selection* selection);
private:
bool _AddShape(Shape* shape);
bool _RemoveShape(Shape* shape);
ShapeListItem* _ItemForShape(Shape* shape) const;
void _MakeEmpty();
BMessage* fMessage;
ShapeContainer* fShapeContainer;
Selection* fSelection;
};
#endif // SHAPE_LIST_VIEW_H
+34 -1
View File
@@ -23,7 +23,9 @@ Shape::Shape(::Style* style)
fPathSource(fPaths), fPathSource(fPaths),
fTransformers(4), fTransformers(4),
fLastBounds(0, 0, -1, -1) fLastBounds(0, 0, -1, -1),
fName("<shape>")
{ {
if (fPaths) if (fPaths)
fPaths->AddListener(this); fPaths->AddListener(this);
@@ -77,6 +79,16 @@ Shape::ObjectChanged(const Observable* object)
// #pragma mark - // #pragma mark -
// SelectedChanged
void
Shape::SelectedChanged()
{
// simply pass on the event for now
Notify();
}
// #pragma mark -
// InitCheck // InitCheck
status_t status_t
Shape::InitCheck() const Shape::InitCheck() const
@@ -158,3 +170,24 @@ Shape::AppendTransformer(Transformer* transformer)
Notify(); Notify();
return true; return true;
} }
// #pragma mark -
// SetName
void
Shape::SetName(const char* name)
{
if (fName == name)
return;
fName = name;
Notify();
}
// Name
const char*
Shape::Name() const
{
return fName.String();
}
+11
View File
@@ -3,18 +3,21 @@
#include <List.h> #include <List.h>
#include <Rect.h> #include <Rect.h>
#include <String.h>
#include "Observable.h" #include "Observable.h"
#include "Observer.h" #include "Observer.h"
#include "PathContainer.h" #include "PathContainer.h"
#include "PathSource.h" #include "PathSource.h"
#include "Referenceable.h" #include "Referenceable.h"
#include "Selectable.h"
class Style; class Style;
class Shape : public Observable, class Shape : public Observable,
public Observer, // observing all the paths public Observer, // observing all the paths
public Referenceable, public Referenceable,
public Selectable,
public PathContainerListener { public PathContainerListener {
public: public:
Shape(::Style* style); Shape(::Style* style);
@@ -27,6 +30,9 @@ class Shape : public Observable,
// Observer interface // Observer interface
virtual void ObjectChanged(const Observable* object); virtual void ObjectChanged(const Observable* object);
// Selectable interface
virtual void SelectedChanged();
// Shape // Shape
status_t InitCheck() const; status_t InitCheck() const;
@@ -45,6 +51,9 @@ class Shape : public Observable,
bool AppendTransformer( bool AppendTransformer(
Transformer* transformer); Transformer* transformer);
void SetName(const char* name);
const char* Name() const;
private: private:
PathContainer* fPaths; PathContainer* fPaths;
::Style* fStyle; ::Style* fStyle;
@@ -53,6 +62,8 @@ class Shape : public Observable,
BList fTransformers; BList fTransformers;
mutable BRect fLastBounds; mutable BRect fLastBounds;
BString fName;
}; };
#endif // SHAPE_H #endif // SHAPE_H
+42 -6
View File
@@ -78,7 +78,8 @@ VectorPath::VectorPath()
fClosed(false), fClosed(false),
fPointCount(0), fPointCount(0),
fAllocCount(0), fAllocCount(0),
fCachedBounds(0.0, 0.0, -1.0, -1.0) fCachedBounds(0.0, 0.0, -1.0, -1.0),
fName("<path>")
{ {
} }
@@ -90,7 +91,8 @@ VectorPath::VectorPath(const VectorPath& from)
fPath(NULL), fPath(NULL),
fPointCount(0), fPointCount(0),
fAllocCount(0), fAllocCount(0),
fCachedBounds(0.0, 0.0, -1.0, -1.0) fCachedBounds(0.0, 0.0, -1.0, -1.0),
fName()
{ {
*this = from; *this = from;
} }
@@ -104,7 +106,8 @@ VectorPath::VectorPath(const BMessage* archive)
fClosed(false), fClosed(false),
fPointCount(0), fPointCount(0),
fAllocCount(0), fAllocCount(0),
fCachedBounds(0.0, 0.0, -1.0, -1.0) fCachedBounds(0.0, 0.0, -1.0, -1.0),
fName()
{ {
if (archive) { if (archive) {
type_code typeFound; type_code typeFound;
@@ -130,6 +133,9 @@ VectorPath::VectorPath(const BMessage* archive)
if (archive->FindBool("path closed", &fClosed) < B_OK) { if (archive->FindBool("path closed", &fClosed) < B_OK) {
fClosed = false; fClosed = false;
} }
if (archive->FindString("name", &fName) < B_OK) {
fName = "<path>";
}
} }
} }
@@ -155,6 +161,7 @@ VectorPath::operator=(const VectorPath& from)
fPointCount = 0; fPointCount = 0;
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0); fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
} }
fName = from.fName;
return *this; return *this;
} }
@@ -171,7 +178,9 @@ status_t
VectorPath::Archive(BMessage* into, bool deep) const VectorPath::Archive(BMessage* into, bool deep) const
{ {
status_t ret = BArchivable::Archive(into, deep); status_t ret = BArchivable::Archive(into, deep);
if (ret >= B_OK) { if (ret < B_OK)
return ret;
if (fPointCount > 0) { if (fPointCount > 0) {
// improve BMessage efficency by preallocating storage for all points // improve BMessage efficency by preallocating storage for all points
// with the first call // with the first call
@@ -203,14 +212,19 @@ VectorPath::Archive(BMessage* into, bool deep) const
} else { } else {
fprintf(stderr, "failed adding points!\n"); fprintf(stderr, "failed adding points!\n");
} }
if (ret >= B_OK) {
ret = into->AddString("name", fName.String());
} else {
fprintf(stderr, "failed adding close!\n");
}
if (ret < B_OK) { if (ret < B_OK) {
fprintf(stderr, "failed adding closed!\n"); fprintf(stderr, "failed adding name!\n");
} }
// finish off // finish off
if (ret < B_OK) { if (ret < B_OK) {
ret = into->AddString("class", "VectorPath"); ret = into->AddString("class", "VectorPath");
} }
}
return ret; return ret;
} }
@@ -829,6 +843,28 @@ VectorPath::_SetPoint(int32 index, BPoint point)
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0); fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
} }
// #pragma mark -
// SetName
void
VectorPath::SetName(const char* name)
{
if (fName == name)
return;
fName = name;
Notify();
}
// Name
const char*
VectorPath::Name() const
{
return fName.String();
}
// #pragma mark -
// _SetPointCount // _SetPointCount
bool bool
VectorPath::_SetPointCount(int32 count) VectorPath::_SetPointCount(int32 count)
+7
View File
@@ -11,6 +11,7 @@
#include <Archivable.h> #include <Archivable.h>
#include <Rect.h> #include <Rect.h>
#include <String.h>
#include <agg_path_storage.h> #include <agg_path_storage.h>
@@ -121,6 +122,9 @@ class VectorPath : public BArchivable,
bool GetAGGPathStorage(agg::path_storage& path) const; bool GetAGGPathStorage(agg::path_storage& path) const;
void SetName(const char* name);
const char* Name() const;
private: private:
BRect _Bounds() const; BRect _Bounds() const;
void _SetPoint(int32 index, BPoint point); void _SetPoint(int32 index, BPoint point);
@@ -134,6 +138,9 @@ class VectorPath : public BArchivable,
int32 fAllocCount; int32 fAllocCount;
mutable BRect fCachedBounds; mutable BRect fCachedBounds;
// TODO: should this really be part of VectorPath?
BString fName;
}; };
#endif // VECTOR_PATH_H #endif // VECTOR_PATH_H