haiku/src/apps/pulse/PulseApp.cpp

347 lines
7.5 KiB
C++

/*
* Copyright 2002-2005 Haiku
* Distributed under the terms of the MIT license.
*
* Updated by Sikosis (beos@gravity24hr.com)
*
* Copyright 1999, Be Incorporated. All Rights Reserved.
* This file may be used under the terms of the Be Sample Code License.
*
* Written by: Daniel Switkin
*/
#include "PulseApp.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <Alert.h>
#include <Catalog.h>
#include <Deskbar.h>
#include <Rect.h>
#include <TextView.h>
#include <syscalls.h>
#include "Common.h"
#include "PulseWindow.h"
#include "DeskbarPulseView.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "PulseApp"
PulseApp::PulseApp(int argc, char **argv)
: BApplication(APP_SIGNATURE),
fPrefs(new Prefs()),
fRunFromReplicant(false),
fIsRunning(false),
fPrefsWindow(NULL)
{
int mini = false, deskbar = false, normal = false;
uint32 framecolor = 0, activecolor = 0, idlecolor = 0;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"deskbar", 0, &deskbar, true},
{"width", 1, 0, 'w'},
{"framecolor", 1, 0, 0},
{"activecolor", 1, 0, 0},
{"idlecolor", 1, 0, 0},
{"mini", 0, &mini, true},
{"normal", 0, &normal, true},
{"help", 0, 0, 'h'},
{0,0,0,0}
};
int c = getopt_long(argc, argv, "hw:", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 2: /* framecolor */
case 3: /* activecolor */
case 4: /* idlecolor */
uint32 rgb = strtoul(optarg, NULL, 0);
rgb = rgb << 8;
rgb |= 0x000000ff;
switch (option_index) {
case 2:
framecolor = rgb;
break;
case 3:
activecolor = rgb;
break;
case 4:
idlecolor = rgb;
break;
}
break;
}
break;
case 'w':
fPrefs->deskbar_icon_width = atoi(optarg);
if (fPrefs->deskbar_icon_width < GetMinimumViewWidth())
fPrefs->deskbar_icon_width = GetMinimumViewWidth();
else if (fPrefs->deskbar_icon_width > 50) fPrefs->deskbar_icon_width = 50;
break;
case 'h':
case '?':
Usage();
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);
break;
}
}
if (deskbar) {
fPrefs->window_mode = DESKBAR_MODE;
if (activecolor != 0)
fPrefs->deskbar_active_color = activecolor;
if (idlecolor != 0)
fPrefs->deskbar_idle_color = idlecolor;
if (framecolor != 0)
fPrefs->deskbar_frame_color = framecolor;
} else if (mini) {
fPrefs->window_mode = MINI_WINDOW_MODE;
if (activecolor != 0)
fPrefs->mini_active_color = activecolor;
if (idlecolor != 0)
fPrefs->mini_idle_color = idlecolor;
if (framecolor != 0)
fPrefs->mini_frame_color = framecolor;
} else if (normal)
fPrefs->window_mode = NORMAL_WINDOW_MODE;
fPrefs->Save();
}
void
PulseApp::ReadyToRun()
{
if (!fRunFromReplicant)
BuildPulse();
fIsRunning = true;
}
void
PulseApp::BuildPulse()
{
PulseWindow *pulseWindow = NULL;
if (fPrefs->window_mode == MINI_WINDOW_MODE)
pulseWindow = new PulseWindow(fPrefs->mini_window_rect);
else
pulseWindow = new PulseWindow(fPrefs->normal_window_rect);
pulseWindow->MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN);
pulseWindow->Show();
}
PulseApp::~PulseApp()
{
fPrefs->Save();
delete fPrefs;
}
void
PulseApp::MessageReceived(BMessage* message)
{
switch (message->what) {
case PV_PREFERENCES:
{
// This message can be posted before ReadyToRun from
// BRoster::Launch, in that case, take note to not show the main
// window but only the preferences
if (!fIsRunning)
fRunFromReplicant = true;
BMessenger from;
message->FindMessenger("settingsListener", &from);
if (fPrefsWindow != NULL) {
fPrefsWindow->Activate(true);
break;
}
// If the window is already open, bring it to the front
if (fPrefsWindow != NULL) {
fPrefsWindow->Activate(true);
break;
}
// Otherwise launch a new preferences window
PulseApp *pulseapp = (PulseApp *)be_app;
fPrefsWindow = new PrefsWindow(pulseapp->fPrefs->prefs_window_rect,
B_TRANSLATE("Pulse settings"), &from,
pulseapp->fPrefs);
if (fRunFromReplicant) {
fPrefsWindow->SetFlags(fPrefsWindow->Flags()
| B_QUIT_ON_WINDOW_CLOSE);
}
fPrefsWindow->Show();
break;
}
case PV_ABOUT:
// This message can be posted before ReadyToRun from
// BRoster::Launch, in that case, take note to not show the main
// window but only the about box
if (!fIsRunning)
fRunFromReplicant = true;
PostMessage(B_ABOUT_REQUESTED);
break;
case PRV_QUIT:
fPrefsWindow = NULL;
fRunFromReplicant = false;
break;
default:
BApplication::MessageReceived(message);
break;
}
}
void
PulseApp::AboutRequested()
{
BString name = B_TRANSLATE("Pulse");
BString message = B_TRANSLATE(
"%s\n\nBy David Ramsey and Arve Hjønnevåg\n"
"Revised by Daniel Switkin\n");
message.ReplaceFirst("%s", name);
BAlert *alert = new BAlert(B_TRANSLATE("Info"),
message.String(), B_TRANSLATE("OK"));
if (fRunFromReplicant)
alert->SetFlags(alert->Flags() | B_QUIT_ON_WINDOW_CLOSE);
BTextView* view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, name.Length(), &font);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
// Use the asynchronous version so we don't block the window's thread
alert->Go(NULL);
fRunFromReplicant = false;
}
// #pragma mark -
/** Make sure we don't disable the last CPU - this is needed by
* descendants of PulseView for the popup menu and for CPUButton
* both as a replicant and not.
*/
bool
LastEnabledCPU(unsigned int my_cpu)
{
system_info sys_info;
get_system_info(&sys_info);
if (sys_info.cpu_count == 1)
return true;
for (unsigned int x = 0; x < sys_info.cpu_count; x++) {
if (x == my_cpu)
continue;
if (_kern_cpu_enabled(x) == 1)
return false;
}
return true;
}
/** Ensure that the mini mode and deskbar mode always show an indicator
* for each CPU, at least one pixel wide.
*/
int
GetMinimumViewWidth()
{
system_info sys_info;
get_system_info(&sys_info);
return (sys_info.cpu_count * 2) + 1;
}
void
Usage()
{
puts(B_TRANSLATE("Usage: Pulse [--mini] [-w width] [--width=width]\n"
"\t[--deskbar] [--normal] [--framecolor 0xrrggbb]\n"
"\t[--activecolor 0xrrggbb] [--idlecolor 0xrrggbb]"));
exit(0);
}
bool
LoadInDeskbar()
{
PulseApp *pulseapp = (PulseApp *)be_app;
BDeskbar *deskbar = new BDeskbar();
// Don't allow two copies in the Deskbar at once
if (deskbar->HasItem("DeskbarPulseView")) {
delete deskbar;
return false;
}
// Must be 16 pixels high, the width is retrieved from the Prefs class
int width = pulseapp->fPrefs->deskbar_icon_width;
int min_width = GetMinimumViewWidth();
if (width < min_width) {
pulseapp->fPrefs->deskbar_icon_width = min_width;
width = min_width;
}
float height = deskbar->MaxItemHeight();
BRect rect(0, 0, width - 1, height - 1);
DeskbarPulseView *replicant = new DeskbarPulseView(rect);
status_t err = deskbar->AddItem(replicant);
delete replicant;
delete deskbar;
if (err != B_OK) {
BString message;
snprintf(message.LockBuffer(512), 512,
B_TRANSLATE("Installing in Deskbar failed\n%s"), strerror(err));
message.UnlockBuffer();
BAlert *alert = new BAlert(B_TRANSLATE("Error"),
message.String(), B_TRANSLATE("OK"));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go(NULL);
return false;
}
return true;
}
int
main(int argc, char **argv)
{
PulseApp *pulseapp = new PulseApp(argc, argv);
pulseapp->Run();
delete pulseapp;
return 0;
}