2 * Copyright 2006-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Stephan Aßmus <superstippi@gmx.de>
9 #include "TransformerListView.h"
14 #include <Application.h>
24 #include "AddTransformersCommand.h"
25 #include "CommandStack.h"
26 #include "MoveTransformersCommand.h"
27 #include "RemoveTransformersCommand.h"
28 #include "Transformer.h"
29 #include "TransformerFactory.h"
31 #include "Selection.h"
34 #undef B_TRANSLATION_CONTEXT
35 #define B_TRANSLATION_CONTEXT "Icon-O-Matic-TransformersList"
40 class TransformerItem
: public SimpleItem
,
43 TransformerItem(Transformer
* t
,
44 TransformerListView
* listView
)
45 : SimpleItem(t
->Name()),
52 virtual ~TransformerItem()
58 virtual void ObjectChanged(const Observable
* object
)
64 void SetTransformer(Transformer
* t
)
70 transformer
->RemoveObserver(this);
71 transformer
->ReleaseReference();
77 transformer
->AcquireReference();
78 transformer
->AddObserver(this);
84 SetText(transformer
->Name());
86 if (fListView
->LockLooper()) {
87 fListView
->InvalidateItem(
88 fListView
->IndexOf(this));
89 fListView
->UnlockLooper();
93 Transformer
* transformer
;
95 TransformerListView
* fListView
;
101 MSG_DRAG_TRANSFORMER
= 'drgt',
102 MSG_ADD_TRANSFORMER
= 'adtr',
106 TransformerListView::TransformerListView(BRect frame
, const char* name
,
107 BMessage
* message
, BHandler
* target
)
108 : SimpleListView(frame
, name
,
109 NULL
, B_MULTIPLE_SELECTION_LIST
),
114 SetDragCommand(MSG_DRAG_TRANSFORMER
);
119 TransformerListView::~TransformerListView()
125 fShape
->RemoveListener(this);
130 TransformerListView::Draw(BRect updateRect
)
132 SimpleListView::Draw(updateRect
);
137 // display helpful messages
138 const char* message1
= B_TRANSLATE_CONTEXT("Click on a shape above",
139 "Empty transformers list - 1st line");
140 const char* message2
= B_TRANSLATE_CONTEXT("to attach transformers.",
141 "Empty transformers list - 2nd line");
144 rgb_color lowColor
= LowColor();
145 if (lowColor
.red
+ lowColor
.green
+ lowColor
.blue
> 128 * 3)
146 SetHighColor(tint_color(LowColor(), B_DARKEN_2_TINT
));
148 SetHighColor(tint_color(LowColor(), B_LIGHTEN_2_TINT
));
155 float textHeight
= (fh
.ascent
+ fh
.descent
) * 1.5;
156 middle
.y
= (b
.top
+ b
.bottom
- textHeight
) / 2.0;
157 middle
.x
= (b
.left
+ b
.right
- StringWidth(message1
)) / 2.0;
158 DrawString(message1
, middle
);
160 middle
.y
+= textHeight
;
161 middle
.x
= (b
.left
+ b
.right
- StringWidth(message2
)) / 2.0;
162 DrawString(message2
, middle
);
167 TransformerListView::SelectionChanged()
169 if (CountSelectedItems() > 0)
170 SimpleListView::SelectionChanged();
172 // TODO: any selected transformer will still be visible in the
175 if (!fSyncingToSelection
) {
176 TransformerItem
* item
177 = dynamic_cast<TransformerItem
*>(ItemAt(CurrentSelection(0)));
179 BMessage
message(*fMessage
);
180 message
.AddPointer("transformer", item
? (void*)item
->transformer
: NULL
);
188 TransformerListView::MessageReceived(BMessage
* message
)
190 switch (message
->what
) {
191 case MSG_ADD_TRANSFORMER
: {
192 if (!fShape
|| !fCommandStack
)
196 if (message
->FindInt32("type", (int32
*)&type
) < B_OK
)
199 Transformer
* transformer
200 = TransformerFactory::TransformerFor(type
,
201 fShape
->VertexSource());
205 Transformer
* transformers
[1];
206 transformers
[0] = transformer
;
207 ::Command
* command
= new (nothrow
) AddTransformersCommand(
208 fShape
, transformers
, 1, fShape
->CountTransformers());
213 fCommandStack
->Perform(command
);
217 SimpleListView::MessageReceived(message
);
224 TransformerListView::MakeDragMessage(BMessage
* message
) const
226 SimpleListView::MakeDragMessage(message
);
227 message
->AddPointer("container", fShape
);
228 int32 count
= CountItems();
229 for (int32 i
= 0; i
< count
; i
++) {
230 TransformerItem
* item
= dynamic_cast<TransformerItem
*>(ItemAt(CurrentSelection(i
)));
232 message
->AddPointer("transformer", (void*)item
->transformer
);
242 TransformerListView::MoveItems(BList
& items
, int32 toIndex
)
244 if (!fCommandStack
|| !fShape
)
247 int32 count
= items
.CountItems();
248 Transformer
** transformers
= new (nothrow
) Transformer
*[count
];
252 for (int32 i
= 0; i
< count
; i
++) {
253 TransformerItem
* item
254 = dynamic_cast<TransformerItem
*>((BListItem
*)items
.ItemAtFast(i
));
255 transformers
[i
] = item
? item
->transformer
: NULL
;
258 MoveTransformersCommand
* command
259 = new (nothrow
) MoveTransformersCommand(fShape
,
260 transformers
, count
, toIndex
);
262 delete[] transformers
;
266 fCommandStack
->Perform(command
);
271 TransformerListView::CopyItems(BList
& items
, int32 toIndex
)
273 MoveItems(items
, toIndex
);
274 // TODO: allow copying items
279 TransformerListView::RemoveItemList(BList
& items
)
281 if (!fCommandStack
|| !fShape
)
284 int32 count
= items
.CountItems();
285 int32 indices
[count
];
286 for (int32 i
= 0; i
< count
; i
++)
287 indices
[i
] = IndexOf((BListItem
*)items
.ItemAtFast(i
));
289 RemoveTransformersCommand
* command
290 = new (nothrow
) RemoveTransformersCommand(fShape
,
292 fCommandStack
->Perform(command
);
297 TransformerListView::CloneItem(int32 index
) const
299 if (TransformerItem
* item
= dynamic_cast<TransformerItem
*>(ItemAt(index
))) {
300 return new TransformerItem(item
->transformer
,
301 const_cast<TransformerListView
*>(this));
308 TransformerListView::IndexOfSelectable(Selectable
* selectable
) const
310 Transformer
* transformer
= dynamic_cast<Transformer
*>(selectable
);
315 TransformerItem
* item
= dynamic_cast<TransformerItem
*>(ItemAt(i
));
317 if (item
->transformer
== transformer
)
326 TransformerListView::SelectableFor(BListItem
* item
) const
328 TransformerItem
* transformerItem
= dynamic_cast<TransformerItem
*>(item
);
330 return transformerItem
->transformer
;
338 TransformerListView::TransformerAdded(Transformer
* transformer
, int32 index
)
340 // NOTE: we are in the thread that messed with the
341 // Shape, so no need to lock the document, when this is
342 // changed to asynchronous notifications, then it would
343 // need to be read-locked!
347 _AddTransformer(transformer
, index
);
352 // TransformerRemoved
354 TransformerListView::TransformerRemoved(Transformer
* transformer
)
356 // NOTE: we are in the thread that messed with the
357 // Shape, so no need to lock the document, when this is
358 // changed to asynchronous notifications, then it would
359 // need to be read-locked!
363 _RemoveTransformer(transformer
);
370 TransformerListView::StyleChanged(Style
* oldStyle
, Style
* newStyle
)
379 TransformerListView::SetMenu(BMenu
* menu
)
388 BMenu
* addMenu
= new BMenu(B_TRANSLATE("Add"));
392 while (TransformerFactory::NextType(&cookie
, &type
, &name
)) {
393 // TODO: Disable the "Transformation" and "Perspective" transformers
394 // since they are not very useful or even implemented at all.
395 if (name
== B_TRANSLATE("Transformation")
396 || name
== B_TRANSLATE("Perspective"))
399 BMessage
* message
= new BMessage(MSG_ADD_TRANSFORMER
);
400 message
->AddInt32("type", type
);
401 addMenu
->AddItem(new BMenuItem(name
.String(), message
));
403 addMenu
->SetTargetForItems(this);
404 fMenu
->AddItem(addMenu
);
411 TransformerListView::SetShape(Shape
* shape
)
416 // detach from old container
418 fShape
->RemoveListener(this);
425 fShape
->AddListener(this);
427 int32 count
= fShape
->CountTransformers();
428 for (int32 i
= 0; i
< count
; i
++)
429 _AddTransformer(fShape
->TransformerAtFast(i
), i
);
437 TransformerListView::SetCommandStack(CommandStack
* stack
)
439 fCommandStack
= stack
;
446 TransformerListView::_AddTransformer(Transformer
* transformer
, int32 index
)
449 return AddItem(new TransformerItem(transformer
, this), index
);
453 // _RemoveTransformer
455 TransformerListView::_RemoveTransformer(Transformer
* transformer
)
457 TransformerItem
* item
= _ItemForTransformer(transformer
);
458 if (item
&& RemoveItem(item
)) {
465 // _ItemForTransformer
467 TransformerListView::_ItemForTransformer(Transformer
* transformer
) const
470 TransformerItem
* item
= dynamic_cast<TransformerItem
*>(ItemAt(i
));
472 if (item
->transformer
== transformer
)
480 TransformerListView::_UpdateMenu()
482 fMenu
->SetEnabled(fShape
!= NULL
);