* 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:
Stephan Aßmus
2007-09-21 15:21:38 +00:00
parent c4ce9e7607
commit 015a014aa7
14 changed files with 145 additions and 51 deletions
+68 -4
View File
@@ -62,7 +62,9 @@ IconEditorApp::IconEditorApp()
fLastOpenPath(""), fLastOpenPath(""),
fLastSavePath(""), fLastSavePath(""),
fLastExportPath("") fLastExportPath(""),
fMessageAfterSave(NULL)
{ {
} }
@@ -76,6 +78,8 @@ IconEditorApp::~IconEditorApp()
delete fOpenPanel; delete fOpenPanel;
delete fSavePanel; delete fSavePanel;
delete fMessageAfterSave;
} }
// #pragma mark - // #pragma mark -
@@ -84,7 +88,9 @@ IconEditorApp::~IconEditorApp()
bool bool
IconEditorApp::QuitRequested() IconEditorApp::QuitRequested()
{ {
// TODO: ask main window if quitting is ok if (!_CheckSaveIcon(CurrentMessage()))
return false;
_StoreSettings(); _StoreSettings();
fMainWindow->Lock(); fMainWindow->Lock();
@@ -103,14 +109,12 @@ IconEditorApp::MessageReceived(BMessage* message)
_MakeIconEmpty(); _MakeIconEmpty();
break; break;
case MSG_OPEN: { case MSG_OPEN: {
// fOpenPanel->Refresh();
BMessage openMessage(B_REFS_RECEIVED); BMessage openMessage(B_REFS_RECEIVED);
fOpenPanel->SetMessage(&openMessage); fOpenPanel->SetMessage(&openMessage);
fOpenPanel->Show(); fOpenPanel->Show();
break; break;
} }
case MSG_APPEND: { case MSG_APPEND: {
// fOpenPanel->Refresh();
BMessage openMessage(B_REFS_RECEIVED); BMessage openMessage(B_REFS_RECEIVED);
openMessage.AddBool("append", true); openMessage.AddBool("append", true);
fOpenPanel->SetMessage(&openMessage); fOpenPanel->SetMessage(&openMessage);
@@ -126,6 +130,7 @@ IconEditorApp::MessageReceived(BMessage* message)
saver = fDocument->ExportSaver(); saver = fDocument->ExportSaver();
if (saver) { if (saver) {
saver->Save(fDocument); saver->Save(fDocument);
_PickUpActionBeforeSave();
break; break;
} // else fall through } // else fall through
} }
@@ -153,6 +158,7 @@ IconEditorApp::MessageReceived(BMessage* message)
else else
fDocument->SetExportSaver(saver); fDocument->SetExportSaver(saver);
saver->Save(fDocument); saver->Save(fDocument);
_PickUpActionBeforeSave();
} }
} }
_SyncPanels(fSavePanel, fOpenPanel); _SyncPanels(fSavePanel, fOpenPanel);
@@ -267,9 +273,61 @@ IconEditorApp::ArgvReceived(int32 argc, char** argv)
// #pragma mark - // #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 void
IconEditorApp::_MakeIconEmpty() IconEditorApp::_MakeIconEmpty()
{ {
if (!_CheckSaveIcon(CurrentMessage()))
return;
bool mainWindowLocked = fMainWindow && fMainWindow->Lock(); bool mainWindowLocked = fMainWindow && fMainWindow->Lock();
AutoWriteLocker locker(fDocument); AutoWriteLocker locker(fDocument);
@@ -289,6 +347,9 @@ IconEditorApp::_MakeIconEmpty()
void void
IconEditorApp::_Open(const entry_ref& ref, bool append) IconEditorApp::_Open(const entry_ref& ref, bool append)
{ {
if (!_CheckSaveIcon(CurrentMessage()))
return;
BFile file(&ref, B_READ_ONLY); BFile file(&ref, B_READ_ONLY);
if (file.InitCheck() < B_OK) if (file.InitCheck() < B_OK)
return; return;
@@ -390,6 +451,9 @@ void
IconEditorApp::_Open(const BMessenger& externalObserver, IconEditorApp::_Open(const BMessenger& externalObserver,
const uint8* data, size_t size) const uint8* data, size_t size)
{ {
if (!_CheckSaveIcon(CurrentMessage()))
return;
if (!externalObserver.IsValid()) if (!externalObserver.IsValid())
return; return;
+5
View File
@@ -63,6 +63,9 @@ class IconEditorApp : public BApplication {
// IconEditorApp // IconEditorApp
private: private:
bool _CheckSaveIcon(const BMessage* currentMessage);
void _PickUpActionBeforeSave();
void _MakeIconEmpty(); void _MakeIconEmpty();
void _Open(const entry_ref& ref, void _Open(const entry_ref& ref,
bool append = false); bool append = false);
@@ -89,6 +92,8 @@ class IconEditorApp : public BApplication {
BString fLastOpenPath; BString fLastOpenPath;
BString fLastSavePath; BString fLastSavePath;
BString fLastExportPath; BString fLastExportPath;
BMessage* fMessageAfterSave;
}; };
#endif // ICON_EDITOR_APP_H #endif // ICON_EDITOR_APP_H
+12 -8
View File
@@ -216,6 +216,10 @@ case MSG_PATH_SELECTED: {
if (message->FindPointer("path", (void**)&path) < B_OK) if (message->FindPointer("path", (void**)&path) < B_OK)
path = NULL; path = NULL;
fPathListView->SetCurrentShape(NULL);
fStyleListView->SetCurrentShape(NULL);
fTransformerListView->SetShape(NULL);
fState->DeleteManipulators(); fState->DeleteManipulators();
if (fDocument->Icon()->Paths()->HasPath(path)) { if (fDocument->Icon()->Paths()->HasPath(path)) {
PathManipulator* pathManipulator = new (nothrow) PathManipulator(path); PathManipulator* pathManipulator = new (nothrow) PathManipulator(path);
@@ -223,7 +227,8 @@ case MSG_PATH_SELECTED: {
} }
break; break;
} }
case MSG_STYLE_SELECTED: { case MSG_STYLE_SELECTED:
case MSG_STYLE_TYPE_CHANGED: {
Style* style; Style* style;
if (message->FindPointer("style", (void**)&style) < B_OK) if (message->FindPointer("style", (void**)&style) < B_OK)
style = NULL; style = NULL;
@@ -231,14 +236,13 @@ case MSG_STYLE_SELECTED: {
style = NULL; style = NULL;
fStyleView->SetStyle(style); fStyleView->SetStyle(style);
break; fPathListView->SetCurrentShape(NULL);
} fStyleListView->SetCurrentShape(NULL);
case MSG_GRADIENT_SELECTED: { fTransformerListView->SetShape(NULL);
// if there is a gradient, add a transform box around it
Gradient* gradient;
if (message->FindPointer("gradient", (void**)&gradient) < B_OK)
gradient = NULL;
fState->DeleteManipulators(); fState->DeleteManipulators();
Gradient* gradient = style ? style->Gradient() : NULL;
if (gradient) { if (gradient) {
TransformGradientBox* transformBox TransformGradientBox* transformBox
= new (nothrow) TransformGradientBox(fCanvasView, = new (nothrow) TransformGradientBox(fCanvasView,
@@ -12,7 +12,10 @@
#include "CommandStack.h" #include "CommandStack.h"
#include "DocumentSaver.h" #include "DocumentSaver.h"
#include "Icon.h" #include "Icon.h"
#include "PathContainer.h"
#include "Selection.h" #include "Selection.h"
#include "ShapeContainer.h"
#include "StyleContainer.h"
#include <Entry.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); void MakeEmpty(bool includingSavers = true);
bool IsEmpty() const;
private: private:
BPrivate::Icon::Icon* fIcon; BPrivate::Icon::Icon* fIcon;
::CommandStack* fCommandStack; ::CommandStack* fCommandStack;
@@ -533,9 +533,10 @@ DragSortableListView::MouseWheelChanged(float x, float y)
void void
DragSortableListView::ObjectChanged(const Observable* object) DragSortableListView::ObjectChanged(const Observable* object)
{ {
if (object != fSelection || fModifyingSelection) if (object != fSelection || fModifyingSelection || fSyncingToSelection)
return; return;
//printf("%s - syncing start\n", Name());
fSyncingToSelection = true; fSyncingToSelection = true;
// try to sync to Selection // try to sync to Selection
@@ -567,6 +568,7 @@ DragSortableListView::ObjectChanged(const Observable* object)
} }
fSyncingToSelection = false; fSyncingToSelection = false;
//printf("%s - done\n", Name());
} }
// #pragma mark - // #pragma mark -
@@ -813,7 +815,7 @@ DragSortableListView::SelectionChanged()
{ {
//printf("%s::SelectionChanged()", typeid(*this).name()); //printf("%s::SelectionChanged()", typeid(*this).name());
// modify global Selection // modify global Selection
if (!fSelection) if (!fSelection || fSyncingToSelection)
return; return;
fModifyingSelection = true; fModifyingSelection = true;
+1 -1
View File
@@ -623,7 +623,7 @@ PathListView::PathAdded(VectorPath* path, int32 index)
return; return;
if (_AddPath(path, index)) if (_AddPath(path, index))
Select(CountItems() - 1); Select(index);
UnlockLooper(); UnlockLooper();
} }
+3 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2006, Haiku. * Copyright 2006-2007, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -129,7 +129,6 @@ ShapeListView::~ShapeListView()
void void
ShapeListView::SelectionChanged() ShapeListView::SelectionChanged()
{ {
SimpleListView::SelectionChanged(); SimpleListView::SelectionChanged();
if (!fSyncingToSelection) { if (!fSyncingToSelection) {
@@ -387,7 +386,8 @@ ShapeListView::ShapeAdded(Shape* shape, int32 index)
if (!LockLooper()) if (!LockLooper())
return; return;
_AddShape(shape, index); if (_AddShape(shape, index))
Select(index);
UnlockLooper(); UnlockLooper();
} }
+1 -3
View File
@@ -555,10 +555,8 @@ StyleListView::StyleAdded(Style* style, int32 index)
if (!LockLooper()) if (!LockLooper())
return; return;
// NOTE: shapes are always added at the end
// of the list, so the sorting is synced...
if (_AddStyle(style, index)) if (_AddStyle(style, index))
Select(CountItems() - 1); Select(index);
UnlockLooper(); UnlockLooper();
} }
+7 -7
View File
@@ -267,7 +267,7 @@ StyleView::ObjectChanged(const Observable* object)
// TODO: is this really necessary? // TODO: is this really necessary?
controlGradient->SetTransform(*fGradient); controlGradient->SetTransform(*fGradient);
if (*fGradient != *controlGradient) { if (!fGradient->ColorStepsAreEqual(*controlGradient)) {
if (fCommandStack) { if (fCommandStack) {
fCommandStack->Perform( fCommandStack->Perform(
new (nothrow) SetGradientCommand( new (nothrow) SetGradientCommand(
@@ -279,7 +279,7 @@ StyleView::ObjectChanged(const Observable* object)
_TransferGradientStopColor(); _TransferGradientStopColor();
} }
} else if (object == fGradient) { } else if (object == fGradient) {
if (*fGradient != *controlGradient) { if (!fGradient->ColorStepsAreEqual(*controlGradient)) {
fGradientControl->SetGradient(fGradient); fGradientControl->SetGradient(fGradient);
_MarkType(fGradientType->Menu(), fGradient->Type()); _MarkType(fGradientType->Menu(), fGradient->Type());
// transfer the current gradient color to the current color // transfer the current gradient color to the current color
@@ -288,7 +288,7 @@ StyleView::ObjectChanged(const Observable* object)
} else if (object == fStyle) { } else if (object == fStyle) {
// maybe the gradient was added or removed // maybe the gradient was added or removed
// or the color changed // or the color changed
_SetGradient(fStyle->Gradient()); _SetGradient(fStyle->Gradient(), false, true);
if (fCurrentColor && !fStyle->Gradient()) if (fCurrentColor && !fStyle->Gradient())
fCurrentColor->SetColor(fStyle->Color()); fCurrentColor->SetColor(fStyle->Color());
} else if (object == fCurrentColor) { } else if (object == fCurrentColor) {
@@ -361,7 +361,7 @@ StyleView::SetCurrentColor(CurrentColor* color)
// _SetGradient // _SetGradient
void void
StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate) StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate, bool sendMessage)
{ {
if (!forceControlUpdate && fGradient == gradient) if (!forceControlUpdate && fGradient == gradient)
return; return;
@@ -387,9 +387,9 @@ StyleView::_SetGradient(Gradient* gradient, bool forceControlUpdate)
_MarkType(fGradientType->Menu(), -1); _MarkType(fGradientType->Menu(), -1);
} }
if (Window()) { if (sendMessage) {
BMessage message(MSG_GRADIENT_SELECTED); BMessage message(MSG_STYLE_TYPE_CHANGED);
message.AddPointer("gradient", (void*)fGradient); message.AddPointer("style", fStyle);
Window()->PostMessage(&message); Window()->PostMessage(&message);
} }
} }
+3 -2
View File
@@ -31,7 +31,7 @@ using namespace BPrivate::Icon;
// TODO: write lock the document when changing something... // TODO: write lock the document when changing something...
enum { enum {
MSG_GRADIENT_SELECTED = 'grsl', MSG_STYLE_TYPE_CHANGED = 'stch',
}; };
class StyleView : public BView, class StyleView : public BView,
@@ -59,7 +59,8 @@ class StyleView : public BView,
private: private:
void _SetGradient(Gradient* gradient, void _SetGradient(Gradient* gradient,
bool forceControlUpdate = false); bool forceControlUpdate = false,
bool sendMessage = false);
void _MarkType(BMenu* menu, void _MarkType(BMenu* menu,
int32 type) const; int32 type) const;
void _SetStyleType(int32 type); void _SetStyleType(int32 type);
@@ -72,8 +72,6 @@ AddShapesCommand::Perform()
fContainer->RemoveShape(fShapes[j]); fContainer->RemoveShape(fShapes[j]);
break; break;
} }
if (fSelection)
fSelection->Select(fShapes[i], i > 0);
index++; index++;
} }
fShapesAdded = true; fShapesAdded = true;
+16 -9
View File
@@ -227,7 +227,22 @@ Gradient::operator=(const Gradient& other)
bool bool
Gradient::operator==(const Gradient& other) const Gradient::operator==(const Gradient& other) const
{ {
if (Transformable::operator==(other)) { if (Transformable::operator==(other))
return ColorStepsAreEqual(other);
return false;
}
// operator!=
bool
Gradient::operator!=(const Gradient& other) const
{
return !(*this == other);
}
// ColorStepsAreEqual
bool
Gradient::ColorStepsAreEqual(const Gradient& other) const
{
int32 count = CountColors(); int32 count = CountColors();
if (count == other.CountColors() && if (count == other.CountColors() &&
fType == other.fType && fType == other.fType &&
@@ -245,17 +260,9 @@ Gradient::operator==(const Gradient& other) const
} }
return equal; return equal;
} }
}
return false; return false;
} }
// operator!=
bool
Gradient::operator!=(const Gradient& other) const
{
return !(*this == other);
}
// SetColors // SetColors
void void
Gradient::SetColors(const Gradient& other) Gradient::SetColors(const Gradient& other)
+2
View File
@@ -78,6 +78,8 @@ class Gradient : public Transformable {
bool operator==(const Gradient& other) const; bool operator==(const Gradient& other) const;
bool operator!=(const Gradient& other) const; bool operator!=(const Gradient& other) const;
bool ColorStepsAreEqual(
const Gradient& other) const;
void SetColors(const Gradient& other); void SetColors(const Gradient& other);