- added full screen mode

- added dia show
- added rotate image clockwise, anti-clockwise, mirror image vertical or -horiztonal and invert image
- added myself to about dialog and copyright holders


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5270 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2003-11-06 20:57:04 +00:00
parent 0e10a7f803
commit ad13f387f9
7 changed files with 409 additions and 43 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageApp
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageApp.cpp
//
@@ -54,7 +54,7 @@ void
ShowImageApp::AboutRequested()
{
BAlert* pAlert = new BAlert("About ShowImage",
"OBOS ShowImage\n\nby Fernando F. Oliveira and Michael Wilber", "OK");
"OBOS ShowImage\n\nby Fernando F. Oliveira, Michael Wilber and Michael Pfeiffer", "OK");
pAlert->Go();
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageApp
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageApp.h
//
+9 -1
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageConstants
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageConstants.h
//
@@ -49,6 +49,14 @@ const uint32 MSG_PAGE_PREV = 'mPGP';
const uint32 MSG_FILE_NEXT = 'mFLN';
const uint32 MSG_FILE_PREV = 'mFLP';
const uint32 MSG_FIT_TO_WINDOW_SIZE = 'mFWS';
const uint32 MSG_ROTATE_CLOCKWISE = 'mRCW';
const uint32 MSG_ROTATE_ACLKWISE = 'mRAC';
const uint32 MSG_MIRROR_VERTICAL = 'mMIV';
const uint32 MSG_MIRROR_HORIZONTAL = 'mMIH';
const uint32 MSG_INVERT = 'mINV';
const uint32 MSG_DIA_SHOW = 'mDIA';
const uint32 MSG_DIA_SHOW_DELAY = 'mDSD';
const uint32 MSG_FULL_SCREEN = 'mFSC';
extern const char *APP_SIG;
+248 -28
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageView
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageView.cpp
//
@@ -27,6 +27,7 @@
/*****************************************************************************/
#include <stdio.h>
#include <Debug.h>
#include <Message.h>
#include <ScrollBar.h>
#include <StopWatch.h>
@@ -116,10 +117,19 @@ ShowImageView::RotatePatterns()
void
ShowImageView::Pulse()
{
RotatePatterns();
if (fbHasSelection) {
RotatePatterns();
DrawSelectionBox(fSelectionRect);
}
if (fDiaShow) {
fDiaShowCountDown --;
if (fDiaShowCountDown <= 0) {
fDiaShowCountDown = fDiaShowDelay;
if (!NextFile()) {
FirstFile();
}
}
}
}
ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
@@ -133,6 +143,8 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
fDocumentCount = 1;
fbHasSelection = false;
fResizeToViewBounds = false;
fDiaShow = false;
SetDiaShowDelay(3); // 3 seconds
SetViewColor(B_TRANSPARENT_COLOR);
SetHighColor(kborderColor);
@@ -168,6 +180,21 @@ ShowImageView::IsImage(const entry_ref *pref)
return true;
}
// send message to parent about new image
void ShowImageView::Notify(const char* status)
{
BMessage msg(MSG_UPDATE_STATUS);
if (status != NULL) {
msg.AddString("status", status);
}
msg.AddRef("ref", &fCurrentRef);
BMessenger msgr(Window());
msgr.SendMessage(&msg);
FixupScrollBars();
Invalidate();
}
void
ShowImageView::SetImage(const entry_ref *pref)
{
@@ -215,15 +242,7 @@ ShowImageView::SetImage(const entry_ref *pref)
else
fDocumentCount = 1;
// send message to parent about new image
BMessage msg(MSG_UPDATE_STATUS);
msg.AddString("status", info.name);
msg.AddRef("ref", &fCurrentRef);
BMessenger msgr(Window());
msgr.SendMessage(&msg);
FixupScrollBars();
Invalidate();
Notify(info.name);
}
void
@@ -415,7 +434,11 @@ ShowImageView::UpdateSelectionRect(BPoint point, bool final) {
}
}
if (oldSelection != fSelectionRect || !fbHasSelection) {
Invalidate();
BRect updateRect;
updateRect = oldSelection | fSelectionRect;
updateRect = ImageToView(updateRect);
updateRect.InsetBy(-PEN_SIZE, -PEN_SIZE);
Invalidate(updateRect);
}
}
@@ -548,8 +571,9 @@ ShowImageView::FreeEntries(BList* entries)
// Notes: BDirectory::GetNextEntry() must not necessary
// return entries sorted by name, thou BFS does.
bool
ShowImageView::FindNextImage(BEntry* image, bool next)
ShowImageView::FindNextImage(BEntry* image, bool next, bool rewind)
{
ASSERT(next || !rewind);
BEntry curImage(&fCurrentRef);
BEntry entry;
BDirectory parent;
@@ -559,19 +583,23 @@ ShowImageView::FindNextImage(BEntry* image, bool next)
return false;
while (parent.GetNextEntry(&entry) == B_OK) {
if (entry == curImage) {
// found current image
if (rewind || entry == curImage) {
// start with first entry or found current image
if (next) {
// start with next entry
if (!rewind && parent.GetNextEntry(&entry) != B_OK) {
break;
}
// find next image in directory
while (parent.GetNextEntry(&entry) == B_OK) {
do {
entry_ref ref;
if (entry.GetRef(&ref) == B_OK && IsImage(&ref)) {
*image = entry;
return true;
}
}
} while (parent.GetNextEntry(&entry) == B_OK);
} else {
// find privous image in directory
// find previous image in directory
for (int32 i = entries.CountItems() - 1; i >= 0; i --) {
BEntry* entry = (BEntry*)entries.ItemAt(i);
entry_ref ref;
@@ -582,6 +610,7 @@ ShowImageView::FindNextImage(BEntry* image, bool next)
}
}
}
break;
}
if (!next) {
// record entries if we search for previous file
@@ -592,24 +621,215 @@ ShowImageView::FindNextImage(BEntry* image, bool next)
return false;
}
void
ShowImageView::NextFile()
bool
ShowImageView::ShowNextImage(bool next, bool rewind)
{
BEntry image;
entry_ref ref;
if (FindNextImage(&image, true) && image.GetRef(&ref) == B_OK) {
SetImage(&ref);
if (FindNextImage(&image, next, rewind) && image.GetRef(&ref) == B_OK) {
SetImage(&ref);
return true;
}
return false;
}
bool
ShowImageView::NextFile()
{
return ShowNextImage(true, false);
}
bool
ShowImageView::PrevFile()
{
return ShowNextImage(false, false);
}
bool
ShowImageView::FirstFile()
{
return ShowNextImage(true, true);
}
void
ShowImageView::SetDiaShowDelay(float seconds)
{
fDiaShowDelay = (int)(seconds * 10.0);
}
void
ShowImageView::StartDiaShow()
{
fDiaShow = true; fDiaShowCountDown = fDiaShowDelay;
}
void
ShowImageView::StopDiaShow()
{
fDiaShow = false;
}
int32
ShowImageView::BytesPerPixel(color_space cs) const
{
switch (cs) {
case B_RGB32: // fall through
case B_RGB32_BIG: // fall through
case B_RGBA32: // fall through
case B_RGBA32_BIG: return 4;
case B_RGB24_BIG: // fall through
case B_RGB24: return 3;
case B_RGB16: // fall through
case B_RGB16_BIG: // fall through
case B_RGB15: // fall through
case B_RGB15_BIG: // fall through
case B_RGBA15: // fall through
case B_RGBA15_BIG: return 2;
case B_GRAY8: // fall through
case B_CMAP8: return 1;
case B_GRAY1: return 0;
default: return -1;
}
}
void
ShowImageView::PrevFile()
ShowImageView::CopyPixel(uchar* dest, int32 destX, int32 destY, int32 destBPR, uchar* src, int32 x, int32 y, int32 bpr, int32 bpp)
{
BEntry image;
entry_ref ref;
dest += destBPR * destY + destX * bpp;
src += bpr * y + x * bpp;
memcpy(dest, src, bpp);
}
if (FindNextImage(&image, false) && image.GetRef(&ref) == B_OK) {
SetImage(&ref);
// FIXME: In color space with alpha channel the alpha value should not be inverted!
// This could be a problem when image is saved and opened in another application.
// Note: For B_CMAP8 InvertPixel inverts the color index not the color value!
void
ShowImageView::InvertPixel(int32 x, int32 y, uchar* dest, int32 destBPR, uchar* src, int32 bpr, int32 bpp)
{
dest += destBPR * y + x * bpp;
src += bpr * y + x * bpp;
for (; bpp > 0; bpp --, dest ++, src ++) {
*dest = ~*src;
}
}
// DoImageOperation supports only color spaces with bytes per pixel >= 1
// See above for limitations about kInvert
void
ShowImageView::DoImageOperation(image_operation op)
{
color_space cs;
int32 bpp;
BBitmap* bm;
int32 width, height;
uchar* src;
uchar* dest;
int32 bpr, destBPR;
int32 x, y, destX, destY;
BRect rect;
if (fpBitmap == NULL) return;
cs = fpBitmap->ColorSpace();
bpp = BytesPerPixel(cs);
if (bpp < 1) return;
width = fpBitmap->Bounds().IntegerWidth();
height = fpBitmap->Bounds().IntegerHeight();
if (op == kRotateClockwise || op == kRotateAntiClockwise) {
rect.Set(0, 0, height, width);
} else {
rect.Set(0, 0, width, height);
}
}
bm = new BBitmap(rect, cs);
if (bm == NULL) return;
src = (uchar*)fpBitmap->Bits();
dest = (uchar*)bm->Bits();
bpr = fpBitmap->BytesPerRow();
destBPR = bm->BytesPerRow();
switch (op) {
case kRotateClockwise:
for (y = 0; y <= height; y ++) {
for (x = 0; x <= width; x ++) {
destX = height - y;
destY = x;
CopyPixel(dest, destX, destY, destBPR, src, x, y, bpr, bpp);
}
}
break;
case kRotateAntiClockwise:
for (y = 0; y <= height; y ++) {
for (x = 0; x <= width; x ++) {
destX = y;
destY = width - x;
CopyPixel(dest, destX, destY, destBPR, src, x, y, bpr, bpp);
}
}
break;
case kMirrorHorizontal:
for (y = 0; y <= height; y ++) {
for (x = 0; x <= width; x ++) {
destX = x;
destY = height - y;
CopyPixel(dest, destX, destY, destBPR, src, x, y, bpr, bpp);
}
}
break;
case kMirrorVertical:
for (y = 0; y <= height; y ++) {
for (x = 0; x <= width; x ++) {
destX = width - x;
destY = y;
CopyPixel(dest, destX, destY, destBPR, src, x, y, bpr, bpp);
}
}
break;
case kInvert:
for (y = 0; y <= height; y ++) {
for (x = 0; x <= width; x ++) {
InvertPixel(x, y, dest, destBPR, src, bpr, bpp);
}
}
break;
}
// set new bitmap
delete fpBitmap; fpBitmap = bm;
// remove selection
fbHasSelection = false;
Notify(NULL);
}
void
ShowImageView::Rotate(int degree)
{
if (degree == 90) {
DoImageOperation(kRotateClockwise);
} else if (degree == 270) {
DoImageOperation(kRotateAntiClockwise);
}
}
void
ShowImageView::Mirror(bool vertical)
{
if (vertical) {
DoImageOperation(kMirrorVertical);
} else {
DoImageOperation(kMirrorHorizontal);
}
}
void
ShowImageView::Invert()
{
DoImageOperation(kInvert);
}
+30 -4
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageView
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageView.h
//
@@ -63,12 +63,32 @@ public:
void LastPage();
void NextPage();
void PrevPage();
void NextFile();
void PrevFile();
bool NextFile();
bool PrevFile();
void SetDiaShowDelay(float seconds);
void StartDiaShow();
void StopDiaShow();
// Image manipulation
void Rotate(int degree); // 90 and 270 only
void Mirror(bool vertical);
void Invert();
private:
enum image_operation {
kRotateClockwise,
kRotateAntiClockwise,
kMirrorVertical,
kMirrorHorizontal,
kInvert
};
void InitPatterns();
void RotatePatterns();
void Notify(const char* status);
int32 BytesPerPixel(color_space cs) const;
inline void CopyPixel(uchar* dest, int32 destX, int32 destY, int32 destBPR, uchar* src, int32 x, int32 y, int32 bpr, int32 bpp);
inline void InvertPixel(int32 x, int32 y, uchar* dest, int32 destBPR, uchar* src, int32 bpr, int32 bpp);
void DoImageOperation(image_operation op);
BRect AlignBitmap() const;
void Setup(BRect r);
BPoint ImageToView(BPoint p) const;
@@ -76,7 +96,9 @@ private:
BRect ImageToView(BRect r) const;
bool IsImage(const entry_ref* pref);
void FreeEntries(BList* entries);
bool FindNextImage(BEntry* entry, bool next);
bool FindNextImage(BEntry* entry, bool next, bool rewind);
bool ShowNextImage(bool next, bool rewind);
bool FirstFile();
void ConstrainToImage(BPoint &point);
void UpdateSelectionRect(BPoint point, bool final);
void DrawBorder(BRect border);
@@ -96,6 +118,10 @@ private:
bool fbHasSelection; // is fSelectionRect valid
BRect fSelectionRect; // the selection in image space
pattern fPatternUp, fPatternDown, fPatternLeft, fPatternRight;
bool fDiaShow;
int fDiaShowDelay;
int fDiaShowCountDown;
};
#endif /* _ShowImageView_h */
+113 -6
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageWindow.cpp
//
@@ -42,6 +42,7 @@
#include <TranslatorRoster.h>
#include <Alert.h>
#include <SupportDefs.h>
#include <Screen.h>
#include "ShowImageConstants.h"
#include "ShowImageWindow.h"
@@ -53,11 +54,8 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref)
{
fpSavePanel = NULL;
fpRef = NULL;
// add shortcuts
AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(MSG_FILE_PREV));
AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(MSG_FILE_NEXT));
fFullScreen = false;
// create menu bar
fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar");
LoadMenus(fpBar);
@@ -156,6 +154,29 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
BMenu *pmenu = new BMenu("File");
AddItemMenu(pmenu, "Open", MSG_FILE_OPEN, 'O', 0, 'A', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Dia Show", MSG_DIA_SHOW, 0, 0, 'W', true);
BMenu* pDelay = new BMenu("Delay");
pDelay->SetRadioMode(true);
// Note: ShowImage loades images in window thread so it becomes unresponsive if
// dia show delay is too short! (Especially if loading the image takes as long as
// or longer than the dia show delay). Should load in background thread!
// AddDelayItem(pDelay, "Half a Second", 0.5, false);
// AddDelayItem(pDelay, "One Second", 1, false);
// AddDelayItem(pDelay, "Two Second", 2, false);
AddDelayItem(pDelay, "Three Seconds", 3, true);
AddDelayItem(pDelay, "Four Second", 4, false);
AddDelayItem(pDelay, "Five Seconds", 5, false);
AddDelayItem(pDelay, "Six Seconds", 6, false);
AddDelayItem(pDelay, "Seven Seconds", 7, false);
AddDelayItem(pDelay, "Eight Seconds", 8, false);
AddDelayItem(pDelay, "Nine Seconds", 9, false);
AddDelayItem(pDelay, "Ten Seconds", 10, false);
AddDelayItem(pDelay, "Tweenty Seconds", 20, false);
pmenu->AddItem(pDelay);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Next", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Previous", MSG_FILE_PREV, B_UP_ARROW, 0, 'W', true);
pmenu->AddSeparatorItem();
BMenu *pmenuSaveAs = new BMenu("Save As...", B_ITEMS_IN_COLUMN);
BTranslationUtils::AddTranslationItems(pmenuSaveAs, B_TRANSLATOR_BITMAP);
// Fill Save As submenu with all types that can be converted
@@ -188,7 +209,19 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
pmenu = new BMenu("Image");
AddItemMenu(pmenu, "Dither Image", MSG_DITHER_IMAGE, 0, 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Rotate Clockwise", MSG_ROTATE_CLOCKWISE, B_RIGHT_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Rotate Anticlockwise", MSG_ROTATE_ACLKWISE, B_LEFT_ARROW, 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Mirror Vertical", MSG_MIRROR_VERTICAL, 0, 0, 'W', true);
AddItemMenu(pmenu, "Mirror Horizontal", MSG_MIRROR_HORIZONTAL, 0, 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Invert", MSG_INVERT, 0, 0, 'W', true);
pbar->AddItem(pmenu);
pmenu = new BMenu("View");
AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true);
AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true);
pbar->AddItem(pmenu);
}
@@ -208,6 +241,22 @@ ShowImageWindow::AddItemMenu(BMenu *pmenu, char *caption, long unsigned int msg,
return pitem;
}
BMenuItem*
ShowImageWindow::AddDelayItem(BMenu *pmenu, char *caption, float value, bool marked)
{
BMenuItem* pitem;
BMessage* pmsg;
pmsg = new BMessage(MSG_DIA_SHOW_DELAY);
pmsg->AddFloat("value", value);
pitem = new BMenuItem(caption, pmsg, 0);
if (marked) pitem->SetMarked(true);
pmenu->AddItem(pitem);
return pitem;
}
void
ShowImageWindow::WindowRedimension(BBitmap *pbitmap)
{
@@ -351,6 +400,40 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
case MSG_FILE_NEXT:
fpImageView->NextFile();
break;
case MSG_ROTATE_CLOCKWISE:
fpImageView->Rotate(90);
break;
case MSG_ROTATE_ACLKWISE:
fpImageView->Rotate(270);
break;
case MSG_MIRROR_VERTICAL:
fpImageView->Mirror(true);
break;
case MSG_MIRROR_HORIZONTAL:
fpImageView->Mirror(false);
break;
case MSG_INVERT:
fpImageView->Invert();
break;
case MSG_DIA_SHOW:
if (ToggleMenuItem(pmsg->what)) {
fpImageView->StartDiaShow();
} else {
fpImageView->StopDiaShow();
}
case MSG_DIA_SHOW_DELAY:
{
float value;
if (pmsg->FindFloat("value", &value) == B_OK) {
fpImageView->SetDiaShowDelay(value);
}
}
break;
case MSG_FULL_SCREEN:
ToggleFullScreen();
break;
default:
BWindow::MessageReceived(pmsg);
@@ -439,6 +522,30 @@ ShowImageWindow::CanQuit()
return true;
}
void
ShowImageWindow::ToggleFullScreen()
{
BRect frame;
fFullScreen = !fFullScreen;
if (fFullScreen) {
BScreen screen;
fWindowFrame = Frame();
frame = screen.Frame();
frame.top -= fpBar->Bounds().Height()+1;
frame.right += B_V_SCROLL_BAR_WIDTH;
frame.bottom += B_H_SCROLL_BAR_HEIGHT;
frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView
SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
} else {
frame = fWindowFrame;
SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
}
MoveTo(frame.left, frame.top);
ResizeTo(frame.Width(), frame.Height());
}
bool
ShowImageWindow::QuitRequested()
{
+6 -1
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// ShowImageWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// ShowImageWindow.h
//
@@ -64,6 +64,8 @@ private:
long unsigned int msg, char shortcut, uint32 modifier,
char target, bool enabled);
BMenuItem* AddDelayItem(BMenu *pmenu, char *caption, float value, bool marked);
bool ToggleMenuItem(uint32 what);
void SaveAs(BMessage *pmsg);
@@ -72,6 +74,7 @@ private:
// Handle save file panel message
bool CanQuit();
// returns true if the window can be closed safely, false if not
void ToggleFullScreen();
BFilePanel *fpSavePanel;
BMenuBar *fpBar;
@@ -79,6 +82,8 @@ private:
entry_ref *fpRef;
ShowImageView *fpImageView;
ShowImageStatusView *fpStatusView;
bool fFullScreen;
BRect fWindowFrame;
};
#endif /* _ShowImageWindow_h */