* when loading an icon via drag&drop, the file will be remembered
for saving later * added "Clean Up" feature to "Path" menu * added "Freeze Transformation" to "Shape" menu (will apply the current shape transformation onto the path and reset the shape transformation to identity) * small cleanup in ShapeListView * implemented zooming in CanvasView * added context menu while editing a path * implemented undo/redo for transforming points (press T or use context menu) * added "Split Points" feature (path editing context menu), it will make two points from one control point * improved selecting path points with selection rect * improved SVG import for zuMis BeOS icons (more precise scale) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18800 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -28,8 +28,8 @@ CanvasView::CanvasView(BRect frame)
|
|||||||
fRenderer(new IconRenderer(fBitmap)),
|
fRenderer(new IconRenderer(fBitmap)),
|
||||||
fDirtyIconArea(fBitmap->Bounds()),
|
fDirtyIconArea(fBitmap->Bounds()),
|
||||||
|
|
||||||
fCanvasOrigin(50.0, 50.0),
|
fCanvasOrigin(0.0, 0.0),
|
||||||
fZoomLevel(8.0),
|
fZoomLevel(1.0),
|
||||||
|
|
||||||
fMouseFilterMode(SNAPPING_OFF),
|
fMouseFilterMode(SNAPPING_OFF),
|
||||||
|
|
||||||
@@ -68,6 +68,8 @@ CanvasView::AttachedToWindow()
|
|||||||
SetHighColor(kStripesLow);
|
SetHighColor(kStripesLow);
|
||||||
|
|
||||||
_AllocBackBitmap(Bounds().Width(), Bounds().Height());
|
_AllocBackBitmap(Bounds().Width(), Bounds().Height());
|
||||||
|
|
||||||
|
_SetZoom(8.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FrameResized
|
// FrameResized
|
||||||
@@ -140,6 +142,25 @@ CanvasView::MouseMoved(BPoint where, uint32 transit,
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
// ScrollOffsetChanged
|
||||||
|
void
|
||||||
|
CanvasView::ScrollOffsetChanged(BPoint oldOffset, BPoint newOffset)
|
||||||
|
{
|
||||||
|
BPoint offset = newOffset - oldOffset;
|
||||||
|
ScrollBy(offset.x, offset.y);
|
||||||
|
|
||||||
|
MouseMoved(fMouseInfo.position + offset, fMouseInfo.transit, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleSizeChanged
|
||||||
|
void
|
||||||
|
CanvasView::VisibleSizeChanged(float oldWidth, float oldHeight,
|
||||||
|
float newWidth, float newHeight)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
// AreaInvalidated
|
// AreaInvalidated
|
||||||
void
|
void
|
||||||
CanvasView::AreaInvalidated(const BRect& area)
|
CanvasView::AreaInvalidated(const BRect& area)
|
||||||
@@ -240,6 +261,13 @@ CanvasView::_HandleKeyDown(uint32 key, uint32 modifiers)
|
|||||||
CommandStack()->Undo();
|
CommandStack()->Undo();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
_SetZoom(_NextZoomInLevel(fZoomLevel));
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
_SetZoom(_NextZoomOutLevel(fZoomLevel));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return StateView::_HandleKeyDown(key, modifiers);
|
return StateView::_HandleKeyDown(key, modifiers);
|
||||||
}
|
}
|
||||||
@@ -446,3 +474,115 @@ CanvasView::_MakeBackground()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _NextZoomInLevel
|
||||||
|
double
|
||||||
|
CanvasView::_NextZoomInLevel(double zoom) const
|
||||||
|
{
|
||||||
|
if (zoom < 1)
|
||||||
|
return 1;
|
||||||
|
if (zoom < 1.5)
|
||||||
|
return 1.5;
|
||||||
|
if (zoom < 2)
|
||||||
|
return 2;
|
||||||
|
if (zoom < 3)
|
||||||
|
return 3;
|
||||||
|
if (zoom < 4)
|
||||||
|
return 4;
|
||||||
|
if (zoom < 6)
|
||||||
|
return 6;
|
||||||
|
if (zoom < 8)
|
||||||
|
return 8;
|
||||||
|
if (zoom < 16)
|
||||||
|
return 16;
|
||||||
|
if (zoom < 32)
|
||||||
|
return 32;
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _NextZoomOutLevel
|
||||||
|
double
|
||||||
|
CanvasView::_NextZoomOutLevel(double zoom) const
|
||||||
|
{
|
||||||
|
if (zoom > 32)
|
||||||
|
return 32;
|
||||||
|
if (zoom > 16)
|
||||||
|
return 16;
|
||||||
|
if (zoom > 8)
|
||||||
|
return 8;
|
||||||
|
if (zoom > 6)
|
||||||
|
return 6;
|
||||||
|
if (zoom > 4)
|
||||||
|
return 4;
|
||||||
|
if (zoom > 3)
|
||||||
|
return 3;
|
||||||
|
if (zoom > 2)
|
||||||
|
return 2;
|
||||||
|
if (zoom > 1.5)
|
||||||
|
return 1.5;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _SetZoom
|
||||||
|
void
|
||||||
|
CanvasView::_SetZoom(double zoomLevel)
|
||||||
|
{
|
||||||
|
if (fZoomLevel == zoomLevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// zoom into mouse position, or into center of view
|
||||||
|
BPoint anchor = MouseInfo()->position;
|
||||||
|
BRect bounds(Bounds());
|
||||||
|
if (!bounds.Contains(anchor)) {
|
||||||
|
bounds = _CanvasRect();
|
||||||
|
anchor.x = (bounds.left + bounds.right) / 2.0;
|
||||||
|
anchor.y = (bounds.top + bounds.bottom) / 2.0;
|
||||||
|
}
|
||||||
|
printf("anchor: %.2f, %.2f\n", anchor.x, anchor.y);
|
||||||
|
|
||||||
|
BPoint offset;
|
||||||
|
if (fZoomLevel < zoomLevel) {
|
||||||
|
offset.x = anchor.x * (zoomLevel / fZoomLevel) - anchor.x;
|
||||||
|
offset.y = anchor.y * (zoomLevel / fZoomLevel) - anchor.y;
|
||||||
|
} else {
|
||||||
|
offset.x = -anchor.x * (zoomLevel / fZoomLevel);
|
||||||
|
offset.y = -anchor.y * (zoomLevel / fZoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
fZoomLevel = zoomLevel;
|
||||||
|
SetDataRect(_LayoutCanvas());
|
||||||
|
|
||||||
|
printf("offset: %.2f, %.2f\n", offset.x, offset.y);
|
||||||
|
|
||||||
|
SetScrollOffset(ScrollOffset() + offset);
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _LayoutCanvas
|
||||||
|
BRect
|
||||||
|
CanvasView::_LayoutCanvas()
|
||||||
|
{
|
||||||
|
if (!fBitmap)
|
||||||
|
return BRect(0, 0, -1, -1);
|
||||||
|
|
||||||
|
// size of zoomed bitmap
|
||||||
|
BRect r(fBitmap->Bounds());
|
||||||
|
r.OffsetTo(0, 0);
|
||||||
|
r.right = floorf((r.Width() + 1) * fZoomLevel + 0.5) - 1;
|
||||||
|
r.bottom = floorf((r.Height() + 1) * fZoomLevel + 0.5) - 1;
|
||||||
|
|
||||||
|
// TODO: ask manipulators to extend size
|
||||||
|
|
||||||
|
// left top of canvas within empty area
|
||||||
|
fCanvasOrigin.x = floorf(r.Width() * 0.25);
|
||||||
|
fCanvasOrigin.y = floorf(r.Height() * 0.25);
|
||||||
|
|
||||||
|
// resize for empty area around bitmap
|
||||||
|
r.right += r.Width() * 0.5;
|
||||||
|
r.bottom += r.Height() * 0.5;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#define CANVAS_VIEW_H
|
#define CANVAS_VIEW_H
|
||||||
|
|
||||||
#include "Icon.h"
|
#include "Icon.h"
|
||||||
|
#include "Scrollable.h"
|
||||||
#include "StateView.h"
|
#include "StateView.h"
|
||||||
|
|
||||||
class BBitmap;
|
class BBitmap;
|
||||||
@@ -23,6 +24,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class CanvasView : public StateView,
|
class CanvasView : public StateView,
|
||||||
|
public Scrollable,
|
||||||
public IconListener {
|
public IconListener {
|
||||||
public:
|
public:
|
||||||
CanvasView(BRect frame);
|
CanvasView(BRect frame);
|
||||||
@@ -37,7 +39,16 @@ class CanvasView : public StateView,
|
|||||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||||
const BMessage* dragMessage);
|
const BMessage* dragMessage);
|
||||||
|
|
||||||
|
// Scrollable interface
|
||||||
|
protected:
|
||||||
|
virtual void ScrollOffsetChanged(BPoint oldOffset,
|
||||||
|
BPoint newOffset);
|
||||||
|
virtual void VisibleSizeChanged(float oldWidth,
|
||||||
|
float oldHeight,
|
||||||
|
float newWidth,
|
||||||
|
float newHeight);
|
||||||
// IconListener interface
|
// IconListener interface
|
||||||
|
public:
|
||||||
virtual void AreaInvalidated(const BRect& area);
|
virtual void AreaInvalidated(const BRect& area);
|
||||||
|
|
||||||
// CanvasView
|
// CanvasView
|
||||||
@@ -74,6 +85,11 @@ class CanvasView : public StateView,
|
|||||||
void _MakeBackground();
|
void _MakeBackground();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
double _NextZoomInLevel(double zoom) const;
|
||||||
|
double _NextZoomOutLevel(double zoom) const;
|
||||||
|
void _SetZoom(double zoomLevel);
|
||||||
|
BRect _LayoutCanvas();
|
||||||
|
|
||||||
BBitmap* fBitmap;
|
BBitmap* fBitmap;
|
||||||
BBitmap* fBackground;
|
BBitmap* fBackground;
|
||||||
|
|
||||||
@@ -82,7 +98,7 @@ class CanvasView : public StateView,
|
|||||||
BRect fDirtyIconArea;
|
BRect fDirtyIconArea;
|
||||||
|
|
||||||
BPoint fCanvasOrigin;
|
BPoint fCanvasOrigin;
|
||||||
float fZoomLevel;
|
double fZoomLevel;
|
||||||
|
|
||||||
uint32 fMouseFilterMode;
|
uint32 fMouseFilterMode;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Icon-O-Matic.rdef
|
||||||
|
*/
|
||||||
|
|
||||||
|
resource app_signature "application/x-vnd.haiku-icon_o_matic";
|
||||||
|
|
||||||
|
resource app_version {
|
||||||
|
major = 1,
|
||||||
|
middle = 0,
|
||||||
|
minor = 0,
|
||||||
|
|
||||||
|
/* 0 = development 1 = alpha 2 = beta
|
||||||
|
3 = gamma 4 = golden master 5 = final */
|
||||||
|
variety = 2,
|
||||||
|
|
||||||
|
internal = 0,
|
||||||
|
|
||||||
|
short_info = "Icon-O-Matic",
|
||||||
|
long_info = "Icon-O-Matic 1.0.0 ©2006 Haiku"
|
||||||
|
};
|
||||||
|
|
||||||
|
resource app_flags B_SINGLE_LAUNCH;
|
||||||
|
|
||||||
|
//resource file_types message {
|
||||||
|
// "types" = "application/x-haiku_icon",
|
||||||
|
//};
|
||||||
|
|
||||||
|
resource(101, "BEOS:ICON") #'RAWT' array {
|
||||||
|
$"6E6369660E050102000603399E0F3D9C0ABF82B23B84A94B88504910C900A5B1"
|
||||||
|
$"FFBCEAF1FFFFB3B8FF020106023E49240000000000003CAAAA4940004A8000FF"
|
||||||
|
$"C0D5FF7C896EFF040192020006023B8E380000000000004000004AAA003A0000"
|
||||||
|
$"002B30A0FFCBDCFA038089D80200060237889D389554BBFC4A3AB9D048DADE4A"
|
||||||
|
$"322000FFF9BAFFFFC10402000602B5B574397997BC15F4B839E3489DF94B8820"
|
||||||
|
$"00C7E3FFFF392FFF0200060237A0CC393C5ABC1AC23A5C164A39B94B1E5400FD"
|
||||||
|
$"B9B9FFCE3232020006023D4D340000000000004000004A50000000000097A3BA"
|
||||||
|
$"FFF8FBFF020006023C08200000000000004000004A4000000000FF7E94B4005F"
|
||||||
|
$"6C9302000602B507E13A82E2BAD599B56BB44A7652479FE4002B2D3DFE444C6D"
|
||||||
|
$"02000603B2F679BA14D43A7FB6B38E9E474F5546D05A00F0CD9B81C0995DCFF0"
|
||||||
|
$"D8B502000602AAB1FB3A081FBE8A26AF5E794C4014448D43FFFDDCAB00DBAB5F"
|
||||||
|
$"140606AE0BB40BC14B33C5ADB75DC371BDEFC805C13ECA02CA28BF80C118BB1E"
|
||||||
|
$"C51BBD3EBF07BA063AB8BA060CAEAABAB40BC14B33C5ADB75DC371BDEFC805C1"
|
||||||
|
$"3ECA02C4E04F41C507374B3A4945C33CC6D1C36FCA28BF80C118BB1EC51BBD3E"
|
||||||
|
$"BF07BA063AB8BA0605AE02B57D43B9B9C5EDB7BB49BBB756BD75CB34CA8EC3AF"
|
||||||
|
$"40340609AEAA02B57D43B9B9C5EDB7BB49BBB756BD75CB34C6F0C5C24E4F514B"
|
||||||
|
$"C9BBC428CA8EC3AF40340A093B5E3D60BFCDCB3C4560C516C7EF604B5B485D4A"
|
||||||
|
$"44560A045A475E445A4257450A06C4E04F41C507374B3A4945C33CC6D1C36F0A"
|
||||||
|
$"04C6F0C5C24E4F514BC9BBC4280A062A452B4D3251364D35452F420A06245225"
|
||||||
|
$"5A2B5E315A31522A4E0A053153315B375F3C5B3C530606B20831245356295625"
|
||||||
|
$"562D532E3126290A063124B8BAB5B2B8BAB779312EB677B6ECB67CB63C0804BA"
|
||||||
|
$"28B4D33027302BBA28B8580A043324B969B5BA4E2751240A04B969B5BAB969B7"
|
||||||
|
$"714E2B4E270A04B969B771332E512E4E2B0003C6E8B4D3C6E8B4D3C690B51750"
|
||||||
|
$"2950B59E50B78DC6E8B858C690B814C6E8B8580604EE532456295625562D532E"
|
||||||
|
$"5029502D50250604EE532755295528552A532B5229522A5228120A0302040500"
|
||||||
|
$"0A0001021001178400040A020103000A050107000A0001001001178400040A01"
|
||||||
|
$"0101000A000108123E7578BF27AD3F27AD3E7578C831624850E201178400040A"
|
||||||
|
$"060108023E7578BF27AD3F27AD3E7578C831624850E20A070109023E7578BF27"
|
||||||
|
$"AD3F27AD3E7578C831624850E20A08010A023E7578BF27AD3F27AD3E7578C831"
|
||||||
|
$"624850E20A040106000A00030B0D11123ED413BED4133ED4133ED41347F4A24A"
|
||||||
|
$"588901178400040A0C010C023ED413BED4133ED4133ED41347F4A24A58890A09"
|
||||||
|
$"010E023ED413BED4133ED4133ED41347F4A24A58890A0A010F023ED413BED413"
|
||||||
|
$"3ED4133ED41347F4A24A58890A0B0110023ED413BED4133ED4133ED41347F4A2"
|
||||||
|
$"4A58890A0D0112023ED413BED4133ED4133ED41347F4A24A58890A0001130A3E"
|
||||||
|
$"D413BED4133ED4133ED41347F4A24A588915FF"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//resource large_icon array {
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//resource mini_icon array {
|
||||||
|
//};
|
||||||
@@ -39,7 +39,7 @@ using std::nothrow;
|
|||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
IconEditorApp::IconEditorApp()
|
IconEditorApp::IconEditorApp()
|
||||||
: BApplication("application/x-vnd.Haiku-Icon-O-Matic"),
|
: BApplication("application/x-vnd.haiku-icon_o_matic"),
|
||||||
fMainWindow(NULL),
|
fMainWindow(NULL),
|
||||||
fDocument(new Document("test")),
|
fDocument(new Document("test")),
|
||||||
|
|
||||||
@@ -275,17 +275,24 @@ IconEditorApp::_Open(const entry_ref& ref, bool append)
|
|||||||
if (!icon)
|
if (!icon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REF_NONE = 0,
|
||||||
|
REF_MESSAGE,
|
||||||
|
REF_FLAT
|
||||||
|
};
|
||||||
|
uint32 refMode = REF_NONE;
|
||||||
|
|
||||||
// try different file types
|
// try different file types
|
||||||
FlatIconImporter flatImporter;
|
FlatIconImporter flatImporter;
|
||||||
status_t ret = flatImporter.Import(icon, &file);
|
status_t ret = flatImporter.Import(icon, &file);
|
||||||
if (ret >= B_OK) {
|
if (ret >= B_OK) {
|
||||||
fDocument->SetExportRef(ref);
|
refMode = REF_FLAT;
|
||||||
} else {
|
} else {
|
||||||
file.Seek(0, SEEK_SET);
|
file.Seek(0, SEEK_SET);
|
||||||
MessageImporter msgImporter;
|
MessageImporter msgImporter;
|
||||||
ret = msgImporter.Import(icon, &file);
|
ret = msgImporter.Import(icon, &file);
|
||||||
if (ret >= B_OK) {
|
if (ret >= B_OK) {
|
||||||
fDocument->SetRef(ref);
|
refMode = REF_MESSAGE;
|
||||||
} else {
|
} else {
|
||||||
file.Seek(0, SEEK_SET);
|
file.Seek(0, SEEK_SET);
|
||||||
SVGImporter svgImporter;
|
SVGImporter svgImporter;
|
||||||
@@ -315,8 +322,18 @@ IconEditorApp::_Open(const entry_ref& ref, bool append)
|
|||||||
fMainWindow->SetIcon(NULL);
|
fMainWindow->SetIcon(NULL);
|
||||||
|
|
||||||
fDocument->MakeEmpty();
|
fDocument->MakeEmpty();
|
||||||
|
|
||||||
fDocument->SetIcon(icon);
|
fDocument->SetIcon(icon);
|
||||||
|
|
||||||
|
switch (refMode) {
|
||||||
|
case REF_MESSAGE:
|
||||||
|
fDocument->SetRef(ref);
|
||||||
|
break;
|
||||||
|
case REF_FLAT:
|
||||||
|
fDocument->SetExportRef(ref);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
if (mainWindowLocked) {
|
if (mainWindowLocked) {
|
||||||
|
|||||||
@@ -231,6 +231,8 @@ Application Icon-O-Matic :
|
|||||||
AddShapesCommand.cpp
|
AddShapesCommand.cpp
|
||||||
AddTransformersCommand.cpp
|
AddTransformersCommand.cpp
|
||||||
ChangePointCommand.cpp
|
ChangePointCommand.cpp
|
||||||
|
CleanUpPathCommand.cpp
|
||||||
|
FreezeTransformationCommand.cpp
|
||||||
InsertPointCommand.cpp
|
InsertPointCommand.cpp
|
||||||
MoveShapesCommand.cpp
|
MoveShapesCommand.cpp
|
||||||
MovePathsCommand.cpp
|
MovePathsCommand.cpp
|
||||||
@@ -242,6 +244,8 @@ Application Icon-O-Matic :
|
|||||||
RemoveShapesCommand.cpp
|
RemoveShapesCommand.cpp
|
||||||
RemoveTransformersCommand.cpp
|
RemoveTransformersCommand.cpp
|
||||||
ReversePathCommand.cpp
|
ReversePathCommand.cpp
|
||||||
|
SplitPointsCommand.cpp
|
||||||
|
TransformPointsCommand.cpp
|
||||||
UnassignPathCommand.cpp
|
UnassignPathCommand.cpp
|
||||||
|
|
||||||
# style
|
# style
|
||||||
@@ -274,6 +278,8 @@ Application Icon-O-Matic :
|
|||||||
Util.cpp
|
Util.cpp
|
||||||
|
|
||||||
: be tracker translation libagg.a libexpat.a
|
: be tracker translation libagg.a libexpat.a
|
||||||
|
|
||||||
|
: Icon-O-Matic.rdef
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -247,6 +247,8 @@ case MSG_SHAPE_SELECTED: {
|
|||||||
Shape* shape;
|
Shape* shape;
|
||||||
if (message->FindPointer("shape", (void**)&shape) < B_OK)
|
if (message->FindPointer("shape", (void**)&shape) < B_OK)
|
||||||
shape = NULL;
|
shape = NULL;
|
||||||
|
if (!fIcon || !fIcon->Shapes()->HasShape(shape))
|
||||||
|
shape = NULL;
|
||||||
|
|
||||||
fPathListView->SetCurrentShape(shape);
|
fPathListView->SetCurrentShape(shape);
|
||||||
fStyleListView->SetCurrentShape(shape);
|
fStyleListView->SetCurrentShape(shape);
|
||||||
@@ -707,10 +709,21 @@ MainWindow::_CreateGUI(BRect bounds)
|
|||||||
// canvas view
|
// canvas view
|
||||||
bounds.left = splitWidth;
|
bounds.left = splitWidth;
|
||||||
bounds.top = fSwatchGroup->Frame().bottom + 1;
|
bounds.top = fSwatchGroup->Frame().bottom + 1;
|
||||||
bounds.right = bg->Bounds().right;
|
bounds.right = bg->Bounds().right - B_V_SCROLL_BAR_WIDTH;
|
||||||
bounds.bottom = bg->Bounds().bottom;
|
bounds.bottom = bg->Bounds().bottom - B_H_SCROLL_BAR_HEIGHT;
|
||||||
fCanvasView = new CanvasView(bounds);
|
fCanvasView = new CanvasView(bounds);
|
||||||
|
|
||||||
|
// scroll view around canvas view
|
||||||
|
bounds.bottom += B_H_SCROLL_BAR_HEIGHT;
|
||||||
|
bounds.right += B_V_SCROLL_BAR_WIDTH;
|
||||||
|
ScrollView* canvasScrollView
|
||||||
|
= new ScrollView(fCanvasView,
|
||||||
|
SCROLL_HORIZONTAL | SCROLL_VERTICAL
|
||||||
|
| SCROLL_VISIBLE_RECT_IS_CHILD_BOUNDS
|
||||||
|
| SCROLL_NO_FRAME,
|
||||||
|
bounds, "canvas scroll view",
|
||||||
|
B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS);
|
||||||
|
|
||||||
// icon previews
|
// icon previews
|
||||||
bounds.left = 5;
|
bounds.left = 5;
|
||||||
bounds.top = fSwatchGroup->Frame().top + 5;
|
bounds.top = fSwatchGroup->Frame().top + 5;
|
||||||
@@ -882,7 +895,7 @@ MainWindow::_CreateGUI(BRect bounds)
|
|||||||
B_WILL_DRAW | B_FRAME_EVENTS));
|
B_WILL_DRAW | B_FRAME_EVENTS));
|
||||||
|
|
||||||
|
|
||||||
bg->AddChild(fCanvasView);
|
bg->AddChild(canvasScrollView);
|
||||||
#endif // __HAIKU__
|
#endif // __HAIKU__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,13 @@ Manipulator::DoubleClicked(BPoint where)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShowContextMenu
|
||||||
|
bool
|
||||||
|
Manipulator::ShowContextMenu(BPoint where)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ class Manipulator : public Observer {
|
|||||||
virtual bool MouseOver(BPoint where);
|
virtual bool MouseOver(BPoint where);
|
||||||
virtual bool DoubleClicked(BPoint where);
|
virtual bool DoubleClicked(BPoint where);
|
||||||
|
|
||||||
|
virtual bool ShowContextMenu(BPoint where);
|
||||||
|
|
||||||
virtual bool MessageReceived(BMessage* message,
|
virtual bool MessageReceived(BMessage* message,
|
||||||
Command** _command);
|
Command** _command);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,10 @@ MultipleManipulatorState::MessageReceived(BMessage* message,
|
|||||||
void
|
void
|
||||||
MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks)
|
MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks)
|
||||||
{
|
{
|
||||||
// NOTE: buttons currently ignored
|
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
|
||||||
|
_ShowContextMenu(where);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (clicks == 2
|
if (clicks == 2
|
||||||
&& fPreviousManipulator
|
&& fPreviousManipulator
|
||||||
@@ -281,3 +284,18 @@ MultipleManipulatorState::_UpdateCursor()
|
|||||||
else
|
else
|
||||||
fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
|
fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _ShowContextMenu
|
||||||
|
void
|
||||||
|
MultipleManipulatorState::_ShowContextMenu(BPoint where)
|
||||||
|
{
|
||||||
|
int32 count = fManipulators.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
Manipulator* manipulator =
|
||||||
|
(Manipulator*)fManipulators.ItemAtFast(i);
|
||||||
|
if (manipulator->ShowContextMenu(where))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ class MultipleManipulatorState : public ViewState {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void _UpdateCursor();
|
void _UpdateCursor();
|
||||||
|
void _ShowContextMenu(BPoint where);
|
||||||
|
|
||||||
|
|
||||||
BList fManipulators;
|
BList fManipulators;
|
||||||
Manipulator* fCurrentManipulator;
|
Manipulator* fCurrentManipulator;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
mouse_info::mouse_info()
|
mouse_info::mouse_info()
|
||||||
: buttons(0),
|
: buttons(0),
|
||||||
position(B_ORIGIN),
|
position(-1, -1),
|
||||||
transit(B_OUTSIDE_VIEW),
|
transit(B_OUTSIDE_VIEW),
|
||||||
modifiers(::modifiers())
|
modifiers(::modifiers())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ class ViewState {
|
|||||||
// modifiers
|
// modifiers
|
||||||
virtual void ModifiersChanged(uint32 modifiers);
|
virtual void ModifiersChanged(uint32 modifiers);
|
||||||
|
|
||||||
|
|
||||||
// TODO: mouse wheel
|
// TODO: mouse wheel
|
||||||
virtual bool HandleKeyDown(uint32 key, uint32 modifiers,
|
virtual bool HandleKeyDown(uint32 key, uint32 modifiers,
|
||||||
Command** _command);
|
Command** _command);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#include "AddPathsCommand.h"
|
#include "AddPathsCommand.h"
|
||||||
|
#include "CleanUpPathCommand.h"
|
||||||
#include "CommandStack.h"
|
#include "CommandStack.h"
|
||||||
#include "MovePathsCommand.h"
|
#include "MovePathsCommand.h"
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
@@ -236,6 +237,7 @@ enum {
|
|||||||
MSG_DUPLICATE = 'dupp',
|
MSG_DUPLICATE = 'dupp',
|
||||||
|
|
||||||
MSG_REVERSE = 'rvrs',
|
MSG_REVERSE = 'rvrs',
|
||||||
|
MSG_CLEAN_UP = 'clup',
|
||||||
MSG_ROTATE_INDICES = 'roti',
|
MSG_ROTATE_INDICES = 'roti',
|
||||||
|
|
||||||
MSG_REMOVE = 'remp',
|
MSG_REMOVE = 'remp',
|
||||||
@@ -430,6 +432,19 @@ PathListView::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSG_CLEAN_UP:
|
||||||
|
if (fCommandStack) {
|
||||||
|
PathListItem* item = dynamic_cast<PathListItem*>(
|
||||||
|
ItemAt(CurrentSelection(0)));
|
||||||
|
if (!item)
|
||||||
|
break;
|
||||||
|
|
||||||
|
CleanUpPathCommand* command
|
||||||
|
= new (nothrow) CleanUpPathCommand(item->path);
|
||||||
|
fCommandStack->Perform(command);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case MSG_REMOVE:
|
case MSG_REMOVE:
|
||||||
RemoveSelected();
|
RemoveSelected();
|
||||||
break;
|
break;
|
||||||
@@ -701,6 +716,7 @@ PathListView::SetMenu(BMenu* menu)
|
|||||||
new BMessage(MSG_ADD_ARC));
|
new BMessage(MSG_ADD_ARC));
|
||||||
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
||||||
fReverseMI = new BMenuItem("Reverse", new BMessage(MSG_REVERSE));
|
fReverseMI = new BMenuItem("Reverse", new BMessage(MSG_REVERSE));
|
||||||
|
fCleanUpMI = new BMenuItem("Clean Up", new BMessage(MSG_CLEAN_UP));
|
||||||
fRotateIndicesMI = new BMenuItem("Rotate Indices",
|
fRotateIndicesMI = new BMenuItem("Rotate Indices",
|
||||||
new BMessage(MSG_ROTATE_INDICES));
|
new BMessage(MSG_ROTATE_INDICES));
|
||||||
fRemoveMI = new BMenuItem("Remove", new BMessage(MSG_REMOVE));
|
fRemoveMI = new BMenuItem("Remove", new BMessage(MSG_REMOVE));
|
||||||
@@ -715,6 +731,7 @@ fAddArcMI->SetEnabled(false);
|
|||||||
|
|
||||||
fMenu->AddItem(fDuplicateMI);
|
fMenu->AddItem(fDuplicateMI);
|
||||||
fMenu->AddItem(fReverseMI);
|
fMenu->AddItem(fReverseMI);
|
||||||
|
fMenu->AddItem(fCleanUpMI);
|
||||||
fMenu->AddItem(fRotateIndicesMI);
|
fMenu->AddItem(fRotateIndicesMI);
|
||||||
|
|
||||||
fMenu->AddSeparatorItem();
|
fMenu->AddSeparatorItem();
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ class PathListView : public SimpleListView,
|
|||||||
BMenuItem* fAddArcMI;
|
BMenuItem* fAddArcMI;
|
||||||
BMenuItem* fDuplicateMI;
|
BMenuItem* fDuplicateMI;
|
||||||
BMenuItem* fReverseMI;
|
BMenuItem* fReverseMI;
|
||||||
|
BMenuItem* fCleanUpMI;
|
||||||
BMenuItem* fRotateIndicesMI;
|
BMenuItem* fRotateIndicesMI;
|
||||||
BMenuItem* fRemoveMI;
|
BMenuItem* fRemoveMI;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "AddShapesCommand.h"
|
#include "AddShapesCommand.h"
|
||||||
#include "AddStylesCommand.h"
|
#include "AddStylesCommand.h"
|
||||||
#include "CommandStack.h"
|
#include "CommandStack.h"
|
||||||
|
#include "FreezeTransformationCommand.h"
|
||||||
#include "MoveShapesCommand.h"
|
#include "MoveShapesCommand.h"
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
#include "RemoveShapesCommand.h"
|
#include "RemoveShapesCommand.h"
|
||||||
@@ -95,6 +96,7 @@ enum {
|
|||||||
MSG_REMOVE = 'rmsh',
|
MSG_REMOVE = 'rmsh',
|
||||||
MSG_DUPLICATE = 'dpsh',
|
MSG_DUPLICATE = 'dpsh',
|
||||||
MSG_RESET_TRANSFORMATION = 'rstr',
|
MSG_RESET_TRANSFORMATION = 'rstr',
|
||||||
|
MSG_FREEZE_TRANSFORMATION = 'frzt',
|
||||||
|
|
||||||
MSG_DRAG_SHAPE = 'drgs',
|
MSG_DRAG_SHAPE = 'drgs',
|
||||||
};
|
};
|
||||||
@@ -165,17 +167,9 @@ ShapeListView::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_RESET_TRANSFORMATION: {
|
case MSG_RESET_TRANSFORMATION: {
|
||||||
int32 count = CountSelectedItems();
|
|
||||||
BList shapes;
|
BList shapes;
|
||||||
for (int32 i = 0; i < count; i++) {
|
_GetSelectedShapes(shapes);
|
||||||
ShapeListItem* item = dynamic_cast<ShapeListItem*>(
|
int32 count = shapes.CountItems();
|
||||||
ItemAt(CurrentSelection(i)));
|
|
||||||
if (item && item->shape) {
|
|
||||||
if (!shapes.AddItem((void*)item->shape))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count = shapes.CountItems();
|
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -191,6 +185,20 @@ ShapeListView::MessageReceived(BMessage* message)
|
|||||||
fCommandStack->Perform(command);
|
fCommandStack->Perform(command);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSG_FREEZE_TRANSFORMATION: {
|
||||||
|
BList shapes;
|
||||||
|
_GetSelectedShapes(shapes);
|
||||||
|
int32 count = shapes.CountItems();
|
||||||
|
if (count < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
FreezeTransformationCommand* command =
|
||||||
|
new FreezeTransformationCommand((Shape**)shapes.Items(),
|
||||||
|
count);
|
||||||
|
|
||||||
|
fCommandStack->Perform(command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
SimpleListView::MessageReceived(message);
|
SimpleListView::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@@ -433,6 +441,8 @@ ShapeListView::SetMenu(BMenu* menu)
|
|||||||
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
||||||
fResetTransformationMI = new BMenuItem("Reset Transformation",
|
fResetTransformationMI = new BMenuItem("Reset Transformation",
|
||||||
new BMessage(MSG_RESET_TRANSFORMATION));
|
new BMessage(MSG_RESET_TRANSFORMATION));
|
||||||
|
fFreezeTransformationMI = new BMenuItem("Freeze Transformation",
|
||||||
|
new BMessage(MSG_FREEZE_TRANSFORMATION));
|
||||||
|
|
||||||
fRemoveMI = new BMenuItem("Remove", new BMessage(MSG_REMOVE));
|
fRemoveMI = new BMenuItem("Remove", new BMessage(MSG_REMOVE));
|
||||||
|
|
||||||
@@ -446,6 +456,7 @@ ShapeListView::SetMenu(BMenu* menu)
|
|||||||
|
|
||||||
fMenu->AddItem(fDuplicateMI);
|
fMenu->AddItem(fDuplicateMI);
|
||||||
fMenu->AddItem(fResetTransformationMI);
|
fMenu->AddItem(fResetTransformationMI);
|
||||||
|
fMenu->AddItem(fFreezeTransformationMI);
|
||||||
|
|
||||||
fMenu->AddSeparatorItem();
|
fMenu->AddSeparatorItem();
|
||||||
|
|
||||||
@@ -453,6 +464,7 @@ ShapeListView::SetMenu(BMenu* menu)
|
|||||||
|
|
||||||
fDuplicateMI->SetTarget(this);
|
fDuplicateMI->SetTarget(this);
|
||||||
fResetTransformationMI->SetTarget(this);
|
fResetTransformationMI->SetTarget(this);
|
||||||
|
fFreezeTransformationMI->SetTarget(this);
|
||||||
fRemoveMI->SetTarget(this);
|
fRemoveMI->SetTarget(this);
|
||||||
|
|
||||||
_UpdateMenu();
|
_UpdateMenu();
|
||||||
@@ -541,4 +553,17 @@ ShapeListView::_UpdateMenu()
|
|||||||
fRemoveMI->SetEnabled(gotSelection);
|
fRemoveMI->SetEnabled(gotSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _GetSelectedShapes
|
||||||
|
void
|
||||||
|
ShapeListView::_GetSelectedShapes(BList& shapes) const
|
||||||
|
{
|
||||||
|
int32 count = CountSelectedItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ShapeListItem* item = dynamic_cast<ShapeListItem*>(
|
||||||
|
ItemAt(CurrentSelection(i)));
|
||||||
|
if (item && item->shape) {
|
||||||
|
if (!shapes.AddItem((void*)item->shape))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ class ShapeListView : public SimpleListView,
|
|||||||
ShapeListItem* _ItemForShape(Shape* shape) const;
|
ShapeListItem* _ItemForShape(Shape* shape) const;
|
||||||
void _UpdateMenu();
|
void _UpdateMenu();
|
||||||
|
|
||||||
|
void _GetSelectedShapes(BList& shapes) const;
|
||||||
|
|
||||||
BMessage* fMessage;
|
BMessage* fMessage;
|
||||||
|
|
||||||
ShapeContainer* fShapeContainer;
|
ShapeContainer* fShapeContainer;
|
||||||
@@ -80,6 +82,7 @@ class ShapeListView : public SimpleListView,
|
|||||||
BMenuItem* fAddWidthPathAndStyleMI;
|
BMenuItem* fAddWidthPathAndStyleMI;
|
||||||
BMenuItem* fDuplicateMI;
|
BMenuItem* fDuplicateMI;
|
||||||
BMenuItem* fResetTransformationMI;
|
BMenuItem* fResetTransformationMI;
|
||||||
|
BMenuItem* fFreezeTransformationMI;
|
||||||
BMenuItem* fRemoveMI;
|
BMenuItem* fRemoveMI;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -477,19 +477,27 @@ DocumentBuilder::GetIcon(Icon* icon, SVGImporter* importer,
|
|||||||
yMax = ceil(yMax);
|
yMax = ceil(yMax);
|
||||||
|
|
||||||
BRect bounds;
|
BRect bounds;
|
||||||
if (fViewBox.IsValid())
|
if (fViewBox.IsValid()) {
|
||||||
bounds = fViewBox;
|
bounds = fViewBox;
|
||||||
else
|
printf("view box: ");
|
||||||
|
bounds.PrintToStream();
|
||||||
|
} else {
|
||||||
bounds.Set(0.0, 0.0, (int32)fWidth - 1, (int32)fHeight - 1);
|
bounds.Set(0.0, 0.0, (int32)fWidth - 1, (int32)fHeight - 1);
|
||||||
|
printf("width/height: ");
|
||||||
|
bounds.PrintToStream();
|
||||||
|
}
|
||||||
|
|
||||||
BRect boundingBox(xMin, yMin, xMax, yMax);
|
BRect boundingBox(xMin, yMin, xMax, yMax);
|
||||||
|
|
||||||
if (!bounds.IsValid() || !boundingBox.Intersects(bounds)) {
|
if (!bounds.IsValid() || !boundingBox.Intersects(bounds)) {
|
||||||
bounds = boundingBox;
|
bounds = boundingBox;
|
||||||
|
printf("using bounding box: ");
|
||||||
|
bounds.PrintToStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
float size = max_c(bounds.Width() + 1.0, bounds.Height() + 1.0);
|
float size = min_c(bounds.Width() + 1.0, bounds.Height() + 1.0);
|
||||||
double scale = 64.0 / size;
|
double scale = 64.0 / size;
|
||||||
|
printf("scale: %f\n", scale);
|
||||||
|
|
||||||
Transformable transform;
|
Transformable transform;
|
||||||
transform.TranslateBy(BPoint(-bounds.left, -bounds.top));
|
transform.TranslateBy(BPoint(-bounds.left, -bounds.top));
|
||||||
@@ -540,6 +548,8 @@ DocumentBuilder::EndGradient()
|
|||||||
fCurrentGradient = NULL;
|
fCurrentGradient = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
// _AddGradient
|
// _AddGradient
|
||||||
void
|
void
|
||||||
DocumentBuilder::_AddGradient(SVGGradient* gradient)
|
DocumentBuilder::_AddGradient(SVGGradient* gradient)
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#include <Cursor.h>
|
#include <Cursor.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#include "cursors.h"
|
#include "cursors.h"
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
//#include "ReversePathCommand.h"
|
//#include "ReversePathCommand.h"
|
||||||
//#include "SelectPathCommand.h"
|
//#include "SelectPathCommand.h"
|
||||||
//#include "SelectPointsCommand.h"
|
//#include "SelectPointsCommand.h"
|
||||||
|
#include "SplitPointsCommand.h"
|
||||||
#include "TransformPointsBox.h"
|
#include "TransformPointsBox.h"
|
||||||
|
|
||||||
#define POINT_EXTEND 3.0
|
#define POINT_EXTEND 3.0
|
||||||
@@ -65,6 +68,14 @@ enum {
|
|||||||
SELECT_SUB_PATH,
|
SELECT_SUB_PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSG_TRANSFORM = 'strn',
|
||||||
|
MSG_REMOVE_POINTS = 'srmp',
|
||||||
|
MSG_UPDATE_SHAPE_UI = 'udsi',
|
||||||
|
|
||||||
|
MSG_SPLIT_POINTS = 'splt',
|
||||||
|
};
|
||||||
|
|
||||||
inline const char*
|
inline const char*
|
||||||
string_for_mode(uint32 mode)
|
string_for_mode(uint32 mode)
|
||||||
{
|
{
|
||||||
@@ -480,18 +491,29 @@ PathManipulator::MouseDown(BPoint where)
|
|||||||
_RemovePointOut(fCurrentPathPoint);
|
_RemovePointOut(fCurrentPathPoint);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SELECT_POINTS:
|
case SELECT_POINTS: {
|
||||||
if (!fShiftDown) {
|
// TODO: this works so that you can deselect all points
|
||||||
|
// when clicking outside the path even if pressing shift
|
||||||
|
// in case the path is open... a better way would be
|
||||||
|
// to deselect all on mouse up, if the mouse has not moved
|
||||||
|
bool appendSelection;
|
||||||
|
if (fPath->IsClosed())
|
||||||
|
appendSelection = fShiftDown;
|
||||||
|
else
|
||||||
|
appendSelection = fShiftDown && fCurrentPathPoint >= 0;
|
||||||
|
|
||||||
|
if (!appendSelection) {
|
||||||
fSelection->MakeEmpty();
|
fSelection->MakeEmpty();
|
||||||
_UpdateSelection();
|
_UpdateSelection();
|
||||||
}
|
}
|
||||||
*fOldSelection = *fSelection;
|
*fOldSelection = *fSelection;
|
||||||
if (fCurrentPathPoint >= 0) {
|
if (fCurrentPathPoint >= 0) {
|
||||||
_Select(fCurrentPathPoint, fShiftDown);
|
_Select(fCurrentPathPoint, appendSelection);
|
||||||
}
|
}
|
||||||
fCanvasView->BeginRectTracking(BRect(where, where),
|
fCanvasView->BeginRectTracking(BRect(where, where),
|
||||||
B_TRACK_RECT_CORNER);
|
B_TRACK_RECT_CORNER);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fTrackingStart = canvasWhere;
|
fTrackingStart = canvasWhere;
|
||||||
@@ -707,6 +729,52 @@ PathManipulator::DoubleClicked(BPoint where)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShowContextMenu
|
||||||
|
bool
|
||||||
|
PathManipulator::ShowContextMenu(BPoint where)
|
||||||
|
{
|
||||||
|
BPopUpMenu* menu = new BPopUpMenu("context menu", false, false);
|
||||||
|
BMessage* message;
|
||||||
|
BMenuItem* item;
|
||||||
|
|
||||||
|
bool hasSelection = fSelection->CountItems() > 0;
|
||||||
|
|
||||||
|
message = new BMessage(B_SELECT_ALL);
|
||||||
|
item = new BMenuItem("Select All", message, 'A');
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
message = new BMessage(MSG_TRANSFORM);
|
||||||
|
item = new BMenuItem("Transform", message);
|
||||||
|
item->SetEnabled(hasSelection);
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
message = new BMessage(MSG_SPLIT_POINTS);
|
||||||
|
item = new BMenuItem("Split", message);
|
||||||
|
item->SetEnabled(hasSelection);
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
message = new BMessage(MSG_REMOVE_POINTS);
|
||||||
|
item = new BMenuItem("Remove", message, 'A');
|
||||||
|
item->SetEnabled(hasSelection);
|
||||||
|
menu->AddItem(item);
|
||||||
|
|
||||||
|
// go
|
||||||
|
menu->SetTargetForItems(fCanvasView);
|
||||||
|
menu->SetAsyncAutoDestruct(true);
|
||||||
|
menu->SetFont(be_plain_font);
|
||||||
|
where = fCanvasView->ConvertToScreen(where);
|
||||||
|
BRect mouseRect(where, where);
|
||||||
|
mouseRect.InsetBy(-10.0, -10.0);
|
||||||
|
where += BPoint(5.0, 5.0);
|
||||||
|
menu->Go(where, true, false, mouseRect, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
// Bounds
|
// Bounds
|
||||||
BRect
|
BRect
|
||||||
PathManipulator::Bounds()
|
PathManipulator::Bounds()
|
||||||
@@ -725,25 +793,24 @@ PathManipulator::TrackingBounds(BView* withinView)
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
enum {
|
|
||||||
MSG_SHAPE_TRANSFORM = 'strn',
|
|
||||||
MSG_SHAPE_REMOVE_POINTS = 'srmp',
|
|
||||||
MSG_UPDATE_SHAPE_UI = 'udsi',
|
|
||||||
};
|
|
||||||
|
|
||||||
// MessageReceived
|
// MessageReceived
|
||||||
bool
|
bool
|
||||||
PathManipulator::MessageReceived(BMessage* message, Command** _command)
|
PathManipulator::MessageReceived(BMessage* message, Command** _command)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case MSG_SHAPE_TRANSFORM:
|
case MSG_TRANSFORM:
|
||||||
if (!fSelection->IsEmpty())
|
if (!fSelection->IsEmpty())
|
||||||
_SetMode(TRANSFORM_POINTS);
|
_SetMode(TRANSFORM_POINTS);
|
||||||
break;
|
break;
|
||||||
case MSG_SHAPE_REMOVE_POINTS:
|
case MSG_REMOVE_POINTS:
|
||||||
*_command = _Delete();
|
*_command = _Delete();
|
||||||
break;
|
break;
|
||||||
|
case MSG_SPLIT_POINTS:
|
||||||
|
*_command = new SplitPointsCommand(fPath,
|
||||||
|
fSelection->Items(),
|
||||||
|
fSelection->CountItems());
|
||||||
|
break;
|
||||||
case B_SELECT_ALL: {
|
case B_SELECT_ALL: {
|
||||||
*fOldSelection = *fSelection;
|
*fOldSelection = *fSelection;
|
||||||
fSelection->MakeEmpty();
|
fSelection->MakeEmpty();
|
||||||
@@ -1292,10 +1359,12 @@ void
|
|||||||
PathManipulator::_Select(BRect r)
|
PathManipulator::_Select(BRect r)
|
||||||
{
|
{
|
||||||
BPoint p;
|
BPoint p;
|
||||||
|
BPoint pIn;
|
||||||
|
BPoint pOut;
|
||||||
int32 count = fPath->CountPoints();
|
int32 count = fPath->CountPoints();
|
||||||
Selection temp;
|
Selection temp;
|
||||||
for (int32 i = 0; i < count && fPath->GetPointAt(i, p); i++) {
|
for (int32 i = 0; i < count && fPath->GetPointsAt(i, p, pIn, pOut); i++) {
|
||||||
if (r.Contains(p)) {
|
if (r.Contains(p) || r.Contains(pIn) || r.Contains(pOut)) {
|
||||||
temp.Add(i);
|
temp.Add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ class PathManipulator : public Manipulator,
|
|||||||
virtual bool MouseOver(BPoint where);
|
virtual bool MouseOver(BPoint where);
|
||||||
virtual bool DoubleClicked(BPoint where);
|
virtual bool DoubleClicked(BPoint where);
|
||||||
|
|
||||||
|
virtual bool ShowContextMenu(BPoint where);
|
||||||
|
|
||||||
virtual BRect Bounds();
|
virtual BRect Bounds();
|
||||||
virtual BRect TrackingBounds(BView* withinView);
|
virtual BRect TrackingBounds(BView* withinView);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CleanUpPathCommand.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
CleanUpPathCommand::CleanUpPathCommand(VectorPath* path)
|
||||||
|
: PathCommand(path),
|
||||||
|
fOriginalPath()
|
||||||
|
{
|
||||||
|
if (fPath)
|
||||||
|
fOriginalPath = *fPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
CleanUpPathCommand::~CleanUpPathCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform
|
||||||
|
status_t
|
||||||
|
CleanUpPathCommand::Perform()
|
||||||
|
{
|
||||||
|
fPath->CleanUp();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undo
|
||||||
|
status_t
|
||||||
|
CleanUpPathCommand::Undo()
|
||||||
|
{
|
||||||
|
*fPath = fOriginalPath;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName
|
||||||
|
void
|
||||||
|
CleanUpPathCommand::GetName(BString& name)
|
||||||
|
{
|
||||||
|
name << "Clean Up Path";
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLEAN_UP_PATH_COMMAND_H
|
||||||
|
#define CLEAN_UP_PATH_COMMAND_H
|
||||||
|
|
||||||
|
#include "PathCommand.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
class CleanUpPathCommand : public PathCommand {
|
||||||
|
public:
|
||||||
|
CleanUpPathCommand(VectorPath* path);
|
||||||
|
virtual ~CleanUpPathCommand();
|
||||||
|
|
||||||
|
virtual status_t Perform();
|
||||||
|
virtual status_t Undo();
|
||||||
|
|
||||||
|
virtual void GetName(BString& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
VectorPath fOriginalPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLEAN_UP_PATH_COMMAND_H
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreezeTransformationCommand.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Gradient.h"
|
||||||
|
#include "Shape.h"
|
||||||
|
#include "Style.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
FreezeTransformationCommand::FreezeTransformationCommand(
|
||||||
|
Shape** const shapes,
|
||||||
|
int32 count)
|
||||||
|
: Command(),
|
||||||
|
fShapes(shapes && count > 0 ? new (nothrow) Shape*[count] : NULL),
|
||||||
|
fOriginalTransformations(count > 0 ? new (nothrow) double[
|
||||||
|
count * Transformable::matrix_size]
|
||||||
|
: NULL),
|
||||||
|
fCount(count)
|
||||||
|
{
|
||||||
|
if (!fShapes || !fOriginalTransformations)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(fShapes, shapes, sizeof(Shape*) * fCount);
|
||||||
|
|
||||||
|
bool initOk = false;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
if (!fShapes[i])
|
||||||
|
continue;
|
||||||
|
if (!fShapes[i]->IsIdentity())
|
||||||
|
initOk = true;
|
||||||
|
fShapes[i]->StoreTo(&fOriginalTransformations[
|
||||||
|
i * Transformable::matrix_size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initOk) {
|
||||||
|
delete[] fShapes;
|
||||||
|
fShapes = NULL;
|
||||||
|
delete[] fOriginalTransformations;
|
||||||
|
fOriginalTransformations = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
FreezeTransformationCommand::~FreezeTransformationCommand()
|
||||||
|
{
|
||||||
|
delete[] fShapes;
|
||||||
|
delete[] fOriginalTransformations;
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
FreezeTransformationCommand::InitCheck()
|
||||||
|
{
|
||||||
|
return fShapes && fOriginalTransformations ? B_OK : B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform
|
||||||
|
status_t
|
||||||
|
FreezeTransformationCommand::Perform()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
if (!fShapes[i] || fShapes[i]->IsIdentity())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_ApplyTransformation(fShapes[i], *(fShapes[i]));
|
||||||
|
fShapes[i]->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undo
|
||||||
|
status_t
|
||||||
|
FreezeTransformationCommand::Undo()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
if (!fShapes[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// restore original transformation
|
||||||
|
fShapes[i]->LoadFrom(&fOriginalTransformations[
|
||||||
|
i * Transformable::matrix_size]);
|
||||||
|
|
||||||
|
Transformable transform(*(fShapes[i]));
|
||||||
|
if (!transform.IsValid() || transform.IsIdentity())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
transform.Invert();
|
||||||
|
_ApplyTransformation(fShapes[i], transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName
|
||||||
|
void
|
||||||
|
FreezeTransformationCommand::GetName(BString& name)
|
||||||
|
{
|
||||||
|
if (fCount > 1)
|
||||||
|
name << "Freeze Shapes";
|
||||||
|
else
|
||||||
|
name << "Freeze Shape";
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _ApplyTransformation
|
||||||
|
void
|
||||||
|
FreezeTransformationCommand::_ApplyTransformation(Shape* shape,
|
||||||
|
const Transformable& transform)
|
||||||
|
{
|
||||||
|
// apply inverse of old shape transformation to every assigned path
|
||||||
|
int32 pathCount = shape->Paths()->CountPaths();
|
||||||
|
for (int32 i = 0; i < pathCount; i++) {
|
||||||
|
VectorPath* path = shape->Paths()->PathAtFast(i);
|
||||||
|
int32 shapes = 0;
|
||||||
|
int32 listeners = path->CountListeners();
|
||||||
|
for (int32 j = 0; j < listeners; j++) {
|
||||||
|
if (dynamic_cast<Shape*>(path->ListenerAtFast(j)))
|
||||||
|
shapes++;
|
||||||
|
}
|
||||||
|
// only freeze transformation of path if only one
|
||||||
|
// shape has it assigned
|
||||||
|
if (shapes == 1) {
|
||||||
|
path->ApplyTransform(transform);
|
||||||
|
} else {
|
||||||
|
printf("Not transfering transformation of \"%s\" onto "
|
||||||
|
"path \"%s\", because %ld other shapes "
|
||||||
|
"have it assigned.\n", shape->Name(), path->Name(),
|
||||||
|
shapes - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// take care of style too
|
||||||
|
if (shape->Style() && shape->Style()->Gradient()) {
|
||||||
|
// TODO: not if more than one shape have this style assigned!
|
||||||
|
shape->Style()->Gradient()->Multiply(transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FREEZE_TRANSFORMATION_COMMAND_H
|
||||||
|
#define FREEZE_TRANSFORMATION_COMMAND_H
|
||||||
|
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class Shape;
|
||||||
|
class Transformable;
|
||||||
|
|
||||||
|
class FreezeTransformationCommand : public Command {
|
||||||
|
public:
|
||||||
|
FreezeTransformationCommand(
|
||||||
|
Shape** const shapes,
|
||||||
|
int32 count);
|
||||||
|
virtual ~FreezeTransformationCommand();
|
||||||
|
|
||||||
|
virtual status_t InitCheck();
|
||||||
|
|
||||||
|
virtual status_t Perform();
|
||||||
|
virtual status_t Undo();
|
||||||
|
|
||||||
|
virtual void GetName(BString& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _ApplyTransformation(Shape* shape,
|
||||||
|
const Transformable& transform);
|
||||||
|
|
||||||
|
Shape** fShapes;
|
||||||
|
double* fOriginalTransformations;
|
||||||
|
int32 fCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FREEZE_TRANSFORMATION_COMMAND_H
|
||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ReversePathCommand.h"
|
#include "ReversePathCommand.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef REVERSE_PATH_COMMAND_H
|
#ifndef REVERSE_PATH_COMMAND_H
|
||||||
#define REVERSE_PATH_COMMAND_H
|
#define REVERSE_PATH_COMMAND_H
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SplitPointsCommand.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
using std::nothrow;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
// * when hitting the Delete key, so the selected points are the
|
||||||
|
// same as the ones to be removed
|
||||||
|
SplitPointsCommand::SplitPointsCommand(VectorPath* path,
|
||||||
|
const int32* indices,
|
||||||
|
int32 count)
|
||||||
|
: PathCommand(path),
|
||||||
|
fIndex(NULL),
|
||||||
|
fPoint(NULL),
|
||||||
|
fPointIn(NULL),
|
||||||
|
fPointOut(NULL),
|
||||||
|
fConnected(NULL),
|
||||||
|
fCount(0)
|
||||||
|
{
|
||||||
|
if (indices && count > 0) {
|
||||||
|
fIndex = new (nothrow) int32[count];
|
||||||
|
fPoint = new (nothrow) BPoint[count];
|
||||||
|
fPointIn = new (nothrow) BPoint[count];
|
||||||
|
fPointOut = new (nothrow) BPoint[count];
|
||||||
|
fConnected = new (nothrow) bool[count];
|
||||||
|
fCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InitCheck() < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(fIndex, indices, count * sizeof(int32));
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
if (!fPath->GetPointsAt(fIndex[i],
|
||||||
|
fPoint[i],
|
||||||
|
fPointIn[i],
|
||||||
|
fPointOut[i],
|
||||||
|
&fConnected[i])) {
|
||||||
|
fPath = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
SplitPointsCommand::~SplitPointsCommand()
|
||||||
|
{
|
||||||
|
delete[] fIndex;
|
||||||
|
delete[] fPoint;
|
||||||
|
delete[] fPointIn;
|
||||||
|
delete[] fPointOut;
|
||||||
|
delete[] fConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
SplitPointsCommand::InitCheck()
|
||||||
|
{
|
||||||
|
status_t status = PathCommand::InitCheck();
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
if (!fIndex || !fPoint || !fPointIn || !fPointOut || !fConnected)
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform
|
||||||
|
status_t
|
||||||
|
SplitPointsCommand::Perform()
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
AutoNotificationSuspender _(fPath);
|
||||||
|
|
||||||
|
// NOTE: fCount guaranteed > 0
|
||||||
|
// add points again at their respective index
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
int32 index = fIndex[i] + 1 + i;
|
||||||
|
// "+ 1" to insert behind existing point
|
||||||
|
// "+ i" to adjust for already inserted points
|
||||||
|
if (fPath->AddPoint(fPoint[i], index)) {
|
||||||
|
fPath->SetPoint(index - 1,
|
||||||
|
fPoint[i],
|
||||||
|
fPointIn[i],
|
||||||
|
fPoint[i],
|
||||||
|
true);
|
||||||
|
fPath->SetPoint(index,
|
||||||
|
fPoint[i],
|
||||||
|
fPoint[i],
|
||||||
|
fPointOut[i],
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Undo
|
||||||
|
status_t
|
||||||
|
SplitPointsCommand::Undo()
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
AutoNotificationSuspender _(fPath);
|
||||||
|
|
||||||
|
// remove inserted points and reset modified
|
||||||
|
// points to previous condition
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
int32 index = fIndex[i] + 1;
|
||||||
|
if (fPath->RemovePoint(index)) {
|
||||||
|
fPath->SetPoint(index - 1,
|
||||||
|
fPoint[i],
|
||||||
|
fPointIn[i],
|
||||||
|
fPointOut[i],
|
||||||
|
fConnected[i]);
|
||||||
|
} else {
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status >= B_OK) {
|
||||||
|
// restore selection
|
||||||
|
_Select(fIndex, fCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName
|
||||||
|
void
|
||||||
|
SplitPointsCommand::GetName(BString& name)
|
||||||
|
{
|
||||||
|
if (fCount > 1)
|
||||||
|
name << "Split Control Points";
|
||||||
|
else
|
||||||
|
name << "Split Control Point";
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPLIT_POINTS_COMMAND_H
|
||||||
|
#define SPLIT_POINTS_COMMAND_H
|
||||||
|
|
||||||
|
#include "PathCommand.h"
|
||||||
|
|
||||||
|
class BPoint;
|
||||||
|
|
||||||
|
class SplitPointsCommand : public PathCommand {
|
||||||
|
public:
|
||||||
|
SplitPointsCommand(VectorPath* path,
|
||||||
|
const int32* indices,
|
||||||
|
int32 count);
|
||||||
|
virtual ~SplitPointsCommand();
|
||||||
|
|
||||||
|
virtual status_t InitCheck();
|
||||||
|
|
||||||
|
virtual status_t Perform();
|
||||||
|
virtual status_t Undo();
|
||||||
|
|
||||||
|
virtual void GetName(BString& name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32* fIndex;
|
||||||
|
BPoint* fPoint;
|
||||||
|
BPoint* fPointIn;
|
||||||
|
BPoint* fPointOut;
|
||||||
|
bool* fConnected;
|
||||||
|
int32 fCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPLIT_POINTS_COMMAND_H
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TransformPointsCommand.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ChannelTransform.h"
|
||||||
|
#include "VectorPath.h"
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
TransformPointsCommand::TransformPointsCommand(
|
||||||
|
TransformBox* box,
|
||||||
|
|
||||||
|
VectorPath* path,
|
||||||
|
const int32* indices,
|
||||||
|
const control_point* points,
|
||||||
|
int32 count,
|
||||||
|
|
||||||
|
BPoint pivot,
|
||||||
|
BPoint translation,
|
||||||
|
double rotation,
|
||||||
|
double xScale,
|
||||||
|
double yScale,
|
||||||
|
|
||||||
|
const char* name,
|
||||||
|
int32 nameIndex)
|
||||||
|
: TransformCommand(pivot,
|
||||||
|
translation,
|
||||||
|
rotation,
|
||||||
|
xScale,
|
||||||
|
yScale,
|
||||||
|
name,
|
||||||
|
nameIndex),
|
||||||
|
fTransformBox(box),
|
||||||
|
fPath(path),
|
||||||
|
fIndices(indices && count > 0 ?
|
||||||
|
new (nothrow) int32[count] : NULL),
|
||||||
|
fPoints(points && count > 0 ?
|
||||||
|
new (nothrow) control_point[count] : NULL),
|
||||||
|
fCount(count)
|
||||||
|
{
|
||||||
|
if (!fIndices || !fPoints)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(fIndices, indices, fCount * sizeof(int32));
|
||||||
|
memcpy(fPoints, points, fCount * sizeof(control_point));
|
||||||
|
|
||||||
|
if (fTransformBox)
|
||||||
|
fTransformBox->AddListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
TransformPointsCommand::~TransformPointsCommand()
|
||||||
|
{
|
||||||
|
if (fTransformBox)
|
||||||
|
fTransformBox->RemoveListener(this);
|
||||||
|
|
||||||
|
delete[] fIndices;
|
||||||
|
delete[] fPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
TransformPointsCommand::InitCheck()
|
||||||
|
{
|
||||||
|
return fPath && fIndices && fPoints ? TransformCommand::InitCheck()
|
||||||
|
: B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// TransformBoxDeleted
|
||||||
|
void
|
||||||
|
TransformPointsCommand::TransformBoxDeleted(
|
||||||
|
const TransformBox* box)
|
||||||
|
{
|
||||||
|
if (fTransformBox == box) {
|
||||||
|
if (fTransformBox)
|
||||||
|
fTransformBox->RemoveListener(this);
|
||||||
|
fTransformBox = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// _SetTransformation
|
||||||
|
status_t
|
||||||
|
TransformPointsCommand::_SetTransformation(
|
||||||
|
BPoint pivot, BPoint translation,
|
||||||
|
double rotation,
|
||||||
|
double xScale, double yScale) const
|
||||||
|
{
|
||||||
|
if (fTransformBox) {
|
||||||
|
fTransformBox->SetTransformation(pivot, translation,
|
||||||
|
rotation, xScale, yScale);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ChannelTransform transform;
|
||||||
|
transform.SetTransformation(pivot, translation,
|
||||||
|
rotation, xScale, yScale);
|
||||||
|
// restore original points and apply transformation
|
||||||
|
for (int32 i = 0; i < fCount; i++) {
|
||||||
|
BPoint point = transform.Transform(fPoints[i].point);
|
||||||
|
BPoint pointIn = transform.Transform(fPoints[i].point_in);
|
||||||
|
BPoint pointOut = transform.Transform(fPoints[i].point_out);
|
||||||
|
if (!fPath->SetPoint(fIndices[i], point, pointIn, pointOut,
|
||||||
|
fPoints[i].connected))
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Stephan Aßmus <superstippi@gmx.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRANSFORM_POINTS_COMMAND_H
|
||||||
|
#define TRANSFORM_POINTS_COMMAND_H
|
||||||
|
|
||||||
|
#include "TransformBox.h"
|
||||||
|
#include "TransformCommand.h"
|
||||||
|
|
||||||
|
class Transformable;
|
||||||
|
class VectorPath;
|
||||||
|
struct control_point;
|
||||||
|
|
||||||
|
class TransformPointsCommand : public TransformCommand,
|
||||||
|
public TransformBoxListener {
|
||||||
|
public:
|
||||||
|
TransformPointsCommand(
|
||||||
|
TransformBox* box,
|
||||||
|
|
||||||
|
VectorPath* path,
|
||||||
|
const int32* indices,
|
||||||
|
const control_point* points,
|
||||||
|
int32 count,
|
||||||
|
|
||||||
|
BPoint pivot,
|
||||||
|
BPoint translation,
|
||||||
|
double rotation,
|
||||||
|
double xScale,
|
||||||
|
double yScale,
|
||||||
|
|
||||||
|
const char* name,
|
||||||
|
int32 nameIndex);
|
||||||
|
virtual ~TransformPointsCommand();
|
||||||
|
|
||||||
|
// Command interface
|
||||||
|
virtual status_t InitCheck();
|
||||||
|
|
||||||
|
// TransformBoxListener interface
|
||||||
|
virtual void TransformBoxDeleted(
|
||||||
|
const TransformBox* box);
|
||||||
|
protected:
|
||||||
|
// TransformCommand interface
|
||||||
|
virtual status_t _SetTransformation(BPoint pivotDiff,
|
||||||
|
BPoint translationDiff,
|
||||||
|
double rotationDiff,
|
||||||
|
double xScaleDiff,
|
||||||
|
double yScaleDiff) const;
|
||||||
|
|
||||||
|
TransformBox* fTransformBox;
|
||||||
|
|
||||||
|
VectorPath* fPath;
|
||||||
|
|
||||||
|
int32* fIndices;
|
||||||
|
control_point* fPoints;
|
||||||
|
int32 fCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSFORM_POINTS_COMMAND_H
|
||||||
@@ -12,9 +12,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
//#include "ExitTransformPointsCommand.h"
|
|
||||||
#include "StateView.h"
|
#include "StateView.h"
|
||||||
//#include "TransformPointsCommand.h"
|
#include "TransformPointsCommand.h"
|
||||||
#include "VectorPath.h"
|
#include "VectorPath.h"
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
@@ -118,19 +117,20 @@ TransformCommand*
|
|||||||
TransformPointsBox::MakeCommand(const char* commandName,
|
TransformPointsBox::MakeCommand(const char* commandName,
|
||||||
uint32 nameIndex)
|
uint32 nameIndex)
|
||||||
{
|
{
|
||||||
return NULL;
|
return new TransformPointsCommand(this, fPath,
|
||||||
// return new TransformPointsAction(fManipulator,
|
|
||||||
// fIndices,
|
fIndices,
|
||||||
// fPoints,
|
fPoints,
|
||||||
// fCount,
|
fCount,
|
||||||
//// Translation(),
|
|
||||||
//// LocalRotation(),
|
Pivot(),
|
||||||
//// LocalXScale(),
|
Translation(),
|
||||||
//// LocalYScale(),
|
LocalRotation(),
|
||||||
// *this,
|
LocalXScale(),
|
||||||
// CenterOffset(),
|
LocalYScale(),
|
||||||
// actionName,
|
|
||||||
// nameIndex);
|
commandName,
|
||||||
|
nameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|||||||
Reference in New Issue
Block a user