Forgot to add new files to the last checkin

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20114 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm 2007-02-07 22:16:45 +00:00
parent e61a091fd0
commit 22c6ae6951
10 changed files with 1594 additions and 0 deletions

View File

@ -0,0 +1,729 @@
#include "BitmapView.h"
#include <Entry.h>
#include <TranslationUtils.h>
#include <TranslatorRoster.h>
#include <TranslatorFormats.h>
#include <Clipboard.h>
#include <BitmapStream.h>
#include <MenuItem.h>
#include <Font.h>
#include <Alert.h>
// TODO: Add support for labels
#define M_REMOVE_IMAGE 'mrmi'
#define M_PASTE_IMAGE 'mpsi'
enum
{
CLIP_NONE=0,
CLIP_BEOS=1,
CLIP_SHOWIMAGE=2,
CLIP_PRODUCTIVE=3
};
inline void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255);
void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a)
{
if(col)
{
col->red=r;
col->green=g;
col->blue=b;
col->alpha=a;
}
}
BitmapView::BitmapView(BRect frame, const char *name, BMessage *mod, BBitmap *bitmap,
const char *label, border_style borderstyle,int32 resize,int32 flags)
: BView(frame, name, resize, flags)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
if(bitmap && bitmap->IsValid())
fBitmap=bitmap;
else
fBitmap=NULL;
if(mod)
SetMessage(mod);
fLabel=label;
fBorderStyle=borderstyle;
fFixedSize=false;
fEnabled=true;
fRemovableBitmap=false;
fAcceptDrops=true;
fAcceptPaste=true;
fConstrainDrops=true;
fMaxWidth=100;
fMaxHeight=100;
fPopUpMenu=new BPopUpMenu("deletepopup",false,false);
fPopUpMenu->AddItem(new BMenuItem("Close This Menu",new BMessage(B_CANCEL)));
fPopUpMenu->AddSeparatorItem();
fPasteItem=new BMenuItem("Paste Photo from Clipboard",new BMessage(M_PASTE_IMAGE));
fPopUpMenu->AddItem(fPasteItem);
fPopUpMenu->AddSeparatorItem();
fRemoveItem=new BMenuItem("Remove Photo",new BMessage(M_REMOVE_IMAGE));
fPopUpMenu->AddItem(fRemoveItem);
CalculateBitmapRect();
// Calculate the offsets for each of the words -- the phrase will be center justified
fNoPhotoWidths[0]=StringWidth("Drop");
fNoPhotoWidths[1]=StringWidth("a");
fNoPhotoWidths[2]=StringWidth("Photo");
fNoPhotoWidths[3]=StringWidth("Here");
font_height fh;
GetFontHeight(&fh);
float totalheight=fh.ascent+fh.descent+fh.leading;
float yoffset=(Bounds().Height()-10-(totalheight*4))/2;
fNoPhotoOffsets[0].Set( (Bounds().Width()-fNoPhotoWidths[0])/2,totalheight+yoffset);
fNoPhotoOffsets[1].Set( (Bounds().Width()-fNoPhotoWidths[1])/2,fNoPhotoOffsets[0].y+totalheight);
fNoPhotoOffsets[2].Set( (Bounds().Width()-fNoPhotoWidths[2])/2,fNoPhotoOffsets[1].y+totalheight);
fNoPhotoOffsets[3].Set( (Bounds().Width()-fNoPhotoWidths[3])/2,fNoPhotoOffsets[2].y+totalheight);
}
BitmapView::~BitmapView(void)
{
delete fPopUpMenu;
}
void BitmapView::AttachedToWindow(void)
{
SetTarget((BHandler*)Window());
fPopUpMenu->SetTargetForItems(this);
}
void BitmapView::SetBitmap(BBitmap *bitmap)
{
if(bitmap && bitmap->IsValid())
{
if(fBitmap==bitmap)
return;
fBitmap=bitmap;
}
else
{
if(fBitmap==NULL)
return;
fBitmap=NULL;
}
CalculateBitmapRect();
if(!IsHidden())
Invalidate();
}
void BitmapView::SetEnabled(bool value)
{
if(fEnabled!=value)
{
fEnabled=value;
Invalidate();
}
}
/*
void BitmapView::SetLabel(const char *label)
{
if(fLabel.Compare(label)!=0)
{
fLabel=label;
CalculateBitmapRect();
if(!IsHidden())
Invalidate();
}
}
*/
void BitmapView::SetStyle(border_style style)
{
if(fBorderStyle!=style)
{
fBorderStyle=style;
CalculateBitmapRect();
if(!IsHidden())
Invalidate();
}
}
void BitmapView::SetFixedSize(bool isfixed)
{
if(fFixedSize!=isfixed)
{
fFixedSize=isfixed;
CalculateBitmapRect();
if(!IsHidden())
Invalidate();
}
}
void BitmapView::MessageReceived(BMessage *msg)
{
if(msg->WasDropped() && AcceptsDrops())
{
// We'll handle two types of drops: those from Tracker and those from ShowImage
if(msg->what==B_SIMPLE_DATA)
{
int32 actions;
if(msg->FindInt32("be:actions",&actions)==B_OK)
{
// ShowImage drop. This is a negotiated drag&drop, so send a reply
BMessage reply(B_COPY_TARGET), response;
reply.AddString("be:types","image/jpeg");
reply.AddString("be:types","image/png");
msg->SendReply(&reply,&response);
// now, we've gotten the response
if(response.what==B_MIME_DATA)
{
// Obtain and translate the received data
uint8 *imagedata;
ssize_t datasize;
// Try JPEG first
if(response.FindData("image/jpeg",B_MIME_DATA,(const void **)&imagedata,&datasize)!=B_OK)
{
// Try PNG next and piddle out if unsuccessful
if(response.FindData("image/png",B_PNG_FORMAT,(const void **)&imagedata,&datasize)!=B_OK)
return;
}
// Set up to decode into memory
BMemoryIO memio(imagedata,datasize);
BTranslatorRoster *roster=BTranslatorRoster::Default();
BBitmapStream bstream;
if(roster->Translate(&memio,NULL,NULL,&bstream, B_TRANSLATOR_BITMAP)==B_OK)
{
BBitmap *bmp;
if(bstream.DetachBitmap(&bmp)!=B_OK)
return;
SetBitmap(bmp);
if(fConstrainDrops)
ConstrainBitmap();
Invoke();
}
}
return;
}
entry_ref ref;
if(msg->FindRef("refs",&ref)==B_OK)
{
// Tracker drop
BBitmap *bmp=BTranslationUtils::GetBitmap(&ref);
if(bmp)
{
SetBitmap(bmp);
if(fConstrainDrops)
ConstrainBitmap();
Invoke();
}
}
}
return;
}
switch(msg->what)
{
case M_REMOVE_IMAGE:
{
BAlert *alert=new BAlert("Mr. Peeps!","This cannot be undone. Remove the image?","Remove",
"Cancel");
int32 value=alert->Go();
if(value==0)
{
SetBitmap(NULL);
if(Target())
{
BMessenger msgr(Target());
msgr.SendMessage(new BMessage(M_BITMAP_REMOVED));
return;
}
}
}
case M_PASTE_IMAGE:
{
PasteBitmap();
Invoke();
}
}
BView::MessageReceived(msg);
}
void BitmapView::Draw(BRect rect)
{
if(fBitmap)
DrawBitmap(fBitmap,fBitmap->Bounds(),fBitmapRect);
else
{
SetHighColor(0,0,0,80);
SetDrawingMode(B_OP_ALPHA);
DrawString("Drop",fNoPhotoOffsets[0]);
DrawString("a",fNoPhotoOffsets[1]);
DrawString("Photo",fNoPhotoOffsets[2]);
DrawString("Here",fNoPhotoOffsets[3]);
SetDrawingMode(B_OP_COPY);
}
if(fBorderStyle==B_FANCY_BORDER)
{
rgb_color base= {216,216,216,255};
rgb_color work;
SetHighColor(base);
StrokeRect(Bounds().InsetByCopy(2,2));
BeginLineArray(12);
BRect r(Bounds());
work=tint_color(base,B_DARKEN_2_TINT);
AddLine(r.LeftTop(),r.RightTop(),work);
AddLine(r.LeftTop(),r.LeftBottom(),work);
r.left++;
work=tint_color(base,B_DARKEN_4_TINT);
AddLine(r.RightTop(),r.RightBottom(),work);
AddLine(r.LeftBottom(),r.RightBottom(),work);
r.right--;
r.top++;
r.bottom--;
work=tint_color(base,B_LIGHTEN_MAX_TINT);
AddLine(r.LeftTop(),r.RightTop(),work);
AddLine(r.LeftTop(),r.LeftBottom(),work);
r.left++;
work=tint_color(base,B_DARKEN_3_TINT);
AddLine(r.RightTop(),r.RightBottom(),work);
AddLine(r.LeftBottom(),r.RightBottom(),work);
// this rect handled by the above StrokeRect, so inset a total of 2 pixels
r.left++;
r.right-=2;
r.top+=2;
r.bottom-=2;
work=tint_color(base,B_DARKEN_3_TINT);
AddLine(r.LeftTop(),r.RightTop(),work);
AddLine(r.LeftTop(),r.LeftBottom(),work);
r.left++;
work=tint_color(base,B_LIGHTEN_MAX_TINT);
AddLine(r.RightTop(),r.RightBottom(),work);
AddLine(r.LeftBottom(),r.RightBottom(),work);
r.right--;
r.top++;
r.bottom--;
EndLineArray();
SetHighColor(tint_color(base,B_DARKEN_2_TINT));
StrokeRect(r);
}
else
{
// Plain border
SetHighColor(0,0,0);
StrokeRect(fBitmapRect);
}
}
void BitmapView::MouseDown(BPoint pt)
{
BPoint mousept;
uint32 buttons;
GetMouse(&mousept,&buttons);
if(buttons & B_SECONDARY_MOUSE_BUTTON)
{
ConvertToScreen(&mousept);
mousept.x= (mousept.x>5) ? mousept.x-5 : 0;
mousept.y= (mousept.y>5) ? mousept.y-5 : 0;
if(AcceptsPaste() && ClipboardHasBitmap())
fPasteItem->SetEnabled(true);
else
fPasteItem->SetEnabled(false);
if(fRemovableBitmap && fBitmap)
fRemoveItem->SetEnabled(true);
else
fRemoveItem->SetEnabled(false);
fPopUpMenu->Go(mousept,true,true,true);
}
}
void BitmapView::FrameResized(float w, float h)
{
CalculateBitmapRect();
}
void BitmapView::CalculateBitmapRect(void)
{
if(!fBitmap || fFixedSize)
{
fBitmapRect=Bounds().InsetByCopy(1,1);
return;
}
/* // Dynamic sizing algorithm
// 1) Check to see if either dimension is bigger than the view's display area
// 2) If smaller along both axes, make bitmap rect centered and return
// 3) Check to see if scaling is to be horizontal or vertical on basis of longer axis
// 4) Calculate scaling factor
// 5) Scale both axes down by scaling factor, accounting for border width
// 6) Center the rectangle in the direction of the smaller axis
uint8 borderwidth=(fBorderStyle==B_FANCY_BORDER)?5:1;
BRect r(Bounds());
r.InsetBy(borderwidth,borderwidth);
if( (fBitmap->Bounds().Width()<=r.Width()) &&
(fBitmap->Bounds().Height()<=r.Height()) )
{
// Smaller than view, so just center and return
fBitmapRect=fBitmap->Bounds();
fBitmapRect.OffsetBy( borderwidth+
((r.Width()-fBitmapRect.Width()-(borderwidth<<2))/2),
((r.Height()-fBitmapRect.Height()-(borderwidth<<2))/2) );
return;
}
float multiplier=fBitmap->Bounds().Width()/fBitmap->Bounds().Height();
float offset;
if(multiplier>1)
{
// Landscape orientation
// Scale rectangle to bounds width and center height
r.bottom=r.top+(r.Width()/multiplier);
offset= ((Bounds().Height()-(borderwidth<<1)) - r.Height())/2;
r.OffsetBy(0,offset);
}
else
{
// Portrait orientation
// Scale rectangle to bounds height and center width
r.right=r.left+(r.Height()*multiplier);
offset= ((Bounds().Width()-(borderwidth<<1)) - r.Width())/2;
r.OffsetBy(offset,0);
}
fBitmapRect=r;
*/
uint8 borderwidth=(fBorderStyle==B_FANCY_BORDER)?5:1;
BRect r(Bounds());
fBitmapRect= ScaleRectToFit(fBitmap->Bounds(),r.InsetByCopy(borderwidth,borderwidth));
}
void BitmapView::SetAcceptDrops(bool accept)
{
fAcceptDrops=accept;
}
void BitmapView::SetAcceptPaste(bool accept)
{
fAcceptPaste=accept;
}
void BitmapView::SetConstrainDrops(bool value)
{
fConstrainDrops=value;
}
void BitmapView::MaxBitmapSize(float *width, float *height) const
{
*width=fMaxWidth;
*height=fMaxHeight;
}
void BitmapView::SetMaxBitmapSize(const float &width, const float &height)
{
fMaxWidth=width;
fMaxHeight=height;
ConstrainBitmap();
}
void BitmapView::SetBitmapRemovable(bool isremovable)
{
fRemovableBitmap=isremovable;
}
void BitmapView::ConstrainBitmap(void)
{
if(!fBitmap || fMaxWidth < 1 || fMaxHeight < 1)
return;
BRect r=ScaleRectToFit(fBitmap->Bounds(),BRect(0,0,fMaxWidth-1,fMaxHeight-1));
r.OffsetTo(0,0);
BBitmap *scaled=new BBitmap(r,fBitmap->ColorSpace(),true);
BView *view=new BView(r,"drawview",0,0);
scaled->Lock();
scaled->AddChild(view);
view->DrawBitmap(fBitmap,fBitmap->Bounds(),scaled->Bounds());
scaled->Unlock();
delete fBitmap;
fBitmap=new BBitmap(scaled,false);
}
bool BitmapView::ClipboardHasBitmap(void)
{
BMessage *clip=NULL,flattened;
uint8 clipval=CLIP_NONE;
bool returnval;
if(be_clipboard->Lock())
{
clip=be_clipboard->Data();
if(!clip->IsEmpty())
{
returnval=(clip->FindMessage("image/bitmap",&flattened)==B_OK);
if(returnval)
clipval=CLIP_BEOS;
else
{
BString string;
returnval=(clip->FindString("class",&string)==B_OK && string=="BBitmap");
// Try method Gobe Productive uses if that, too, didn't work
if(returnval)
clipval=CLIP_SHOWIMAGE;
else
{
returnval=(clip->FindMessage("image/x-vnd.Be-bitmap",&flattened)==B_OK);
if(returnval)
clipval=CLIP_SHOWIMAGE;
else
clipval=CLIP_NONE;
}
}
}
be_clipboard->Unlock();
}
return (clipval!=CLIP_NONE)?true:false;
}
BBitmap *BitmapView::BitmapFromClipboard(void)
{
BMessage *clip=NULL,flattened;
BBitmap *bitmap;
if(!be_clipboard->Lock())
return NULL;
clip=be_clipboard->Data();
if(!clip)
return NULL;
uint8 clipval=CLIP_NONE;
// Try ArtPaint-style storage
status_t status=clip->FindMessage("image/bitmap",&flattened);
// If that didn't work, try ShowImage-style
if(status!=B_OK)
{
BString string;
status=clip->FindString("class",&string);
// Try method Gobe Productive uses if that, too, didn't work
if(status==B_OK && string=="BBitmap")
clipval=CLIP_SHOWIMAGE;
else
{
status=clip->FindMessage("image/x-vnd.Be-bitmap",&flattened);
if(status==B_OK)
clipval=CLIP_PRODUCTIVE;
else
clipval=CLIP_NONE;
}
}
else
clipval=CLIP_BEOS;
be_clipboard->Unlock();
switch(clipval)
{
case CLIP_SHOWIMAGE:
{
// Showimage does it a slightly different way -- it dumps the BBitmap
// data directly to the clipboard message instead of packaging it in
// a bitmap like everyone else.
if(!be_clipboard->Lock())
return NULL;
BMessage datamsg(*be_clipboard->Data());
be_clipboard->Unlock();
const void *buffer;
int32 bufferLength;
BRect frame;
color_space cspace=B_NO_COLOR_SPACE;
status=datamsg.FindRect("_frame",&frame);
if(status!=B_OK)
return NULL;
status=datamsg.FindInt32("_cspace",(int32)cspace);
if(status!=B_OK)
return NULL;
cspace=B_RGBA32;
bitmap=new BBitmap(frame,cspace,true);
status=datamsg.FindData("_data",B_RAW_TYPE,(const void **)&buffer, &bufferLength);
if(status!=B_OK)
{
delete bitmap;
return NULL;
}
memcpy(bitmap->Bits(), buffer, bufferLength);
return bitmap;
}
case CLIP_PRODUCTIVE:
// Productive doesn't name the packaged BBitmap data message the same, but
// uses exactly the same data format.
case CLIP_BEOS:
{
const void *buffer;
int32 bufferLength;
BRect frame;
color_space cspace=B_NO_COLOR_SPACE;
status=flattened.FindRect("_frame",&frame);
if(status!=B_OK)
return NULL;
status=flattened.FindInt32("_cspace",(int32)cspace);
if(status!=B_OK)
return NULL;
cspace=B_RGBA32;
bitmap=new BBitmap(frame,cspace,true);
status=flattened.FindData("_data",B_RAW_TYPE,(const void **)&buffer, &bufferLength);
if(status!=B_OK)
{
delete bitmap;
return NULL;
}
memcpy(bitmap->Bits(), buffer, bufferLength);
return bitmap;
}
default:
return NULL;
}
// shut the compiler up
return NULL;
}
BRect ScaleRectToFit(const BRect &from, const BRect &to)
{
// Dynamic sizing algorithm
// 1) Check to see if either dimension is bigger than the view's display area
// 2) If smaller along both axes, make bitmap rect centered and return
// 3) Check to see if scaling is to be horizontal or vertical on basis of longer axis
// 4) Calculate scaling factor
// 5) Scale both axes down by scaling factor, accounting for border width
// 6) Center the rectangle in the direction of the smaller axis
if(!to.IsValid())
return from;
if(!from.IsValid())
return to;
BRect r(to);
if( (from.Width()<=r.Width()) &&
(from.Height()<=r.Height()) )
{
// Smaller than view, so just center and return
r=from;
r.OffsetBy( (to.Width()-r.Width())/2, (to.Height()-r.Height())/2 );
return r;
}
float multiplier=from.Width()/from.Height();
if(multiplier>1)
{
// Landscape orientation
// Scale rectangle to bounds width and center height
r.bottom=r.top+(r.Width()/multiplier);
r.OffsetBy(0,(to.Height() - r.Height())/2);
}
else
{
// Portrait orientation
// Scale rectangle to bounds height and center width
r.right=r.left+(r.Height()*multiplier);
r.OffsetBy((to.Width() - r.Width())/2,0);
}
return r;
}
void BitmapView::RemoveBitmap(void)
{
SetBitmap(NULL);
}
void BitmapView::PasteBitmap(void)
{
BBitmap *bmp=BitmapFromClipboard();
if(bmp)
SetBitmap(bmp);
if(fConstrainDrops)
ConstrainBitmap();
}

View File

@ -0,0 +1,93 @@
#ifndef BMPVIEW_H
#define BMPVIEW_H
#include <Message.h>
#include <Bitmap.h>
#include <Invoker.h>
#include <String.h>
#include <View.h>
#include <PopUpMenu.h>
enum
{
M_BITMAP_ADDED='mbma',
M_BITMAP_REMOVED='mbmr'
};
class BitmapView : public BView, public BInvoker
{
public:
BitmapView(BRect frame, const char *name, BMessage *mod, BBitmap *bitmap,
const char *label = NULL, border_style = B_PLAIN_BORDER,
int32 resize = B_FOLLOW_LEFT | B_FOLLOW_TOP, int32 flags = B_WILL_DRAW);
~BitmapView(void);
virtual void AttachedToWindow(void);
virtual void Draw(BRect rect);
virtual void MessageReceived(BMessage *msg);
virtual void MouseDown(BPoint pt);
virtual void FrameResized(float w, float h);
virtual void SetBitmap(BBitmap *bitmap);
BBitmap *GetBitmap(void) const { return fBitmap; }
bool IsEnabled(void) const { return fEnabled; }
virtual void SetEnabled(bool value);
// const char *Label(void) const { return fLabel.String(); }
// virtual void SetLabel(const char *label);
border_style Style(void) const { return fBorderStyle; }
virtual void SetStyle(border_style style);
bool IsFixedSize(void) const { return fFixedSize; }
void SetFixedSize(bool isfixed);
bool AcceptsDrops(void) const { return fAcceptDrops; }
virtual void SetAcceptDrops(bool accept);
bool AcceptsPaste(void) const { return fAcceptPaste; }
virtual void SetAcceptPaste(bool accept);
bool ConstrainsDrops(void) const { return fConstrainDrops; }
virtual void SetConstrainDrops(bool value);
void MaxBitmapSize(float *width, float *height) const;
virtual void SetMaxBitmapSize(const float &width, const float &height);
bool IsBitmapRemovable(void) const { return fRemovableBitmap; }
void SetBitmapRemovable(bool isremovable);
void RemoveBitmap(void);
void PasteBitmap(void);
private:
void CalculateBitmapRect(void);
void ConstrainBitmap(void);
bool ClipboardHasBitmap(void);
BBitmap *BitmapFromClipboard(void);
float fNoPhotoWidths[4];
BPoint fNoPhotoOffsets[4];
BBitmap *fBitmap;
BRect fBitmapRect;
bool fEnabled;
BString fLabel;
border_style fBorderStyle;
bool fFixedSize;
bool fAcceptDrops;
bool fAcceptPaste;
bool fConstrainDrops;
float fMaxWidth, fMaxHeight;
bool fRemovableBitmap;
BPopUpMenu *fPopUpMenu;
uint32 fMouseButtons;
BMenuItem *fPasteItem;
BMenuItem *fRemoveItem;
};
BRect ScaleRectToFit(const BRect &from, const BRect &to);
#endif

View File

@ -0,0 +1,113 @@
#include "InternalEditors.h"
#include "BitmapView.h"
#include "ResourceData.h"
#include <TranslationUtils.h>
#include <DataIO.h>
#define M_IMAGE_CHANGED 'imch'
ImageEditor::ImageEditor(const BRect &frame, ResourceData *data, BHandler *owner)
: Editor(frame, data, owner)
{
SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_ZOOMABLE);
SetTitle(data->GetName());
// Set up the image and the viewer for such
BMemoryIO memio(data->GetData(),data->GetLength());
fImage = BTranslationUtils::GetBitmap(&memio);
BRect imgsize;
if (fImage)
imgsize = ScaleRectToFit(fImage->Bounds(),BRect(0,0,200,200));
else
imgsize.Set(0,0,200,200);
BView *back = new BView(Bounds(),"back",B_FOLLOW_ALL,B_WILL_DRAW);
back->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
AddChild(back);
BRect r;
float labelwidth = be_plain_font->StringWidth("ID: ");
float strwidth = be_plain_font->StringWidth("(attr) ");
font_height fh;
be_plain_font->GetHeight(&fh);
float strheight = fh.ascent + fh.descent + fh.leading + 5;
fIDBox = new BTextControl(BRect(10,10,10 + (strwidth + labelwidth) + 15,
10 + strheight),
"id","ID: ",data->GetIDString(), NULL);
fIDBox->SetDivider(labelwidth + 5);
back->AddChild(fIDBox);
r = fIDBox->Frame();
r.OffsetBy(r.Width() + 10, 0);
r.right = Bounds().right - 10;
fNameBox = new BTextControl(r,"name","Name: ",data->GetName(), NULL,
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
fNameBox->SetDivider(be_plain_font->StringWidth("Name: ") + 5);
back->AddChild(fNameBox);
r = imgsize;
r.OffsetTo( (Bounds().Width() - r.Width()) / 2,fNameBox->Frame().bottom + 10);
fImageView = new BitmapView(r,"imageview",new BMessage(M_IMAGE_CHANGED),fImage,
NULL, B_PLAIN_BORDER, B_FOLLOW_NONE,
B_WILL_DRAW | B_FRAME_EVENTS);
back->AddChild(fImageView);
fImageView->SetConstrainDrops(false);
// No limit on bitmap size
fImageView->SetMaxBitmapSize(0,0);
fImageView->SetBitmapRemovable(false);
fOK = new BButton(BRect(10,10,11,11),"ok","Cancel",new BMessage(M_UPDATE_RESOURCE),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
fOK->ResizeToPreferred();
fOK->SetLabel("OK");
fOK->MakeDefault(true);
back->AddChild(fOK);
fOK->MoveTo(Bounds().right - fOK->Bounds().Width() - 10,
Bounds().bottom - fOK->Bounds().Height() - 10);
r = fOK->Frame();
r.OffsetBy(-r.Width() - 10, 0);
fCancel = new BButton(r,"cancel","Cancel",new BMessage(B_QUIT_REQUESTED),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
back->AddChild(fCancel);
ResizeTo(MAX(fImageView->Frame().right, fNameBox->Frame().right) + 20,
fImageView->Frame().bottom + fOK->Frame().Height() + 20);
}
ImageEditor::~ImageEditor(void)
{
delete fImage;
}
void
ImageEditor::MessageReceived(BMessage *msg)
{
if (msg->WasDropped()) {
fImageView->MessageReceived(msg);
} else if (msg->what == M_IMAGE_CHANGED) {
fImage = fImageView->GetBitmap();
BRect r = ScaleRectToFit(fImage->Bounds(), BRect(0,0,200,200));
fImageView->ResizeTo(r.Width(),r.Height());
ResizeTo(MAX(fImageView->Frame().right, fNameBox->Frame().right) + 20,
fImageView->Frame().bottom + fOK->Frame().Height() + 20);
} else
BWindow::MessageReceived(msg);
}
void
ImageEditor::FrameResized(float w, float h)
{
fImageView->MoveTo( (w - fImageView->Bounds().Width()) / 2,
fNameBox->Frame().bottom + 10);
}

View File

@ -0,0 +1,94 @@
#include "InlineEditor.h"
#include <MessageFilter.h>
#include <Handler.h>
class EditFilter : public BMessageFilter
{
public:
EditFilter(BTextControl *textbox)
: BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE,B_KEY_DOWN)
{
fTextBox = textbox;
}
~EditFilter(void)
{
}
filter_result Filter(BMessage *msg, BHandler **target)
{
int32 rawchar;
msg->FindInt32("raw_char",&rawchar);
if (rawchar == B_ESCAPE) {
BLooper *loop = (*target)->Looper();
if (loop) {
BMessenger msgr(loop);
msgr.SendMessage(B_QUIT_REQUESTED);
return B_SKIP_MESSAGE;
}
} else if (rawchar == B_ENTER) {
fTextBox->Invoke();
return B_SKIP_MESSAGE;
}
return B_DISPATCH_MESSAGE;
}
private:
BTextControl *fTextBox;
};
InlineEditor::InlineEditor(BMessenger target, const BRect &frame,
const char *text)
: BWindow(frame,"InlineEditor",B_NO_BORDER_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS),
fMessenger(target),
fCommand(M_INLINE_TEXT)
{
fTextBox = new BTextControl(BRect(0,0,1,1), "inlinebox",NULL, text,
new BMessage(fCommand), B_FOLLOW_ALL,
B_WILL_DRAW);
AddChild(fTextBox);
fTextBox->SetDivider(0);
fTextBox->MakeFocus(true);
fTextBox->ResizeToPreferred();
fTextBox->ResizeTo(Bounds().Width(),fTextBox->Bounds().Height());
ResizeTo(Bounds().Width(), fTextBox->Bounds().Height());
AddCommonFilter(new EditFilter(fTextBox));
}
bool
InlineEditor::QuitRequested(void)
{
return true;
}
void
InlineEditor::SetMessage(BMessage *msg)
{
fCommand = msg ? msg->what : 0;
fTextBox->SetMessage(msg);
}
void
InlineEditor::MessageReceived(BMessage *msg)
{
if (msg->what == fCommand) {
fMessenger.SendMessage(msg);
PostMessage(B_QUIT_REQUESTED);
}
}
void
InlineEditor::WindowActivated(bool active)
{
if (!active)
PostMessage(B_QUIT_REQUESTED);
}

View File

@ -0,0 +1,27 @@
#ifndef INLINE_EDITOR
#define INLINE_EDITOR
#include <Window.h>
#include <TextControl.h>
#include <Messenger.h>
#define M_INLINE_TEXT 'intx'
class InlineEditor : public BWindow
{
public:
InlineEditor(BMessenger target, const BRect &frame,
const char *text);
bool QuitRequested(void);
void SetMessage(BMessage *msg);
void MessageReceived(BMessage *msg);
void WindowActivated(bool active);
private:
BTextControl *fTextBox;
BMessenger fMessenger;
uint32 fCommand;
};
#endif

View File

@ -0,0 +1,85 @@
#ifndef INTERNALEDITORS_H
#define INTERNALEDITORS_H
#include <View.h>
#include <TextControl.h>
#include <Button.h>
#include "Editor.h"
class StringEditView : public BView
{
public:
StringEditView(const BRect &frame);
~StringEditView(void);
void AttachedToWindow(void);
const char * GetID(void) const { return fIDBox->Text(); }
void SetID(const char *idstring) { fIDBox->SetText(idstring); }
const char * GetName(void) const { return fNameBox->Text(); }
void SetName(const char *name) { fNameBox->SetText(name); }
const char * GetValue(void) const { return fValueBox->Text(); }
void SetValue(const char *value) { fValueBox->SetText(value); }
void EnableID(const bool &value) { fIDBox->SetEnabled(value); }
bool IsIDEnabled(void) const { return fIDBox->IsEnabled(); }
float GetPreferredWidth(void) const;
float GetPreferredHeight(void) const;
private:
BTextControl *fIDBox,
*fNameBox,
*fValueBox;
BButton *fCancel,
*fOK;
};
class DoubleEditor : public Editor
{
public:
DoubleEditor(const BRect &frame, ResourceData *data,
BHandler *owner);
void MessageReceived(BMessage *msg);
private:
StringEditView *fView;
};
class StringEditor : public Editor
{
public:
StringEditor(const BRect &frame, ResourceData *data,
BHandler *owner);
void MessageReceived(BMessage *msg);
private:
StringEditView *fView;
};
class BitmapView;
class ImageEditor : public Editor
{
public:
ImageEditor(const BRect &frame, ResourceData *data,
BHandler *owner);
~ImageEditor(void);
void MessageReceived(BMessage *msg);
void FrameResized(float w, float h);
private:
BTextControl *fIDBox;
BTextControl *fNameBox;
BButton *fOK,
*fCancel;
BBitmap *fImage;
BitmapView *fImageView;
};
#endif

View File

@ -0,0 +1,153 @@
#include "InternalEditors.h"
#include "ResourceData.h"
#include <Messenger.h>
#include <Message.h>
#include <String.h>
#include <stdlib.h>
StringEditor::StringEditor(const BRect &frame, ResourceData *data,
BHandler *owner)
: Editor(frame, data, owner)
{
if (data->GetName())
SetTitle(data->GetName());
fView = new StringEditView(Bounds());
AddChild(fView);
if (data->IsAttribute())
fView->EnableID(false);
else
fView->SetID(data->GetIDString());
fView->SetName(data->GetName());
fView->SetValue(data->GetData());
SetFlags(Flags() | B_NOT_V_RESIZABLE);
}
void
StringEditor::MessageReceived(BMessage *msg)
{
if (msg->what == M_UPDATE_RESOURCE) {
// We have to have an ID, so if the squirrely developer didn't give us
// one, don't do anything
if (fView->GetID()) {
int32 newid = atol(fView->GetID());
GetData()->SetID(newid);
}
GetData()->SetName(fView->GetName());
GetData()->SetData(fView->GetValue(),strlen(fView->GetValue()));
BMessage updatemsg(M_UPDATE_RESOURCE);
updatemsg.AddPointer("item",GetData());
BMessenger msgr(GetOwner());
msgr.SendMessage(&updatemsg);
PostMessage(B_QUIT_REQUESTED);
} else {
Editor::MessageReceived(msg);
}
}
Editor::Editor(const BRect &frame, ResourceData *data, BHandler *owner)
: BWindow(frame, "Untitled", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS),
fResData(data),
fOwner(owner)
{
}
Editor::~Editor(void)
{
}
StringEditView::StringEditView(const BRect &frame)
: BView(frame, "edit", B_FOLLOW_ALL, B_WILL_DRAW)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BRect r;
float labelwidth = be_plain_font->StringWidth("ID: ");
float strwidth = be_plain_font->StringWidth("(attr) ");
font_height fh;
be_plain_font->GetHeight(&fh);
float strheight = fh.ascent + fh.descent + fh.leading + 5;
fIDBox = new BTextControl(BRect(10,10,10 + (strwidth + labelwidth) + 15,
10 + strheight),
"id","ID: ","", NULL);
fIDBox->SetDivider(labelwidth + 5);
AddChild(fIDBox);
r = fIDBox->Frame();
r.OffsetBy(r.Width() + 10, 0);
r.right = Bounds().right - 10;
fNameBox = new BTextControl(r,"name","Name: ","", NULL,
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
fNameBox->SetDivider(be_plain_font->StringWidth("Name: ") + 5);
AddChild(fNameBox);
r.OffsetBy(0,r.Height() + 10);
r.left = 10;
fValueBox = new BTextControl(r,"value","Value: ","", NULL,
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
fValueBox->SetDivider(be_plain_font->StringWidth("Value: ") + 5);
AddChild(fValueBox);
fOK = new BButton(BRect(10,10,11,11),"ok","Cancel",new BMessage(M_UPDATE_RESOURCE),
B_FOLLOW_RIGHT);
fOK->ResizeToPreferred();
fOK->SetLabel("OK");
fOK->MakeDefault(true);
AddChild(fOK);
fOK->MoveTo(r.right - fOK->Bounds().Width(), r.bottom + 10);
r = fOK->Frame();
r.OffsetBy(-r.Width() - 10, 0);
fCancel = new BButton(r,"cancel","Cancel",new BMessage(B_QUIT_REQUESTED),
B_FOLLOW_RIGHT);
AddChild(fCancel);
}
StringEditView::~StringEditView(void)
{
}
void
StringEditView::AttachedToWindow(void)
{
if (Bounds().Height() < fCancel->Frame().bottom + 10)
Window()->ResizeTo(Window()->Bounds().Width(), fCancel->Frame().bottom + 10);
Window()->SetSizeLimits(Window()->Bounds().Width(), 30000,
Window()->Bounds().Height(), 30000);
}
float
StringEditView::GetPreferredWidth(void) const
{
float idwidth = be_plain_font->StringWidth("ID: ") +
be_plain_font->StringWidth("(attr) ") + 15;
float namewidth = be_plain_font->StringWidth("Name: ") +
be_plain_font->StringWidth(fNameBox->Text()) + 15;
return idwidth + namewidth + 30;
}
float
StringEditView::GetPreferredHeight(void) const
{
font_height fh;
be_plain_font->GetHeight(&fh);
float strheight = fh.ascent + fh.descent + fh.leading + 5;
return fOK->Frame().Height() + (strheight * 2) + 40;
}

View File

@ -0,0 +1,48 @@
#include "InternalEditors.h"
#include "ResourceData.h"
#include <Messenger.h>
#include <Message.h>
#include <String.h>
#include <stdlib.h>
DoubleEditor::DoubleEditor(const BRect &frame, ResourceData *data,
BHandler *owner)
: Editor(frame, data, owner)
{
if (data->GetName())
SetTitle(data->GetName());
fView = new StringEditView(Bounds());
AddChild(fView);
fView->SetID(data->GetIDString());
fView->SetName(data->GetName());
fView->SetValue(data->GetData());
}
void
DoubleEditor::MessageReceived(BMessage *msg)
{
if (msg->what == M_UPDATE_RESOURCE) {
// We have to have an ID, so if the squirrely developer didn't give us
// one, don't do anything
if (fView->GetID()) {
int32 newid = atol(fView->GetID());
GetData()->SetID(newid);
}
GetData()->SetName(fView->GetName());
GetData()->SetData(fView->GetValue(),strlen(fView->GetValue()));
BMessage updatemsg(M_UPDATE_RESOURCE);
updatemsg.AddPointer("item",GetData());
BMessenger msgr(GetOwner());
msgr.SendMessage(&updatemsg);
PostMessage(B_QUIT_REQUESTED);
} else {
Editor::MessageReceived(msg);
}
}

View File

@ -0,0 +1,177 @@
#include "ResFields.h"
#include "ResourceData.h"
#include <DataIO.h>
#include <TranslationUtils.h>
TypeCodeField::TypeCodeField(const type_code &code, ResourceData *data)
: BStringField(MakeTypeString(code).String()),
fTypeCode(code),
fData(data)
{
}
PreviewField::PreviewField(void)
{
}
PreviewField::~PreviewField(void)
{
}
BitmapPreviewField::BitmapPreviewField(BBitmap *bitmap)
{
fBitmap = bitmap;
}
BitmapPreviewField::~BitmapPreviewField(void)
{
delete fBitmap;
}
void
BitmapPreviewField::DrawField(BRect rect, BView *parent)
{
if (fBitmap) {
// Scale the fBitmap down to completely fit within the field's height
BRect drawrect(fBitmap->Bounds().OffsetToCopy(rect.LeftTop()));
if (drawrect.Height() > rect.Height()) {
drawrect = rect;
drawrect.right = drawrect.left +
(fBitmap->Bounds().Width() *
(rect.Height() / fBitmap->Bounds().Height()));
}
parent->SetDrawingMode(B_OP_ALPHA);
parent->DrawBitmap(fBitmap, fBitmap->Bounds(), drawrect);
parent->SetDrawingMode(B_OP_COPY);
BString out;
out << fBitmap->Bounds().IntegerWidth() << " x "
<< fBitmap->Bounds().IntegerHeight() << " x "
<< (int32(fBitmap->BytesPerRow() / fBitmap->Bounds().Width()) * 8);
BRect stringrect = rect;
stringrect.right -= 10;
stringrect.left = stringrect.right - parent->StringWidth(out.String());
if (stringrect.left < drawrect.right + 5)
stringrect.left = drawrect.right + 5;
parent->TruncateString(&out, B_TRUNCATE_END, stringrect.Width());
parent->DrawString(out.String(), stringrect.LeftTop());
}
}
void
BitmapPreviewField::SetData(char *data, const size_t &length)
{
BMemoryIO memio(data,length);
fBitmap = BTranslationUtils::GetBitmap(&memio);
}
IntegerPreviewField::IntegerPreviewField(const int64 &value)
{
fValue = value;
}
IntegerPreviewField::~IntegerPreviewField(void)
{
}
void
IntegerPreviewField::DrawField(BRect rect, BView *parent)
{
BPoint point(rect.LeftBottom());
point.y -= 2;
BString string;
string << fValue;
parent->TruncateString(&string, B_TRUNCATE_MIDDLE, rect.Width() - 14);
parent->DrawString(string.String(), point);
}
void
IntegerPreviewField::SetData(char *data, const size_t &length)
{
switch(length) {
case 8: {
fValue = *((int8*)data);
break;
}
case 16: {
fValue = *((int16*)data);
break;
}
case 32: {
fValue = *((int32*)data);
break;
}
case 64: {
fValue = *((int32*)data);
break;
}
default: {
break;
}
}
}
StringPreviewField::StringPreviewField(const char *string)
{
fClipped = fString = string;
}
StringPreviewField::~StringPreviewField(void)
{
}
void
StringPreviewField::DrawField(BRect rect, BView *parent)
{
BPoint point(rect.LeftBottom());
point.y -= 2;
fClipped = fString;
parent->TruncateString(&fClipped, B_TRUNCATE_END, rect.Width() - 14);
parent->DrawString(fClipped.String(), point);
}
void
StringPreviewField::SetData(char *data, const size_t &length)
{
char *temp = fString.LockBuffer(length + 2);
if (temp)
memcpy(temp, data, length);
temp[length] = '\0';
fString.UnlockBuffer();
fClipped = fString;
}
BString
MakeTypeString(int32 type)
{
char typestring[7];
char *typeptr = (char *) &type;
typestring[0] = '\'';
typestring[1] = typeptr[3];
typestring[2] = typeptr[2];
typestring[3] = typeptr[1];
typestring[4] = typeptr[0];
typestring[5] = '\'';
typestring[6] = '\0';
return BString(typestring);
}

View File

@ -0,0 +1,75 @@
#ifndef RESFIELDS_H
#define RESFIELDS_H
#include <ColumnTypes.h>
#include <Resources.h>
class ResourceData;
class TypeCodeField : public BStringField
{
public:
TypeCodeField(const type_code &code, ResourceData *data);
type_code GetTypeCode(void) const { return fTypeCode; }
ResourceData * GetResourceData(void) const { return fData; }
private:
type_code fTypeCode;
ResourceData *fData;
};
// This is the base class for fields displaying the preview in the Data
// column of the main window. Each child class must implement all methods
class PreviewField : public BField
{
public:
PreviewField(void);
virtual ~PreviewField(void);
virtual void DrawField(BRect rect, BView* parent) = 0;
virtual void SetData(char *data, const size_t &length) = 0;
};
// Unlike the BBitmapField class, this one actually takes ownership of the
// bitmap passed to it. This is good because the bitmap given to it is
// allocated by the Translation Kit.
class BitmapPreviewField : public PreviewField
{
public:
BitmapPreviewField(BBitmap *bitmap);
virtual ~BitmapPreviewField(void);
virtual void DrawField(BRect rect, BView* parent);
virtual void SetData(char *data, const size_t &length);
private:
BBitmap *fBitmap;
};
class IntegerPreviewField : public PreviewField
{
public:
IntegerPreviewField(const int64 &value);
virtual ~IntegerPreviewField(void);
virtual void DrawField(BRect rect, BView* parent);
virtual void SetData(char *data, const size_t &length);
private:
int64 fValue;
};
class StringPreviewField : public PreviewField
{
public:
StringPreviewField(const char *string);
virtual ~StringPreviewField(void);
virtual void DrawField(BRect rect, BView* parent);
virtual void SetData(char *data, const size_t &length);
private:
BString fString;
BString fClipped;
};
BString MakeTypeString(int32 type);
#endif