* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2016, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "ImageListView.h"
#include <stdio.h>
#include <new>
#include <Looper.h>
#include <Message.h>
#include <AutoLocker.h>
#include <ObjectList.h>
#include "GuiSettingsUtils.h"
#include "table/TableColumns.h"
#include "TargetAddressTableColumn.h"
#include "Tracing.h"
enum {
MSG_SYNC_IMAGE_LIST = 'sytl'
};
class ImageListView::ImagesTableModel : public TableModel {
public:
ImagesTableModel(Team* team)
:
fTeam(team)
{
Update();
}
~ImagesTableModel()
{
fTeam = NULL;
Update();
}
bool Update()
{
if (fTeam == NULL) {
for (int32 i = 0; Image* image = fImages.ItemAt(i); i++)
image->ReleaseReference();
fImages.MakeEmpty();
return true;
}
AutoLocker<Team> locker(fTeam);
ImageList::ConstIterator it = fTeam->Images().GetIterator();
Image* newImage = it.Next();
int32 index = 0;
while (Image* oldImage = fImages.ItemAt(index)) {
if (oldImage == newImage) {
index++;
newImage = it.Next();
} else {
fImages.RemoveItemAt(index);
oldImage->ReleaseReference();
NotifyRowsRemoved(index, 1);
}
}
int32 countBefore = fImages.CountItems();
while (newImage != NULL) {
if (!fImages.AddItem(newImage))
return false;
newImage->AcquireReference();
newImage = it.Next();
}
int32 count = fImages.CountItems();
if (count > countBefore)
NotifyRowsAdded(countBefore, count - countBefore);
return true;
}
virtual int32 CountColumns() const
{
return 6;
}
virtual int32 CountRows() const
{
return fImages.CountItems();
}
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
{
Image* image = fImages.ItemAt(rowIndex);
if (image == NULL)
return false;
const ImageInfo& info = image->Info();
switch (columnIndex) {
case 0:
value.SetTo(image->ID());
return true;
case 1:
value.SetTo(image->Name(), B_VARIANT_DONT_COPY_DATA);
return true;
case 2:
value.SetTo(info.TextBase());
return true;
case 3:
value.SetTo(info.TextBase() + info.TextSize());
return true;
case 4:
value.SetTo(info.DataBase());
return true;
case 5:
value.SetTo(info.DataBase() + info.DataSize());
return true;
default:
return false;
}
}
Image* ImageAt(int32 index) const
{
return fImages.ItemAt(index);
}
private:
Team* fTeam;
BObjectList<Image> fImages;
};
ImageListView::ImageListView(Team* team, Listener* listener)
:
BGroupView(B_VERTICAL),
fTeam(team),
fImage(NULL),
fImagesTable(NULL),
fImagesTableModel(NULL),
fListener(listener)
{
SetName("Images");
fTeam->AddListener(this);
}
ImageListView::~ImageListView()
{
SetImage(NULL);
fTeam->RemoveListener(this);
fImagesTable->SetTableModel(NULL);
delete fImagesTableModel;
}
ImageListView*
ImageListView::Create(Team* team, Listener* listener)
{
ImageListView* self = new ImageListView(team, listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
ImageListView::UnsetListener()
{
fListener = NULL;
}
void
ImageListView::SetImage(Image* image)
{
if (image == fImage)
return;
TRACE_GUI("ImageListView::SetImage(%p)\n", image);
if (fImage != NULL)
fImage->ReleaseReference();
fImage = image;
if (fImage != NULL) {
fImage->AcquireReference();
for (int32 i = 0; Image* other = fImagesTableModel->ImageAt(i); i++) {
if (fImage == other) {
fImagesTable->SelectRow(i, false);
TRACE_GUI("ImageListView::SetImage() done\n");
return;
}
}
}
fImagesTable->DeselectAllRows();
TRACE_GUI("ImageListView::SetImage() done\n");
}
void
ImageListView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SYNC_IMAGE_LIST:
if (fImagesTableModel != NULL)
fImagesTableModel->Update();
break;
default:
BGroupView::MessageReceived(message);
break;
}
}
void
ImageListView::LoadSettings(const BMessage& settings)
{
BMessage tableSettings;
if (settings.FindMessage("imagesTable", &tableSettings) == B_OK) {
GuiSettingsUtils::UnarchiveTableSettings(tableSettings,
fImagesTable);
}
}
status_t
ImageListView::SaveSettings(BMessage& settings)
{
settings.MakeEmpty();
BMessage tableSettings;
status_t result = GuiSettingsUtils::ArchiveTableSettings(tableSettings,
fImagesTable);
if (result == B_OK)
result = settings.AddMessage("imagesTable", &tableSettings);
return result;
}
void
ImageListView::ImageAdded(const Team::ImageEvent& event)
{
Looper()->PostMessage(MSG_SYNC_IMAGE_LIST, this);
}
void
ImageListView::ImageRemoved(const Team::ImageEvent& event)
{
Looper()->PostMessage(MSG_SYNC_IMAGE_LIST, this);
}
void
ImageListView::TableSelectionChanged(Table* table)
{
if (fListener == NULL)
return;
Image* image = NULL;
if (fImagesTableModel != NULL) {
TableSelectionModel* selectionModel = table->SelectionModel();
image = fImagesTableModel->ImageAt(selectionModel->RowAt(0));
}
fListener->ImageSelectionChanged(image);
}
void
ImageListView::_Init()
{
fImagesTable = new Table("images list", 0, B_FANCY_BORDER);
fImagesTable->SetFont(B_FONT_ROW, be_fixed_font);
AddChild(fImagesTable->ToView());
fImagesTable->AddColumn(new Int32TableColumn(0, "ID", 40, 20, 1000,
B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fImagesTable->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000,
B_TRUNCATE_BEGINNING, B_ALIGN_LEFT));
fImagesTable->AddColumn(new TargetAddressTableColumn(2, "Text Base", 80,
40, 1000, B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fImagesTable->AddColumn(new TargetAddressTableColumn(3, "Text End", 80, 40,
1000, B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fImagesTable->AddColumn(new TargetAddressTableColumn(4, "Data Base", 80,
40, 1000, B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fImagesTable->AddColumn(new TargetAddressTableColumn(5, "Data End", 80, 40,
1000, B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fImagesTable->AddTableListener(this);
fImagesTableModel = new ImagesTableModel(fTeam);
fImagesTable->SetTableModel(fImagesTableModel);
fImagesTable->ResizeAllColumnsToPreferred();
}
ImageListView::Listener::~Listener()
{
}