* fixed quite a few selections bugs, most were caused by cyclic notifications,
and the mechanism to prevent them not working... * could have fixed the "there are still listeners attached" bug (debugger drop) on exit, I have not seen it again, but I am not sure if it is really fixed * introduced a way to ask the user, if changes should be saved and then pick up the line of thought after saving git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22269 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c4ce9e7607
commit
015a014aa7
@ -62,7 +62,9 @@ IconEditorApp::IconEditorApp()
|
||||
|
||||
fLastOpenPath(""),
|
||||
fLastSavePath(""),
|
||||
fLastExportPath("")
|
||||
fLastExportPath(""),
|
||||
|
||||
fMessageAfterSave(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -76,6 +78,8 @@ IconEditorApp::~IconEditorApp()
|
||||
|
||||
delete fOpenPanel;
|
||||
delete fSavePanel;
|
||||
|
||||
delete fMessageAfterSave;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
@ -84,7 +88,9 @@ IconEditorApp::~IconEditorApp()
|
||||
bool
|
||||
IconEditorApp::QuitRequested()
|
||||
{
|
||||
// TODO: ask main window if quitting is ok
|
||||
if (!_CheckSaveIcon(CurrentMessage()))
|
||||
return false;
|
||||
|
||||
_StoreSettings();
|
||||
|
||||
fMainWindow->Lock();
|
||||
@ -103,14 +109,12 @@ IconEditorApp::MessageReceived(BMessage* message)
|
||||
_MakeIconEmpty();
|
||||
break;
|
||||
case MSG_OPEN: {
|
||||
// fOpenPanel->Refresh();
|
||||
BMessage openMessage(B_REFS_RECEIVED);
|
||||
fOpenPanel->SetMessage(&openMessage);
|
||||
fOpenPanel->Show();
|
||||
break;
|
||||
}
|
||||
case MSG_APPEND: {
|
||||
// fOpenPanel->Refresh();
|
||||
BMessage openMessage(B_REFS_RECEIVED);
|
||||
openMessage.AddBool("append", true);
|
||||
fOpenPanel->SetMessage(&openMessage);
|
||||
@ -126,6 +130,7 @@ IconEditorApp::MessageReceived(BMessage* message)
|
||||
saver = fDocument->ExportSaver();
|
||||
if (saver) {
|
||||
saver->Save(fDocument);
|
||||
_PickUpActionBeforeSave();
|
||||
break;
|
||||
} // else fall through
|
||||
}
|
||||
@ -153,6 +158,7 @@ IconEditorApp::MessageReceived(BMessage* message)
|
||||
else
|
||||
fDocument->SetExportSaver(saver);
|
||||
saver->Save(fDocument);
|
||||
_PickUpActionBeforeSave();
|
||||
}
|
||||
}
|
||||
_SyncPanels(fSavePanel, fOpenPanel);
|
||||
@ -267,9 +273,61 @@ IconEditorApp::ArgvReceived(int32 argc, char** argv)
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _CheckSaveIcon
|
||||
bool
|
||||
IconEditorApp::_CheckSaveIcon(const BMessage* currentMessage)
|
||||
{
|
||||
if (fDocument->IsEmpty() || fDocument->CommandStack()->IsSaved())
|
||||
return true;
|
||||
|
||||
BAlert* alert = new BAlert("save", "Save changes to current icon?",
|
||||
"Discard", "Cancel", "Save");
|
||||
int32 choice = alert->Go();
|
||||
switch (choice) {
|
||||
case 0:
|
||||
// discard
|
||||
return true;
|
||||
case 1:
|
||||
// cancel
|
||||
return false;
|
||||
case 2:
|
||||
default:
|
||||
// cancel (save first) but pick what we were doing before
|
||||
PostMessage(MSG_SAVE);
|
||||
if (currentMessage) {
|
||||
delete fMessageAfterSave;
|
||||
fMessageAfterSave = new BMessage(*currentMessage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// _PickUpActionBeforeSave
|
||||
void
|
||||
IconEditorApp::_PickUpActionBeforeSave()
|
||||
{
|
||||
if (fDocument->WriteLock()) {
|
||||
fDocument->CommandStack()->Save();
|
||||
fDocument->WriteUnlock();
|
||||
}
|
||||
|
||||
if (!fMessageAfterSave)
|
||||
return;
|
||||
|
||||
PostMessage(fMessageAfterSave);
|
||||
delete fMessageAfterSave;
|
||||
fMessageAfterSave = NULL;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _MakeIconEmpty
|
||||
void
|
||||
IconEditorApp::_MakeIconEmpty()
|
||||
{
|
||||
if (!_CheckSaveIcon(CurrentMessage()))
|
||||
return;
|
||||
|
||||
bool mainWindowLocked = fMainWindow && fMainWindow->Lock();
|
||||
|
||||
AutoWriteLocker locker(fDocument);
|
||||
@ -289,6 +347,9 @@ IconEditorApp::_MakeIconEmpty()
|
||||
void
|
||||
IconEditorApp::_Open(const entry_ref& ref, bool append)
|
||||
{
|
||||
if (!_CheckSaveIcon(CurrentMessage()))
|
||||
return;
|
||||
|
||||
BFile file(&ref, B_READ_ONLY);
|
||||
if (file.InitCheck() < B_OK)
|
||||
return;
|
||||
@ -390,6 +451,9 @@ void
|
||||
IconEditorApp::_Open(const BMessenger& externalObserver,
|
||||
const uint8* data, size_t size)
|
||||
{
|
||||
if (!_CheckSaveIcon(CurrentMessage()))
|
||||
return;
|
||||
|
||||
if (!externalObserver.IsValid())
|
||||
return;
|
||||
|
||||
|
@ -63,6 +63,9 @@ class IconEditorApp : public BApplication {
|
||||
// IconEditorApp
|
||||
|
||||
private:
|
||||
bool _CheckSaveIcon(const BMessage* currentMessage);
|
||||
void _PickUpActionBeforeSave();
|
||||
|
||||
void _MakeIconEmpty();
|
||||
void _Open(const entry_ref& ref,
|
||||
bool append = false);
|
||||
@ -89,6 +92,8 @@ class IconEditorApp : public BApplication {
|
||||
BString fLastOpenPath;
|
||||
BString fLastSavePath;
|
||||
BString fLastExportPath;
|
||||
|
||||
BMessage* fMessageAfterSave;
|
||||
};
|
||||
|
||||
#endif // ICON_EDITOR_APP_H
|
||||
|
@ -215,6 +215,10 @@ case MSG_PATH_SELECTED: {
|
||||
VectorPath* path;
|
||||
if (message->FindPointer("path", (void**)&path) < B_OK)
|
||||
path = NULL;
|
||||
|
||||
fPathListView->SetCurrentShape(NULL);
|
||||
fStyleListView->SetCurrentShape(NULL);
|
||||
fTransformerListView->SetShape(NULL);
|
||||
|
||||
fState->DeleteManipulators();
|
||||
if (fDocument->Icon()->Paths()->HasPath(path)) {
|
||||
@ -223,7 +227,8 @@ case MSG_PATH_SELECTED: {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_STYLE_SELECTED: {
|
||||
case MSG_STYLE_SELECTED:
|
||||
case MSG_STYLE_TYPE_CHANGED: {
|
||||
Style* style;
|
||||
if (message->FindPointer("style", (void**)&style) < B_OK)
|
||||
style = NULL;
|
||||
@ -231,14 +236,13 @@ case MSG_STYLE_SELECTED: {
|
||||
style = NULL;
|
||||
|
||||
fStyleView->SetStyle(style);
|
||||
break;
|
||||
}
|
||||
case MSG_GRADIENT_SELECTED: {
|
||||
// if there is a gradient, add a transform box around it
|
||||
Gradient* gradient;
|
||||
if (message->FindPointer("gradient", (void**)&gradient) < B_OK)
|
||||
gradient = NULL;
|
||||
fPathListView->SetCurrentShape(NULL);
|
||||
fStyleListView->SetCurrentShape(NULL);
|
||||
fTransformerListView->SetShape(NULL);
|
||||
|
||||
fState->DeleteManipulators();
|
||||
Gradient* gradient = style ? style->Gradient() : NULL;
|
||||
|
||||
if (gradient) {
|
||||
TransformGradientBox* transformBox
|
||||
= new (nothrow) TransformGradientBox(fCanvasView,
|
||||
|
@ -12,7 +12,10 @@
|
||||
#include "CommandStack.h"
|
||||
#include "DocumentSaver.h"
|
||||
#include "Icon.h"
|
||||
#include "PathContainer.h"
|
||||
#include "Selection.h"
|
||||
#include "ShapeContainer.h"
|
||||
#include "StyleContainer.h"
|
||||
|
||||
#include <Entry.h>
|
||||
|
||||
@ -112,4 +115,12 @@ Document::MakeEmpty(bool includingSavers)
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty
|
||||
bool
|
||||
Document::IsEmpty() const
|
||||
{
|
||||
return fIcon->Styles()->CountStyles() == 0
|
||||
&& fIcon->Paths()->CountPaths() == 0
|
||||
&& fIcon->Shapes()->CountShapes() == 0;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,8 @@ class Document : public RWLocker,
|
||||
|
||||
void MakeEmpty(bool includingSavers = true);
|
||||
|
||||
bool IsEmpty() const;
|
||||
|
||||
private:
|
||||
BPrivate::Icon::Icon* fIcon;
|
||||
::CommandStack* fCommandStack;
|
||||
|
@ -533,9 +533,10 @@ DragSortableListView::MouseWheelChanged(float x, float y)
|
||||
void
|
||||
DragSortableListView::ObjectChanged(const Observable* object)
|
||||
{
|
||||
if (object != fSelection || fModifyingSelection)
|
||||
if (object != fSelection || fModifyingSelection || fSyncingToSelection)
|
||||
return;
|
||||
|
||||
//printf("%s - syncing start\n", Name());
|
||||
fSyncingToSelection = true;
|
||||
|
||||
// try to sync to Selection
|
||||
@ -567,6 +568,7 @@ DragSortableListView::ObjectChanged(const Observable* object)
|
||||
}
|
||||
|
||||
fSyncingToSelection = false;
|
||||
//printf("%s - done\n", Name());
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
@ -813,7 +815,7 @@ DragSortableListView::SelectionChanged()
|
||||
{
|
||||
//printf("%s::SelectionChanged()", typeid(*this).name());
|
||||
// modify global Selection
|
||||
if (!fSelection)
|
||||
if (!fSelection || fSyncingToSelection)
|
||||
return;
|
||||
|
||||
fModifyingSelection = true;
|
||||
|
@ -623,7 +623,7 @@ PathListView::PathAdded(VectorPath* path, int32 index)
|
||||
return;
|
||||
|
||||
if (_AddPath(path, index))
|
||||
Select(CountItems() - 1);
|
||||
Select(index);
|
||||
|
||||
UnlockLooper();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku.
|
||||
* Copyright 2006-2007, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -129,7 +129,6 @@ ShapeListView::~ShapeListView()
|
||||
void
|
||||
ShapeListView::SelectionChanged()
|
||||
{
|
||||
|
||||
SimpleListView::SelectionChanged();
|
||||
|
||||
if (!fSyncingToSelection) {
|
||||
@ -387,7 +386,8 @@ ShapeListView::ShapeAdded(Shape* shape, int32 index)
|
||||
if (!LockLooper())
|
||||
return;
|
||||
|
||||
_AddShape(shape, index);
|
||||
if (_AddShape(shape, index))
|
||||
Select(index);
|
||||
|
||||
UnlockLooper();
|
||||
}
|
||||
|
@ -555,10 +555,8 @@ StyleListView::StyleAdded(Style* style, int32 index)
|
||||
if (!LockLooper())
|
||||
return;
|
||||
|
||||
// NOTE: shapes are always added at the end
|
||||
// of the list, so the sorting is synced...
|
||||
if (_AddStyle(style, index))
|
||||
Select(CountItems() - 1);
|
||||
Select(index);
|
||||
|
||||
UnlockLooper();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ StyleView::ObjectChanged(const Observable* object)
|
||||
// TODO: is this really necessary?
|
||||
controlGradient->SetTransform(*fGradient);
|
||||
|
||||
if (*fGradient != *controlGradient) {
|
||||
if (!fGradient->ColorStepsAreEqual(*controlGradient)) {
|
||||
if (fCommandStack) {
|
||||
fCommandStack->Perform(
|
||||
new (nothrow) SetGradientCommand(
|
||||
@ -279,7 +279,7 @@ StyleView::ObjectChanged(const Observable* object)
|
||||
_TransferGradientStopColor();
|
||||
}
|
||||
} else if (object == fGradient) {
|
||||
if (*fGradient != *controlGradient) {
|
||||
if (!fGradient->ColorStepsAreEqual(*controlGradient)) {
|
||||
fGradientControl->SetGradient(fGradient);
|
||||
_MarkType(fGradientType->Menu(), fGradient->Type());
|
||||
// transfer the current gradient color to the current color
|
||||
@ -288,7 +288,7 @@ StyleView::ObjectChanged(const Observable* object)
|
||||
} else if (object == fStyle) {
|
||||
// maybe the gradient was added or removed
|
||||
// or the color changed
|
||||
_SetGradient(fStyle->Gradient());
|
||||
_SetGradient(fStyle->Gradient(), false, true);
|
||||
if (fCurrentColor && !fStyle->Gradient())
|
||||
fCurrentColor->SetColor(fStyle->Color());
|
||||
} else if (object == fCurrentColor) {
|
||||
@ -361,7 +361,7 @@ StyleView::SetCurrentColor(CurrentColor* color)
|
||||
|
||||
// _SetGradient
|
||||
void
|
||||
StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate)
|
||||
StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate, bool sendMessage)
|
||||
{
|
||||
if (!forceControlUpdate && fGradient == gradient)
|
||||
return;
|
||||
@ -387,9 +387,9 @@ StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate)
|
||||
_MarkType(fGradientType->Menu(), -1);
|
||||
}
|
||||
|
||||
if (Window()) {
|
||||
BMessage message(MSG_GRADIENT_SELECTED);
|
||||
message.AddPointer("gradient", (void*)fGradient);
|
||||
if (sendMessage) {
|
||||
BMessage message(MSG_STYLE_TYPE_CHANGED);
|
||||
message.AddPointer("style", fStyle);
|
||||
Window()->PostMessage(&message);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ using namespace BPrivate::Icon;
|
||||
// TODO: write lock the document when changing something...
|
||||
|
||||
enum {
|
||||
MSG_GRADIENT_SELECTED = 'grsl',
|
||||
MSG_STYLE_TYPE_CHANGED = 'stch',
|
||||
};
|
||||
|
||||
class StyleView : public BView,
|
||||
@ -59,7 +59,8 @@ class StyleView : public BView,
|
||||
|
||||
private:
|
||||
void _SetGradient(Gradient* gradient,
|
||||
bool forceControlUpdate = false);
|
||||
bool forceControlUpdate = false,
|
||||
bool sendMessage = false);
|
||||
void _MarkType(BMenu* menu,
|
||||
int32 type) const;
|
||||
void _SetStyleType(int32 type);
|
||||
|
@ -72,8 +72,6 @@ AddShapesCommand::Perform()
|
||||
fContainer->RemoveShape(fShapes[j]);
|
||||
break;
|
||||
}
|
||||
if (fSelection)
|
||||
fSelection->Select(fShapes[i], i > 0);
|
||||
index++;
|
||||
}
|
||||
fShapesAdded = true;
|
||||
|
@ -227,25 +227,8 @@ Gradient::operator=(const Gradient& other)
|
||||
bool
|
||||
Gradient::operator==(const Gradient& other) const
|
||||
{
|
||||
if (Transformable::operator==(other)) {
|
||||
int32 count = CountColors();
|
||||
if (count == other.CountColors() &&
|
||||
fType == other.fType &&
|
||||
fInterpolation == other.fInterpolation &&
|
||||
fInheritTransformation == other.fInheritTransformation) {
|
||||
|
||||
bool equal = true;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
color_step* ourStep = ColorAtFast(i);
|
||||
color_step* otherStep = other.ColorAtFast(i);
|
||||
if (*ourStep != *otherStep) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
}
|
||||
if (Transformable::operator==(other))
|
||||
return ColorStepsAreEqual(other);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -256,6 +239,30 @@ Gradient::operator!=(const Gradient& other) const
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// ColorStepsAreEqual
|
||||
bool
|
||||
Gradient::ColorStepsAreEqual(const Gradient& other) const
|
||||
{
|
||||
int32 count = CountColors();
|
||||
if (count == other.CountColors() &&
|
||||
fType == other.fType &&
|
||||
fInterpolation == other.fInterpolation &&
|
||||
fInheritTransformation == other.fInheritTransformation) {
|
||||
|
||||
bool equal = true;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
color_step* ourStep = ColorAtFast(i);
|
||||
color_step* otherStep = other.ColorAtFast(i);
|
||||
if (*ourStep != *otherStep) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// SetColors
|
||||
void
|
||||
Gradient::SetColors(const Gradient& other)
|
||||
|
@ -78,6 +78,8 @@ class Gradient : public Transformable {
|
||||
|
||||
bool operator==(const Gradient& other) const;
|
||||
bool operator!=(const Gradient& other) const;
|
||||
bool ColorStepsAreEqual(
|
||||
const Gradient& other) const;
|
||||
|
||||
void SetColors(const Gradient& other);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user