- added printing support

- added zoom in and out
- next/previous file sorts directory entries by itself; does not rely on file system
- added shortcuts to the first 10 menu items of Go To sub menu


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5299 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2003-11-10 17:38:35 +00:00
parent 257e63ba7f
commit 780d8a62d7
8 changed files with 674 additions and 76 deletions

View File

@ -0,0 +1,265 @@
/*****************************************************************************/
// PrintOptionsWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// PrintOptionsWindow.cpp
//
//
// Copyright (c) 2003 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/
#include <Box.h>
#include <Button.h>
#include <String.h>
#include <stdio.h> // for sprintf
#include <stdlib.h> // for atof
#include "PrintOptionsWindow.h"
#include "ShowImageConstants.h"
PrintOptions::PrintOptions()
: fOption(kFitToPage)
, fZoomFactor(1.0)
, fDPI(72.0)
, fWidth(1024 / 72.0)
, fHeight(768 / 72.0)
{
}
void
PrintOptions::SetBounds(BRect rect)
{
fBounds = rect;
}
void
PrintOptions::SetZoomFactor(float f)
{
fZoomFactor = f;
fDPI = 72.0 / fZoomFactor;
}
void
PrintOptions::SetDPI(float dpi)
{
fDPI = dpi;
fZoomFactor = 72.0 / dpi;
}
void
PrintOptions::SetWidth(float w)
{
fWidth = w;
fHeight = (fBounds.Height()+1) * w / (fBounds.Width()+1);
}
void
PrintOptions::SetHeight(float h)
{
fWidth = (fBounds.Width()+1) * h / (fBounds.Height()+1);
fHeight = h;
}
PrintOptionsWindow::PrintOptionsWindow(BPoint at, PrintOptions *options, BWindow* listener)
: BWindow(BRect(at.x, at.y, at.x+300, at.y+200), "Print Options",
B_TITLED_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
, fPrintOptions(options)
, fCurrentOptions(*options)
, fListener(listener)
, fStatus(B_ERROR)
{
AddToSubset(listener);
Setup();
Show();
}
PrintOptionsWindow::~PrintOptionsWindow()
{
BMessage msg(MSG_PRINT);
msg.AddInt32("status", fStatus);
fListener.SendMessage(&msg);
}
BRadioButton*
PrintOptionsWindow::AddRadioButton(BView* view, BPoint& at, const char* name, const char* label, uint32 what, bool selected)
{
BRect rect(0, 0, 100, 20);
BRadioButton* button;
rect.OffsetBy(at);
button = new BRadioButton(rect, name, label, new BMessage(what));
view->AddChild(button);
button->ResizeToPreferred();
at.y += button->Bounds().Height() + kLineSkip;
button->SetValue(selected ? B_CONTROL_ON : B_CONTROL_OFF);
return button;
}
BTextControl*
PrintOptionsWindow::AddTextControl(BView* view, BPoint& at, const char* name, const char* label, float value, float divider, uint32 what)
{
BRect rect(0, 0, divider + 45, 20);
BTextControl* text;
rect.OffsetBy(at);
text = new BTextControl(rect, name, label, "", new BMessage(what));
view->AddChild(text);
text->SetModificationMessage(new BMessage(what));
text->SetDivider(divider);
text->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT);
SetValue(text, value);
at.y += text->Bounds().Height() + kLineSkip;
return text;
}
void
PrintOptionsWindow::Setup()
{
BRect rect(Bounds());
BPoint at(kIndent, kIndent), textAt;
BString value;
enum PrintOptions::Option op = fCurrentOptions.Option();
BRadioButton* rb;
BBox* line;
BButton* button;
BBox *panel = new BBox(rect, "top_panel", B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
B_PLAIN_BORDER);
AddChild(panel);
AddRadioButton(panel, at, "fit_to_page", "Fit Image to Page", kMsgFitToPageSelected, op == PrintOptions::kFitToPage);
textAt = at;
rb = AddRadioButton(panel, at, "zoom_factor", "Zoom Factor in %: ", kMsgZoomFactorSelected, op == PrintOptions::kZoomFactor);
textAt.x = rb->Bounds().right + 5;
fZoomFactor = AddTextControl(panel, textAt, "zoom_factor_text", "", fCurrentOptions.ZoomFactor()*100, 0, kMsgZoomFactorChanged);
textAt = at;
rb = AddRadioButton(panel, at, "dpi", "DPI: ", kMsgDPISelected, op == PrintOptions::kDPI);
textAt.x = rb->Bounds().right + 5;
fDPI = AddTextControl(panel, textAt, "dpi_text", "", fCurrentOptions.DPI(), 0, kMsgDPIChanged);
rb = AddRadioButton(panel, at, "width_and_height", "Resize To (in 1/72 Inches):", kMsgWidthAndHeightSelected, op == PrintOptions::kWidth || op == PrintOptions::kHeight);
at.x += 15;
textAt = at;
fWidth = AddTextControl(panel, textAt, "width", "Width: ", fCurrentOptions.Width(), 40, kMsgWidthChanged);
textAt = at;
textAt.x += fWidth->Bounds().Width() + 5;
fHeight = AddTextControl(panel, textAt, "height", "Height: ", fCurrentOptions.Height(), 40, kMsgHeightChanged);
at.x = 0;
at.y = textAt.y;
line = new BBox(BRect(rect.left+3, at.y, rect.right-3, at.y + 1), NULL,
B_FOLLOW_LEFT | B_FOLLOW_TOP);
panel->AddChild(line);
at.y += 10;
rect.OffsetBy(at);
button = new BButton(rect, "job setup", "Job Setup", new BMessage(kMsgJobSetup));
panel->AddChild(button);
button->ResizeToPreferred();
SetDefaultButton(button);
// resize window
ResizeTo(fHeight->Frame().right + kIndent, button->Frame().bottom + kIndent);
// center button
button->MoveTo((Bounds().Width()-button->Bounds().Width())/2, button->Frame().top);
}
enum PrintOptions::Option
PrintOptionsWindow::MsgToOption(uint32 what) {
switch (what) {
case kMsgFitToPageSelected: return PrintOptions::kFitToPage;
case kMsgZoomFactorSelected: return PrintOptions::kZoomFactor;
case kMsgDPISelected: return PrintOptions::kDPI;
case kMsgWidthAndHeightSelected: return PrintOptions::kWidth;
}
return PrintOptions::kFitToPage;
}
bool
PrintOptionsWindow::GetValue(BTextControl* text, float* value)
{
*value = atof(text->Text());
return true;
}
void
PrintOptionsWindow::SetValue(BTextControl* text, float value)
{
BMessage* msg;
char s[80];
sprintf(s, "%0.0f", value);
// prevent sending a notification when text is set
msg = new BMessage(*text->ModificationMessage());
text->SetModificationMessage(NULL);
text->SetText(s);
text->SetModificationMessage(msg);
}
void
PrintOptionsWindow::MessageReceived(BMessage* msg)
{
float value;
switch (msg->what) {
case kMsgFitToPageSelected:
case kMsgZoomFactorSelected:
case kMsgDPISelected:
case kMsgWidthAndHeightSelected:
fCurrentOptions.SetOption(MsgToOption(msg->what));
break;
case kMsgZoomFactorChanged:
if (GetValue(fZoomFactor, &value) && fCurrentOptions.ZoomFactor() != value) {
fCurrentOptions.SetZoomFactor(value/100);
SetValue(fDPI, fCurrentOptions.DPI());
}
break;
case kMsgDPIChanged:
if (GetValue(fDPI, &value) && fCurrentOptions.DPI() != value) {
fCurrentOptions.SetDPI(value);
SetValue(fZoomFactor, 100*fCurrentOptions.ZoomFactor());
}
break;
case kMsgWidthChanged:
if (GetValue(fWidth, &value) && fCurrentOptions.Width() != value) {
fCurrentOptions.SetWidth(value);
SetValue(fHeight, fCurrentOptions.Height());
}
break;
case kMsgHeightChanged:
if (GetValue(fHeight, &value) && fCurrentOptions.Height() != value) {
fCurrentOptions.SetHeight(value);
SetValue(fWidth, fCurrentOptions.Width());
}
break;
case kMsgJobSetup:
*fPrintOptions = fCurrentOptions;
fStatus = B_OK;
PostMessage(B_QUIT_REQUESTED);
break;
default:
BWindow::MessageReceived(msg);
}
}

View File

@ -0,0 +1,119 @@
/*****************************************************************************/
// PrintOptionsWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
//
// PrintOptionsWindow.h
//
//
// Copyright (c) 2003 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/
#ifndef _PrintOptionsWindow_h
#define _PrintOptionsWindow_h
#include <Window.h>
#include <RadioButton.h>
#include <TextControl.h>
#include <Messenger.h>
#include <Rect.h>
class PrintOptions {
public:
enum Option {
kFitToPage,
kZoomFactor,
kDPI,
kWidth,
kHeight
};
PrintOptions();
// bounds of the image
BRect Bounds() const { return fBounds; }
void SetBounds(BRect bounds);
Option Option() const { return fOption; }
void SetOption(Option op) { fOption = op; }
// zoomFactor = 72.0 / dpi
float ZoomFactor() const { return fZoomFactor; }
void SetZoomFactor(float z);
float DPI() const { return fDPI; }
void SetDPI(float dpi);
// setting width/height updates height/width to keep aspect ratio
float Width() const { return fWidth; }
float Height() const { return fHeight; }
void SetWidth(float width);
void SetHeight(float height);
private:
BRect fBounds;
Option fOption;
float fZoomFactor;
float fDPI;
float fWidth, fHeight; // 1/72 Inches
};
class PrintOptionsWindow : public BWindow
{
public:
PrintOptionsWindow(BPoint at, PrintOptions* options, BWindow* listener);
~PrintOptionsWindow();
void MessageReceived(BMessage* msg);
private:
BRadioButton* AddRadioButton(BView* view, BPoint& at, const char* name, const char* label, uint32 what, bool selected);
BTextControl* AddTextControl(BView* view, BPoint& at, const char* name, const char* label, float value, float divider, uint32 what);
void Setup();
enum PrintOptions::Option MsgToOption(uint32 what);
bool GetValue(BTextControl* text, float* value);
void SetValue(BTextControl* text, float value);
enum {
kMsgOK = 'mPOW',
kMsgFitToPageSelected,
kMsgZoomFactorSelected,
kMsgDPISelected,
kMsgWidthAndHeightSelected,
kMsgZoomFactorChanged,
kMsgDPIChanged,
kMsgWidthChanged,
kMsgHeightChanged,
kMsgJobSetup,
kIndent = 5,
kLineSkip = 5,
};
PrintOptions* fPrintOptions;
PrintOptions fCurrentOptions;
BMessenger fListener;
status_t fStatus;
BTextControl* fZoomFactor;
BTextControl* fDPI;
BTextControl* fWidth;
BTextControl* fHeight;
};
#endif

View File

@ -60,6 +60,12 @@ const uint32 MSG_SLIDE_SHOW_DELAY = 'mSSD';
const uint32 MSG_FULL_SCREEN = 'mFSC'; const uint32 MSG_FULL_SCREEN = 'mFSC';
const uint32 MSG_UPDATE_RECENT_DOCUMENTS = 'mURD'; const uint32 MSG_UPDATE_RECENT_DOCUMENTS = 'mURD';
const uint32 MSG_SHOW_CAPTION = 'mSCP'; const uint32 MSG_SHOW_CAPTION = 'mSCP';
const uint32 MSG_PAGE_SETUP = 'mPSU';
const uint32 MSG_PREPARE_PRINT = 'mPPT';
const uint32 MSG_PRINT = 'mPRT';
const uint32 MSG_ZOOM_IN = 'mZIN';
const uint32 MSG_ZOOM_OUT = 'mZOU';
const uint32 MSG_ORIGINAL_SIZE = 'mOSZ';
extern const char *APP_SIG; extern const char *APP_SIG;

View File

@ -160,6 +160,7 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
SetSlideShowDelay(3); // 3 seconds SetSlideShowDelay(3); // 3 seconds
fBeginDrag = false; fBeginDrag = false;
fShowCaption = false; fShowCaption = false;
fZoom = 1.0;
SetViewColor(B_TRANSPARENT_COLOR); SetViewColor(B_TRANSPARENT_COLOR);
SetHighColor(kborderColor); SetHighColor(kborderColor);
@ -300,6 +301,19 @@ ShowImageView::GetBitmap()
return fpBitmap; return fpBitmap;
} }
void
ShowImageView::GetName(BString *name)
{
*name = "";
BEntry entry(&fCurrentRef);
if (entry.InitCheck() == B_OK) {
char n[B_FILE_NAME_LENGTH];
if (entry.GetName(n) == B_OK) {
name->SetTo(n);
}
}
}
void void
ShowImageView::GetPath(BString *name) ShowImageView::GetPath(BString *name)
{ {
@ -353,6 +367,7 @@ ShowImageView::AlignBitmap() const
} }
} }
} else { } else {
rect.right *= fZoom; rect.bottom *= fZoom;
rect.OffsetBy(BORDER_WIDTH, BORDER_WIDTH); rect.OffsetBy(BORDER_WIDTH, BORDER_WIDTH);
} }
rect.OffsetBy(PEN_SIZE, PEN_SIZE); rect.OffsetBy(PEN_SIZE, PEN_SIZE);
@ -421,7 +436,7 @@ ShowImageView::DrawCaption()
width = font.StringWidth(fCaption.String())+1; // 1 for text shadow width = font.StringWidth(fCaption.String())+1; // 1 for text shadow
font.GetHeight(&fontHeight); font.GetHeight(&fontHeight);
height = fontHeight.ascent + fontHeight.descent; height = fontHeight.ascent + fontHeight.descent;
// center text vertically // center text horizontally
pos.x = (bounds.left + bounds.right - width)/2; pos.x = (bounds.left + bounds.right - width)/2;
// flush bottom // flush bottom
pos.y = bounds.bottom - fontHeight.descent - 5; pos.y = bounds.bottom - fontHeight.descent - 5;
@ -456,26 +471,30 @@ void
ShowImageView::Draw(BRect updateRect) ShowImageView::Draw(BRect updateRect)
{ {
if (fpBitmap) { if (fpBitmap) {
BRect rect = AlignBitmap(); if (!IsPrinting()) {
Setup(rect); BRect rect = AlignBitmap();
Setup(rect);
BRect border(rect);
border.InsetBy(-PEN_SIZE, -PEN_SIZE); BRect border(rect);
border.InsetBy(-PEN_SIZE, -PEN_SIZE);
DrawBorder(border);
DrawBorder(border);
// Draw black rectangle around image
StrokeRect(border); // Draw black rectangle around image
StrokeRect(border);
// Draw image
DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect); // Draw image
DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect);
if (fShowCaption) {
DrawCaption(); if (fShowCaption) {
} DrawCaption();
}
if (fbHasSelection) {
DrawSelectionBox(fSelectionRect); if (fbHasSelection) {
DrawSelectionBox(fSelectionRect);
}
} else {
DrawBitmap(fpBitmap);
} }
} }
} }
@ -783,6 +802,7 @@ void
ShowImageView::FixupScrollBars() ShowImageView::FixupScrollBars()
{ {
BScrollBar *psb; BScrollBar *psb;
if (fResizeToViewBounds) { if (fResizeToViewBounds) {
psb = ScrollBar(B_HORIZONTAL); psb = ScrollBar(B_HORIZONTAL);
if (psb) psb->SetRange(0, 0); if (psb) psb->SetRange(0, 0);
@ -792,8 +812,10 @@ ShowImageView::FixupScrollBars()
} }
BRect rctview = Bounds(), rctbitmap(0, 0, 0, 0); BRect rctview = Bounds(), rctbitmap(0, 0, 0, 0);
if (fpBitmap) if (fpBitmap) {
rctbitmap = fpBitmap->Bounds(); BRect rect(AlignBitmap());
rctbitmap.Set(0, 0, rect.Width(), rect.Height());
}
float prop, range; float prop, range;
psb = ScrollBar(B_HORIZONTAL); psb = ScrollBar(B_HORIZONTAL);
@ -914,6 +936,15 @@ ShowImageView::PrevPage()
} }
} }
int
ShowImageView::CompareEntries(const void* a, const void* b)
{
entry_ref *r1, *r2;
r1 = *(entry_ref**)a;
r2 = *(entry_ref**)b;
return strcasecmp(r1->name, r2->name);
}
void void
ShowImageView::GoToPage(int32 page) ShowImageView::GoToPage(int32 page)
{ {
@ -928,73 +959,77 @@ ShowImageView::FreeEntries(BList* entries)
{ {
const int32 n = entries->CountItems(); const int32 n = entries->CountItems();
for (int32 i = 0; i < n; i ++) { for (int32 i = 0; i < n; i ++) {
BEntry* entry = (BEntry*)entries->ItemAt(i); entry_ref* ref = (entry_ref*)entries->ItemAt(i);
delete entry; delete ref;
} }
entries->MakeEmpty(); entries->MakeEmpty();
} }
// Notes: BDirectory::GetNextEntry() must not necessary
// return entries sorted by name, thou BFS does.
bool bool
ShowImageView::FindNextImage(BEntry* image, bool next, bool rewind) ShowImageView::FindNextImage(entry_ref* image, bool next, bool rewind)
{ {
ASSERT(next || !rewind); ASSERT(next || !rewind);
BEntry curImage(&fCurrentRef); BEntry curImage(&fCurrentRef);
BEntry entry; entry_ref entry, *ref;
BDirectory parent; BDirectory parent;
BList entries; BList entries;
bool found = false;
int32 cur;
if (curImage.GetParent(&parent) != B_OK) if (curImage.GetParent(&parent) != B_OK)
return false; return false;
while (parent.GetNextEntry(&entry) == B_OK) { while (parent.GetNextRef(&entry) == B_OK) {
if (rewind || entry == curImage) { if (entry != fCurrentRef) {
// start with first entry or found current image entries.AddItem(new entry_ref(entry));
if (next) { } else {
// start with next entry // insert current ref, so we can find it easily after sorting
if (!rewind && parent.GetNextEntry(&entry) != B_OK) { entries.AddItem(&fCurrentRef);
break;
}
// find next image in directory
do {
entry_ref ref;
if (entry.GetRef(&ref) == B_OK && IsImage(&ref)) {
*image = entry;
return true;
}
} while (parent.GetNextEntry(&entry) == B_OK);
} else {
// find previous image in directory
for (int32 i = entries.CountItems() - 1; i >= 0; i --) {
BEntry* entry = (BEntry*)entries.ItemAt(i);
entry_ref ref;
if (entry->GetRef(&ref) == B_OK && IsImage(&ref)) {
*image = *entry;
FreeEntries(&entries);
return true;
}
}
}
break;
}
if (!next) {
// record entries if we search for previous file
entries.AddItem(new BEntry(entry));
} }
} }
entries.SortItems(CompareEntries);
cur = entries.IndexOf(&fCurrentRef);
ASSERT(cur >= 0);
// remove it so FreeEntries() does not delete it
entries.RemoveItem(&fCurrentRef);
if (next) {
// find the next image in the list
if (rewind) cur = 0; // start with first
for (; (ref = (entry_ref*)entries.ItemAt(cur)) != NULL; cur ++) {
if (IsImage(ref)) {
found = true;
*image = (const entry_ref)*ref;
break;
}
}
} else {
// find the previous image in the list
cur --;
for (; cur >= 0; cur --) {
ref = (entry_ref*)entries.ItemAt(cur);
if (IsImage(ref)) {
found = true;
*image = (const entry_ref)*ref;
break;
}
}
}
FreeEntries(&entries); FreeEntries(&entries);
return false; return found;
} }
bool bool
ShowImageView::ShowNextImage(bool next, bool rewind) ShowImageView::ShowNextImage(bool next, bool rewind)
{ {
BEntry image;
entry_ref ref; entry_ref ref;
if (FindNextImage(&image, next, rewind) && image.GetRef(&ref) == B_OK) { if (FindNextImage(&ref, next, rewind)) {
SetImage(&ref); SetImage(&ref);
return true; return true;
} }
return false; return false;
@ -1018,6 +1053,28 @@ ShowImageView::FirstFile()
return ShowNextImage(true, true); return ShowNextImage(true, true);
} }
void
ShowImageView::SetZoom(float zoom)
{
fZoom = zoom;
FixupScrollBars();
Invalidate();
}
void
ShowImageView::ZoomIn()
{
SetZoom(fZoom + 0.25);
}
void
ShowImageView::ZoomOut()
{
if (fZoom > 0.25) {
SetZoom(fZoom - 0.25);
}
}
void void
ShowImageView::SetSlideShowDelay(float seconds) ShowImageView::SetSlideShowDelay(float seconds)
{ {

View File

@ -47,6 +47,7 @@ public:
void SetShowCaption(bool show); void SetShowCaption(bool show);
void ResizeToViewBounds(bool resize); void ResizeToViewBounds(bool resize);
BBitmap *GetBitmap(); BBitmap *GetBitmap();
void GetName(BString *name);
void GetPath(BString *name); void GetPath(BString *name);
void FlushToLeftTop(); void FlushToLeftTop();
@ -78,6 +79,9 @@ public:
void SetSlideShowDelay(float seconds); void SetSlideShowDelay(float seconds);
void StartSlideShow(); void StartSlideShow();
void StopSlideShow(); void StopSlideShow();
void SetZoom(float zoom);
void ZoomIn();
void ZoomOut();
// Image manipulation // Image manipulation
void Rotate(int degree); // 90 and 270 only void Rotate(int degree); // 90 and 270 only
@ -107,8 +111,9 @@ private:
BPoint ViewToImage(BPoint p) const; BPoint ViewToImage(BPoint p) const;
BRect ImageToView(BRect r) const; BRect ImageToView(BRect r) const;
bool IsImage(const entry_ref* pref); bool IsImage(const entry_ref* pref);
static int CompareEntries(const void* a, const void* b);
void FreeEntries(BList* entries); void FreeEntries(BList* entries);
bool FindNextImage(BEntry* entry, bool next, bool rewind); bool FindNextImage(entry_ref* ref, bool next, bool rewind);
bool ShowNextImage(bool next, bool rewind); bool ShowNextImage(bool next, bool rewind);
bool FirstFile(); bool FirstFile();
void ConstrainToImage(BPoint &point); void ConstrainToImage(BPoint &point);
@ -128,6 +133,7 @@ private:
int32 fDocumentIndex; int32 fDocumentIndex;
int32 fDocumentCount; int32 fDocumentCount;
BBitmap *fpBitmap; BBitmap *fpBitmap;
float fZoom;
bool fResizeToViewBounds; bool fResizeToViewBounds;
float fLeft; // the origin of the image in the view float fLeft; // the origin of the image in the view
float fTop; float fTop;

View File

@ -44,6 +44,7 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#include <Screen.h> #include <Screen.h>
#include <Roster.h> #include <Roster.h>
#include <PrintJob.h>
#include "ShowImageConstants.h" #include "ShowImageConstants.h"
#include "ShowImageWindow.h" #include "ShowImageWindow.h"
@ -56,6 +57,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref)
fpSavePanel = NULL; fpSavePanel = NULL;
fFullScreen = false; fFullScreen = false;
fShowCaption = true; // XXX what is best for default? fShowCaption = true; // XXX what is best for default?
fPrintSettings = NULL;
// create menu bar // create menu bar
fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar"); fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar");
@ -104,13 +106,13 @@ ShowImageWindow::ShowImageWindow(const entry_ref *pref)
SetSizeLimits(250, 100000, 100, 100000); SetSizeLimits(250, 100000, 100, 100000);
// finish creating window // finish creating window
UpdateTitle();
fpImageView->SetImage(pref); fpImageView->SetImage(pref);
SetPulseRate(100000); // every 1/10 second; ShowImageView needs it for marching ants
if (InitCheck() == B_OK) { if (InitCheck() == B_OK) {
UpdateTitle();
SetPulseRate(100000); // every 1/10 second; ShowImageView needs it for marching ants
fpImageView->FlushToLeftTop(); fpImageView->FlushToLeftTop();
WindowRedimension(fpImageView->GetBitmap()); WindowRedimension(fpImageView->GetBitmap());
Show(); Show();
@ -182,14 +184,17 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
fpOpenMenu->Superitem()->SetTarget(be_app); fpOpenMenu->Superitem()->SetTarget(be_app);
fpOpenMenu->Superitem()->SetShortcut('O', 0); fpOpenMenu->Superitem()->SetShortcut('O', 0);
pmenu->AddSeparatorItem(); pmenu->AddSeparatorItem();
BMenu *pmenuSaveAs = new BMenu("Save As...", B_ITEMS_IN_COLUMN); BMenu *pmenuSaveAs = new BMenu("Save As" B_UTF8_ELLIPSIS, B_ITEMS_IN_COLUMN);
BTranslationUtils::AddTranslationItems(pmenuSaveAs, B_TRANSLATOR_BITMAP); BTranslationUtils::AddTranslationItems(pmenuSaveAs, B_TRANSLATOR_BITMAP);
// Fill Save As submenu with all types that can be converted // Fill Save As submenu with all types that can be converted
// to from the Be bitmap image format // to from the Be bitmap image format
pmenu->AddItem(pmenuSaveAs); pmenu->AddItem(pmenuSaveAs);
AddItemMenu(pmenu, "Close", MSG_CLOSE, 'W', 0, 'W', true); AddItemMenu(pmenu, "Close", MSG_CLOSE, 'W', 0, 'W', true);
pmenu->AddSeparatorItem(); pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "About ShowImage...", B_ABOUT_REQUESTED, 0, 0, 'A', true); AddItemMenu(pmenu, "Page Setup" B_UTF8_ELLIPSIS, MSG_PAGE_SETUP, 0, 0, 'W', true);
AddItemMenu(pmenu, "Print" B_UTF8_ELLIPSIS, MSG_PREPARE_PRINT, 0, 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "About ShowImage" B_UTF8_ELLIPSIS, B_ABOUT_REQUESTED, 0, 0, 'A', true);
pmenu->AddSeparatorItem(); pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Quit", B_QUIT_REQUESTED, 'Q', 0, 'A', true); AddItemMenu(pmenu, "Quit", B_QUIT_REQUESTED, 'Q', 0, 'A', true);
pbar->AddItem(pmenu); pbar->AddItem(pmenu);
@ -250,6 +255,10 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
AddDelayItem(pDelay, "Twenty Seconds", 20, false); AddDelayItem(pDelay, "Twenty Seconds", 20, false);
pmenu->AddItem(pDelay); pmenu->AddItem(pDelay);
pmenu->AddSeparatorItem(); pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Original Size", MSG_ORIGINAL_SIZE, 0, 0, 'W', true);
AddItemMenu(pmenu, "Zoom In", MSG_ZOOM_IN, '+', 0, 'W', true);
AddItemMenu(pmenu, "Zoom Out", MSG_ZOOM_OUT, '-', 0, 'W', true);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true); 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); AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true);
AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true); AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true);
@ -406,15 +415,21 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
// Remove all page numbers // Remove all page numbers
delete fpGoToPageMenu->RemoveItem(0L); delete fpGoToPageMenu->RemoveItem(0L);
for (int32 i = 1; i > 0 && i <= pages; i++) { for (int32 i = 1; i <= pages; i++) {
// Fill Go To page submenu with an entry for each page // Fill Go To page submenu with an entry for each page
BMessage *pgomsg; BMessage *pgomsg;
char shortcut = 0;
pgomsg = new BMessage(MSG_GOTO_PAGE); pgomsg = new BMessage(MSG_GOTO_PAGE);
pgomsg->AddInt32("page", i); pgomsg->AddInt32("page", i);
BString strCaption; BString strCaption;
strCaption << i; strCaption << i;
BMenuItem *pitem; BMenuItem *pitem;
pitem = new BMenuItem(strCaption.String(), pgomsg, 0); if (i < 10) {
shortcut = '0' + i;
} else if (i == 10) {
shortcut = '0';
}
pitem = new BMenuItem(strCaption.String(), pgomsg, shortcut);
if (curPage == i) if (curPage == i)
pitem->SetMarked(true); pitem->SetMarked(true);
fpGoToPageMenu->AddItem(pitem); fpGoToPageMenu->AddItem(pitem);
@ -503,6 +518,9 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
bool resize; bool resize;
resize = ToggleMenuItem(pmsg->what); resize = ToggleMenuItem(pmsg->what);
fpImageView->ResizeToViewBounds(resize); fpImageView->ResizeToViewBounds(resize);
EnableMenuItem(MSG_ORIGINAL_SIZE, !resize);
EnableMenuItem(MSG_ZOOM_IN, !resize);
EnableMenuItem(MSG_ZOOM_OUT, !resize);
} }
break; break;
@ -557,6 +575,26 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
case MSG_UPDATE_RECENT_DOCUMENTS: case MSG_UPDATE_RECENT_DOCUMENTS:
UpdateRecentDocumentsMenu(); UpdateRecentDocumentsMenu();
break; break;
case MSG_PAGE_SETUP:
PageSetup();
break;
case MSG_PREPARE_PRINT:
PrepareForPrint();
break;
case MSG_PRINT:
Print(pmsg);
break;
case MSG_ZOOM_IN:
fpImageView->ZoomIn();
break;
case MSG_ZOOM_OUT:
fpImageView->ZoomOut();
break;
case MSG_ORIGINAL_SIZE:
fpImageView->SetZoom(1.0);
break;
default: default:
BWindow::MessageReceived(pmsg); BWindow::MessageReceived(pmsg);
@ -670,6 +708,106 @@ ShowImageWindow::ToggleFullScreen()
ResizeTo(frame.Width(), frame.Height()); ResizeTo(frame.Width(), frame.Height());
} }
bool
ShowImageWindow::PageSetup()
{
status_t st;
BString name;
fpImageView->GetName(&name);
BPrintJob printJob(name.String());
if (fPrintSettings != NULL) {
printJob.SetSettings(new BMessage(*fPrintSettings));
}
st = printJob.ConfigPage();
if (st == B_OK) {
delete fPrintSettings;
fPrintSettings = printJob.Settings();
}
return st == B_OK;
}
void
ShowImageWindow::PrepareForPrint()
{
if (fPrintSettings == NULL && !PageSetup()) {
return;
}
fPrintOptions.SetBounds(fpImageView->GetBitmap()->Bounds());
fPrintOptions.SetWidth(fpImageView->GetBitmap()->Bounds().Width()+1);
new PrintOptionsWindow(BPoint(Frame().left+30, Frame().top+50), &fPrintOptions, this);
}
void
ShowImageWindow::Print(BMessage *msg)
{
status_t st;
if (msg->FindInt32("status", &st) != B_OK || st != B_OK) {
return;
}
BString name;
fPrintOptions.SetBounds(fpImageView->GetBitmap()->Bounds());
fpImageView->GetName(&name);
BPrintJob printJob(name.String());
printJob.SetSettings(new BMessage(*fPrintSettings));
if (printJob.ConfigJob() == B_OK) {
int32 firstPage;
int32 lastPage;
BRect printableRect = printJob.PrintableRect();
float width, imageWidth, imageHeight, w1, w2;
BBitmap* bitmap;
// first/lastPage is unused for now
firstPage = printJob.FirstPage();
lastPage = printJob.LastPage();
if (firstPage < 1) {
firstPage = 1;
}
if (lastPage < firstPage) {
lastPage = firstPage;
}
bitmap = fpImageView->GetBitmap();
imageWidth = bitmap->Bounds().Width() + 1.0;
imageHeight = bitmap->Bounds().Height() + 1.0;
switch (fPrintOptions.Option()) {
case PrintOptions::kFitToPage:
w1 = printableRect.Width()+1;
w2 = imageWidth * (printableRect.Height() + 1) / imageHeight;
if (w2 < w1) {
width = w2;
} else {
width = w1;
}
break;
case PrintOptions::kZoomFactor:
width = imageWidth * fPrintOptions.ZoomFactor();
break;
case PrintOptions::kDPI:
width = imageWidth * 72.0 / fPrintOptions.DPI();
break;
case PrintOptions::kWidth:
case PrintOptions::kHeight:
width = fPrintOptions.Width();
break;
default:
// keep compiler silent; should not reach here
width = imageWidth;
}
// XXX: eventually print large images on several pages
printJob.BeginJob();
fpImageView->SetScale(width / imageWidth);
printJob.DrawView(fpImageView, bitmap->Bounds(), BPoint(printableRect.left, printableRect.top));
fpImageView->SetScale(1.0);
printJob.SpoolPage();
printJob.CommitJob();
}
}
bool bool
ShowImageWindow::QuitRequested() ShowImageWindow::QuitRequested()
{ {

View File

@ -34,6 +34,8 @@
#include <TranslationDefs.h> #include <TranslationDefs.h>
#include <String.h> #include <String.h>
#include "PrintOptionsWindow.h"
class ShowImageView; class ShowImageView;
class ShowImageStatusView; class ShowImageStatusView;
@ -77,6 +79,9 @@ private:
bool CanQuit(); bool CanQuit();
// returns true if the window can be closed safely, false if not // returns true if the window can be closed safely, false if not
void ToggleFullScreen(); void ToggleFullScreen();
bool PageSetup();
void PrepareForPrint();
void Print(BMessage *msg);
BFilePanel *fpSavePanel; BFilePanel *fpSavePanel;
BMenuBar *fpBar; BMenuBar *fpBar;
@ -88,6 +93,8 @@ private:
bool fFullScreen; bool fFullScreen;
BRect fWindowFrame; BRect fWindowFrame;
bool fShowCaption; bool fShowCaption;
BMessage *fPrintSettings;
PrintOptions fPrintOptions;
}; };
#endif /* _ShowImageWindow_h */ #endif /* _ShowImageWindow_h */

Binary file not shown.