* 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)),
|
||||
fDirtyIconArea(fBitmap->Bounds()),
|
||||
|
||||
fCanvasOrigin(50.0, 50.0),
|
||||
fZoomLevel(8.0),
|
||||
fCanvasOrigin(0.0, 0.0),
|
||||
fZoomLevel(1.0),
|
||||
|
||||
fMouseFilterMode(SNAPPING_OFF),
|
||||
|
||||
@@ -68,6 +68,8 @@ CanvasView::AttachedToWindow()
|
||||
SetHighColor(kStripesLow);
|
||||
|
||||
_AllocBackBitmap(Bounds().Width(), Bounds().Height());
|
||||
|
||||
_SetZoom(8.0);
|
||||
}
|
||||
|
||||
// FrameResized
|
||||
@@ -140,6 +142,25 @@ CanvasView::MouseMoved(BPoint where, uint32 transit,
|
||||
|
||||
// #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
|
||||
void
|
||||
CanvasView::AreaInvalidated(const BRect& area)
|
||||
@@ -240,6 +261,13 @@ CanvasView::_HandleKeyDown(uint32 key, uint32 modifiers)
|
||||
CommandStack()->Undo();
|
||||
break;
|
||||
|
||||
case '+':
|
||||
_SetZoom(_NextZoomInLevel(fZoomLevel));
|
||||
break;
|
||||
case '-':
|
||||
_SetZoom(_NextZoomOutLevel(fZoomLevel));
|
||||
break;
|
||||
|
||||
default:
|
||||
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
|
||||
|
||||
#include "Icon.h"
|
||||
#include "Scrollable.h"
|
||||
#include "StateView.h"
|
||||
|
||||
class BBitmap;
|
||||
@@ -23,6 +24,7 @@ enum {
|
||||
};
|
||||
|
||||
class CanvasView : public StateView,
|
||||
public Scrollable,
|
||||
public IconListener {
|
||||
public:
|
||||
CanvasView(BRect frame);
|
||||
@@ -37,7 +39,16 @@ class CanvasView : public StateView,
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
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
|
||||
public:
|
||||
virtual void AreaInvalidated(const BRect& area);
|
||||
|
||||
// CanvasView
|
||||
@@ -74,6 +85,11 @@ class CanvasView : public StateView,
|
||||
void _MakeBackground();
|
||||
|
||||
private:
|
||||
double _NextZoomInLevel(double zoom) const;
|
||||
double _NextZoomOutLevel(double zoom) const;
|
||||
void _SetZoom(double zoomLevel);
|
||||
BRect _LayoutCanvas();
|
||||
|
||||
BBitmap* fBitmap;
|
||||
BBitmap* fBackground;
|
||||
|
||||
@@ -82,7 +98,7 @@ class CanvasView : public StateView,
|
||||
BRect fDirtyIconArea;
|
||||
|
||||
BPoint fCanvasOrigin;
|
||||
float fZoomLevel;
|
||||
double fZoomLevel;
|
||||
|
||||
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
|
||||
IconEditorApp::IconEditorApp()
|
||||
: BApplication("application/x-vnd.Haiku-Icon-O-Matic"),
|
||||
: BApplication("application/x-vnd.haiku-icon_o_matic"),
|
||||
fMainWindow(NULL),
|
||||
fDocument(new Document("test")),
|
||||
|
||||
@@ -275,17 +275,24 @@ IconEditorApp::_Open(const entry_ref& ref, bool append)
|
||||
if (!icon)
|
||||
return;
|
||||
|
||||
enum {
|
||||
REF_NONE = 0,
|
||||
REF_MESSAGE,
|
||||
REF_FLAT
|
||||
};
|
||||
uint32 refMode = REF_NONE;
|
||||
|
||||
// try different file types
|
||||
FlatIconImporter flatImporter;
|
||||
status_t ret = flatImporter.Import(icon, &file);
|
||||
if (ret >= B_OK) {
|
||||
fDocument->SetExportRef(ref);
|
||||
refMode = REF_FLAT;
|
||||
} else {
|
||||
file.Seek(0, SEEK_SET);
|
||||
MessageImporter msgImporter;
|
||||
ret = msgImporter.Import(icon, &file);
|
||||
if (ret >= B_OK) {
|
||||
fDocument->SetRef(ref);
|
||||
refMode = REF_MESSAGE;
|
||||
} else {
|
||||
file.Seek(0, SEEK_SET);
|
||||
SVGImporter svgImporter;
|
||||
@@ -315,8 +322,18 @@ IconEditorApp::_Open(const entry_ref& ref, bool append)
|
||||
fMainWindow->SetIcon(NULL);
|
||||
|
||||
fDocument->MakeEmpty();
|
||||
|
||||
fDocument->SetIcon(icon);
|
||||
|
||||
switch (refMode) {
|
||||
case REF_MESSAGE:
|
||||
fDocument->SetRef(ref);
|
||||
break;
|
||||
case REF_FLAT:
|
||||
fDocument->SetExportRef(ref);
|
||||
break;
|
||||
}
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (mainWindowLocked) {
|
||||
|
||||
@@ -231,6 +231,8 @@ Application Icon-O-Matic :
|
||||
AddShapesCommand.cpp
|
||||
AddTransformersCommand.cpp
|
||||
ChangePointCommand.cpp
|
||||
CleanUpPathCommand.cpp
|
||||
FreezeTransformationCommand.cpp
|
||||
InsertPointCommand.cpp
|
||||
MoveShapesCommand.cpp
|
||||
MovePathsCommand.cpp
|
||||
@@ -242,6 +244,8 @@ Application Icon-O-Matic :
|
||||
RemoveShapesCommand.cpp
|
||||
RemoveTransformersCommand.cpp
|
||||
ReversePathCommand.cpp
|
||||
SplitPointsCommand.cpp
|
||||
TransformPointsCommand.cpp
|
||||
UnassignPathCommand.cpp
|
||||
|
||||
# style
|
||||
@@ -274,6 +278,8 @@ Application Icon-O-Matic :
|
||||
Util.cpp
|
||||
|
||||
: be tracker translation libagg.a libexpat.a
|
||||
|
||||
: Icon-O-Matic.rdef
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -247,6 +247,8 @@ case MSG_SHAPE_SELECTED: {
|
||||
Shape* shape;
|
||||
if (message->FindPointer("shape", (void**)&shape) < B_OK)
|
||||
shape = NULL;
|
||||
if (!fIcon || !fIcon->Shapes()->HasShape(shape))
|
||||
shape = NULL;
|
||||
|
||||
fPathListView->SetCurrentShape(shape);
|
||||
fStyleListView->SetCurrentShape(shape);
|
||||
@@ -707,10 +709,21 @@ MainWindow::_CreateGUI(BRect bounds)
|
||||
// canvas view
|
||||
bounds.left = splitWidth;
|
||||
bounds.top = fSwatchGroup->Frame().bottom + 1;
|
||||
bounds.right = bg->Bounds().right;
|
||||
bounds.bottom = bg->Bounds().bottom;
|
||||
bounds.right = bg->Bounds().right - B_V_SCROLL_BAR_WIDTH;
|
||||
bounds.bottom = bg->Bounds().bottom - B_H_SCROLL_BAR_HEIGHT;
|
||||
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
|
||||
bounds.left = 5;
|
||||
bounds.top = fSwatchGroup->Frame().top + 5;
|
||||
@@ -882,7 +895,7 @@ MainWindow::_CreateGUI(BRect bounds)
|
||||
B_WILL_DRAW | B_FRAME_EVENTS));
|
||||
|
||||
|
||||
bg->AddChild(fCanvasView);
|
||||
bg->AddChild(canvasScrollView);
|
||||
#endif // __HAIKU__
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,13 @@ Manipulator::DoubleClicked(BPoint where)
|
||||
return false;
|
||||
}
|
||||
|
||||
// ShowContextMenu
|
||||
bool
|
||||
Manipulator::ShowContextMenu(BPoint where)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
bool
|
||||
|
||||
@@ -33,6 +33,8 @@ class Manipulator : public Observer {
|
||||
virtual bool MouseOver(BPoint where);
|
||||
virtual bool DoubleClicked(BPoint where);
|
||||
|
||||
virtual bool ShowContextMenu(BPoint where);
|
||||
|
||||
virtual bool MessageReceived(BMessage* message,
|
||||
Command** _command);
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ MultipleManipulatorState::MessageReceived(BMessage* message,
|
||||
void
|
||||
MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks)
|
||||
{
|
||||
// NOTE: buttons currently ignored
|
||||
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
|
||||
_ShowContextMenu(where);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clicks == 2
|
||||
&& fPreviousManipulator
|
||||
@@ -281,3 +284,18 @@ MultipleManipulatorState::_UpdateCursor()
|
||||
else
|
||||
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:
|
||||
void _UpdateCursor();
|
||||
void _ShowContextMenu(BPoint where);
|
||||
|
||||
|
||||
BList fManipulators;
|
||||
Manipulator* fCurrentManipulator;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
mouse_info::mouse_info()
|
||||
: buttons(0),
|
||||
position(B_ORIGIN),
|
||||
position(-1, -1),
|
||||
transit(B_OUTSIDE_VIEW),
|
||||
modifiers(::modifiers())
|
||||
{
|
||||
|
||||
@@ -51,7 +51,6 @@ class ViewState {
|
||||
// modifiers
|
||||
virtual void ModifiersChanged(uint32 modifiers);
|
||||
|
||||
|
||||
// TODO: mouse wheel
|
||||
virtual bool HandleKeyDown(uint32 key, uint32 modifiers,
|
||||
Command** _command);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <Window.h>
|
||||
|
||||
#include "AddPathsCommand.h"
|
||||
#include "CleanUpPathCommand.h"
|
||||
#include "CommandStack.h"
|
||||
#include "MovePathsCommand.h"
|
||||
#include "Observer.h"
|
||||
@@ -236,6 +237,7 @@ enum {
|
||||
MSG_DUPLICATE = 'dupp',
|
||||
|
||||
MSG_REVERSE = 'rvrs',
|
||||
MSG_CLEAN_UP = 'clup',
|
||||
MSG_ROTATE_INDICES = 'roti',
|
||||
|
||||
MSG_REMOVE = 'remp',
|
||||
@@ -430,6 +432,19 @@ PathListView::MessageReceived(BMessage* message)
|
||||
}
|
||||
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:
|
||||
RemoveSelected();
|
||||
break;
|
||||
@@ -701,6 +716,7 @@ PathListView::SetMenu(BMenu* menu)
|
||||
new BMessage(MSG_ADD_ARC));
|
||||
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
||||
fReverseMI = new BMenuItem("Reverse", new BMessage(MSG_REVERSE));
|
||||
fCleanUpMI = new BMenuItem("Clean Up", new BMessage(MSG_CLEAN_UP));
|
||||
fRotateIndicesMI = new BMenuItem("Rotate Indices",
|
||||
new BMessage(MSG_ROTATE_INDICES));
|
||||
fRemoveMI = new BMenuItem("Remove", new BMessage(MSG_REMOVE));
|
||||
@@ -715,6 +731,7 @@ fAddArcMI->SetEnabled(false);
|
||||
|
||||
fMenu->AddItem(fDuplicateMI);
|
||||
fMenu->AddItem(fReverseMI);
|
||||
fMenu->AddItem(fCleanUpMI);
|
||||
fMenu->AddItem(fRotateIndicesMI);
|
||||
|
||||
fMenu->AddSeparatorItem();
|
||||
|
||||
@@ -86,6 +86,7 @@ class PathListView : public SimpleListView,
|
||||
BMenuItem* fAddArcMI;
|
||||
BMenuItem* fDuplicateMI;
|
||||
BMenuItem* fReverseMI;
|
||||
BMenuItem* fCleanUpMI;
|
||||
BMenuItem* fRotateIndicesMI;
|
||||
BMenuItem* fRemoveMI;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "AddShapesCommand.h"
|
||||
#include "AddStylesCommand.h"
|
||||
#include "CommandStack.h"
|
||||
#include "FreezeTransformationCommand.h"
|
||||
#include "MoveShapesCommand.h"
|
||||
#include "Observer.h"
|
||||
#include "RemoveShapesCommand.h"
|
||||
@@ -95,6 +96,7 @@ enum {
|
||||
MSG_REMOVE = 'rmsh',
|
||||
MSG_DUPLICATE = 'dpsh',
|
||||
MSG_RESET_TRANSFORMATION = 'rstr',
|
||||
MSG_FREEZE_TRANSFORMATION = 'frzt',
|
||||
|
||||
MSG_DRAG_SHAPE = 'drgs',
|
||||
};
|
||||
@@ -165,17 +167,9 @@ ShapeListView::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
case MSG_RESET_TRANSFORMATION: {
|
||||
int32 count = CountSelectedItems();
|
||||
BList shapes;
|
||||
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;
|
||||
}
|
||||
}
|
||||
count = shapes.CountItems();
|
||||
_GetSelectedShapes(shapes);
|
||||
int32 count = shapes.CountItems();
|
||||
if (count < 0)
|
||||
break;
|
||||
|
||||
@@ -191,6 +185,20 @@ ShapeListView::MessageReceived(BMessage* message)
|
||||
fCommandStack->Perform(command);
|
||||
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:
|
||||
SimpleListView::MessageReceived(message);
|
||||
break;
|
||||
@@ -433,6 +441,8 @@ ShapeListView::SetMenu(BMenu* menu)
|
||||
fDuplicateMI = new BMenuItem("Duplicate", new BMessage(MSG_DUPLICATE));
|
||||
fResetTransformationMI = new BMenuItem("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));
|
||||
|
||||
@@ -446,6 +456,7 @@ ShapeListView::SetMenu(BMenu* menu)
|
||||
|
||||
fMenu->AddItem(fDuplicateMI);
|
||||
fMenu->AddItem(fResetTransformationMI);
|
||||
fMenu->AddItem(fFreezeTransformationMI);
|
||||
|
||||
fMenu->AddSeparatorItem();
|
||||
|
||||
@@ -453,6 +464,7 @@ ShapeListView::SetMenu(BMenu* menu)
|
||||
|
||||
fDuplicateMI->SetTarget(this);
|
||||
fResetTransformationMI->SetTarget(this);
|
||||
fFreezeTransformationMI->SetTarget(this);
|
||||
fRemoveMI->SetTarget(this);
|
||||
|
||||
_UpdateMenu();
|
||||
@@ -541,4 +553,17 @@ ShapeListView::_UpdateMenu()
|
||||
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;
|
||||
void _UpdateMenu();
|
||||
|
||||
void _GetSelectedShapes(BList& shapes) const;
|
||||
|
||||
BMessage* fMessage;
|
||||
|
||||
ShapeContainer* fShapeContainer;
|
||||
@@ -80,6 +82,7 @@ class ShapeListView : public SimpleListView,
|
||||
BMenuItem* fAddWidthPathAndStyleMI;
|
||||
BMenuItem* fDuplicateMI;
|
||||
BMenuItem* fResetTransformationMI;
|
||||
BMenuItem* fFreezeTransformationMI;
|
||||
BMenuItem* fRemoveMI;
|
||||
};
|
||||
|
||||
|
||||
@@ -477,19 +477,27 @@ DocumentBuilder::GetIcon(Icon* icon, SVGImporter* importer,
|
||||
yMax = ceil(yMax);
|
||||
|
||||
BRect bounds;
|
||||
if (fViewBox.IsValid())
|
||||
if (fViewBox.IsValid()) {
|
||||
bounds = fViewBox;
|
||||
else
|
||||
printf("view box: ");
|
||||
bounds.PrintToStream();
|
||||
} else {
|
||||
bounds.Set(0.0, 0.0, (int32)fWidth - 1, (int32)fHeight - 1);
|
||||
printf("width/height: ");
|
||||
bounds.PrintToStream();
|
||||
}
|
||||
|
||||
BRect boundingBox(xMin, yMin, xMax, yMax);
|
||||
|
||||
if (!bounds.IsValid() || !boundingBox.Intersects(bounds)) {
|
||||
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;
|
||||
printf("scale: %f\n", scale);
|
||||
|
||||
Transformable transform;
|
||||
transform.TranslateBy(BPoint(-bounds.left, -bounds.top));
|
||||
@@ -540,6 +548,8 @@ DocumentBuilder::EndGradient()
|
||||
fCurrentGradient = NULL;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _AddGradient
|
||||
void
|
||||
DocumentBuilder::_AddGradient(SVGGradient* gradient)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <Cursor.h>
|
||||
#include <Message.h>
|
||||
#include <MenuItem.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "cursors.h"
|
||||
@@ -31,6 +33,7 @@
|
||||
//#include "ReversePathCommand.h"
|
||||
//#include "SelectPathCommand.h"
|
||||
//#include "SelectPointsCommand.h"
|
||||
#include "SplitPointsCommand.h"
|
||||
#include "TransformPointsBox.h"
|
||||
|
||||
#define POINT_EXTEND 3.0
|
||||
@@ -65,6 +68,14 @@ enum {
|
||||
SELECT_SUB_PATH,
|
||||
};
|
||||
|
||||
enum {
|
||||
MSG_TRANSFORM = 'strn',
|
||||
MSG_REMOVE_POINTS = 'srmp',
|
||||
MSG_UPDATE_SHAPE_UI = 'udsi',
|
||||
|
||||
MSG_SPLIT_POINTS = 'splt',
|
||||
};
|
||||
|
||||
inline const char*
|
||||
string_for_mode(uint32 mode)
|
||||
{
|
||||
@@ -480,18 +491,29 @@ PathManipulator::MouseDown(BPoint where)
|
||||
_RemovePointOut(fCurrentPathPoint);
|
||||
break;
|
||||
|
||||
case SELECT_POINTS:
|
||||
if (!fShiftDown) {
|
||||
case SELECT_POINTS: {
|
||||
// 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();
|
||||
_UpdateSelection();
|
||||
}
|
||||
*fOldSelection = *fSelection;
|
||||
if (fCurrentPathPoint >= 0) {
|
||||
_Select(fCurrentPathPoint, fShiftDown);
|
||||
_Select(fCurrentPathPoint, appendSelection);
|
||||
}
|
||||
fCanvasView->BeginRectTracking(BRect(where, where),
|
||||
B_TRACK_RECT_CORNER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fTrackingStart = canvasWhere;
|
||||
@@ -707,6 +729,52 @@ PathManipulator::DoubleClicked(BPoint where)
|
||||
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
|
||||
BRect
|
||||
PathManipulator::Bounds()
|
||||
@@ -725,25 +793,24 @@ PathManipulator::TrackingBounds(BView* withinView)
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
enum {
|
||||
MSG_SHAPE_TRANSFORM = 'strn',
|
||||
MSG_SHAPE_REMOVE_POINTS = 'srmp',
|
||||
MSG_UPDATE_SHAPE_UI = 'udsi',
|
||||
};
|
||||
|
||||
// MessageReceived
|
||||
bool
|
||||
PathManipulator::MessageReceived(BMessage* message, Command** _command)
|
||||
{
|
||||
bool result = true;
|
||||
switch (message->what) {
|
||||
case MSG_SHAPE_TRANSFORM:
|
||||
case MSG_TRANSFORM:
|
||||
if (!fSelection->IsEmpty())
|
||||
_SetMode(TRANSFORM_POINTS);
|
||||
break;
|
||||
case MSG_SHAPE_REMOVE_POINTS:
|
||||
case MSG_REMOVE_POINTS:
|
||||
*_command = _Delete();
|
||||
break;
|
||||
case MSG_SPLIT_POINTS:
|
||||
*_command = new SplitPointsCommand(fPath,
|
||||
fSelection->Items(),
|
||||
fSelection->CountItems());
|
||||
break;
|
||||
case B_SELECT_ALL: {
|
||||
*fOldSelection = *fSelection;
|
||||
fSelection->MakeEmpty();
|
||||
@@ -1292,10 +1359,12 @@ void
|
||||
PathManipulator::_Select(BRect r)
|
||||
{
|
||||
BPoint p;
|
||||
BPoint pIn;
|
||||
BPoint pOut;
|
||||
int32 count = fPath->CountPoints();
|
||||
Selection temp;
|
||||
for (int32 i = 0; i < count && fPath->GetPointAt(i, p); i++) {
|
||||
if (r.Contains(p)) {
|
||||
for (int32 i = 0; i < count && fPath->GetPointsAt(i, p, pIn, pOut); i++) {
|
||||
if (r.Contains(p) || r.Contains(pIn) || r.Contains(pOut)) {
|
||||
temp.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ class PathManipulator : public Manipulator,
|
||||
virtual bool MouseOver(BPoint where);
|
||||
virtual bool DoubleClicked(BPoint where);
|
||||
|
||||
virtual bool ShowContextMenu(BPoint where);
|
||||
|
||||
virtual BRect Bounds();
|
||||
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 <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
|
||||
#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 <string.h>
|
||||
|
||||
//#include "ExitTransformPointsCommand.h"
|
||||
#include "StateView.h"
|
||||
//#include "TransformPointsCommand.h"
|
||||
#include "TransformPointsCommand.h"
|
||||
#include "VectorPath.h"
|
||||
|
||||
using std::nothrow;
|
||||
@@ -118,19 +117,20 @@ TransformCommand*
|
||||
TransformPointsBox::MakeCommand(const char* commandName,
|
||||
uint32 nameIndex)
|
||||
{
|
||||
return NULL;
|
||||
// return new TransformPointsAction(fManipulator,
|
||||
// fIndices,
|
||||
// fPoints,
|
||||
// fCount,
|
||||
//// Translation(),
|
||||
//// LocalRotation(),
|
||||
//// LocalXScale(),
|
||||
//// LocalYScale(),
|
||||
// *this,
|
||||
// CenterOffset(),
|
||||
// actionName,
|
||||
// nameIndex);
|
||||
return new TransformPointsCommand(this, fPath,
|
||||
|
||||
fIndices,
|
||||
fPoints,
|
||||
fCount,
|
||||
|
||||
Pivot(),
|
||||
Translation(),
|
||||
LocalRotation(),
|
||||
LocalXScale(),
|
||||
LocalYScale(),
|
||||
|
||||
commandName,
|
||||
nameIndex);
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
Reference in New Issue
Block a user