haiku/src/apps/showimage/ShowImageApp.cpp

265 lines
5.4 KiB
C++

/*
* Copyright 2003-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Fernando Francisco de Oliveira
* Michael Wilber
* Michael Pfeiffer
* Ryan Leavengood
*/
#include "ShowImageApp.h"
#include <stdio.h>
#include <Catalog.h>
#include <Clipboard.h>
#include <FilePanel.h>
#include <Locale.h>
#include <Path.h>
#include <Screen.h>
#include <String.h>
#include "ShowImageConstants.h"
#include "ShowImageWindow.h"
#include "ToolBarIcons.h"
const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage";
const int32 kWindowsToIgnore = 1;
// ignore the always open file panel
ShowImageApp::ShowImageApp()
:
BApplication(kApplicationSignature),
fOpenPanel(new BFilePanel(B_OPEN_PANEL)),
fPulseStarted(false),
fLastWindowFrame(BRect(30, 30, 430, 330))
{
B_TRANSLATE_MARK_SYSTEM_NAME_VOID("ShowImage");
_UpdateLastWindowFrame();
// BBitmap can be created after there is a BApplication instance.
init_tool_bar_icons();
}
ShowImageApp::~ShowImageApp()
{
// BBitmap must be deleted while there is still a BApplication instance.
uninit_tool_bar_icons();
}
void
ShowImageApp::ArgvReceived(int32 argc, char **argv)
{
BMessage message;
bool hasRefs = false;
// get current working directory
const char* cwd;
if (CurrentMessage() == NULL
|| CurrentMessage()->FindString("cwd", &cwd) != B_OK)
cwd = "";
for (int32 i = 1; i < argc; i++) {
BPath path;
if (argv[i][0] == '/') {
// absolute path
path.SetTo(argv[i]);
} else {
// relative path
path.SetTo(cwd);
path.Append(argv[i]);
}
entry_ref ref;
status_t err = get_ref_for_path(path.Path(), &ref);
if (err == B_OK) {
message.AddRef("refs", &ref);
hasRefs = true;
}
}
if (hasRefs)
RefsReceived(&message);
}
void
ShowImageApp::ReadyToRun()
{
if (CountWindows() == kWindowsToIgnore)
fOpenPanel->Show();
else {
// If image windows are already open
// (paths supplied on the command line)
// start checking the number of open windows
_StartPulse();
}
be_clipboard->StartWatching(be_app_messenger);
// tell the clipboard to notify this app when its contents change
}
void
ShowImageApp::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_FILE_OPEN:
fOpenPanel->Show();
break;
case B_CANCEL:
// File open panel was closed,
// start checking count of open windows
_StartPulse();
break;
case B_CLIPBOARD_CHANGED:
_CheckClipboard();
break;
case MSG_WINDOW_HAS_QUIT:
// Make sure that new windows open with the location/size of the
// last closed window.
_UpdateLastWindowFrame();
break;
default:
BApplication::MessageReceived(message);
break;
}
}
void
ShowImageApp::Pulse()
{
// Bug: The BFilePanel is automatically closed if the volume that
// is displayed is unmounted.
if (!IsLaunching() && CountWindows() <= kWindowsToIgnore) {
// If the application is not launching and
// all windows are closed except for the file open panel,
// quit the application
PostMessage(B_QUIT_REQUESTED);
}
}
void
ShowImageApp::RefsReceived(BMessage* message)
{
// If a tracker window opened me, get a messenger from it.
BMessenger trackerMessenger;
if (message->HasMessenger("TrackerViewToken"))
message->FindMessenger("TrackerViewToken", &trackerMessenger);
entry_ref ref;
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++)
_Open(ref, trackerMessenger);
}
bool
ShowImageApp::QuitRequested()
{
// Give the windows a chance to prompt the user if there are changes
bool result = BApplication::QuitRequested();
if (result) {
be_clipboard->StopWatching(be_app_messenger);
// tell clipboard we don't want anymore notification
}
DefaultCache().Stop();
return result;
}
void
ShowImageApp::_StartPulse()
{
if (!fPulseStarted) {
// Tell the app to begin checking
// for the number of open windows
fPulseStarted = true;
SetPulseRate(250000);
// Set pulse to every 1/4 second
}
}
void
ShowImageApp::_Open(const entry_ref& ref, const BMessenger& trackerMessenger)
{
fLastWindowFrame.OffsetBy(20, 20);
if (!BScreen(B_MAIN_SCREEN_ID).Frame().Contains(fLastWindowFrame))
fLastWindowFrame.OffsetTo(50, 50);
new ShowImageWindow(fLastWindowFrame, ref, trackerMessenger);
}
void
ShowImageApp::_BroadcastToWindows(BMessage* message)
{
const int32 count = CountWindows();
for (int32 i = 0; i < count; i++) {
// BMessenger checks for us if BWindow is still a valid object
BMessenger messenger(WindowAt(i));
messenger.SendMessage(message);
}
}
void
ShowImageApp::_CheckClipboard()
{
// Determines if the contents of the clipboard contain
// data that is useful to this application.
// After checking the clipboard, a message is sent to
// all windows indicating that the clipboard has changed
// and whether or not the clipboard contains useful data.
bool dataAvailable = false;
if (be_clipboard->Lock()) {
BMessage* clip = be_clipboard->Data();
if (clip != NULL) {
dataAvailable = clip->HasMessage("image/bitmap")
|| clip->HasMessage("image/x-be-bitmap");
}
be_clipboard->Unlock();
}
BMessage msg(B_CLIPBOARD_CHANGED);
msg.AddBool("data_available", dataAvailable);
_BroadcastToWindows(&msg);
}
void
ShowImageApp::_UpdateLastWindowFrame()
{
fLastWindowFrame = fSettings.GetRect("WindowFrame", fLastWindowFrame);
// Compensate the offset which we always add to new windows.
fLastWindowFrame.OffsetBy(-20, -20);
}
// #pragma mark -
int
main(int, char**)
{
ShowImageApp app;
app.Run();
return 0;
}