* 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

View File

@ -0,0 +1,99 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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);
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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

View File

@ -41,10 +41,12 @@ Application Icon-O-Matic :
# generic/command
Command.cpp
CommandStack.cpp
# generic/selection
Selectable.cpp
Selection.cpp
# generic/gui
Group.cpp
ListViews.cpp
SwatchView.cpp
# generic/gui/panel
Panel.cpp
@ -70,6 +72,8 @@ Application Icon-O-Matic :
support.cpp
support_ui.cpp
# gui
PathListView.cpp
ShapeListView.cpp
SwatchGroup.cpp
# gradient
Gradient.cpp
@ -98,6 +102,7 @@ Application Icon-O-Matic :
#
CanvasView.cpp
IconEditorApp.cpp
IconView.cpp
main.cpp
MainWindow.cpp
: be libagg.a

View File

@ -11,10 +11,14 @@
#include <stdio.h>
#include <Message.h>
#include <ScrollView.h>
#include "Document.h"
#include "CanvasView.h"
#include "IconEditorApp.h"
#include "IconView.h"
#include "PathListView.h"
#include "ShapeListView.h"
#include "SwatchGroup.h"
// TODO: just for testing
@ -25,6 +29,7 @@
#include "PathManipulator.h"
#include "Shape.h"
#include "ShapeContainer.h"
#include "ShapeListView.h"
#include "StrokeTransformer.h"
#include "Style.h"
#include "StyleManager.h"
@ -36,8 +41,7 @@ MainWindow::MainWindow(IconEditorApp* app, Document* document)
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS),
fApp(app),
fDocument(document),
fCanvasView(NULL)
fDocument(document)
{
_Init();
}
@ -87,6 +91,19 @@ MainWindow::_Init()
// fCanvasView->SetSelection(fDocument->Selection());
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:
MultipleManipulatorState* state = new MultipleManipulatorState(fCanvasView);
fCanvasView->SetState(state);
@ -112,6 +129,7 @@ MainWindow::_Init()
Shape* shape = new Shape(style2);
shape->Paths()->AddPath(path);
shape->SetName("Gradient");
fDocument->Icon()->Shapes()->AddShape(shape);
shape = new Shape(style1);
@ -121,6 +139,7 @@ MainWindow::_Init()
transformer->width(5.0);
shape->AppendTransformer(transformer);
shape->SetName("Outline");
fDocument->Icon()->Shapes()->AddShape(shape);
Style* style3 = new Style();
@ -137,6 +156,7 @@ MainWindow::_Init()
*transformer2 *= agg::trans_affine_scaling(0.8, 0.6);
shape->AppendTransformer(transformer2);
shape->SetName("Transformed");
fDocument->Icon()->Shapes()->AddShape(shape);
PathManipulator* pathManipulator = new PathManipulator(path);
@ -157,7 +177,54 @@ MainWindow::_CreateGUI(BRect 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(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);
return bg;

View File

@ -14,6 +14,9 @@
class CanvasView;
class Document;
class IconEditorApp;
class IconView;
class PathListView;
class ShapeListView;
class SwatchGroup;
class ViewState;
@ -36,6 +39,14 @@ class MainWindow : public BWindow {
CanvasView* fCanvasView;
SwatchGroup* fSwatchGroup;
IconView* fIconPreview16;
IconView* fIconPreview32;
IconView* fIconPreview48;
IconView* fIconPreview64;
PathListView* fPathListView;
ShapeListView* fShapeListView;
// TODO: for testing only...
ViewState* fState;
};

View File

@ -103,6 +103,7 @@ StyleHandler::generate_span(agg::rgba8* span, int x, int y,
agg::trans_affine transformation;
// TODO: construct the gradient transformation here
// remember to invert() it!
switch (gradient->Type()) {
case GRADIENT_LINEAR: {
@ -191,7 +192,9 @@ IconRenderer::IconRenderer(BBitmap* bitmap)
fBinaryScanline(),
fSpanAllocator(),
fRasterizer()
fRasterizer(),
fGlobalTransform()
{
// attach rendering buffer to bitmap
fRenderingBuffer.attach((uint8*)bitmap->Bits(),
@ -230,6 +233,14 @@ IconRenderer::Render(const BRect& area)
_Render(fBitmap->Bounds() & area);
}
//SetScale
void
IconRenderer::SetScale(double scale)
{
fGlobalTransform.reset();
fGlobalTransform.multiply(agg::trans_affine_scaling(scale));
}
// #pragma mark -
// _Render
@ -247,17 +258,23 @@ IconRenderer::_Render(const BRect& r)
(int)ceilf(r.bottom));
fRasterizer.reset();
// iterate over shapes in icon and
// iterate over the shapes in the icon,
// add the vector paths to the rasterizer
// and associate the shapes style
// and associate each shapes style
int32 shapeCount = fIcon->Shapes()->CountShapes();
for (int32 s = 0; s < shapeCount; s++) {
Shape* shape = fIcon->Shapes()->ShapeAtFast(s);
for (int32 i = 0; i < shapeCount; i++) {
Shape* shape = fIcon->Shapes()->ShapeAtFast(i);
int32 styleIndex = fStyles->IndexOf(shape->Style());
fRasterizer.styles(styleIndex, -1);
if (fGlobalTransform.is_identity()) {
fRasterizer.add_path(shape->VertexSource());
} else {
agg::conv_transform<VertexSource, Transformation>
scaledPath(shape->VertexSource(), fGlobalTransform);
fRasterizer.add_path(scaledPath);
}
}
StyleHandler styleHandler(fStyles, fGammaTable);
@ -269,6 +286,7 @@ IconRenderer::_Render(const BRect& r)
fSpanAllocator,
styleHandler);
fPixelFormat.apply_gamma_dir(fGammaTable);
if (fGammaTable.gamma() != 1.0)
fPixelFormat.apply_gamma_inv(fGammaTable);
}

View File

@ -10,13 +10,14 @@
#define ICON_RENDERER_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_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 Icon;
@ -37,6 +38,8 @@ typedef agg::span_allocator<agg::rgba8> SpanAllocator;
typedef agg::rasterizer_compound_aa
<agg::rasterizer_sl_clip_dbl> CompoundRasterizer;
typedef agg::trans_affine Transformation;
class IconRenderer {
public:
IconRenderer(BBitmap* bitmap);
@ -47,6 +50,8 @@ class IconRenderer {
void Render();
void Render(const BRect& area);
void SetScale(double scale);
private:
void _Render(const BRect& area);
@ -67,6 +72,8 @@ class IconRenderer {
SpanAllocator fSpanAllocator;
CompoundRasterizer fRasterizer;
Transformation fGlobalTransform;
};
#endif // ICON_RENDERER_H

View File

@ -32,8 +32,8 @@ enum {
};
// SimpleItem class
SimpleItem::SimpleItem( const char *name )
: BStringItem( name )
SimpleItem::SimpleItem(const char *name)
: BStringItem(name)
{
}
@ -47,13 +47,13 @@ SimpleItem::Draw(BView *owner, BRect frame, uint32 flags)
{
DrawBackground(owner, frame, flags);
// label
owner->SetHighColor( 0, 0, 0, 255 );
owner->SetHighColor(0, 0, 0, 255);
font_height fh;
owner->GetFontHeight( &fh );
owner->GetFontHeight(&fh);
const char* text = Text();
BString truncatedString( text );
owner->TruncateString( &truncatedString, B_TRUNCATE_MIDDLE,
frame.Width() - TEXT_OFFSET - 4.0 );
BString truncatedString(text);
owner->TruncateString(&truncatedString, B_TRUNCATE_MIDDLE,
frame.Width() - TEXT_OFFSET - 4.0);
float height = frame.Height();
float textHeight = fh.ascent + fh.descent;
BPoint textPoint;
@ -76,13 +76,13 @@ SimpleItem::DrawBackground(BView *owner, BRect frame, uint32 flags)
}
// figure out bg-color
rgb_color color = (rgb_color){ 255, 255, 255, 255 };
if ( flags & FLAGS_TINTED_LINE )
color = tint_color( color, 1.06 );
if (flags & FLAGS_TINTED_LINE)
color = tint_color(color, 1.06);
// background
if ( IsSelected() )
color = tint_color( color, B_DARKEN_2_TINT );
owner->SetLowColor( color );
owner->FillRect( frame, B_SOLID_LOW );
if (IsSelected())
color = tint_color(color, B_DARKEN_2_TINT);
owner->SetLowColor(color);
owner->FillRect(frame, B_SOLID_LOW);
}
// DragSortableListView class
@ -150,7 +150,7 @@ DragSortableListView::MakeFocus(bool focused)
*/
// Draw
void
DragSortableListView::Draw( BRect updateRect )
DragSortableListView::Draw(BRect updateRect)
{
int32 firstIndex = IndexOf(updateRect.LeftTop());
int32 lastIndex = IndexOf(updateRect.RightBottom());
@ -206,58 +206,59 @@ DragSortableListView::TargetedByScrollView(BScrollView* scrollView)
// InitiateDrag
bool
DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
DragSortableListView::InitiateDrag(BPoint point, int32 index, bool)
{
// supress drag&drop while an item is focused
if (fFocusedIndex >= 0)
return false;
bool success = false;
BListItem* item = ItemAt( CurrentSelection( 0 ) );
if ( !item ) {
BListItem* item = ItemAt(CurrentSelection(0));
if (!item) {
// workarround a timing problem
Select( index );
item = ItemAt( index );
Select(index);
item = ItemAt(index);
}
if ( item ) {
if (item) {
// create drag message
BMessage msg( fDragCommand );
MakeDragMessage( &msg );
BMessage msg(fDragCommand);
MakeDragMessage(&msg);
// figure out drag rect
float width = Bounds().Width();
BRect dragRect(0.0, 0.0, width, -1.0);
// figure out, how many items fit into our bitmap
int32 numItems;
bool fade = false;
for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) {
dragRect.bottom += ceilf( item->Height() ) + 1.0;
if ( dragRect.Height() > MAX_DRAG_HEIGHT ) {
for (numItems = 0; BListItem* item = ItemAt(CurrentSelection(numItems)); numItems++) {
dragRect.bottom += ceilf(item->Height()) + 1.0;
if (dragRect.Height() > MAX_DRAG_HEIGHT) {
fade = true;
dragRect.bottom = MAX_DRAG_HEIGHT;
numItems++;
break;
}
}
BBitmap* dragBitmap = new BBitmap( dragRect, B_RGB32, true );
if ( dragBitmap && dragBitmap->IsValid() ) {
if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) {
dragBitmap->AddChild( v );
BBitmap* dragBitmap = new BBitmap(dragRect, B_RGB32, true);
if (dragBitmap && dragBitmap->IsValid()) {
if (BView *v = new BView(dragBitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW)) {
dragBitmap->AddChild(v);
dragBitmap->Lock();
BRect itemBounds( dragRect) ;
BRect itemBounds(dragRect) ;
itemBounds.bottom = 0.0;
// let all selected items, that fit into our drag_bitmap, draw
for ( int32 i = 0; i < numItems; i++ ) {
int32 index = CurrentSelection( i );
BListItem* item = ItemAt( index );
itemBounds.bottom = itemBounds.top + ceilf( item->Height() );
if ( itemBounds.bottom > dragRect.bottom )
for (int32 i = 0; i < numItems; i++) {
int32 index = CurrentSelection(i);
BListItem* item = ItemAt(index);
itemBounds.bottom = itemBounds.top + ceilf(item->Height());
if (itemBounds.bottom > dragRect.bottom)
itemBounds.bottom = dragRect.bottom;
DrawListItem( v, index, itemBounds );
DrawListItem(v, index, itemBounds);
itemBounds.top = itemBounds.bottom + 1.0;
}
// make a black frame arround the edge
v->SetHighColor( 0, 0, 0, 255 );
v->StrokeRect( v->Bounds() );
v->SetHighColor(0, 0, 0, 255);
v->StrokeRect(v->Bounds());
v->Sync();
uint8 *bits = (uint8 *)dragBitmap->Bits();
@ -266,18 +267,18 @@ DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
int32 bpr = dragBitmap->BytesPerRow();
if (fade) {
for ( int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr ) {
for (int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
for ( int32 y = height - ALPHA / 2; y < height; y++, bits += bpr ) {
for (int32 y = height - ALPHA / 2; y < height; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = (height - y) << 1;
}
} else {
for ( int32 y = 0; y < height; y++, bits += bpr ) {
for (int32 y = 0; y < height; y++, bits += bpr) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
@ -290,9 +291,9 @@ DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
dragBitmap = NULL;
}
if (dragBitmap)
DragMessage( &msg, dragBitmap, B_OP_ALPHA, BPoint( 0.0, 0.0 ) );
DragMessage(&msg, dragBitmap, B_OP_ALPHA, BPoint(0.0, 0.0));
else
DragMessage( &msg, dragRect.OffsetToCopy( point ), this );
DragMessage(&msg, dragRect.OffsetToCopy(point), this);
_SetDragMessage(&msg);
success = true;
@ -302,10 +303,10 @@ DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
// WindowActivated
void
DragSortableListView::WindowActivated( bool active )
DragSortableListView::WindowActivated(bool active)
{
// workarround for buggy focus indication of BScrollView
if ( BView* view = Parent() )
if (BView* view = Parent())
view->Invalidate();
}
@ -315,26 +316,26 @@ DragSortableListView::MessageReceived(BMessage* message)
{
if (message->what == fDragCommand) {
DragSortableListView *list = NULL;
if ( message->FindPointer( "list", (void **)&list ) == B_OK
&& list == this ) {
if (message->FindPointer("list", (void **)&list) == B_OK
&& list == this) {
int32 count = CountItems();
if ( fDropIndex < 0 || fDropIndex > count )
if (fDropIndex < 0 || fDropIndex > count)
fDropIndex = count;
BList items;
int32 index;
for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ )
if ( BListItem* item = ItemAt(index) )
items.AddItem( (void*)item );
if ( items.CountItems() > 0 ) {
if ( modifiers() & B_SHIFT_KEY )
CopyItems( items, fDropIndex );
for (int32 i = 0; message->FindInt32("index", i, &index) == B_OK; i++)
if (BListItem* item = ItemAt(index))
items.AddItem((void*)item);
if (items.CountItems() > 0) {
if (modifiers() & B_SHIFT_KEY)
CopyItems(items, fDropIndex);
else
MoveItems( items, fDropIndex );
MoveItems(items, fDropIndex);
}
fDropIndex = -1;
}
} else {
switch ( message->what ) {
switch (message->what) {
case MSG_TICK: {
float scrollV = 0.0;
BRect rect(Bounds());
@ -370,7 +371,7 @@ DragSortableListView::MessageReceived(BMessage* message)
// ModifiersChanged();
// break;
case B_MOUSE_WHEEL_CHANGED: {
BListView::MessageReceived( message );
BListView::MessageReceived(message);
BPoint point;
uint32 buttons;
GetMouse(&point, &buttons, false);
@ -379,7 +380,7 @@ DragSortableListView::MessageReceived(BMessage* message)
break;
}
default:
BListView::MessageReceived( message );
BListView::MessageReceived(message);
break;
}
}
@ -387,20 +388,20 @@ DragSortableListView::MessageReceived(BMessage* message)
// KeyDown
void
DragSortableListView::KeyDown( const char* bytes, int32 numBytes )
DragSortableListView::KeyDown(const char* bytes, int32 numBytes)
{
if ( numBytes < 1 )
if (numBytes < 1)
return;
if ( ( bytes[0] == B_BACKSPACE ) || ( bytes[0] == B_DELETE ) )
if ((bytes[0] == B_BACKSPACE) || (bytes[0] == B_DELETE))
RemoveSelected();
BListView::KeyDown( bytes, numBytes );
BListView::KeyDown(bytes, numBytes);
}
// MouseDown
void
DragSortableListView::MouseDown( BPoint where )
DragSortableListView::MouseDown(BPoint where)
{
int32 clicks = 1;
uint32 buttons = 0;
@ -478,14 +479,14 @@ DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *m
// MouseUp
void
DragSortableListView::MouseUp( BPoint where )
DragSortableListView::MouseUp(BPoint where)
{
// remove drop mark
_SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
_SetDropAnticipationRect(BRect(0.0, 0.0, -1.0, -1.0));
SetAutoScrolling(false);
// be sure to forget drag message
_SetDragMessage(NULL);
BListView::MouseUp( where );
BListView::MouseUp(where);
BCursor cursor(B_HAND_CURSOR);
SetViewCursor(&cursor, true);
@ -493,9 +494,9 @@ DragSortableListView::MouseUp( BPoint where )
// DrawItem
void
DragSortableListView::DrawItem( BListItem *item, BRect itemFrame, bool complete )
DragSortableListView::DrawItem(BListItem *item, BRect itemFrame, bool complete)
{
DrawListItem( this, IndexOf( item ), itemFrame );
DrawListItem(this, IndexOf(item), itemFrame);
/* if (IsFocus()) {
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
StrokeRect(Bounds());
@ -620,7 +621,7 @@ DragSortableListView::ScrollTo(int32 index)
// MoveItems
void
DragSortableListView::MoveItems( BList& items, int32 index )
DragSortableListView::MoveItems(BList& items, int32 index)
{
DeselectAll();
// we remove the items while we look at them, the insertion index is decreased
@ -628,34 +629,30 @@ DragSortableListView::MoveItems( BList& items, int32 index )
// removal
BList removedItems;
int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ )
{
BListItem* item = (BListItem*)items.ItemAt( i );
int32 removeIndex = IndexOf( item );
if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) )
{
if ( removeIndex < index )
for (int32 i = 0; i < count; i++) {
BListItem* item = (BListItem*)items.ItemAt(i);
int32 removeIndex = IndexOf(item);
if (RemoveItem(item) && removedItems.AddItem((void*)item)) {
if (removeIndex < index)
index--;
}
// else ??? -> blow up
}
for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ )
{
if ( AddItem( item, index ) )
{
for (int32 i = 0;
BListItem* item = (BListItem*)removedItems.ItemAt(i); i++) {
if (AddItem(item, index)) {
// 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
index++;
}
else
} else
delete item;
}
}
// CopyItems
void
DragSortableListView::CopyItems( BList& items, int32 index )
DragSortableListView::CopyItems(BList& items, int32 index)
{
DeselectAll();
// by inserting the items after we copied all items first, we avoid
@ -664,35 +661,31 @@ DragSortableListView::CopyItems( BList& items, int32 index )
// need to be cloned
BList clonedItems;
int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ )
{
BListItem* item = CloneItem( IndexOf( (BListItem*)items.ItemAt( i ) ) );
if ( item && !clonedItems.AddItem( (void*)item ) )
for (int32 i = 0; i < count; i++) {
BListItem* item = CloneItem(IndexOf((BListItem*)items.ItemAt(i)));
if (item && !clonedItems.AddItem((void*)item))
delete item;
}
for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ )
{
if ( AddItem( item, index ) )
{
for (int32 i = 0;
BListItem* item = (BListItem*)clonedItems.ItemAt(i); i++) {
if (AddItem(item, index)) {
// 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
index++;
}
else
} else
delete item;
}
}
// RemoveItemList
void
DragSortableListView::RemoveItemList( BList& items )
DragSortableListView::RemoveItemList(BList& items)
{
int32 count = items.CountItems();
for ( int32 i = 0; i < count; i++ )
{
BListItem* item = (BListItem*)items.ItemAt( i );
if ( RemoveItem( item ) )
for (int32 i = 0; i < count; i++) {
BListItem* item = (BListItem*)items.ItemAt(i);
if (RemoveItem(item))
delete item;
}
}
@ -705,9 +698,9 @@ DragSortableListView::RemoveSelected()
// return;
BList items;
for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ )
items.AddItem( (void*)item );
RemoveItemList( items );
for (int32 i = 0; BListItem* item = ItemAt(CurrentSelection(i)); i++)
items.AddItem((void*)item);
RemoveItemList(items);
}
// CountSelectedItems
@ -715,7 +708,7 @@ int32
DragSortableListView::CountSelectedItems() const
{
int32 count = 0;
while ( CurrentSelection( count ) >= 0 )
while (CurrentSelection(count) >= 0)
count++;
return count;
}
@ -802,22 +795,22 @@ DragSortableListView::_SetDragMessage(const BMessage* message)
// SimpleListView class
SimpleListView::SimpleListView( BRect frame, BMessage* selectionChangeMessage )
: DragSortableListView( frame, "playlist listview",
SimpleListView::SimpleListView(BRect frame, BMessage* selectionChangeMessage)
: DragSortableListView(frame, "playlist listview",
B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL,
B_WILL_DRAW | B_NAVIGABLE
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE ),
fSelectionChangeMessage( selectionChangeMessage )
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
fSelectionChangeMessage(selectionChangeMessage)
{
}
// SimpleListView class
SimpleListView::SimpleListView( BRect frame, const char* name,
SimpleListView::SimpleListView(BRect frame, const char* name,
BMessage* selectionChangeMessage,
list_view_type type,
uint32 resizingMode, uint32 flags )
: DragSortableListView( frame, name, type, resizingMode, flags ),
fSelectionChangeMessage( selectionChangeMessage )
uint32 resizingMode, uint32 flags)
: DragSortableListView(frame, name, type, resizingMode, flags),
fSelectionChangeMessage(selectionChangeMessage)
{
}
@ -827,6 +820,7 @@ SimpleListView::~SimpleListView()
delete fSelectionChangeMessage;
}
#ifdef LIB_LAYOUT
// layoutprefs
minimax
SimpleListView::layoutprefs()
@ -847,14 +841,15 @@ SimpleListView::layout(BRect frame)
ResizeTo(frame.Width(), frame.Height());
return Frame();
}
#endif // LIB_LAYOUT
// MessageReceived
void
SimpleListView::MessageReceived( BMessage* message)
SimpleListView::MessageReceived(BMessage* message)
{
switch ( message->what ) {
switch (message->what) {
default:
DragSortableListView::MessageReceived( message );
DragSortableListView::MessageReceived(message);
break;
}
}
@ -899,10 +894,10 @@ void
SimpleListView::MakeDragMessage(BMessage* message) const
{
if (message) {
message->AddPointer( "list", (void*)dynamic_cast<const DragSortableListView*>(this));
message->AddPointer("list", (void*)dynamic_cast<const DragSortableListView*>(this));
int32 index;
for (int32 i = 0; (index = CurrentSelection(i)) >= 0; i++)
message->AddInt32( "index", index );
message->AddInt32("index", index);
}
}

View File

@ -13,7 +13,9 @@
#include <ListView.h>
#include <Message.h>
#include <layout.h>
#ifdef LIB_LAYOUT
# include <layout.h>
#endif
#include "MouseWheelFilter.h"
@ -59,7 +61,7 @@ class SimpleItem : public BStringItem
class DragSortableListView : public MouseWheelTarget,
public BListView {
public:
DragSortableListView( BRect frame,
DragSortableListView(BRect frame,
const char* name,
list_view_type type
= B_SINGLE_SELECTION_LIST,
@ -69,7 +71,7 @@ class DragSortableListView : public MouseWheelTarget,
uint32 flags
= B_WILL_DRAW
| B_NAVIGABLE
| B_FRAME_EVENTS );
| B_FRAME_EVENTS);
virtual ~DragSortableListView();
// BListView
@ -77,19 +79,19 @@ class DragSortableListView : public MouseWheelTarget,
virtual void DetachedFromWindow();
virtual void FrameResized(float width, float height);
// virtual void MakeFocus(bool focused);
virtual void Draw( BRect updateRect );
virtual void Draw(BRect updateRect);
virtual void ScrollTo(BPoint where);
virtual void TargetedByScrollView(BScrollView* scrollView);
virtual bool InitiateDrag( BPoint point, int32 index,
bool wasSelected );
virtual void MessageReceived( BMessage* message );
virtual void KeyDown( const char* bytes, int32 numBytes );
virtual void MouseDown( BPoint where );
virtual void MouseMoved( BPoint where, uint32 transit,
const BMessage* dragMessage );
virtual void MouseUp( BPoint where );
virtual void WindowActivated( bool active );
virtual void DrawItem( BListItem *item, BRect itemFrame,
virtual bool InitiateDrag(BPoint point, int32 index,
bool wasSelected);
virtual void MessageReceived(BMessage* message);
virtual void KeyDown(const char* bytes, int32 numBytes);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MouseUp(BPoint where);
virtual void WindowActivated(bool active);
virtual void DrawItem(BListItem *item, BRect itemFrame,
bool complete = false);
// MouseWheelTarget
@ -148,11 +150,15 @@ class DragSortableListView : public MouseWheelTarget,
};
// SimpleListView
class SimpleListView : public MView, public DragSortableListView {
class SimpleListView :
#ifdef LIB_LAYOUT
public MView,
#endif
public DragSortableListView {
public:
SimpleListView( BRect frame,
BMessage* selectionChangeMessage = NULL );
SimpleListView( BRect frame,
SimpleListView(BRect frame,
BMessage* selectionChangeMessage = NULL);
SimpleListView(BRect frame,
const char* name,
BMessage* selectionChangeMessage = NULL,
list_view_type type
@ -161,13 +167,14 @@ class SimpleListView : public MView, public DragSortableListView {
= B_FOLLOW_ALL_SIDES,
uint32 flags
= B_WILL_DRAW | B_NAVIGABLE
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE );
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE);
~SimpleListView();
#ifdef LIB_LAYOUT
// MView
virtual minimax layoutprefs();
virtual BRect layout(BRect frame);
#endif
// BListView
virtual void MessageReceived(BMessage* message);
virtual void SelectionChanged();

View File

@ -0,0 +1,308 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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);
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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

View File

@ -0,0 +1,340 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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);
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
*/
#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

View File

@ -23,7 +23,9 @@ Shape::Shape(::Style* style)
fPathSource(fPaths),
fTransformers(4),
fLastBounds(0, 0, -1, -1)
fLastBounds(0, 0, -1, -1),
fName("<shape>")
{
if (fPaths)
fPaths->AddListener(this);
@ -77,6 +79,16 @@ Shape::ObjectChanged(const Observable* object)
// #pragma mark -
// SelectedChanged
void
Shape::SelectedChanged()
{
// simply pass on the event for now
Notify();
}
// #pragma mark -
// InitCheck
status_t
Shape::InitCheck() const
@ -158,3 +170,24 @@ Shape::AppendTransformer(Transformer* transformer)
Notify();
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();
}

View File

@ -3,18 +3,21 @@
#include <List.h>
#include <Rect.h>
#include <String.h>
#include "Observable.h"
#include "Observer.h"
#include "PathContainer.h"
#include "PathSource.h"
#include "Referenceable.h"
#include "Selectable.h"
class Style;
class Shape : public Observable,
public Observer, // observing all the paths
public Referenceable,
public Selectable,
public PathContainerListener {
public:
Shape(::Style* style);
@ -27,6 +30,9 @@ class Shape : public Observable,
// Observer interface
virtual void ObjectChanged(const Observable* object);
// Selectable interface
virtual void SelectedChanged();
// Shape
status_t InitCheck() const;
@ -45,6 +51,9 @@ class Shape : public Observable,
bool AppendTransformer(
Transformer* transformer);
void SetName(const char* name);
const char* Name() const;
private:
PathContainer* fPaths;
::Style* fStyle;
@ -53,6 +62,8 @@ class Shape : public Observable,
BList fTransformers;
mutable BRect fLastBounds;
BString fName;
};
#endif // SHAPE_H

View File

@ -78,7 +78,8 @@ VectorPath::VectorPath()
fClosed(false),
fPointCount(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),
fPointCount(0),
fAllocCount(0),
fCachedBounds(0.0, 0.0, -1.0, -1.0)
fCachedBounds(0.0, 0.0, -1.0, -1.0),
fName()
{
*this = from;
}
@ -104,7 +106,8 @@ VectorPath::VectorPath(const BMessage* archive)
fClosed(false),
fPointCount(0),
fAllocCount(0),
fCachedBounds(0.0, 0.0, -1.0, -1.0)
fCachedBounds(0.0, 0.0, -1.0, -1.0),
fName()
{
if (archive) {
type_code typeFound;
@ -130,6 +133,9 @@ VectorPath::VectorPath(const BMessage* archive)
if (archive->FindBool("path closed", &fClosed) < B_OK) {
fClosed = false;
}
if (archive->FindString("name", &fName) < B_OK) {
fName = "<path>";
}
}
}
@ -155,6 +161,7 @@ VectorPath::operator=(const VectorPath& from)
fPointCount = 0;
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
}
fName = from.fName;
return *this;
}
@ -171,7 +178,9 @@ status_t
VectorPath::Archive(BMessage* into, bool deep) const
{
status_t ret = BArchivable::Archive(into, deep);
if (ret >= B_OK) {
if (ret < B_OK)
return ret;
if (fPointCount > 0) {
// improve BMessage efficency by preallocating storage for all points
// with the first call
@ -203,14 +212,19 @@ VectorPath::Archive(BMessage* into, bool deep) const
} else {
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) {
fprintf(stderr, "failed adding closed!\n");
fprintf(stderr, "failed adding name!\n");
}
// finish off
if (ret < B_OK) {
ret = into->AddString("class", "VectorPath");
}
}
return ret;
}
@ -829,6 +843,28 @@ VectorPath::_SetPoint(int32 index, BPoint point)
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
bool
VectorPath::_SetPointCount(int32 count)

View File

@ -11,6 +11,7 @@
#include <Archivable.h>
#include <Rect.h>
#include <String.h>
#include <agg_path_storage.h>
@ -121,6 +122,9 @@ class VectorPath : public BArchivable,
bool GetAGGPathStorage(agg::path_storage& path) const;
void SetName(const char* name);
const char* Name() const;
private:
BRect _Bounds() const;
void _SetPoint(int32 index, BPoint point);
@ -134,6 +138,9 @@ class VectorPath : public BArchivable,
int32 fAllocCount;
mutable BRect fCachedBounds;
// TODO: should this really be part of VectorPath?
BString fName;
};
#endif // VECTOR_PATH_H