Merge branch 'master' into x86_64

This commit is contained in:
Alex Smith
2012-07-06 15:55:59 +01:00
65 changed files with 17700 additions and 18 deletions
+1 -1
View File
@@ -199,7 +199,7 @@ rule ExtractArchive directory : entries : archiveFile : grist
# <directory> and <archiveFile> combo.
#
# <directory> - The directory into which to extract the archive file. The
# directory is created is by this rule and it is the target
# directory is created by this rule and it is the target
# that the extract action is associated with.
# <entries> - The entries of the archive file one is interested in. The
# rule always extracts the complete archive file, from the
+33
View File
@@ -419,3 +419,36 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) {
}
}
# WebKit
local webkitBaseURL = http://haiku-files.org/files/optional-packages ;
if $(TARGET_ARCH) = x86 {
if $(HAIKU_GCC_VERSION[1]) < 4 {
Echo "WebKit support not available on gcc $(HAIKU_GCC_VERSION[1])" ;
} else {
HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ;
local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE)
: $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ;
HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR)
$(HAIKU_WEBKIT_FILE:B) ] ;
HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR)
: include/ : $(zipFile) : extracted-webkit ] ;
HAIKU_WEBKIT_LIBS = [ ExtractArchive $(HAIKU_WEBKIT_DIR)
:
lib/libwtf.so
lib/libjavascriptcore.so
lib/libwebcore.so
lib/libwebkit.so
: $(zipFile)
: extracted-webkit
] ;
HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ;
}
} else {
Echo "WebKit support not available on $(TARGET_ARCH)" ;
}
+2 -2
View File
@@ -359,8 +359,8 @@ if [ IsOptionalHaikuImagePackageAdded Bzip ] {
# CARootCertificates
if [ IsOptionalHaikuImagePackageAdded CARootCertificates ] {
InstallOptionalHaikuImagePackage cert-2012-05-02.zip
: $(baseURL)/cert-2012-05-02.zip
InstallOptionalHaikuImagePackage cert-2012-07-04.zip
: $(baseURL)/cert-2012-07-04.zip
: common data ssl ;
}
+1
View File
@@ -59,5 +59,6 @@ HaikuSubInclude terminal ;
HaikuSubInclude text_search ;
HaikuSubInclude tracker ;
HaikuSubInclude tv ;
HaikuSubInclude webpositive ;
HaikuSubInclude webwatch ;
HaikuSubInclude workspaces ;
@@ -0,0 +1,218 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "AuthenticationPanel.h"
#include <Button.h>
#include <CheckBox.h>
#include <ControlLook.h>
#include <GridLayoutBuilder.h>
#include <GroupLayoutBuilder.h>
#include <Message.h>
#include <Screen.h>
#include <SeparatorView.h>
#include <SpaceLayoutItem.h>
#include <StringView.h>
#include <TextControl.h>
#include <stdio.h>
static const uint32 kMsgPanelOK = 'pnok';
static const uint32 kMsgJitter = 'jitr';
static const uint32 kHidePassword = 'hdpw';
AuthenticationPanel::AuthenticationPanel(BRect parentFrame)
: BWindow(BRect(-1000, -1000, -900, -900), "Authentication Required",
B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE
| B_CLOSE_ON_ESCAPE | B_AUTO_UPDATE_SIZE_LIMITS)
, m_parentWindowFrame(parentFrame)
, m_usernameTextControl(new BTextControl("user", "Username:", "", NULL))
, m_passwordTextControl(new BTextControl("pass", "Password:", "", NULL))
, m_hidePasswordCheckBox(new BCheckBox("hide", "Hide password text", new BMessage(kHidePassword)))
, m_rememberCredentialsCheckBox(new BCheckBox("remember", "Remember username and password for this site", NULL))
, m_okButton(new BButton("ok", "OK", new BMessage(kMsgPanelOK)))
, m_cancelButton(new BButton("cancel", "Cancel", new BMessage(B_QUIT_REQUESTED)))
, m_cancelled(false)
, m_exitSemaphore(create_sem(0, "Authentication Panel"))
{
}
AuthenticationPanel::~AuthenticationPanel()
{
delete_sem(m_exitSemaphore);
}
bool
AuthenticationPanel::QuitRequested()
{
m_cancelled = true;
release_sem(m_exitSemaphore);
return false;
}
void
AuthenticationPanel::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgPanelOK:
release_sem(m_exitSemaphore);
break;
case kHidePassword: {
// TODO: Toggling this is broken in BTextView. Workaround is to
// set the text and selection again.
BString text = m_passwordTextControl->Text();
int32 selectionStart;
int32 selectionEnd;
m_passwordTextControl->TextView()->GetSelection(&selectionStart, &selectionEnd);
m_passwordTextControl->TextView()->HideTyping(
m_hidePasswordCheckBox->Value() == B_CONTROL_ON);
m_passwordTextControl->SetText(text.String());
m_passwordTextControl->TextView()->Select(selectionStart, selectionEnd);
break;
}
case kMsgJitter: {
UpdateIfNeeded();
BPoint leftTop = Frame().LeftTop();
const float jitterOffsets[] = { -10, 0, 10, 0 };
const int32 jitterOffsetCount = sizeof(jitterOffsets) / sizeof(float);
for (int32 i = 0; i < 20; i++) {
float offset = jitterOffsets[i % jitterOffsetCount];
MoveTo(leftTop.x + offset, leftTop.y);
snooze(15000);
}
MoveTo(leftTop);
break;
}
default:
BWindow::MessageReceived(message);
}
}
bool AuthenticationPanel::getAuthentication(const BString& text,
const BString& previousUser, const BString& previousPass,
bool previousRememberCredentials, bool badPassword,
BString& user, BString& pass, bool* rememberCredentials)
{
// Configure panel and layout controls.
rgb_color infoColor = ui_color(B_PANEL_TEXT_COLOR);
BRect textBounds(0, 0, 250, 200);
BTextView* textView = new BTextView(textBounds, "text", textBounds,
be_plain_font, &infoColor, B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT);
textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
textView->SetText(text.String());
textView->MakeEditable(false);
textView->MakeSelectable(false);
m_usernameTextControl->SetText(previousUser.String());
m_passwordTextControl->TextView()->HideTyping(true);
// Ignore the previous password, if it didn't work.
if (!badPassword)
m_passwordTextControl->SetText(previousPass.String());
m_hidePasswordCheckBox->SetValue(B_CONTROL_ON);
m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials);
// create layout
SetLayout(new BGroupLayout(B_VERTICAL, 0.0));
float spacing = be_control_look->DefaultItemSpacing();
AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
.Add(BGridLayoutBuilder(0, spacing)
.Add(textView, 0, 0, 2)
.Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 1)
.Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 1)
.Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 2)
.Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 2)
.Add(BSpaceLayoutItem::CreateGlue(), 0, 3)
.Add(m_hidePasswordCheckBox, 1, 3)
.Add(m_rememberCredentialsCheckBox, 0, 4, 2)
.SetInsets(spacing, spacing, spacing, spacing)
)
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
.AddGlue()
.Add(m_cancelButton)
.Add(m_okButton)
.SetInsets(spacing, spacing, spacing, spacing)
)
);
float textHeight = textView->LineHeight(0) * textView->CountLines();
textView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight));
SetDefaultButton(m_okButton);
if (badPassword && previousUser.Length())
m_passwordTextControl->MakeFocus(true);
else
m_usernameTextControl->MakeFocus(true);
if (m_parentWindowFrame.IsValid())
CenterIn(m_parentWindowFrame);
else
CenterOnScreen();
// Start AuthenticationPanel window thread
Show();
// Let the window jitter, if the previous password was invalid
if (badPassword)
PostMessage(kMsgJitter);
// Block calling thread
// Get the originating window, if it exists, to let it redraw itself.
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
if (window) {
status_t err;
for (;;) {
do {
err = acquire_sem_etc(m_exitSemaphore, 1, B_RELATIVE_TIMEOUT, 10000);
// We've (probably) had our time slice taken away from us
} while (err == B_INTERRUPTED);
if (err != B_TIMED_OUT) {
// Semaphore was finally released or nuked.
break;
}
window->UpdateIfNeeded();
}
} else {
// No window to update, so just hang out until we're done.
while (acquire_sem(m_exitSemaphore) == B_INTERRUPTED) {
}
}
// AuthenticationPanel wants to quit.
Lock();
user = m_usernameTextControl->Text();
pass = m_passwordTextControl->Text();
if (rememberCredentials)
*rememberCredentials = m_rememberCredentialsCheckBox->Value() == B_CONTROL_ON;
bool canceled = m_cancelled;
Quit();
// AuthenticationPanel object is TOAST here.
return !canceled;
}
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AuthenticationPanel_h
#define AuthenticationPanel_h
#include <String.h>
#include <Window.h>
class BCheckBox;
class BTextControl;
class AuthenticationPanel : public BWindow {
public:
AuthenticationPanel(BRect parentFrame = BRect());
virtual ~AuthenticationPanel();
virtual bool QuitRequested();
virtual void MessageReceived(BMessage *message);
bool getAuthentication(const BString& text, const BString& previousUser,
const BString& previousPass, bool previousRememberCredentials,
bool badPassword, BString& user, BString& pass,
bool* rememberCredentials);
private:
BRect m_parentWindowFrame;
BTextControl* m_usernameTextControl;
BTextControl* m_passwordTextControl;
BCheckBox* m_hidePasswordCheckBox;
BCheckBox* m_rememberCredentialsCheckBox;
BButton* m_okButton;
BButton* m_cancelButton;
bool m_cancelled;
sem_id m_exitSemaphore;
};
#endif // AuthenticationPanel_h
+449
View File
@@ -0,0 +1,449 @@
/*
* Copyright (C) 2007 Ryan Leavengood <[email protected]>
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BrowserApp.h"
#include "BrowserWindow.h"
#include "BrowsingHistory.h"
#include "DownloadWindow.h"
#include "SettingsMessage.h"
#include "SettingsWindow.h"
#include "svn_revision.h"
#include "NetworkCookieJar.h"
#include "WebPage.h"
#include "WebSettings.h"
#include "WebView.h"
#include <Alert.h>
#include <Autolock.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <Locale.h>
#include <Path.h>
#include <Screen.h>
#include <debugger.h>
#include <stdio.h>
const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive";
const char* kApplicationName = "WebPositive";
static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh';
#define ENABLE_NATIVE_COOKIES 0
BrowserApp::BrowserApp()
:
BApplication(kApplicationSignature),
fWindowCount(0),
fLastWindowFrame(50, 50, 950, 750),
fLaunchRefsMessage(0),
fInitialized(false),
fSettings(NULL),
fCookies(NULL),
fCookieJar(NULL),
fDownloadWindow(NULL),
fSettingsWindow(NULL)
{
}
BrowserApp::~BrowserApp()
{
delete fLaunchRefsMessage;
delete fSettings;
delete fCookies;
delete fCookieJar;
}
void
BrowserApp::AboutRequested()
{
BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, "
"Maxime Simon, Michael Lotz, Rene Gollent and Stephan Aßmus");
aboutText << "\n\nSVN revision: " << kSVNRevision;
BAlert* alert = new BAlert("About WebPositive", aboutText.String(),
"Sweet!");
alert->Go(NULL);
}
void
BrowserApp::ArgvReceived(int32 argc, char** argv)
{
BMessage message(B_REFS_RECEIVED);
for (int i = 1; i < argc; i++) {
if (strcmp("-f", argv[i]) == 0
|| strcmp("--fullscreen", argv[i]) == 0) {
message.AddBool("fullscreen", true);
continue;
}
const char* url = argv[i];
BEntry entry(argv[i], true);
BPath path;
if (entry.Exists() && entry.GetPath(&path) == B_OK)
url = path.Path();
message.AddString("url", url);
}
// Upon program launch, it will buffer a copy of the message, since
// ArgReceived() is called before ReadyToRun().
RefsReceived(&message);
}
void
BrowserApp::ReadyToRun()
{
// Since we will essentially run the GUI...
set_thread_priority(Thread(), B_DISPLAY_PRIORITY);
BWebPage::InitializeOnce();
BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER);
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK
&& path.Append(kApplicationName) == B_OK
&& create_directory(path.Path(), 0777) == B_OK) {
BWebSettings::SetPersistentStoragePath(path.Path());
}
BString mainSettingsPath(kApplicationName);
mainSettingsPath << "/Application";
fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
mainSettingsPath.String());
#if ENABLE_NATIVE_COOKIES
mainSettingsPath = kApplicationName;
mainSettingsPath << "/Cookies";
fCookies = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
mainSettingsPath.String());
BMessage cookieArchive;
cookieArchive = fCookies->GetValue("cookies", cookieArchive);
fCookieJar = new BNetworkCookieJar(cookieArchive);
BWebPage::SetCookieJar(fCookieJar);
#endif
fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame);
BRect defaultDownloadWindowFrame(-10, -10, 365, 265);
BRect downloadWindowFrame = fSettings->GetValue("downloads window frame",
defaultDownloadWindowFrame);
BRect settingsWindowFrame = fSettings->GetValue("settings window frame",
BRect());
bool showDownloads = fSettings->GetValue("show downloads", false);
fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads,
fSettings);
if (downloadWindowFrame == defaultDownloadWindowFrame) {
// Initially put download window in lower right of screen.
BRect screenFrame = BScreen().Frame();
BMessage decoratorSettings;
fDownloadWindow->GetDecoratorSettings(&decoratorSettings);
float borderWidth = 0;
if (decoratorSettings.FindFloat("border width", &borderWidth) != B_OK)
borderWidth = 5;
fDownloadWindow->MoveTo(screenFrame.Width() - fDownloadWindow->Frame().Width() - borderWidth,
screenFrame.Height() - fDownloadWindow->Frame().Height() - borderWidth);
}
fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings);
BWebPage::SetDownloadListener(BMessenger(fDownloadWindow));
fInitialized = true;
int32 pagesCreated = 0;
bool fullscreen = false;
if (fLaunchRefsMessage) {
_RefsReceived(fLaunchRefsMessage, &pagesCreated, &fullscreen);
delete fLaunchRefsMessage;
fLaunchRefsMessage = NULL;
}
if (pagesCreated == 0)
_CreateNewWindow("", fullscreen);
PostMessage(PRELOAD_BROWSING_HISTORY);
}
void
BrowserApp::MessageReceived(BMessage* message)
{
switch (message->what) {
case PRELOAD_BROWSING_HISTORY:
// Accessing the default instance will load the history from disk.
BrowsingHistory::DefaultInstance();
break;
case B_SILENT_RELAUNCH:
_CreateNewPage("");
break;
case NEW_WINDOW: {
BString url;
if (message->FindString("url", &url) != B_OK)
break;
_CreateNewWindow(url);
break;
}
case NEW_TAB: {
BrowserWindow* window;
if (message->FindPointer("window", reinterpret_cast<void**>(&window)) != B_OK)
break;
BString url;
message->FindString("url", &url);
bool select = false;
message->FindBool("select", &select);
_CreateNewTab(window, url, select);
break;
}
case WINDOW_OPENED:
fWindowCount++;
fDownloadWindow->SetMinimizeOnClose(false);
break;
case WINDOW_CLOSED:
fWindowCount--;
message->FindRect("window frame", &fLastWindowFrame);
if (fWindowCount <= 0)
PostMessage(B_QUIT_REQUESTED);
break;
case SHOW_DOWNLOAD_WINDOW:
_ShowWindow(message, fDownloadWindow);
break;
case SHOW_SETTINGS_WINDOW:
_ShowWindow(message, fSettingsWindow);
break;
default:
BApplication::MessageReceived(message);
break;
}
}
void
BrowserApp::RefsReceived(BMessage* message)
{
if (!fInitialized) {
delete fLaunchRefsMessage;
fLaunchRefsMessage = new BMessage(*message);
return;
}
_RefsReceived(message);
}
bool
BrowserApp::QuitRequested()
{
if (fDownloadWindow->DownloadsInProgress()) {
BAlert* alert = new BAlert("Downloads in progress",
"There are still downloads in progress, do you really want to "
"quit WebPositive now?", "Quit", "Continue downloads");
int32 choice = alert->Go();
if (choice == 1) {
if (fWindowCount == 0) {
if (fDownloadWindow->Lock()) {
fDownloadWindow->SetWorkspaces(1 << current_workspace());
if (fDownloadWindow->IsHidden())
fDownloadWindow->Show();
else
fDownloadWindow->Activate();
fDownloadWindow->SetMinimizeOnClose(true);
fDownloadWindow->Unlock();
return false;
}
} else
return false;
}
}
for (int i = 0; BWindow* window = WindowAt(i); i++) {
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
if (!webWindow)
continue;
if (!webWindow->Lock())
continue;
if (webWindow->QuitRequested()) {
fLastWindowFrame = webWindow->WindowFrame();
webWindow->Quit();
i--;
} else {
webWindow->Unlock();
return false;
}
}
BWebPage::ShutdownOnce();
fSettings->SetValue("window frame", fLastWindowFrame);
if (fDownloadWindow->Lock()) {
fSettings->SetValue("downloads window frame", fDownloadWindow->Frame());
fSettings->SetValue("show downloads", !fDownloadWindow->IsHidden());
fDownloadWindow->Unlock();
}
if (fSettingsWindow->Lock()) {
fSettings->SetValue("settings window frame", fSettingsWindow->Frame());
fSettingsWindow->Unlock();
}
BMessage cookieArchive;
if (fCookieJar != NULL && fCookieJar->Archive(&cookieArchive) == B_OK)
fCookies->SetValue("cookies", cookieArchive);
return true;
}
void
BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated,
bool* _fullscreen)
{
int32 pagesCreated = 0;
bool fullscreen;
if (message->FindBool("fullscreen", &fullscreen) != B_OK)
fullscreen = false;
entry_ref ref;
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
BEntry entry(&ref, true);
if (!entry.Exists())
continue;
BPath path;
if (entry.GetPath(&path) != B_OK)
continue;
BString url;
url << path.Path();
_CreateNewPage(url, fullscreen);
pagesCreated++;
}
BString url;
for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) {
_CreateNewPage(url, fullscreen);
pagesCreated++;
}
if (_pagesCreated != NULL)
*_pagesCreated = pagesCreated;
if (_fullscreen != NULL)
*_fullscreen = fullscreen;
}
void
BrowserApp::_CreateNewPage(const BString& url, bool fullscreen)
{
uint32 workspace = 1 << current_workspace();
bool loadedInWindowOnCurrentWorkspace = false;
for (int i = 0; BWindow* window = WindowAt(i); i++) {
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
if (!webWindow)
continue;
if (webWindow->Lock()) {
if (webWindow->Workspaces() & workspace) {
if (webWindow->IsBlankTab()) {
if (url.Length() != 0)
webWindow->CurrentWebView()->LoadURL(url);
} else
webWindow->CreateNewTab(url, true);
webWindow->Activate();
webWindow->CurrentWebView()->MakeFocus(true);
loadedInWindowOnCurrentWorkspace = true;
}
webWindow->Unlock();
}
if (loadedInWindowOnCurrentWorkspace)
return;
}
_CreateNewWindow(url, fullscreen);
}
void
BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen)
{
// Offset the window frame unless this is the first window created in the
// session.
if (fWindowCount > 0)
fLastWindowFrame.OffsetBy(20, 20);
if (!BScreen().Frame().Contains(fLastWindowFrame))
fLastWindowFrame.OffsetTo(50, 50);
BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings,
url);
if (fullscreen)
window->ToggleFullscreen();
window->Show();
}
void
BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url,
bool select)
{
if (!window->Lock())
return;
window->CreateNewTab(url, select);
window->Unlock();
}
void
BrowserApp::_ShowWindow(const BMessage* message, BWindow* window)
{
BAutolock _(window);
uint32 workspaces;
if (message->FindUInt32("workspaces", &workspaces) == B_OK)
window->SetWorkspaces(workspaces);
if (window->IsHidden())
window->Show();
else
window->Activate();
}
// #pragma mark -
int
main(int, char**)
{
try {
new BrowserApp();
be_app->Run();
delete be_app;
} catch (...) {
debugger("Exception caught.");
}
return 0;
}
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2007 Ryan Leavengood <[email protected]>
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BROWSER_APP_H
#define BROWSER_APP_H
#include <Application.h>
#include <Catalog.h>
#include <Rect.h>
class BNetworkCookieJar;
class DownloadWindow;
class BrowserWindow;
class SettingsMessage;
class SettingsWindow;
class BrowserApp : public BApplication {
public:
BrowserApp();
virtual ~BrowserApp();
virtual void AboutRequested();
virtual void ArgvReceived(int32 agrc, char** argv);
virtual void MessageReceived(BMessage* message);
virtual void RefsReceived(BMessage* message);
virtual void ReadyToRun();
virtual bool QuitRequested();
private:
void _RefsReceived(BMessage* message,
int32* pagesCreated = NULL,
bool* fullscreen = NULL);
void _CreateNewPage(const BString& url,
bool fullscreen = false);
void _CreateNewWindow(const BString& url,
bool fullscreen = false);
void _CreateNewTab(BrowserWindow* window,
const BString& url, bool select);
void _ShowWindow(const BMessage* message,
BWindow* window);
private:
int fWindowCount;
BRect fLastWindowFrame;
BMessage* fLaunchRefsMessage;
bool fInitialized;
SettingsMessage* fSettings;
SettingsMessage* fCookies;
BNetworkCookieJar* fCookieJar;
DownloadWindow* fDownloadWindow;
SettingsWindow* fSettingsWindow;
};
extern const char* kApplicationSignature;
extern const char* kApplicationName;
#endif // BROWSER_APP_H
File diff suppressed because it is too large Load Diff
+257
View File
@@ -0,0 +1,257 @@
/*
* Copyright (C) 2007 Ryan Leavengood <[email protected]>
* Copyright (C) 2009 Maxime Simon <[email protected]>
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BROWSER_WINDOW_H
#define BROWSER_WINDOW_H
#include "WebWindow.h"
#include <Messenger.h>
#include <String.h>
class BButton;
class BCheckBox;
class BDirectory;
class BFile;
class BLayoutItem;
class BMenu;
class BMenuItem;
class BMessageRunner;
class BPath;
class BStatusBar;
class BStringView;
class BTextControl;
class BWebView;
class IconButton;
class SettingsMessage;
class TabManager;
class URLInputGroup;
enum {
INTERFACE_ELEMENT_MENU = 1 << 0,
INTERFACE_ELEMENT_TABS = 1 << 1,
INTERFACE_ELEMENT_NAVIGATION = 1 << 2,
INTERFACE_ELEMENT_STATUS = 1 << 3,
INTERFACE_ELEMENT_ALL = 0xffff
};
enum NewPagePolicy {
OpenBlankPage = 0,
OpenStartPage = 1,
OpenSearchPage = 2,
CloneCurrentPage = 3
};
enum {
NEW_WINDOW = 'nwnd',
NEW_TAB = 'ntab',
WINDOW_OPENED = 'wndo',
WINDOW_CLOSED = 'wndc',
SHOW_DOWNLOAD_WINDOW = 'sdwd',
SHOW_SETTINGS_WINDOW = 'sswd'
};
#define INTEGRATE_MENU_INTO_TAB_BAR 0
class BrowserWindow : public BWebWindow {
public:
BrowserWindow(BRect frame,
SettingsMessage* appSettings,
const BString& url,
uint32 interfaceElements
= INTERFACE_ELEMENT_ALL,
BWebView* webView = NULL);
virtual ~BrowserWindow();
virtual void DispatchMessage(BMessage* message,
BHandler* target);
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
virtual void MenusBeginning();
virtual void Zoom(BPoint origin, float width, float height);
virtual void ScreenChanged(BRect screenSize,
color_space format);
virtual void WorkspacesChanged(uint32 oldWorkspaces,
uint32 newWorkspaces);
virtual void SetCurrentWebView(BWebView* view);
bool IsBlankTab() const;
void CreateNewTab(const BString& url, bool select,
BWebView* webView = 0);
BRect WindowFrame() const;
void ToggleFullscreen();
private:
// WebPage notification API implementations
virtual void NavigationRequested(const BString& url,
BWebView* view);
virtual void NewWindowRequested(const BString& url,
bool primaryAction);
virtual void CloseWindowRequested(BWebView* view);
virtual void NewPageCreated(BWebView* view,
BRect windowFrame, bool modalDialog,
bool resizable, bool activate);
virtual void LoadNegotiating(const BString& url,
BWebView* view);
virtual void LoadCommitted(const BString& url,
BWebView* view);
virtual void LoadProgress(float progress, BWebView* view);
virtual void LoadFailed(const BString& url, BWebView* view);
virtual void LoadFinished(const BString& url,
BWebView* view);
virtual void MainDocumentError(const BString& failingURL,
const BString& localizedDescription,
BWebView* view);
virtual void TitleChanged(const BString& title,
BWebView* view);
virtual void IconReceived(const BBitmap* icon,
BWebView* view);
virtual void ResizeRequested(float width, float height,
BWebView* view);
virtual void SetToolBarsVisible(bool flag, BWebView* view);
virtual void SetStatusBarVisible(bool flag, BWebView* view);
virtual void SetMenuBarVisible(bool flag, BWebView* view);
virtual void SetResizable(bool flag, BWebView* view);
virtual void StatusChanged(const BString& status,
BWebView* view);
virtual void NavigationCapabilitiesChanged(
bool canGoBackward, bool canGoForward,
bool canStop, BWebView* view);
virtual void UpdateGlobalHistory(const BString& url);
virtual bool AuthenticationChallenge(BString message,
BString& inOutUser, BString& inOutPassword,
bool& inOutRememberCredentials,
uint32 failureCount, BWebView* view);
private:
void _UpdateTitle(const BString &title);
void _UpdateTabGroupVisibility();
bool _TabGroupShouldBeVisible() const;
void _ShutdownTab(int32 index);
void _TabChanged(int32 index);
status_t _BookmarkPath(BPath& path) const;
void _CreateBookmark();
void _ShowBookmarks();
bool _CheckBookmarkExists(BDirectory& directory,
const BString& fileName,
const BString& url) const;
bool _ReadURLAttr(BFile& bookmarkFile,
BString& url) const;
void _AddBookmarkURLsRecursively(
BDirectory& directory,
BMessage* message,
uint32& addedCount) const;
void _SetPageIcon(BWebView* view,
const BBitmap* icon);
void _UpdateHistoryMenu();
void _UpdateClipboardItems();
bool _ShowPage(BWebView* view);
void _ToggleFullscreen();
void _ResizeToScreen();
void _SetAutoHideInterfaceInFullscreen(bool doIt);
void _CheckAutoHideInterface();
void _ShowInterface(bool show);
void _ShowProgressBar(bool);
void _InvokeButtonVisibly(BButton* button);
BString _NewTabURL(bool isNewWindow) const;
BString _SmartURLHandler(const BString& url) const;
void _HandlePageSourceResult(
const BMessage* message);
private:
BMenu* fHistoryMenu;
int32 fHistoryMenuFixedItemCount;
BMenuItem* fCutMenuItem;
BMenuItem* fCopyMenuItem;
BMenuItem* fPasteMenuItem;
BMenuItem* fFindPreviousMenuItem;
BMenuItem* fFindNextMenuItem;
BMenuItem* fZoomTextOnlyMenuItem;
BMenuItem* fFullscreenItem;
BMenuItem* fBackMenuItem;
BMenuItem* fForwardMenuItem;
IconButton* fBackButton;
IconButton* fForwardButton;
IconButton* fStopButton;
IconButton* fHomeButton;
URLInputGroup* fURLInputGroup;
BStringView* fStatusText;
BStatusBar* fLoadingProgressBar;
BLayoutItem* fMenuGroup;
BLayoutItem* fTabGroup;
BLayoutItem* fNavigationGroup;
BLayoutItem* fFindGroup;
BLayoutItem* fStatusGroup;
BLayoutItem* fToggleFullscreenButton;
BTextControl* fFindTextControl;
BButton* fFindPreviousButton;
BButton* fFindNextButton;
BButton* fFindCloseButton;
BCheckBox* fFindCaseSensitiveCheckBox;
TabManager* fTabManager;
bool fIsFullscreen;
bool fInterfaceVisible;
BRect fNonFullscreenWindowFrame;
BMessageRunner* fPulseRunner;
uint32 fVisibleInterfaceElements;
bigtime_t fLastMouseMovedTime;
BPoint fLastMousePos;
// cached settings
SettingsMessage* fAppSettings;
bool fZoomTextOnly;
bool fShowTabsIfSinglePageOpen;
bool fAutoHideInterfaceInFullscreenMode;
bool fAutoHidePointer;
uint32 fNewWindowPolicy;
uint32 fNewTabPolicy;
BString fStartPageURL;
BString fSearchPageURL;
};
#endif // BROWSER_WINDOW_H
+381
View File
@@ -0,0 +1,381 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BrowsingHistory.h"
#include <new>
#include <stdio.h>
#include <Autolock.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <Message.h>
#include <Path.h>
#include "BrowserApp.h"
BrowsingHistoryItem::BrowsingHistoryItem(const BString& url)
:
fURL(url),
fDateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)),
fInvokationCount(0)
{
}
BrowsingHistoryItem::BrowsingHistoryItem(const BrowsingHistoryItem& other)
{
*this = other;
}
BrowsingHistoryItem::BrowsingHistoryItem(const BMessage* archive)
{
if (!archive)
return;
BMessage dateTimeArchive;
if (archive->FindMessage("date time", &dateTimeArchive) == B_OK)
fDateTime = BDateTime(&dateTimeArchive);
archive->FindString("url", &fURL);
archive->FindUInt32("invokations", &fInvokationCount);
}
BrowsingHistoryItem::~BrowsingHistoryItem()
{
}
status_t
BrowsingHistoryItem::Archive(BMessage* archive) const
{
if (!archive)
return B_BAD_VALUE;
BMessage dateTimeArchive;
status_t status = fDateTime.Archive(&dateTimeArchive);
if (status == B_OK)
status = archive->AddMessage("date time", &dateTimeArchive);
if (status == B_OK)
status = archive->AddString("url", fURL.String());
if (status == B_OK)
status = archive->AddUInt32("invokations", fInvokationCount);
return status;
}
BrowsingHistoryItem&
BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other)
{
if (this == &other)
return *this;
fURL = other.fURL;
fDateTime = other.fDateTime;
fInvokationCount = other.fInvokationCount;
return *this;
}
bool
BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const
{
if (this == &other)
return true;
return fURL == other.fURL && fDateTime == other.fDateTime
&& fInvokationCount == other.fInvokationCount;
}
bool
BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const
{
return !(*this == other);
}
bool
BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const
{
if (this == &other)
return false;
return fDateTime < other.fDateTime || fURL < other.fURL;
}
bool
BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const
{
return (*this == other) || (*this < other);
}
bool
BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const
{
if (this == &other)
return false;
return fDateTime > other.fDateTime || fURL > other.fURL;
}
bool
BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const
{
return (*this == other) || (*this > other);
}
void
BrowsingHistoryItem::Invoked()
{
// Eventually, we may overflow...
uint32 count = fInvokationCount + 1;
if (count > fInvokationCount)
fInvokationCount = count;
fDateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
}
// #pragma mark - BrowsingHistory
BrowsingHistory
BrowsingHistory::sDefaultInstance;
BrowsingHistory::BrowsingHistory()
:
BLocker("browsing history"),
fHistoryItems(64),
fMaxHistoryItemAge(7),
fSettingsLoaded(false)
{
}
BrowsingHistory::~BrowsingHistory()
{
_SaveSettings();
_Clear();
}
/*static*/ BrowsingHistory*
BrowsingHistory::DefaultInstance()
{
if (sDefaultInstance.Lock()) {
sDefaultInstance._LoadSettings();
sDefaultInstance.Unlock();
}
return &sDefaultInstance;
}
bool
BrowsingHistory::AddItem(const BrowsingHistoryItem& item)
{
BAutolock _(this);
return _AddItem(item, false);
}
int32
BrowsingHistory::BrowsingHistory::CountItems() const
{
BAutolock _(const_cast<BrowsingHistory*>(this));
return fHistoryItems.CountItems();
}
BrowsingHistoryItem
BrowsingHistory::HistoryItemAt(int32 index) const
{
BAutolock _(const_cast<BrowsingHistory*>(this));
BrowsingHistoryItem* existingItem = reinterpret_cast<BrowsingHistoryItem*>(
fHistoryItems.ItemAt(index));
if (!existingItem)
return BrowsingHistoryItem(BString());
return BrowsingHistoryItem(*existingItem);
}
void
BrowsingHistory::Clear()
{
BAutolock _(this);
_Clear();
_SaveSettings();
}
void
BrowsingHistory::SetMaxHistoryItemAge(int32 days)
{
BAutolock _(this);
if (fMaxHistoryItemAge != days) {
fMaxHistoryItemAge = days;
_SaveSettings();
}
}
int32
BrowsingHistory::MaxHistoryItemAge() const
{
return fMaxHistoryItemAge;
}
// #pragma mark - private
void
BrowsingHistory::_Clear()
{
int32 count = CountItems();
for (int32 i = 0; i < count; i++) {
BrowsingHistoryItem* item = reinterpret_cast<BrowsingHistoryItem*>(
fHistoryItems.ItemAtFast(i));
delete item;
}
fHistoryItems.MakeEmpty();
}
bool
BrowsingHistory::_AddItem(const BrowsingHistoryItem& item, bool internal)
{
int32 count = CountItems();
int32 insertionIndex = count;
for (int32 i = 0; i < count; i++) {
BrowsingHistoryItem* existingItem
= reinterpret_cast<BrowsingHistoryItem*>(
fHistoryItems.ItemAtFast(i));
if (item.URL() == existingItem->URL()) {
if (!internal) {
existingItem->Invoked();
_SaveSettings();
}
return true;
}
if (item < *existingItem)
insertionIndex = i;
}
BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item);
if (!newItem || !fHistoryItems.AddItem(newItem, insertionIndex)) {
delete newItem;
return false;
}
if (!internal) {
newItem->Invoked();
_SaveSettings();
}
return true;
}
void
BrowsingHistory::_LoadSettings()
{
if (fSettingsLoaded)
return;
fSettingsLoaded = true;
BFile settingsFile;
if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) {
BMessage settingsArchive;
settingsArchive.Unflatten(&settingsFile);
if (settingsArchive.FindInt32("max history item age",
&fMaxHistoryItemAge) != B_OK) {
fMaxHistoryItemAge = 7;
}
BDateTime oldestAllowedDateTime
= BDateTime::CurrentDateTime(B_LOCAL_TIME);
oldestAllowedDateTime.Date().AddDays(-fMaxHistoryItemAge);
BMessage historyItemArchive;
for (int32 i = 0; settingsArchive.FindMessage("history item", i,
&historyItemArchive) == B_OK; i++) {
BrowsingHistoryItem item(&historyItemArchive);
if (oldestAllowedDateTime < item.DateTime())
_AddItem(item, true);
historyItemArchive.MakeEmpty();
}
}
}
void
BrowsingHistory::_SaveSettings()
{
BFile settingsFile;
if (_OpenSettingsFile(settingsFile,
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) {
BMessage settingsArchive;
settingsArchive.AddInt32("max history item age", fMaxHistoryItemAge);
BMessage historyItemArchive;
int32 count = CountItems();
for (int32 i = 0; i < count; i++) {
BrowsingHistoryItem item = HistoryItemAt(i);
if (item.Archive(&historyItemArchive) != B_OK)
break;
if (settingsArchive.AddMessage("history item",
&historyItemArchive) != B_OK) {
break;
}
historyItemArchive.MakeEmpty();
}
settingsArchive.Flatten(&settingsFile);
}
}
bool
BrowsingHistory::_OpenSettingsFile(BFile& file, uint32 mode)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|| path.Append(kApplicationName) != B_OK
|| path.Append("BrowsingHistory") != B_OK) {
return false;
}
return file.SetTo(path.Path(), mode) == B_OK;
}
+112
View File
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BROWSING_HISTORY_H
#define BROWSING_HISTORY_H
#include "DateTime.h"
#include <List.h>
#include <Locker.h>
class BFile;
class BString;
class BrowsingHistoryItem {
public:
BrowsingHistoryItem(const BString& url);
BrowsingHistoryItem(
const BrowsingHistoryItem& other);
BrowsingHistoryItem(const BMessage* archive);
~BrowsingHistoryItem();
status_t Archive(BMessage* archive) const;
BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other);
bool operator==(
const BrowsingHistoryItem& other) const;
bool operator!=(
const BrowsingHistoryItem& other) const;
bool operator<(
const BrowsingHistoryItem& other) const;
bool operator<=(
const BrowsingHistoryItem& other) const;
bool operator>(
const BrowsingHistoryItem& other) const;
bool operator>=(
const BrowsingHistoryItem& other) const;
const BString& URL() const { return fURL; }
const BDateTime& DateTime() const { return fDateTime; }
uint32 InvokationCount() const {
return fInvokationCount; }
void Invoked();
private:
BString fURL;
BDateTime fDateTime;
uint32 fInvokationCount;
};
class BrowsingHistory : public BLocker {
public:
static BrowsingHistory* DefaultInstance();
bool AddItem(const BrowsingHistoryItem& item);
// Should Lock() the object when using these in some loop or so:
int32 CountItems() const;
BrowsingHistoryItem HistoryItemAt(int32 index) const;
void Clear();
void SetMaxHistoryItemAge(int32 days);
int32 MaxHistoryItemAge() const;
private:
BrowsingHistory();
virtual ~BrowsingHistory();
void _Clear();
bool _AddItem(const BrowsingHistoryItem& item,
bool invoke);
void _LoadSettings();
void _SaveSettings();
bool _OpenSettingsFile(BFile& file, uint32 mode);
private:
BList fHistoryItems;
int32 fMaxHistoryItemAge;
static BrowsingHistory sDefaultInstance;
bool fSettingsLoaded;
};
#endif // BROWSING_HISTORY_H
+275
View File
@@ -0,0 +1,275 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "CredentialsStorage.h"
#include <new>
#include <stdio.h>
#include <Autolock.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <Message.h>
#include <Path.h>
#include "BrowserApp.h"
Credentials::Credentials()
:
fUsername(),
fPassword()
{
}
Credentials::Credentials(const BString& username, const BString& password)
:
fUsername(username),
fPassword(password)
{
}
Credentials::Credentials(const Credentials& other)
{
*this = other;
}
Credentials::Credentials(const BMessage* archive)
{
if (archive == NULL)
return;
archive->FindString("username", &fUsername);
archive->FindString("password", &fPassword);
}
Credentials::~Credentials()
{
}
status_t
Credentials::Archive(BMessage* archive) const
{
if (archive == NULL)
return B_BAD_VALUE;
status_t status = archive->AddString("username", fUsername);
if (status == B_OK)
status = archive->AddString("password", fPassword);
return status;
}
Credentials&
Credentials::operator=(const Credentials& other)
{
if (this == &other)
return *this;
fUsername = other.fUsername;
fPassword = other.fPassword;
return *this;
}
bool
Credentials::operator==(const Credentials& other) const
{
if (this == &other)
return true;
return fUsername == other.fUsername && fPassword == other.fPassword;
}
bool
Credentials::operator!=(const Credentials& other) const
{
return !(*this == other);
}
const BString&
Credentials::Username() const
{
return fUsername;
}
const BString&
Credentials::Password() const
{
return fPassword;
}
// #pragma mark - CredentialsStorage
CredentialsStorage
CredentialsStorage::sPersistentInstance(true);
CredentialsStorage
CredentialsStorage::sSessionInstance(false);
CredentialsStorage::CredentialsStorage(bool persistent)
:
BLocker(persistent ? "persistent credential storage"
: "credential storage"),
fCredentialMap(),
fSettingsLoaded(false),
fPersistent(persistent)
{
}
CredentialsStorage::~CredentialsStorage()
{
_SaveSettings();
}
/*static*/ CredentialsStorage*
CredentialsStorage::SessionInstance()
{
return &sSessionInstance;
}
/*static*/ CredentialsStorage*
CredentialsStorage::PersistentInstance()
{
if (sPersistentInstance.Lock()) {
sPersistentInstance._LoadSettings();
sPersistentInstance.Unlock();
}
return &sPersistentInstance;
}
bool
CredentialsStorage::Contains(const HashKeyString& key)
{
BAutolock _(this);
return fCredentialMap.ContainsKey(key);
}
status_t
CredentialsStorage::PutCredentials(const HashKeyString& key,
const Credentials& credentials)
{
BAutolock _(this);
return fCredentialMap.Put(key, credentials);
}
Credentials
CredentialsStorage::GetCredentials(const HashKeyString& key)
{
BAutolock _(this);
return fCredentialMap.Get(key);
}
// #pragma mark - private
void
CredentialsStorage::_LoadSettings()
{
if (!fPersistent || fSettingsLoaded)
return;
fSettingsLoaded = true;
BFile settingsFile;
if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) {
BMessage settingsArchive;
settingsArchive.Unflatten(&settingsFile);
BMessage credentialsArchive;
for (int32 i = 0; settingsArchive.FindMessage("credentials", i,
&credentialsArchive) == B_OK; i++) {
BString key;
if (credentialsArchive.FindString("key", &key) == B_OK) {
Credentials credentials(&credentialsArchive);
fCredentialMap.Put(key, credentials);
}
}
}
}
void
CredentialsStorage::_SaveSettings() const
{
BFile settingsFile;
if (_OpenSettingsFile(settingsFile,
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) {
BMessage settingsArchive;
BMessage credentialsArchive;
CredentialMap::Iterator iterator = fCredentialMap.GetIterator();
while (iterator.HasNext()) {
const CredentialMap::Entry& entry = iterator.Next();
if (entry.value.Archive(&credentialsArchive) != B_OK
|| credentialsArchive.AddString("key",
entry.key.value) != B_OK) {
break;
}
if (settingsArchive.AddMessage("credentials",
&credentialsArchive) != B_OK) {
break;
}
credentialsArchive.MakeEmpty();
}
settingsArchive.Flatten(&settingsFile);
}
}
bool
CredentialsStorage::_OpenSettingsFile(BFile& file, uint32 mode) const
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|| path.Append(kApplicationName) != B_OK
|| path.Append("CredentialsStorage") != B_OK) {
return false;
}
return file.SetTo(path.Path(), mode) == B_OK;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CREDENTIAL_STORAGE_H
#define CREDENTIAL_STORAGE_H
#include "HashKeys.h"
#include "HashMap.h"
#include <Locker.h>
#include <String.h>
class BFile;
class BMessage;
class BString;
class Credentials {
public:
Credentials();
Credentials(const BString& username,
const BString& password);
Credentials(
const Credentials& other);
Credentials(const BMessage* archive);
~Credentials();
status_t Archive(BMessage* archive) const;
Credentials& operator=(const Credentials& other);
bool operator==(const Credentials& other) const;
bool operator!=(const Credentials& other) const;
const BString& Username() const;
const BString& Password() const;
private:
BString fUsername;
BString fPassword;
};
class CredentialsStorage : public BLocker {
public:
static CredentialsStorage* SessionInstance();
static CredentialsStorage* PersistentInstance();
bool Contains(const HashKeyString& key);
status_t PutCredentials(const HashKeyString& key,
const Credentials& credentials);
Credentials GetCredentials(const HashKeyString& key);
private:
CredentialsStorage(bool persistent);
virtual ~CredentialsStorage();
void _LoadSettings();
void _SaveSettings() const;
bool _OpenSettingsFile(BFile& file,
uint32 mode) const;
private:
typedef HashMap<HashKeyString, Credentials> CredentialMap;
CredentialMap fCredentialMap;
static CredentialsStorage sPersistentInstance;
static CredentialsStorage sSessionInstance;
bool fSettingsLoaded;
bool fPersistent;
};
#endif // CREDENTIAL_STORAGE_H
@@ -0,0 +1,838 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "DownloadProgressView.h"
#include <stdio.h>
#include <Alert.h>
#include <Bitmap.h>
#include <Button.h>
#include <Clipboard.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <GroupLayoutBuilder.h>
#include <MenuItem.h>
#include <NodeInfo.h>
#include <NodeMonitor.h>
#include <PopUpMenu.h>
#include <Roster.h>
#include <SpaceLayoutItem.h>
#include <StatusBar.h>
#include <StringView.h>
#include "WebDownload.h"
#include "WebPage.h"
#include "StringForSize.h"
enum {
OPEN_DOWNLOAD = 'opdn',
RESTART_DOWNLOAD = 'rsdn',
CANCEL_DOWNLOAD = 'cndn',
REMOVE_DOWNLOAD = 'rmdn',
COPY_URL_TO_CLIPBOARD = 'curl',
OPEN_CONTAINING_FOLDER = 'opfd',
};
const bigtime_t kMaxUpdateInterval = 100000LL;
const bigtime_t kSpeedReferenceInterval = 500000LL;
const bigtime_t kShowSpeedInterval = 8000000LL;
const bigtime_t kShowEstimatedFinishInterval = 4000000LL;
bigtime_t DownloadProgressView::sLastEstimatedFinishSpeedToggleTime = -1;
bool DownloadProgressView::sShowSpeed = true;
class IconView : public BView {
public:
IconView(const BEntry& entry)
:
BView("Download icon", B_WILL_DRAW),
fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32),
fDimmedIcon(false)
{
SetDrawingMode(B_OP_OVER);
SetTo(entry);
}
IconView()
:
BView("Download icon", B_WILL_DRAW),
fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32),
fDimmedIcon(false)
{
SetDrawingMode(B_OP_OVER);
memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength());
}
IconView(BMessage* archive)
:
BView("Download icon", B_WILL_DRAW),
fIconBitmap(archive),
fDimmedIcon(true)
{
SetDrawingMode(B_OP_OVER);
}
void SetTo(const BEntry& entry)
{
BNode node(&entry);
BNodeInfo info(&node);
info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON);
Invalidate();
}
void SetIconDimmed(bool iconDimmed)
{
if (fDimmedIcon != iconDimmed) {
fDimmedIcon = iconDimmed;
Invalidate();
}
}
bool IsIconDimmed() const
{
return fDimmedIcon;
}
status_t SaveSettings(BMessage* archive)
{
return fIconBitmap.Archive(archive);
}
virtual void AttachedToWindow()
{
SetViewColor(Parent()->ViewColor());
}
virtual void Draw(BRect updateRect)
{
if (fDimmedIcon) {
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
SetHighColor(0, 0, 0, 100);
}
DrawBitmapAsync(&fIconBitmap);
}
virtual BSize MinSize()
{
return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height());
}
virtual BSize PreferredSize()
{
return MinSize();
}
virtual BSize MaxSize()
{
return MinSize();
}
private:
BBitmap fIconBitmap;
bool fDimmedIcon;
};
class SmallButton : public BButton {
public:
SmallButton(const char* label, BMessage* message = NULL)
:
BButton(label, message)
{
BFont font;
GetFont(&font);
float size = ceilf(font.Size() * 0.8);
font.SetSize(max_c(8, size));
SetFont(&font, B_FONT_SIZE);
}
};
// #pragma mark - DownloadProgressView
DownloadProgressView::DownloadProgressView(BWebDownload* download)
:
BGroupView(B_HORIZONTAL, 8),
fDownload(download),
fURL(download->URL()),
fPath(download->Path())
{
}
DownloadProgressView::DownloadProgressView(const BMessage* archive)
:
BGroupView(B_HORIZONTAL, 8),
fDownload(NULL),
fURL(),
fPath()
{
const char* string;
if (archive->FindString("path", &string) == B_OK)
fPath.SetTo(string);
if (archive->FindString("url", &string) == B_OK)
fURL = string;
}
bool
DownloadProgressView::Init(BMessage* archive)
{
fCurrentSize = 0;
fExpectedSize = 0;
fLastUpdateTime = 0;
fBytesPerSecond = 0.0;
for (size_t i = 0; i < kBytesPerSecondSlots; i++)
fBytesPerSecondSlot[i] = 0.0;
fCurrentBytesPerSecondSlot = 0;
fLastSpeedReferenceSize = 0;
fEstimatedFinishReferenceSize = 0;
fProcessStartTime = fLastSpeedReferenceTime = fEstimatedFinishReferenceTime
= system_time();
SetViewColor(245, 245, 245);
SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW);
if (archive) {
fStatusBar = new BStatusBar("download progress", fPath.Leaf());
float value;
if (archive->FindFloat("value", &value) == B_OK)
fStatusBar->SetTo(value);
} else
fStatusBar = new BStatusBar("download progress", "Download");
fStatusBar->SetMaxValue(100);
fStatusBar->SetBarHeight(12);
// fPath is only valid when constructed from archive (fDownload == NULL)
BEntry entry(fPath.Path());
if (archive) {
if (!entry.Exists())
fIconView = new IconView(archive);
else
fIconView = new IconView(entry);
} else
fIconView = new IconView();
if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists()))
fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD));
else {
fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD));
fTopButton->SetEnabled(fDownload == NULL);
}
if (fDownload)
fBottomButton = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD));
else {
fBottomButton = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD));
fBottomButton->SetEnabled(fDownload == NULL);
}
fInfoView = new BStringView("info view", "");
BGroupLayout* layout = GroupLayout();
layout->SetInsets(8, 5, 5, 6);
layout->AddView(fIconView);
BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
.Add(fStatusBar)
.Add(fInfoView)
.TopView()
;
verticalGroup->SetViewColor(ViewColor());
layout->AddView(verticalGroup);
verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
.Add(fTopButton)
.Add(fBottomButton)
.TopView()
;
verticalGroup->SetViewColor(ViewColor());
layout->AddView(verticalGroup);
BFont font;
fInfoView->GetFont(&font);
float fontSize = font.Size() * 0.8f;
font.SetSize(max_c(8.0f, fontSize));
fInfoView->SetFont(&font, B_FONT_SIZE);
fInfoView->SetHighColor(tint_color(fInfoView->LowColor(),
B_DARKEN_4_TINT));
fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
return true;
}
status_t
DownloadProgressView::SaveSettings(BMessage* archive)
{
if (!archive)
return B_BAD_VALUE;
status_t ret = archive->AddString("path", fPath.Path());
if (ret == B_OK)
ret = archive->AddString("url", fURL.String());
if (ret == B_OK)
ret = archive->AddFloat("value", fStatusBar->CurrentValue());
if (ret == B_OK)
ret = fIconView->SaveSettings(archive);
return ret;
}
void
DownloadProgressView::AttachedToWindow()
{
if (fDownload) {
fDownload->SetProgressListener(BMessenger(this));
// Will start node monitor upon receiving the B_DOWNLOAD_STARTED
// message.
} else {
BEntry entry(fPath.Path());
if (entry.Exists())
_StartNodeMonitor(entry);
}
fTopButton->SetTarget(this);
fBottomButton->SetTarget(this);
}
void
DownloadProgressView::DetachedFromWindow()
{
_StopNodeMonitor();
}
void
DownloadProgressView::AllAttached()
{
SetViewColor(B_TRANSPARENT_COLOR);
SetLowColor(245, 245, 245);
SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT));
}
void
DownloadProgressView::Draw(BRect updateRect)
{
BRect bounds(Bounds());
bounds.bottom--;
FillRect(bounds, B_SOLID_LOW);
bounds.bottom++;
StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
}
void
DownloadProgressView::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_DOWNLOAD_STARTED:
{
BString path;
if (message->FindString("path", &path) != B_OK)
break;
fPath.SetTo(path);
BEntry entry(fPath.Path());
fIconView->SetTo(entry);
fStatusBar->Reset(fPath.Leaf());
_StartNodeMonitor(entry);
// Immediately switch to speed display whenever a new download
// starts.
sShowSpeed = true;
sLastEstimatedFinishSpeedToggleTime
= fProcessStartTime = fLastSpeedReferenceTime
= fEstimatedFinishReferenceTime = system_time();
break;
}
case B_DOWNLOAD_PROGRESS:
{
int64 currentSize;
int64 expectedSize;
if (message->FindInt64("current size", &currentSize) == B_OK
&& message->FindInt64("expected size", &expectedSize) == B_OK) {
_UpdateStatus(currentSize, expectedSize);
}
break;
}
case B_DOWNLOAD_REMOVED:
// TODO: This is a bit asymetric. The removed notification
// arrives here, but it would be nicer if it arrived
// at the window...
Window()->PostMessage(message);
break;
case OPEN_DOWNLOAD:
{
// TODO: In case of executable files, ask the user first!
entry_ref ref;
status_t status = get_ref_for_path(fPath.Path(), &ref);
if (status == B_OK)
status = be_roster->Launch(&ref);
if (status != B_OK && status != B_ALREADY_RUNNING) {
BAlert* alert = new BAlert("Open download error",
"The download could not be opened.", "OK");
alert->Go(NULL);
}
break;
}
case RESTART_DOWNLOAD:
BWebPage::RequestDownload(fURL);
break;
case CANCEL_DOWNLOAD:
fDownload->Cancel();
DownloadCanceled();
break;
case REMOVE_DOWNLOAD:
{
Window()->PostMessage(SAVE_SETTINGS);
RemoveSelf();
delete this;
// TOAST!
return;
}
case B_NODE_MONITOR:
{
int32 opCode;
if (message->FindInt32("opcode", &opCode) != B_OK)
break;
switch (opCode) {
case B_ENTRY_REMOVED:
fIconView->SetIconDimmed(true);
DownloadCanceled();
break;
case B_ENTRY_MOVED:
{
// Follow the entry to the new location
dev_t device;
ino_t directory;
const char* name;
if (message->FindInt32("device",
reinterpret_cast<int32*>(&device)) != B_OK
|| message->FindInt64("to directory",
reinterpret_cast<int64*>(&directory)) != B_OK
|| message->FindString("name", &name) != B_OK
|| strlen(name) == 0) {
break;
}
// Construct the BEntry and update fPath
entry_ref ref(device, directory, name);
BEntry entry(&ref);
if (entry.GetPath(&fPath) != B_OK)
break;
// Find out if the directory is the Trash for this
// volume
char trashPath[B_PATH_NAME_LENGTH];
if (find_directory(B_TRASH_DIRECTORY, device, false,
trashPath, B_PATH_NAME_LENGTH) == B_OK) {
BPath trashDirectory(trashPath);
BPath parentDirectory;
fPath.GetParent(&parentDirectory);
if (parentDirectory == trashDirectory) {
// The entry was moved into the Trash.
// If the download is still in progress,
// cancel it.
if (fDownload)
fDownload->Cancel();
fIconView->SetIconDimmed(true);
DownloadCanceled();
break;
} else if (fIconView->IsIconDimmed()) {
// Maybe it was moved out of the trash.
fIconView->SetIconDimmed(false);
}
}
// Inform download of the new path
if (fDownload)
fDownload->HasMovedTo(fPath);
float value = fStatusBar->CurrentValue();
fStatusBar->Reset(name);
fStatusBar->SetTo(value);
Window()->PostMessage(SAVE_SETTINGS);
break;
}
case B_ATTR_CHANGED:
{
BEntry entry(fPath.Path());
fIconView->SetIconDimmed(false);
fIconView->SetTo(entry);
break;
}
}
break;
}
// Context menu messages
case COPY_URL_TO_CLIPBOARD:
if (be_clipboard->Lock()) {
BMessage* data = be_clipboard->Data();
if (data != NULL) {
be_clipboard->Clear();
data->AddData("text/plain", B_MIME_TYPE, fURL.String(),
fURL.Length());
}
be_clipboard->Commit();
be_clipboard->Unlock();
}
break;
case OPEN_CONTAINING_FOLDER:
if (fPath.InitCheck() == B_OK) {
BPath containingFolder;
if (fPath.GetParent(&containingFolder) != B_OK)
break;
BEntry entry(containingFolder.Path());
if (!entry.Exists())
break;
entry_ref ref;
if (entry.GetRef(&ref) != B_OK)
break;
be_roster->Launch(&ref);
// Use Tracker scripting and select the download pose
// in the window.
// TODO: We should somehow get the window that just openend.
// Using the name like this is broken when there are multiple
// windows open with this name. Also Tracker does not scroll
// to this entry.
BString windowName = ref.name;
BString fullWindowName = containingFolder.Path();
BMessenger trackerMessenger("application/x-vnd.Be-TRAK");
if (trackerMessenger.IsValid()
&& get_ref_for_path(fPath.Path(), &ref) == B_OK) {
// We need to wait a bit until the folder is open.
// TODO: This is also too fragile... we should be able
// to wait for the roster message.
snooze(250000);
int32 tries = 2;
while (tries > 0) {
BMessage selectionCommand(B_SET_PROPERTY);
selectionCommand.AddSpecifier("Selection");
selectionCommand.AddSpecifier("Poses");
selectionCommand.AddSpecifier("Window",
windowName.String());
selectionCommand.AddRef("data", &ref);
BMessage reply;
trackerMessenger.SendMessage(&selectionCommand, &reply);
int32 error;
if (reply.FindInt32("error", &error) != B_OK
|| error == B_OK) {
break;
}
windowName = fullWindowName;
tries--;
}
}
}
break;
default:
BGroupView::MessageReceived(message);
}
}
void
DownloadProgressView::ShowContextMenu(BPoint screenWhere)
{
screenWhere += BPoint(2, 2);
BPopUpMenu* contextMenu = new BPopUpMenu("download context");
BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard",
new BMessage(COPY_URL_TO_CLIPBOARD));
copyURL->SetEnabled(fURL.Length() > 0);
contextMenu->AddItem(copyURL);
BMenuItem* openFolder = new BMenuItem("Open containing folder",
new BMessage(OPEN_CONTAINING_FOLDER));
contextMenu->AddItem(openFolder);
contextMenu->SetTargetForItems(this);
contextMenu->Go(screenWhere, true, true, true);
}
BWebDownload*
DownloadProgressView::Download() const
{
return fDownload;
}
const BString&
DownloadProgressView::URL() const
{
return fURL;
}
bool
DownloadProgressView::IsMissing() const
{
return fIconView->IsIconDimmed();
}
bool
DownloadProgressView::IsFinished() const
{
return !fDownload && fStatusBar->CurrentValue() == 100;
}
void
DownloadProgressView::DownloadFinished()
{
fDownload = NULL;
if (fExpectedSize == -1) {
fStatusBar->SetTo(100.0);
fExpectedSize = fCurrentSize;
}
fTopButton->SetEnabled(true);
fBottomButton->SetLabel("Remove");
fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD));
fBottomButton->SetEnabled(true);
fInfoView->SetText("");
}
void
DownloadProgressView::DownloadCanceled()
{
fDownload = NULL;
fTopButton->SetLabel("Restart");
fTopButton->SetMessage(new BMessage(RESTART_DOWNLOAD));
fTopButton->SetEnabled(true);
fBottomButton->SetLabel("Remove");
fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD));
fBottomButton->SetEnabled(true);
fInfoView->SetText("");
fPath.Unset();
}
/*static*/ void
DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse()
{
bigtime_t now = system_time();
if (sShowSpeed
&& sLastEstimatedFinishSpeedToggleTime + kShowSpeedInterval
<= now) {
sShowSpeed = false;
sLastEstimatedFinishSpeedToggleTime = now;
} else if (!sShowSpeed
&& sLastEstimatedFinishSpeedToggleTime
+ kShowEstimatedFinishInterval <= now) {
sShowSpeed = true;
sLastEstimatedFinishSpeedToggleTime = now;
}
}
// #pragma mark - private
void
DownloadProgressView::_UpdateStatus(off_t currentSize, off_t expectedSize)
{
fCurrentSize = currentSize;
fExpectedSize = expectedSize;
fStatusBar->SetTo(100.0 * currentSize / expectedSize);
bigtime_t currentTime = system_time();
if ((currentTime - fLastUpdateTime) > kMaxUpdateInterval) {
fLastUpdateTime = currentTime;
if (currentTime >= fLastSpeedReferenceTime + kSpeedReferenceInterval) {
// update current speed every kSpeedReferenceInterval
fCurrentBytesPerSecondSlot
= (fCurrentBytesPerSecondSlot + 1) % kBytesPerSecondSlots;
fBytesPerSecondSlot[fCurrentBytesPerSecondSlot]
= (double)(currentSize - fLastSpeedReferenceSize)
* 1000000LL / (currentTime - fLastSpeedReferenceTime);
fLastSpeedReferenceSize = currentSize;
fLastSpeedReferenceTime = currentTime;
fBytesPerSecond = 0.0;
size_t count = 0;
for (size_t i = 0; i < kBytesPerSecondSlots; i++) {
if (fBytesPerSecondSlot[i] != 0.0) {
fBytesPerSecond += fBytesPerSecondSlot[i];
count++;
}
}
if (count > 0)
fBytesPerSecond /= count;
}
_UpdateStatusText();
}
}
void
DownloadProgressView::_UpdateStatusText()
{
fInfoView->SetText("");
BString buffer;
if (sShowSpeed && fBytesPerSecond != 0.0) {
// Draw speed info
char sizeBuffer[128];
buffer = "(";
// Get strings for current and expected size and remove the unit
// from the current size string if it's the same as the expected
// size unit.
BString currentSize = string_for_size((double)fCurrentSize, sizeBuffer,
sizeof(sizeBuffer));
BString expectedSize = string_for_size((double)fExpectedSize, sizeBuffer,
sizeof(sizeBuffer));
int currentSizeUnitPos = currentSize.FindLast(' ');
int expectedSizeUnitPos = expectedSize.FindLast(' ');
if (currentSizeUnitPos >= 0 && expectedSizeUnitPos >= 0
&& strcmp(currentSize.String() + currentSizeUnitPos,
expectedSize.String() + expectedSizeUnitPos) == 0) {
currentSize.Truncate(currentSizeUnitPos);
}
buffer << currentSize;
buffer << " of ";
buffer << expectedSize;
buffer << ", ";
buffer << string_for_size(fBytesPerSecond, sizeBuffer,
sizeof(sizeBuffer));
buffer << "/s)";
float stringWidth = fInfoView->StringWidth(buffer.String());
if (stringWidth < fInfoView->Bounds().Width())
fInfoView->SetText(buffer.String());
else {
// complete string too wide, try with shorter version
buffer << string_for_size(fBytesPerSecond, sizeBuffer,
sizeof(sizeBuffer));
buffer << "/s";
stringWidth = fInfoView->StringWidth(buffer.String());
if (stringWidth < fInfoView->Bounds().Width())
fInfoView->SetText(buffer.String());
}
} else if (!sShowSpeed && fCurrentSize < fExpectedSize) {
double totalBytesPerSecond = (double)(fCurrentSize
- fEstimatedFinishReferenceSize)
* 1000000LL / (system_time() - fEstimatedFinishReferenceTime);
double secondsRemaining = (fExpectedSize - fCurrentSize)
/ totalBytesPerSecond;
time_t now = (time_t)real_time_clock();
time_t finishTime = (time_t)(now + secondsRemaining);
tm _time;
tm* time = localtime_r(&finishTime, &_time);
int32 year = time->tm_year + 1900;
char timeText[32];
time_t secondsPerDay = 24 * 60 * 60;
// TODO: Localization of time string...
if (now < finishTime - secondsPerDay) {
// process is going to take more than a day!
sprintf(timeText, "%0*d:%0*d %0*d/%0*d/%ld",
2, time->tm_hour, 2, time->tm_min,
2, time->tm_mon + 1, 2, time->tm_mday, year);
} else {
sprintf(timeText, "%0*d:%0*d",
2, time->tm_hour, 2, time->tm_min);
}
BString buffer1("Finish: ");
buffer1 << timeText;
finishTime -= now;
time = gmtime(&finishTime);
BString buffer2;
if (finishTime > secondsPerDay) {
int64 days = finishTime / secondsPerDay;
if (days == 1)
buffer2 << "Over 1 day";
else
buffer2 << "Over " << days << " days";
} else if (finishTime > 60 * 60) {
int64 hours = finishTime / (60 * 60);
if (hours == 1)
buffer2 << "Over 1 hour";
else
buffer2 << "Over " << hours << " hours";
} else if (finishTime > 60) {
int64 minutes = finishTime / 60;
if (minutes == 1)
buffer2 << "Over 1 minute";
else
buffer2 << minutes << " minutes";
} else {
if (finishTime == 1)
buffer2 << "1 second";
else
buffer2 << finishTime << " seconds";
}
buffer2 << " left";
buffer = "(";
buffer << buffer1 << " - " << buffer2 << ")";
float stringWidth = fInfoView->StringWidth(buffer.String());
if (stringWidth < fInfoView->Bounds().Width())
fInfoView->SetText(buffer.String());
else {
// complete string too wide, try with shorter version
buffer = "(";
buffer << buffer1 << ")";
stringWidth = fInfoView->StringWidth(buffer.String());
if (stringWidth < fInfoView->Bounds().Width())
fInfoView->SetText(buffer.String());
}
}
}
void
DownloadProgressView::_StartNodeMonitor(const BEntry& entry)
{
node_ref nref;
if (entry.GetNodeRef(&nref) == B_OK)
watch_node(&nref, B_WATCH_ALL, this);
}
void
DownloadProgressView::_StopNodeMonitor()
{
stop_watching(this);
}
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DOWNLOAD_PROGRESS_VIEW_H
#define DOWNLOAD_PROGRESS_VIEW_H
#include <GroupView.h>
#include <Path.h>
#include <String.h>
class BEntry;
class BStatusBar;
class BStringView;
class BWebDownload;
class IconView;
class SmallButton;
enum {
SAVE_SETTINGS = 'svst'
};
class DownloadProgressView : public BGroupView {
public:
DownloadProgressView(BWebDownload* download);
DownloadProgressView(const BMessage* archive);
bool Init(BMessage* archive = NULL);
status_t SaveSettings(BMessage* archive);
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void AllAttached();
virtual void Draw(BRect updateRect);
virtual void MessageReceived(BMessage* message);
void ShowContextMenu(BPoint screenWhere);
BWebDownload* Download() const;
const BString& URL() const;
bool IsMissing() const;
bool IsFinished() const;
void DownloadFinished();
void DownloadCanceled();
static void SpeedVersusEstimatedFinishTogglePulse();
private:
void _UpdateStatus(off_t currentSize,
off_t expectedSize);
void _UpdateStatusText();
void _StartNodeMonitor(const BEntry& entry);
void _StopNodeMonitor();
private:
IconView* fIconView;
BStatusBar* fStatusBar;
BStringView* fInfoView;
SmallButton* fTopButton;
SmallButton* fBottomButton;
BWebDownload* fDownload;
BString fURL;
BPath fPath;
off_t fCurrentSize;
off_t fExpectedSize;
off_t fLastSpeedReferenceSize;
off_t fEstimatedFinishReferenceSize;
bigtime_t fLastUpdateTime;
bigtime_t fLastSpeedReferenceTime;
bigtime_t fProcessStartTime;
bigtime_t fLastSpeedUpdateTime;
bigtime_t fEstimatedFinishReferenceTime;
static const size_t kBytesPerSecondSlots = 10;
size_t fCurrentBytesPerSecondSlot;
double fBytesPerSecondSlot[kBytesPerSecondSlots];
double fBytesPerSecond;
static bigtime_t sLastEstimatedFinishSpeedToggleTime;
static bool sShowSpeed;
};
#endif // DOWNLOAD_PROGRESS_VIEW_H
+573
View File
@@ -0,0 +1,573 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "DownloadWindow.h"
#include <stdio.h>
#include <Alert.h>
#include <Button.h>
#include <ControlLook.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <Path.h>
#include <Roster.h>
#include <ScrollView.h>
#include <SeparatorView.h>
#include <SpaceLayoutItem.h>
#include "BrowserApp.h"
#include "BrowserWindow.h"
#include "DownloadProgressView.h"
#include "SettingsKeys.h"
#include "SettingsMessage.h"
#include "WebDownload.h"
#include "WebPage.h"
enum {
INIT = 'init',
OPEN_DOWNLOADS_FOLDER = 'odnf',
REMOVE_FINISHED_DOWNLOADS = 'rmfd',
REMOVE_MISSING_DOWNLOADS = 'rmmd'
};
class DownloadsContainerView : public BGroupView {
public:
DownloadsContainerView()
:
BGroupView(B_VERTICAL, 0.0)
{
SetFlags(Flags() | B_PULSE_NEEDED);
SetViewColor(245, 245, 245);
AddChild(BSpaceLayoutItem::CreateGlue());
}
virtual BSize MinSize()
{
BSize minSize = BGroupView::MinSize();
return BSize(minSize.width, 80);
}
virtual void Pulse()
{
DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse();
}
protected:
virtual void DoLayout()
{
BGroupView::DoLayout();
if (BScrollBar* scrollBar = ScrollBar(B_VERTICAL)) {
BSize minSize = BGroupView::MinSize();
float height = Bounds().Height();
float max = minSize.height - height;
scrollBar->SetRange(0, max);
if (minSize.height > 0)
scrollBar->SetProportion(height / minSize.height);
else
scrollBar->SetProportion(1);
}
}
};
class DownloadContainerScrollView : public BScrollView {
public:
DownloadContainerScrollView(BView* target)
:
BScrollView("Downloads scroll view", target, 0, false, true,
B_NO_BORDER)
{
}
protected:
virtual void DoLayout()
{
BScrollView::DoLayout();
// Tweak scroll bar layout to hide part of the frame for better looks.
BScrollBar* scrollBar = ScrollBar(B_VERTICAL);
scrollBar->MoveBy(1, -1);
scrollBar->ResizeBy(0, 2);
Target()->ResizeBy(1, 0);
// Set the scroll steps
if (BView* item = Target()->ChildAt(0)) {
scrollBar->SetSteps(item->MinSize().height + 1,
item->MinSize().height + 1);
}
}
};
// #pragma mark -
DownloadWindow::DownloadWindow(BRect frame, bool visible,
SettingsMessage* settings)
: BWindow(frame, "Downloads",
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
fMinimizeOnClose(false)
{
SetPulseRate(1000000);
settings->AddListener(BMessenger(this));
BPath downloadPath;
if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK)
downloadPath.SetTo("/boot/home/Desktop");
fDownloadPath = settings->GetValue(kSettingsKeyDownloadPath,
downloadPath.Path());
settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath);
SetLayout(new BGroupLayout(B_VERTICAL, 0.0));
DownloadsContainerView* downloadsGroupView = new DownloadsContainerView();
fDownloadViewsLayout = downloadsGroupView->GroupLayout();
BMenuBar* menuBar = new BMenuBar("Menu bar");
BMenu* menu = new BMenu("Downloads");
menu->AddItem(new BMenuItem("Open downloads folder",
new BMessage(OPEN_DOWNLOADS_FOLDER)));
BMessage* newWindowMessage = new BMessage(NEW_WINDOW);
newWindowMessage->AddString("url", "");
BMenuItem* newWindowItem = new BMenuItem("New browser window",
newWindowMessage, 'N');
menu->AddItem(newWindowItem);
newWindowItem->SetTarget(be_app);
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'D'));
menuBar->AddItem(menu);
fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView);
fRemoveFinishedButton = new BButton("Remove finished",
new BMessage(REMOVE_FINISHED_DOWNLOADS));
fRemoveFinishedButton->SetEnabled(false);
fRemoveMissingButton = new BButton("Remove missing",
new BMessage(REMOVE_MISSING_DOWNLOADS));
fRemoveMissingButton->SetEnabled(false);
const float spacing = be_control_look->DefaultItemSpacing();
AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
.Add(menuBar)
.Add(fDownloadsScrollView)
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
.AddGlue()
.Add(fRemoveMissingButton)
.Add(fRemoveFinishedButton)
.SetInsets(12, 5, 12, 5)
)
);
PostMessage(INIT);
if (!visible)
Hide();
Show();
}
DownloadWindow::~DownloadWindow()
{
// Only necessary to save the current progress of unfinished downloads:
_SaveSettings();
}
void
DownloadWindow::DispatchMessage(BMessage* message, BHandler* target)
{
// We need to intercept mouse down events inside the area of download
// progress views (regardless of whether they have children at the click),
// so that they may display a context menu.
BPoint where;
int32 buttons;
if (message->what == B_MOUSE_DOWN
&& message->FindPoint("screen_where", &where) == B_OK
&& message->FindInt32("buttons", &buttons) == B_OK
&& (buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
BPoint viewWhere(where);
view->ConvertFromScreen(&viewWhere);
if (view->Bounds().Contains(viewWhere)) {
view->ShowContextMenu(where);
return;
}
}
}
BWindow::DispatchMessage(message, target);
}
void
DownloadWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case INIT:
{
_LoadSettings();
// Small trick to get the correct enabled status of the Remove
// finished button
_DownloadFinished(NULL);
break;
}
case B_DOWNLOAD_ADDED:
{
BWebDownload* download;
if (message->FindPointer("download", reinterpret_cast<void**>(
&download)) == B_OK) {
_DownloadStarted(download);
}
break;
}
case B_DOWNLOAD_REMOVED:
{
BWebDownload* download;
if (message->FindPointer("download", reinterpret_cast<void**>(
&download)) == B_OK) {
_DownloadFinished(download);
}
break;
}
case OPEN_DOWNLOADS_FOLDER:
{
entry_ref ref;
status_t status = get_ref_for_path(fDownloadPath.String(), &ref);
if (status == B_OK)
status = be_roster->Launch(&ref);
if (status != B_OK && status != B_ALREADY_RUNNING) {
BString errorString("The downloads folder could not be "
"opened.\n\n");
errorString << "Error: " << strerror(status);
BAlert* alert = new BAlert("Error opening downloads folder",
errorString.String(), "OK");
alert->Go(NULL);
}
break;
}
case REMOVE_FINISHED_DOWNLOADS:
_RemoveFinishedDownloads();
break;
case REMOVE_MISSING_DOWNLOADS:
_RemoveMissingDownloads();
break;
case SAVE_SETTINGS:
_ValidateButtonStatus();
_SaveSettings();
break;
case SETTINGS_VALUE_CHANGED:
{
BString string;
if (message->FindString("name", &string) == B_OK
&& string == kSettingsKeyDownloadPath
&& message->FindString("value", &string) == B_OK) {
fDownloadPath = string;
}
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
bool
DownloadWindow::QuitRequested()
{
if (fMinimizeOnClose) {
if (!IsMinimized())
Minimize(true);
} else {
if (!IsHidden())
Hide();
}
return false;
}
bool
DownloadWindow::DownloadsInProgress()
{
bool downloadsInProgress = false;
if (!Lock())
return downloadsInProgress;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (view->Download() != NULL) {
downloadsInProgress = true;
break;
}
}
Unlock();
return downloadsInProgress;
}
void
DownloadWindow::SetMinimizeOnClose(bool minimize)
{
if (Lock()) {
fMinimizeOnClose = minimize;
Unlock();
}
}
// #pragma mark - private
void
DownloadWindow::_DownloadStarted(BWebDownload* download)
{
download->Start(BPath(fDownloadPath.String()));
int32 finishedCount = 0;
int32 missingCount = 0;
int32 index = 0;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (view->URL() == download->URL()) {
index = i;
view->RemoveSelf();
delete view;
continue;
}
if (view->IsFinished())
finishedCount++;
if (view->IsMissing())
missingCount++;
}
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
fRemoveMissingButton->SetEnabled(missingCount > 0);
DownloadProgressView* view = new DownloadProgressView(download);
if (!view->Init()) {
delete view;
return;
}
fDownloadViewsLayout->AddView(index, view);
// Scroll new download into view
if (BScrollBar* scrollBar = fDownloadsScrollView->ScrollBar(B_VERTICAL)) {
float min;
float max;
scrollBar->GetRange(&min, &max);
float viewHeight = view->MinSize().height + 1;
float scrollOffset = min + index * viewHeight;
float scrollBarHeight = scrollBar->Bounds().Height() - 1;
float value = scrollBar->Value();
if (scrollOffset < value)
scrollBar->SetValue(scrollOffset);
else if (scrollOffset + viewHeight > value + scrollBarHeight) {
float diff = scrollOffset + viewHeight - (value + scrollBarHeight);
scrollBar->SetValue(value + diff);
}
}
_SaveSettings();
SetWorkspaces(B_CURRENT_WORKSPACE);
if (IsHidden())
Show();
}
void
DownloadWindow::_DownloadFinished(BWebDownload* download)
{
int32 finishedCount = 0;
int32 missingCount = 0;
for (int32 i = 0;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i++) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (download && view->Download() == download) {
view->DownloadFinished();
finishedCount++;
continue;
}
if (view->IsFinished())
finishedCount++;
if (view->IsMissing())
missingCount++;
}
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
fRemoveMissingButton->SetEnabled(missingCount > 0);
if (download)
_SaveSettings();
}
void
DownloadWindow::_RemoveFinishedDownloads()
{
int32 missingCount = 0;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (view->IsFinished()) {
view->RemoveSelf();
delete view;
} else if (view->IsMissing())
missingCount++;
}
fRemoveFinishedButton->SetEnabled(false);
fRemoveMissingButton->SetEnabled(missingCount > 0);
_SaveSettings();
}
void
DownloadWindow::_RemoveMissingDownloads()
{
int32 finishedCount = 0;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (view->IsMissing()) {
view->RemoveSelf();
delete view;
} else if (view->IsFinished())
finishedCount++;
}
fRemoveMissingButton->SetEnabled(false);
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
_SaveSettings();
}
void
DownloadWindow::_ValidateButtonStatus()
{
int32 finishedCount = 0;
int32 missingCount = 0;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
if (view->IsFinished())
finishedCount++;
if (view->IsMissing())
missingCount++;
}
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
fRemoveMissingButton->SetEnabled(missingCount > 0);
}
void
DownloadWindow::_SaveSettings()
{
BFile file;
if (!_OpenSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY))
return;
BMessage message;
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
item->View());
if (!view)
continue;
BMessage downloadArchive;
if (view->SaveSettings(&downloadArchive) == B_OK)
message.AddMessage("download", &downloadArchive);
}
message.Flatten(&file);
}
void
DownloadWindow::_LoadSettings()
{
BFile file;
if (!_OpenSettingsFile(file, B_READ_ONLY))
return;
BMessage message;
if (message.Unflatten(&file) != B_OK)
return;
BMessage downloadArchive;
for (int32 i = 0;
message.FindMessage("download", i, &downloadArchive) == B_OK;
i++) {
DownloadProgressView* view = new DownloadProgressView(
&downloadArchive);
if (!view->Init(&downloadArchive))
continue;
fDownloadViewsLayout->AddView(0, view);
}
}
bool
DownloadWindow::_OpenSettingsFile(BFile& file, uint32 mode)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|| path.Append(kApplicationName) != B_OK
|| path.Append("Downloads") != B_OK) {
return false;
}
return file.SetTo(path.Path(), mode) == B_OK;
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DOWNLOAD_WINDOW_H
#define DOWNLOAD_WINDOW_H
#include <String.h>
#include <Window.h>
class BButton;
class BFile;
class BGroupLayout;
class BScrollView;
class BWebDownload;
class SettingsMessage;
class DownloadWindow : public BWindow {
public:
DownloadWindow(BRect frame, bool visible,
SettingsMessage* settings);
virtual ~DownloadWindow();
virtual void DispatchMessage(BMessage* message,
BHandler* target);
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
bool DownloadsInProgress();
void SetMinimizeOnClose(bool minimize);
private:
void _DownloadStarted(BWebDownload* download);
void _DownloadFinished(BWebDownload* download);
void _RemoveFinishedDownloads();
void _RemoveMissingDownloads();
void _ValidateButtonStatus();
void _SaveSettings();
void _LoadSettings();
bool _OpenSettingsFile(BFile& file, uint32 mode);
private:
BScrollView* fDownloadsScrollView;
BGroupLayout* fDownloadViewsLayout;
BButton* fRemoveFinishedButton;
BButton* fRemoveMissingButton;
BString fDownloadPath;
bool fMinimizeOnClose;
};
#endif // DOWNLOAD_WINDOW_H
+71
View File
@@ -0,0 +1,71 @@
SubDir HAIKU_TOP src apps webpositive ;
SubDirSysHdrs $(HAIKU_WEBKIT_HEADERS) ;
SubDirC++Flags $(defines) -Wno-error=sequence-point ;
SubDirCcFlags $(defines) -Wno-error=sequence-point ;
# source directories
local sourceDirs =
autocompletion
support
tabview
;
local sourceDir ;
for sourceDir in $(sourceDirs) {
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps webpositive $(sourceDir) ] ;
}
local sources =
# autocompletion
AutoCompleter.cpp
AutoCompleterDefaultImpl.cpp
TextViewCompleter.cpp
# support
BaseURL.cpp
BitmapButton.cpp
DateTime.cpp
FontSelectionView.cpp
IconButton.cpp
SettingsMessage.cpp
StringForSize.cpp
# tabview
TabContainerView.cpp
TabManager.cpp
TabView.cpp
AuthenticationPanel.cpp
BrowserApp.cpp
BrowserWindow.cpp
BrowsingHistory.cpp
CredentialsStorage.cpp
DownloadProgressView.cpp
DownloadWindow.cpp
SettingsKeys.cpp
SettingsWindow.cpp
svn_revision.cpp
URLInputGroup.cpp
;
Includes [ FGristFiles $(sources) ] : $(HAIKU_WEBKIT_HEADERS_DEPENDENCY) ;
# Dependency needed to trigger downloading/unzipping the package before
# compiling the files.
# SVN revision
#local svnRevisionFile = [ FGristFiles svn_revision ] ;
#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ;
#CreateSVNRevisionFile $(svnRevisionFile) ;
Application WebPositive :
$(sources)
:
$(HAIKU_WEBKIT_LIBS)
$(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS)
be network tracker translation
:
WebPositive.rdef
;
+51
View File
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SettingsKeys.h"
const char* kSettingsKeyDownloadPath = "download path";
const char* kSettingsKeyShowTabsIfSinglePageOpen
= "show tabs if single page open";
const char* kSettingsKeyAutoHideInterfaceInFullscreenMode
= "auto hide interface in full screen mode";
const char* kSettingsKeyAutoHidePointer = "auto hide pointer";
const char* kSettingsKeyShowHomeButton = "show home button";
const char* kSettingsKeyNewWindowPolicy = "new window policy";
const char* kSettingsKeyNewTabPolicy = "new tab policy";
const char* kSettingsKeyStartPageURL = "start page url";
const char* kSettingsKeySearchPageURL = "search page url";
const char* kDefaultDownloadPath = "/boot/home/Desktop/";
const char* kDefaultStartPageURL
= "file:///boot/home/config/settings/WebPositive/LoaderPages/Welcome";
const char* kDefaultSearchPageURL = "http://www.google.com";
const char* kSettingsKeyUseProxy = "use http proxy";
const char* kSettingsKeyProxyAddress = "http proxy address";
const char* kSettingsKeyProxyPort = "http proxy port";
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SETTINGS_KEYS_H
#define SETTINGS_KEYS_H
#include <SupportDefs.h>
extern const char* kSettingsKeyDownloadPath;
extern const char* kSettingsKeyShowTabsIfSinglePageOpen;
extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode;
extern const char* kSettingsKeyAutoHidePointer;
extern const char* kSettingsKeyShowHomeButton;
extern const char* kSettingsKeyNewWindowPolicy;
extern const char* kSettingsKeyNewTabPolicy;
extern const char* kSettingsKeyStartPageURL;
extern const char* kSettingsKeySearchPageURL;
extern const char* kDefaultDownloadPath;
extern const char* kDefaultStartPageURL;
extern const char* kDefaultSearchPageURL;
extern const char* kSettingsKeyUseProxy;
extern const char* kSettingsKeyProxyAddress;
extern const char* kSettingsKeyProxyPort;
#endif // SETTINGS_KEYS_H
+885
View File
@@ -0,0 +1,885 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "SettingsWindow.h"
#include <Button.h>
#include <CheckBox.h>
#include <ControlLook.h>
#include <GridLayoutBuilder.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Locale.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <ScrollView.h>
#include <SeparatorView.h>
#include <SpaceLayoutItem.h>
#include <TabView.h>
#include <TextControl.h>
#include <debugger.h>
#include <stdio.h>
#include <stdlib.h>
#include "BrowserApp.h"
#include "BrowsingHistory.h"
#include "BrowserWindow.h"
#include "FontSelectionView.h"
#include "SettingsKeys.h"
#include "SettingsMessage.h"
#include "WebSettings.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Settings Window"
enum {
MSG_APPLY = 'aply',
MSG_CANCEL = 'cncl',
MSG_REVERT = 'rvrt',
MSG_START_PAGE_CHANGED = 'hpch',
MSG_SEARCH_PAGE_CHANGED = 'spch',
MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc',
MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc',
MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc',
MSG_HISTORY_MENU_DAYS_CHANGED = 'digm',
MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc',
MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED = 'ahic',
MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED = 'ahpc',
MSG_SHOW_HOME_BUTTON_CHANGED = 'shbc',
MSG_STANDARD_FONT_CHANGED = 'stfc',
MSG_SERIF_FONT_CHANGED = 'sefc',
MSG_SANS_SERIF_FONT_CHANGED = 'ssfc',
MSG_FIXED_FONT_CHANGED = 'ffch',
MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss',
MSG_FIXED_FONT_SIZE_SELECTED = 'ffss',
MSG_USE_PROXY_CHANGED = 'upsc',
MSG_PROXY_ADDRESS_CHANGED = 'psac',
MSG_PROXY_PORT_CHANGED = 'pspc',
};
static const int32 kDefaultFontSize = 14;
SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings)
:
BWindow(frame, B_TRANSLATE("Settings"), B_TITLED_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS
| B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
fSettings(settings)
{
SetLayout(new BGroupLayout(B_VERTICAL));
fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(MSG_APPLY));
fCancelButton = new BButton(B_TRANSLATE("Cancel"),
new BMessage(MSG_CANCEL));
fRevertButton = new BButton(B_TRANSLATE("Revert"),
new BMessage(MSG_REVERT));
float spacing = be_control_look->DefaultItemSpacing();
BTabView* tabView = new BTabView("settings pages", B_WIDTH_FROM_LABEL);
AddChild(BGroupLayoutBuilder(B_VERTICAL, spacing)
.Add(tabView)
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
.Add(fRevertButton)
.AddGlue()
.Add(fCancelButton)
.Add(fApplyButton)
)
.SetInsets(spacing, spacing, spacing, spacing)
);
tabView->AddTab(_CreateGeneralPage(spacing));
tabView->AddTab(_CreateFontsPage(spacing));
tabView->AddTab(_CreateProxyPage(spacing));
_SetupFontSelectionView(fStandardFontView,
new BMessage(MSG_STANDARD_FONT_CHANGED));
_SetupFontSelectionView(fSerifFontView,
new BMessage(MSG_SERIF_FONT_CHANGED));
_SetupFontSelectionView(fSansSerifFontView,
new BMessage(MSG_SANS_SERIF_FONT_CHANGED));
_SetupFontSelectionView(fFixedFontView,
new BMessage(MSG_FIXED_FONT_CHANGED));
fApplyButton->MakeDefault(true);
if (!frame.IsValid())
CenterOnScreen();
// load settings from disk
_RevertSettings();
// apply to WebKit
_ApplySettings();
// Start hidden
Hide();
Show();
}
SettingsWindow::~SettingsWindow()
{
RemoveHandler(fStandardFontView);
delete fStandardFontView;
RemoveHandler(fSerifFontView);
delete fSerifFontView;
RemoveHandler(fSansSerifFontView);
delete fSansSerifFontView;
RemoveHandler(fFixedFontView);
delete fFixedFontView;
}
void
SettingsWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_APPLY:
_ApplySettings();
break;
case MSG_CANCEL:
_RevertSettings();
PostMessage(B_QUIT_REQUESTED);
break;
case MSG_REVERT:
_RevertSettings();
break;
case MSG_STANDARD_FONT_SIZE_SELECTED:
{
int32 size = _SizesMenuValue(fStandardSizesMenu->Menu());
fStandardFontView->SetSize(size);
fSerifFontView->SetSize(size);
fSansSerifFontView->SetSize(size);
_ValidateControlsEnabledStatus();
break;
}
case MSG_FIXED_FONT_SIZE_SELECTED:
{
int32 size = _SizesMenuValue(fFixedSizesMenu->Menu());
fFixedFontView->SetSize(size);
_ValidateControlsEnabledStatus();
break;
}
case MSG_START_PAGE_CHANGED:
case MSG_SEARCH_PAGE_CHANGED:
case MSG_DOWNLOAD_FOLDER_CHANGED:
case MSG_NEW_WINDOWS_BEHAVIOR_CHANGED:
case MSG_NEW_TABS_BEHAVIOR_CHANGED:
case MSG_HISTORY_MENU_DAYS_CHANGED:
case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED:
case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED:
case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED:
case MSG_SHOW_HOME_BUTTON_CHANGED:
case MSG_STANDARD_FONT_CHANGED:
case MSG_SERIF_FONT_CHANGED:
case MSG_SANS_SERIF_FONT_CHANGED:
case MSG_FIXED_FONT_CHANGED:
case MSG_USE_PROXY_CHANGED:
case MSG_PROXY_ADDRESS_CHANGED:
case MSG_PROXY_PORT_CHANGED:
// TODO: Some settings could change live, some others not?
_ValidateControlsEnabledStatus();
break;
default:
BWindow::MessageReceived(message);
break;
}
}
bool
SettingsWindow::QuitRequested()
{
if (!IsHidden())
Hide();
return false;
}
void
SettingsWindow::Show()
{
// When showing the window, the this is always the
// point to which we can revert the settings.
_RevertSettings();
BWindow::Show();
}
// #pragma mark - private
BView*
SettingsWindow::_CreateGeneralPage(float spacing)
{
fStartPageControl = new BTextControl("start page",
B_TRANSLATE("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED));
fStartPageControl->SetModificationMessage(
new BMessage(MSG_START_PAGE_CHANGED));
fStartPageControl->SetText(
fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
fSearchPageControl = new BTextControl("search page",
B_TRANSLATE("Search page:"), "",
new BMessage(MSG_SEARCH_PAGE_CHANGED));
fSearchPageControl->SetModificationMessage(
new BMessage(MSG_SEARCH_PAGE_CHANGED));
fSearchPageControl->SetText(
fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
fDownloadFolderControl = new BTextControl("download folder",
B_TRANSLATE("Download folder:"), "",
new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
fDownloadFolderControl->SetModificationMessage(
new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
fDownloadFolderControl->SetText(
fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
fNewWindowBehaviorOpenHomeItem = new BMenuItem(
B_TRANSLATE("Open start page"),
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
fNewWindowBehaviorOpenSearchItem = new BMenuItem(
B_TRANSLATE("Open search page"),
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
fNewWindowBehaviorOpenBlankItem = new BMenuItem(
B_TRANSLATE("Open blank page"),
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
fNewTabBehaviorCloneCurrentItem = new BMenuItem(
B_TRANSLATE("Clone current page"),
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
fNewTabBehaviorOpenHomeItem = new BMenuItem(
B_TRANSLATE("Open start page"),
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
fNewTabBehaviorOpenSearchItem = new BMenuItem(
B_TRANSLATE("Open search page"),
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
fNewTabBehaviorOpenBlankItem = new BMenuItem(
B_TRANSLATE("Open blank page"),
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
fNewWindowBehaviorOpenHomeItem->SetMarked(true);
fNewTabBehaviorOpenBlankItem->SetMarked(true);
BPopUpMenu* newWindowBehaviorMenu = new BPopUpMenu("New windows");
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenHomeItem);
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem);
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem);
fNewWindowBehaviorMenu = new BMenuField("new window behavior",
B_TRANSLATE("New windows:"), newWindowBehaviorMenu);
BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs");
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem);
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenHomeItem);
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem);
newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem);
fNewTabBehaviorMenu = new BMenuField("new tab behavior",
B_TRANSLATE("New tabs:"), newTabBehaviorMenu);
fDaysInHistoryMenuControl = new BTextControl("days in history",
B_TRANSLATE("Number of days to keep links in History menu:"), "",
new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
fDaysInHistoryMenuControl->SetModificationMessage(
new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
BString maxHistoryAge;
maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
fDaysInHistoryMenuControl->SetText(maxHistoryAge.String());
for (uchar i = 0; i < '0'; i++)
fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
for (uchar i = '9' + 1; i <= 128; i++)
fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page",
B_TRANSLATE("Show tabs if only one page is open."),
new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED));
fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON);
fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface",
B_TRANSLATE("Auto-hide interface in fullscreen mode."),
new BMessage(MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED));
fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF);
fAutoHidePointer = new BCheckBox("auto-hide pointer",
B_TRANSLATE("Auto-hide mouse pointer."),
new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED));
fAutoHidePointer->SetValue(B_CONTROL_OFF);
fShowHomeButton = new BCheckBox("show home button",
B_TRANSLATE("Show Home Button"),
new BMessage(MSG_SHOW_HOME_BUTTON_CHANGED));
fShowHomeButton->SetValue(B_CONTROL_ON);
BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
.Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0)
.Add(fStartPageControl->CreateTextViewLayoutItem(), 1, 0)
.Add(fSearchPageControl->CreateLabelLayoutItem(), 0, 1)
.Add(fSearchPageControl->CreateTextViewLayoutItem(), 1, 1)
.Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 2)
.Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 2)
.Add(fNewWindowBehaviorMenu->CreateLabelLayoutItem(), 0, 3)
.Add(fNewWindowBehaviorMenu->CreateMenuBarLayoutItem(), 1, 3)
.Add(fNewTabBehaviorMenu->CreateLabelLayoutItem(), 0, 4)
.Add(fNewTabBehaviorMenu->CreateMenuBarLayoutItem(), 1, 4)
)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
.Add(fShowTabsIfOnlyOnePage)
.Add(fAutoHideInterfaceInFullscreenMode)
.Add(fAutoHidePointer)
.Add(fShowHomeButton)
.Add(fDaysInHistoryMenuControl)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
.SetInsets(spacing, spacing, spacing, spacing)
.TopView()
;
view->SetName(B_TRANSLATE("General"));
return view;
}
BView*
SettingsWindow::_CreateFontsPage(float spacing)
{
fStandardFontView = new FontSelectionView("standard",
B_TRANSLATE("Standard font:"), true, be_plain_font);
BFont defaultSerifFont = _FindDefaultSerifFont();
fSerifFontView = new FontSelectionView("serif",
B_TRANSLATE("Serif font:"), true, &defaultSerifFont);
fSansSerifFontView = new FontSelectionView("sans serif",
B_TRANSLATE("Sans serif font:"), true, be_plain_font);
fFixedFontView = new FontSelectionView("fixed",
B_TRANSLATE("Fixed font:"), true, be_fixed_font);
fStandardSizesMenu = new BMenuField("standard font size",
B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"),
B_WILL_DRAW);
_BuildSizesMenu(fStandardSizesMenu->Menu(),
MSG_STANDARD_FONT_SIZE_SELECTED);
fFixedSizesMenu = new BMenuField("fixed font size",
B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"),
B_WILL_DRAW);
_BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED);
BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2)
.Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0)
.Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0)
.Add(fStandardFontView->PreviewBox(), 0, 1, 2)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2)
.Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3)
.Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3)
.Add(fSerifFontView->PreviewBox(), 0, 4, 2)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2)
.Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6)
.Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6)
.Add(fSansSerifFontView->PreviewBox(), 0, 7, 2)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2)
.Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9)
.Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9)
.Add(fFixedFontView->PreviewBox(), 0, 10, 2)
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2)
.Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12)
.Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12)
.Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13)
.Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13)
.SetInsets(spacing, spacing, spacing, spacing)
.View()
;
view->SetName(B_TRANSLATE("Fonts"));
return view;
}
BView*
SettingsWindow::_CreateProxyPage(float spacing)
{
fUseProxyCheckBox = new BCheckBox("use proxy",
B_TRANSLATE("Use proxy server to connect to the internet."),
new BMessage(MSG_USE_PROXY_CHANGED));
fUseProxyCheckBox->SetValue(B_CONTROL_ON);
fProxyAddressControl = new BTextControl("proxy address",
B_TRANSLATE("Proxy server address:"), "",
new BMessage(MSG_PROXY_ADDRESS_CHANGED));
fProxyAddressControl->SetModificationMessage(
new BMessage(MSG_PROXY_ADDRESS_CHANGED));
fProxyAddressControl->SetText(
fSettings->GetValue(kSettingsKeyProxyAddress, ""));
fProxyPortControl = new BTextControl("proxy port",
B_TRANSLATE("Proxy server port:"), "",
new BMessage(MSG_PROXY_PORT_CHANGED));
fProxyPortControl->SetModificationMessage(
new BMessage(MSG_PROXY_PORT_CHANGED));
fProxyPortControl->SetText(
fSettings->GetValue(kSettingsKeyProxyAddress, ""));
BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
.Add(fUseProxyCheckBox)
.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
.Add(fProxyAddressControl->CreateLabelLayoutItem(), 0, 0)
.Add(fProxyAddressControl->CreateTextViewLayoutItem(), 1, 0)
.Add(fProxyPortControl->CreateLabelLayoutItem(), 0, 1)
.Add(fProxyPortControl->CreateTextViewLayoutItem(), 1, 1)
)
.Add(BSpaceLayoutItem::CreateGlue())
.SetInsets(spacing, spacing, spacing, spacing)
.TopView()
;
view->SetName(B_TRANSLATE("Proxy server"));
return view;
}
void
SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat)
{
const float kMinSize = 8.0;
const float kMaxSize = 18.0;
const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0};
for (int32 i = 0; kSizes[i]; i++) {
int32 size = kSizes[i];
if (size < kMinSize || size > kMaxSize)
continue;
char label[32];
snprintf(label, sizeof(label), "%ld", size);
BMessage* message = new BMessage(messageWhat);
message->AddInt32("size", size);
BMenuItem* item = new BMenuItem(label, message);
menu->AddItem(item);
item->SetTarget(this);
}
}
void
SettingsWindow::_SetupFontSelectionView(FontSelectionView* view,
BMessage* message)
{
AddHandler(view);
view->AttachedToLooper();
view->SetMessage(message);
view->SetTarget(this);
}
// #pragma mark -
bool
SettingsWindow::_CanApplySettings() const
{
bool canApply = false;
// General settings
canApply = canApply || (strcmp(fStartPageControl->Text(),
fSettings->GetValue(kSettingsKeyStartPageURL,
kDefaultStartPageURL)) != 0);
canApply = canApply || (strcmp(fSearchPageControl->Text(),
fSettings->GetValue(kSettingsKeySearchPageURL,
kDefaultSearchPageURL)) != 0);
canApply = canApply || (strcmp(fDownloadFolderControl->Text(),
fSettings->GetValue(kSettingsKeyDownloadPath,
kDefaultDownloadPath)) != 0);
canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON)
!= fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
canApply = canApply || (
(fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON)
!= fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
false));
canApply = canApply || (
(fAutoHidePointer->Value() == B_CONTROL_ON)
!= fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON)
!= fSettings->GetValue(kSettingsKeyShowHomeButton, true));
canApply = canApply || (_MaxHistoryAge()
!= BrowsingHistory::DefaultInstance()->MaxHistoryItemAge());
// New window policy
canApply = canApply || (_NewWindowPolicy()
!= fSettings->GetValue(kSettingsKeyNewWindowPolicy,
(uint32)OpenStartPage));
// New tab policy
canApply = canApply || (_NewTabPolicy()
!= fSettings->GetValue(kSettingsKeyNewTabPolicy,
(uint32)OpenBlankPage));
// Font settings
canApply = canApply || (fStandardFontView->Font()
!= fSettings->GetValue("standard font", *be_plain_font));
canApply = canApply || (fSerifFontView->Font()
!= fSettings->GetValue("serif font", _FindDefaultSerifFont()));
canApply = canApply || (fSansSerifFontView->Font()
!= fSettings->GetValue("sans serif font", *be_plain_font));
canApply = canApply || (fFixedFontView->Font()
!= fSettings->GetValue("fixed font", *be_fixed_font));
canApply = canApply || (_SizesMenuValue(fStandardSizesMenu->Menu())
!= fSettings->GetValue("standard font size", kDefaultFontSize));
canApply = canApply || (_SizesMenuValue(fFixedSizesMenu->Menu())
!= fSettings->GetValue("fixed font size", kDefaultFontSize));
// Proxy settings
canApply = canApply || ((fUseProxyCheckBox->Value() == B_CONTROL_ON)
!= fSettings->GetValue(kSettingsKeyUseProxy, false));
canApply = canApply || (strcmp(fProxyAddressControl->Text(),
fSettings->GetValue(kSettingsKeyProxyAddress, "")) != 0);
canApply = canApply || (_ProxyPort()
!= fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0));
return canApply;
}
void
SettingsWindow::_ApplySettings()
{
// Store general settings
int32 maxHistoryAge = _MaxHistoryAge();
BString text;
text << maxHistoryAge;
fDaysInHistoryMenuControl->SetText(text.String());
BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge);
fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text());
fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text());
fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text());
fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen,
fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON);
fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON);
fSettings->SetValue(kSettingsKeyAutoHidePointer,
fAutoHidePointer->Value() == B_CONTROL_ON);
fSettings->SetValue(kSettingsKeyShowHomeButton,
fShowHomeButton->Value() == B_CONTROL_ON);
// New page policies
fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy());
fSettings->SetValue(kSettingsKeyNewTabPolicy, _NewTabPolicy());
// Store fond settings
fSettings->SetValue("standard font", fStandardFontView->Font());
fSettings->SetValue("serif font", fSerifFontView->Font());
fSettings->SetValue("sans serif font", fSansSerifFontView->Font());
fSettings->SetValue("fixed font", fFixedFontView->Font());
int32 standardFontSize = _SizesMenuValue(fStandardSizesMenu->Menu());
int32 fixedFontSize = _SizesMenuValue(fFixedSizesMenu->Menu());
fSettings->SetValue("standard font size", standardFontSize);
fSettings->SetValue("fixed font size", fixedFontSize);
// Store proxy settings
fSettings->SetValue(kSettingsKeyUseProxy,
fUseProxyCheckBox->Value() == B_CONTROL_ON);
fSettings->SetValue(kSettingsKeyProxyAddress,
fProxyAddressControl->Text());
uint32 proxyPort = _ProxyPort();
fSettings->SetValue(kSettingsKeyProxyPort, proxyPort);
fSettings->Save();
// Apply settings to default web page settings.
BWebSettings::Default()->SetStandardFont(fStandardFontView->Font());
BWebSettings::Default()->SetSerifFont(fSerifFontView->Font());
BWebSettings::Default()->SetSansSerifFont(fSansSerifFontView->Font());
BWebSettings::Default()->SetFixedFont(fFixedFontView->Font());
BWebSettings::Default()->SetDefaultStandardFontSize(standardFontSize);
BWebSettings::Default()->SetDefaultFixedFontSize(fixedFontSize);
if (fUseProxyCheckBox->Value() == B_CONTROL_ON) {
BWebSettings::Default()->SetProxyInfo(fProxyAddressControl->Text(),
proxyPort, B_PROXY_TYPE_HTTP, "", "");
} else
BWebSettings::Default()->SetProxyInfo();
// This will find all currently instantiated page settings and apply
// the default values, unless the page settings have local overrides.
BWebSettings::Default()->Apply();
_ValidateControlsEnabledStatus();
}
void
SettingsWindow::_RevertSettings()
{
fStartPageControl->SetText(
fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
fSearchPageControl->SetText(
fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
fDownloadFolderControl->SetText(
fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
fShowTabsIfOnlyOnePage->SetValue(
fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
fAutoHideInterfaceInFullscreenMode->SetValue(
fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
false));
fAutoHidePointer->SetValue(
fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
fShowHomeButton->SetValue(
fSettings->GetValue(kSettingsKeyShowHomeButton, true));
BString text;
text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
fDaysInHistoryMenuControl->SetText(text.String());
// New window policy
uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy,
(uint32)OpenStartPage);
switch (newWindowPolicy) {
default:
case OpenStartPage:
fNewWindowBehaviorOpenHomeItem->SetMarked(true);
break;
case OpenSearchPage:
fNewWindowBehaviorOpenSearchItem->SetMarked(true);
break;
case OpenBlankPage:
fNewWindowBehaviorOpenBlankItem->SetMarked(true);
break;
}
// New tab policy
uint32 newTabPolicy = fSettings->GetValue(kSettingsKeyNewTabPolicy,
(uint32)OpenBlankPage);
switch (newTabPolicy) {
default:
case OpenBlankPage:
fNewTabBehaviorOpenBlankItem->SetMarked(true);
break;
case OpenStartPage:
fNewTabBehaviorOpenHomeItem->SetMarked(true);
break;
case OpenSearchPage:
fNewTabBehaviorOpenSearchItem->SetMarked(true);
break;
case CloneCurrentPage:
fNewTabBehaviorCloneCurrentItem->SetMarked(true);
break;
}
// Font settings
int32 defaultFontSize = fSettings->GetValue("standard font size",
kDefaultFontSize);
int32 defaultFixedFontSize = fSettings->GetValue("fixed font size",
kDefaultFontSize);
_SetSizesMenuValue(fStandardSizesMenu->Menu(), defaultFontSize);
_SetSizesMenuValue(fFixedSizesMenu->Menu(), defaultFixedFontSize);
fStandardFontView->SetFont(fSettings->GetValue("standard font",
*be_plain_font), defaultFontSize);
fSerifFontView->SetFont(fSettings->GetValue("serif font",
_FindDefaultSerifFont()), defaultFontSize);
fSansSerifFontView->SetFont(fSettings->GetValue("sans serif font",
*be_plain_font), defaultFontSize);
fFixedFontView->SetFont(fSettings->GetValue("fixed font",
*be_fixed_font), defaultFixedFontSize);
// Proxy settings
fUseProxyCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxy,
false));
fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress,
""));
text = "";
text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0);
fProxyPortControl->SetText(text.String());
_ValidateControlsEnabledStatus();
}
void
SettingsWindow::_ValidateControlsEnabledStatus()
{
bool canApply = _CanApplySettings();
fApplyButton->SetEnabled(canApply);
fRevertButton->SetEnabled(canApply);
// Let the Cancel button be enabled always, as another way to close the
// window...
fCancelButton->SetEnabled(true);
bool useProxy = fUseProxyCheckBox->Value() == B_CONTROL_ON;
fProxyAddressControl->SetEnabled(useProxy);
fProxyPortControl->SetEnabled(useProxy);
}
// #pragma mark -
uint32
SettingsWindow::_NewWindowPolicy() const
{
uint32 newWindowPolicy = OpenStartPage;
BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked();
if (markedItem == fNewWindowBehaviorOpenSearchItem)
newWindowPolicy = OpenSearchPage;
else if (markedItem == fNewWindowBehaviorOpenBlankItem)
newWindowPolicy = OpenBlankPage;
return newWindowPolicy;
}
uint32
SettingsWindow::_NewTabPolicy() const
{
uint32 newTabPolicy = OpenBlankPage;
BMenuItem* markedItem = fNewTabBehaviorMenu->Menu()->FindMarked();
if (markedItem == fNewTabBehaviorCloneCurrentItem)
newTabPolicy = CloneCurrentPage;
else if (markedItem == fNewTabBehaviorOpenHomeItem)
newTabPolicy = OpenStartPage;
else if (markedItem == fNewTabBehaviorOpenSearchItem)
newTabPolicy = OpenSearchPage;
return newTabPolicy;
}
int32
SettingsWindow::_MaxHistoryAge() const
{
int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text());
if (maxHistoryAge <= 0)
maxHistoryAge = 1;
if (maxHistoryAge >= 35)
maxHistoryAge = 35;
return maxHistoryAge;
}
void
SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value)
{
for (int32 i = 0; BMenuItem* item = menu->ItemAt(i); i++) {
bool marked = false;
if (BMessage* message = item->Message()) {
int32 size;
if (message->FindInt32("size", &size) == B_OK && size == value)
marked = true;
}
item->SetMarked(marked);
}
}
int32
SettingsWindow::_SizesMenuValue(BMenu* menu) const
{
if (BMenuItem* item = menu->FindMarked()) {
if (BMessage* message = item->Message()) {
int32 size;
if (message->FindInt32("size", &size) == B_OK)
return size;
}
}
return kDefaultFontSize;
}
BFont
SettingsWindow::_FindDefaultSerifFont() const
{
// Default to the first "serif" font we find.
BFont serifFont(*be_plain_font);
font_family family;
int32 familyCount = count_font_families();
for (int32 i = 0; i < familyCount; i++) {
if (get_font_family(i, &family) == B_OK) {
BString familyString(family);
if (familyString.IFindFirst("sans") >= 0)
continue;
if (familyString.IFindFirst("serif") >= 0) {
serifFont.SetFamilyAndFace(family, B_REGULAR_FACE);
break;
}
}
}
return serifFont;
}
uint32
SettingsWindow::_ProxyPort() const
{
return atoul(fProxyPortControl->Text());
}
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SETTINGS_WINDOW_H
#define SETTINGS_WINDOW_H
#include <Window.h>
class BButton;
class BCheckBox;
class BMenu;
class BMenuField;
class BMenuItem;
class BTextControl;
class FontSelectionView;
class SettingsMessage;
class SettingsWindow : public BWindow {
public:
SettingsWindow(BRect frame,
SettingsMessage* settings);
virtual ~SettingsWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
virtual void Show();
private:
BView* _CreateGeneralPage(float spacing);
BView* _CreateFontsPage(float spacing);
BView* _CreateProxyPage(float spacing);
void _BuildSizesMenu(BMenu* menu,
uint32 messageWhat);
void _SetupFontSelectionView(
FontSelectionView* view,
BMessage* message);
bool _CanApplySettings() const;
void _ApplySettings();
void _RevertSettings();
void _ValidateControlsEnabledStatus();
uint32 _NewWindowPolicy() const;
uint32 _NewTabPolicy() const;
int32 _MaxHistoryAge() const;
void _SetSizesMenuValue(BMenu* menu, int32 value);
int32 _SizesMenuValue(BMenu* menu) const;
BFont _FindDefaultSerifFont() const;
uint32 _ProxyPort() const;
private:
SettingsMessage* fSettings;
BTextControl* fStartPageControl;
BTextControl* fSearchPageControl;
BTextControl* fDownloadFolderControl;
BMenuField* fNewWindowBehaviorMenu;
BMenuItem* fNewWindowBehaviorOpenHomeItem;
BMenuItem* fNewWindowBehaviorOpenSearchItem;
BMenuItem* fNewWindowBehaviorOpenBlankItem;
BMenuField* fNewTabBehaviorMenu;
BMenuItem* fNewTabBehaviorCloneCurrentItem;
BMenuItem* fNewTabBehaviorOpenHomeItem;
BMenuItem* fNewTabBehaviorOpenSearchItem;
BMenuItem* fNewTabBehaviorOpenBlankItem;
BTextControl* fDaysInHistoryMenuControl;
BCheckBox* fShowTabsIfOnlyOnePage;
BCheckBox* fAutoHideInterfaceInFullscreenMode;
BCheckBox* fAutoHidePointer;
BCheckBox* fShowHomeButton;
FontSelectionView* fStandardFontView;
FontSelectionView* fSerifFontView;
FontSelectionView* fSansSerifFontView;
FontSelectionView* fFixedFontView;
BCheckBox* fUseProxyCheckBox;
BTextControl* fProxyAddressControl;
BTextControl* fProxyPortControl;
BButton* fApplyButton;
BButton* fCancelButton;
BButton* fRevertButton;
BMenuField* fStandardSizesMenu;
BMenuField* fFixedSizesMenu;
};
#endif // SETTINGS_WINDOW_H
+654
View File
@@ -0,0 +1,654 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "URLInputGroup.h"
#include <Bitmap.h>
#include <Button.h>
#include <ControlLook.h>
#include <Clipboard.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <LayoutUtils.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <SeparatorView.h>
#include <TextView.h>
#include <Window.h>
#include <stdio.h>
#include <stdlib.h>
#include "BaseURL.h"
#include "BitmapButton.h"
#include "BrowsingHistory.h"
#include "IconButton.h"
#include "TextViewCompleter.h"
class URLChoice : public BAutoCompleter::Choice {
public:
URLChoice(const BString& choiceText, const BString& displayText,
int32 matchPos, int32 matchLen, int32 priority)
:
BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen),
fPriority(priority)
{
}
bool operator<(const URLChoice& other) const
{
if (fPriority > other.fPriority)
return true;
return DisplayText() < other.DisplayText();
}
bool operator==(const URLChoice& other) const
{
return fPriority == other.fPriority
&& DisplayText() < other.DisplayText();
}
private:
int32 fPriority;
};
class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel {
virtual void FetchChoicesFor(const BString& pattern)
{
int32 count = CountChoices();
for (int32 i = 0; i < count; i++) {
delete reinterpret_cast<BAutoCompleter::Choice*>(
fChoices.ItemAtFast(i));
}
fChoices.MakeEmpty();
// Search through BrowsingHistory for any matches.
BrowsingHistory* history = BrowsingHistory::DefaultInstance();
if (!history->Lock())
return;
BString lastBaseURL;
int32 priority = INT_MAX;
count = history->CountItems();
for (int32 i = 0; i < count; i++) {
BrowsingHistoryItem item = history->HistoryItemAt(i);
const BString& choiceText = item.URL();
int32 matchPos = choiceText.IFindFirst(pattern);
if (matchPos < 0)
continue;
if (lastBaseURL.Length() > 0
&& choiceText.FindFirst(lastBaseURL) >= 0) {
priority--;
} else
priority = INT_MAX;
lastBaseURL = baseURL(choiceText);
fChoices.AddItem(new URLChoice(choiceText,
choiceText, matchPos, pattern.Length(), priority));
}
history->Unlock();
fChoices.SortItems(_CompareChoices);
}
virtual int32 CountChoices() const
{
return fChoices.CountItems();
}
virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const
{
return reinterpret_cast<BAutoCompleter::Choice*>(
fChoices.ItemAt(index));
}
static int _CompareChoices(const void* a, const void* b)
{
const URLChoice* aChoice
= *reinterpret_cast<const URLChoice* const *>(a);
const URLChoice* bChoice
= *reinterpret_cast<const URLChoice* const *>(b);
if (*aChoice < *bChoice)
return -1;
else if (*aChoice == *bChoice)
return 0;
return 1;
}
private:
BList fChoices;
};
// #pragma mark - URLTextView
static const float kHorizontalTextRectInset = 4.0;
class URLInputGroup::URLTextView : public BTextView {
private:
static const uint32 MSG_CLEAR = 'cler';
public:
URLTextView(URLInputGroup* parent);
virtual ~URLTextView();
virtual void MessageReceived(BMessage* message);
virtual void FrameResized(float width, float height);
virtual void MouseDown(BPoint where);
virtual void KeyDown(const char* bytes, int32 numBytes);
virtual void MakeFocus(bool focused = true);
virtual BSize MinSize();
virtual BSize MaxSize();
void SetUpdateAutoCompleterChoices(bool update);
protected:
virtual void InsertText(const char* inText, int32 inLength,
int32 inOffset,
const text_run_array* inRuns);
virtual void DeleteText(int32 fromOffset, int32 toOffset);
private:
void _AlignTextRect();
private:
URLInputGroup* fURLInputGroup;
TextViewCompleter* fURLAutoCompleter;
BString fPreviousText;
bool fUpdateAutoCompleterChoices;
};
URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent)
:
BTextView("url"),
fURLInputGroup(parent),
fURLAutoCompleter(new TextViewCompleter(this,
new BrowsingHistoryChoiceModel())),
fPreviousText(""),
fUpdateAutoCompleterChoices(true)
{
MakeResizable(true);
SetStylable(true);
fURLAutoCompleter->SetModificationsReported(true);
}
URLInputGroup::URLTextView::~URLTextView()
{
delete fURLAutoCompleter;
}
void
URLInputGroup::URLTextView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_CLEAR:
SetText("");
break;
default:
BTextView::MessageReceived(message);
break;
}
}
void
URLInputGroup::URLTextView::FrameResized(float width, float height)
{
BTextView::FrameResized(width, height);
_AlignTextRect();
}
void
URLInputGroup::URLTextView::MouseDown(BPoint where)
{
bool wasFocus = IsFocus();
if (!wasFocus)
MakeFocus(true);
int32 buttons;
if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK)
buttons = B_PRIMARY_MOUSE_BUTTON;
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
// Display context menu
int32 selectionStart;
int32 selectionEnd;
GetSelection(&selectionStart, &selectionEnd);
bool canCutOrCopy = selectionEnd > selectionStart;
bool canPaste = false;
if (be_clipboard->Lock()) {
if (BMessage* data = be_clipboard->Data())
canPaste = data->HasData("text/plain", B_MIME_TYPE);
be_clipboard->Unlock();
}
BMenuItem* cutItem = new BMenuItem("Cut", new BMessage(B_CUT));
BMenuItem* copyItem = new BMenuItem("Copy", new BMessage(B_COPY));
BMenuItem* pasteItem = new BMenuItem("Paste", new BMessage(B_PASTE));
BMenuItem* clearItem = new BMenuItem("Clear", new BMessage(MSG_CLEAR));
cutItem->SetEnabled(canCutOrCopy);
copyItem->SetEnabled(canCutOrCopy);
pasteItem->SetEnabled(canPaste);
clearItem->SetEnabled(strlen(Text()) > 0);
BPopUpMenu* menu = new BPopUpMenu("url context");
menu->AddItem(cutItem);
menu->AddItem(copyItem);
menu->AddItem(pasteItem);
menu->AddItem(clearItem);
menu->SetTargetForItems(this);
menu->Go(ConvertToScreen(where), true, true, true);
return;
}
// Only pass through to base class if we already have focus.
if (!wasFocus)
return;
BTextView::MouseDown(where);
}
void
URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes)
{
switch (bytes[0]) {
case B_TAB:
BView::KeyDown(bytes, numBytes);
break;
case B_ESCAPE:
// Revert to text as it was when we received keyboard focus.
SetText(fPreviousText.String());
SelectAll();
break;
case B_RETURN:
// Don't let this through to the text view.
break;
default:
BTextView::KeyDown(bytes, numBytes);
break;
}
}
void
URLInputGroup::URLTextView::MakeFocus(bool focus)
{
if (focus == IsFocus())
return;
BTextView::MakeFocus(focus);
if (focus) {
fPreviousText = Text();
SelectAll();
}
fURLInputGroup->Invalidate();
}
BSize
URLInputGroup::URLTextView::MinSize()
{
BSize min;
min.height = ceilf(LineHeight(0) + kHorizontalTextRectInset);
// we always add at least one pixel vertical inset top/bottom for
// the text rect.
min.width = min.height * 3;
return BLayoutUtils::ComposeSize(ExplicitMinSize(), min);
}
BSize
URLInputGroup::URLTextView::MaxSize()
{
BSize max(MinSize());
max.width = B_SIZE_UNLIMITED;
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max);
}
void
URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update)
{
fUpdateAutoCompleterChoices = update;
}
void
URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength,
int32 inOffset, const text_run_array* inRuns)
{
// Filter all line breaks, note that inText is not terminated.
if (inLength == 1) {
if (*inText == '\n' || *inText == '\r')
BTextView::InsertText(" ", 1, inOffset, inRuns);
else
BTextView::InsertText(inText, 1, inOffset, inRuns);
} else {
BString filteredText(inText, inLength);
filteredText.ReplaceAll('\n', ' ');
filteredText.ReplaceAll('\r', ' ');
BTextView::InsertText(filteredText.String(), inLength, inOffset,
inRuns);
}
// Make the base URL part bold.
BString text(Text(), TextLength());
int32 baseUrlStart = text.FindFirst("://");
if (baseUrlStart >= 0)
baseUrlStart += 3;
else
baseUrlStart = 0;
int32 baseUrlEnd = text.FindFirst("/", baseUrlStart);
if (baseUrlEnd < 0)
baseUrlEnd = TextLength();
BFont font;
GetFont(&font);
const rgb_color black = (rgb_color){ 0, 0, 0, 255 };
const rgb_color gray = (rgb_color){ 60, 60, 60, 255 };
if (baseUrlStart > 0)
SetFontAndColor(0, baseUrlStart - 1, &font, B_FONT_ALL, &gray);
if (baseUrlEnd > baseUrlStart) {
font.SetFace(B_BOLD_FACE);
SetFontAndColor(baseUrlStart, baseUrlEnd, &font, B_FONT_ALL, &black);
}
if (baseUrlEnd < TextLength()) {
font.SetFace(B_REGULAR_FACE);
SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray);
}
fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
}
void
URLInputGroup::URLTextView::DeleteText(int32 fromOffset, int32 toOffset)
{
BTextView::DeleteText(fromOffset, toOffset);
fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
}
void
URLInputGroup::URLTextView::_AlignTextRect()
{
// Layout the text rect to be in the middle, normally this means there
// is one pixel spacing on each side.
BRect textRect(Bounds());
textRect.left = 0.0;
float vInset = max_c(1,
floorf((textRect.Height() - LineHeight(0)) / 2.0 + 0.5));
float hInset = kHorizontalTextRectInset;
if (be_control_look)
hInset = be_control_look->DefaultLabelSpacing();
textRect.InsetBy(hInset, vInset);
SetTextRect(textRect);
}
const uint32 kGoBitmapWidth = 14;
const uint32 kGoBitmapHeight = 14;
const color_space kGoBitmapFormat = B_RGBA32;
const unsigned char kGoBitmapBits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0,
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x56, 0x50, 0x50, 0x50, 0xff, 0x4d, 0x4d, 0x4d, 0xed,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x50, 0x50, 0x50, 0xff, 0x37, 0x37, 0x37, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x50, 0x50, 0x50, 0xff, 0x4b, 0x4b, 0x4b, 0xec, 0x37, 0x37, 0x37, 0x77, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// #pragma mark - PageIconView
class URLInputGroup::PageIconView : public BView {
public:
PageIconView()
:
BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fIcon(NULL)
{
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
}
~PageIconView()
{
delete fIcon;
}
virtual void Draw(BRect updateRect)
{
if (fIcon == NULL)
return;
BRect bounds(Bounds());
BRect iconBounds(0, 0, 15, 15);
iconBounds.OffsetTo(
floorf((bounds.left + bounds.right
- (iconBounds.left + iconBounds.right)) / 2 + 0.5f),
floorf((bounds.top + bounds.bottom
- (iconBounds.top + iconBounds.bottom)) / 2 + 0.5f));
DrawBitmap(fIcon, fIcon->Bounds(), iconBounds,
B_FILTER_BITMAP_BILINEAR);
}
virtual BSize MinSize()
{
if (fIcon != NULL)
return BSize(18, 18);
return BSize(0, 0);
}
virtual BSize MaxSize()
{
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
virtual BSize PreferredSize()
{
return MinSize();
}
void SetIcon(const BBitmap* icon)
{
if (icon == NULL && fIcon == NULL)
return;
if (!(fIcon != NULL && icon != NULL))
InvalidateLayout();
delete fIcon;
if (icon)
fIcon = new BBitmap(icon);
else
fIcon = NULL;
Invalidate();
}
private:
BBitmap* fIcon;
};
// #pragma mark - URLInputGroup
URLInputGroup::URLInputGroup(BMessage* goMessage)
:
BGroupView(B_HORIZONTAL, 0.0),
fWindowActive(false)
{
GroupLayout()->SetInsets(2, 2, 2, 2);
fIconView = new PageIconView();
GroupLayout()->AddView(fIconView, 0.0f);
fTextView = new URLTextView(this);
AddChild(fTextView);
AddChild(new BSeparatorView(B_VERTICAL, B_PLAIN_BORDER));
// TODO: Fix in Haiku, no in-built support for archived BBitmaps from
// resources?
// fGoButton = new BitmapButton("kActionGo", NULL);
fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth,
kGoBitmapHeight, kGoBitmapFormat, goMessage);
GroupLayout()->AddView(fGoButton, 0.0f);
SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
SetLowColor(ViewColor());
SetViewColor(B_TRANSPARENT_COLOR);
SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
B_ALIGN_VERTICAL_CENTER));
}
URLInputGroup::~URLInputGroup()
{
}
void
URLInputGroup::AttachedToWindow()
{
BGroupView::AttachedToWindow();
fWindowActive = Window()->IsActive();
}
void
URLInputGroup::WindowActivated(bool active)
{
BGroupView::WindowActivated(active);
if (fWindowActive != active) {
fWindowActive = active;
Invalidate();
}
}
void
URLInputGroup::Draw(BRect updateRect)
{
BRect bounds(Bounds());
rgb_color base(LowColor());
uint32 flags = 0;
if (fWindowActive && fTextView->IsFocus())
flags |= BControlLook::B_FOCUSED;
be_control_look->DrawTextControlBorder(this, bounds, updateRect, base,
flags);
}
void
URLInputGroup::MakeFocus(bool focus)
{
// Forward this to the text view, we never accept focus ourselves.
fTextView->MakeFocus(focus);
}
BTextView*
URLInputGroup::TextView() const
{
return fTextView;
}
void
URLInputGroup::SetText(const char* text)
{
if (!text || !Text() || strcmp(Text(), text) != 0) {
fTextView->SetUpdateAutoCompleterChoices(false);
fTextView->SetText(text);
fTextView->SetUpdateAutoCompleterChoices(true);
}
}
const char*
URLInputGroup::Text() const
{
return fTextView->Text();
}
BButton*
URLInputGroup::GoButton() const
{
return fGoButton;
}
void
URLInputGroup::SetPageIcon(const BBitmap* icon)
{
fIconView->SetIcon(icon);
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef URL_INPUT_GROUP_H
#define URL_INPUT_GROUP_H
#include <GroupView.h>
class BButton;
class BTextView;
class URLInputGroup : public BGroupView {
public:
URLInputGroup(BMessage* goMessage);
virtual ~URLInputGroup();
virtual void AttachedToWindow();
virtual void WindowActivated(bool active);
virtual void Draw(BRect updateRect);
virtual void MakeFocus(bool focus = true);
BTextView* TextView() const;
void SetText(const char* text);
const char* Text() const;
BButton* GoButton() const;
void SetPageIcon(const BBitmap* icon);
private:
class PageIconView;
class URLTextView;
PageIconView* fIconView;
URLTextView* fTextView;
BButton* fGoButton;
bool fWindowActive;
};
#endif // URL_INPUT_GROUP_H
+350
View File
@@ -0,0 +1,350 @@
resource app_signature "application/x-vnd.Haiku-WebPositive";
resource app_version {
major = 0,
middle = 0,
minor = 1,
variety = B_APPV_ALPHA,
internal = 0,
short_info = "WebPositive",
long_info = "WebPositive ©2007-2010 The WebKit Haiku Project"
};
resource app_flags B_SINGLE_LAUNCH;
resource file_types message {
"types" = "text/html",
"types" = "image/svg+xml",
"types" = "application/x-vnd.Be.URL.file",
"types" = "application/x-vnd.Be.URL.ftp",
"types" = "application/x-vnd.Be.URL.http",
"types" = "application/x-vnd.Be.URL.https"
};
resource vector_icon {
$"6E636966450500020106033D0AFE000000000000BD0AFE48F10748A0783133FF"
$"FFC80066FFFF0034CC020106033D0AFE000000000000BD0AFE48F10748A07854"
$"09B4B6D8033784FF051D61020106043D950B0000000000003D950B494FBC479B"
$"EC00FFFFFF4C00FF008F00B200FF008000050002030605B812A5BE03E13DE784"
$"B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BEDBFFF4F4F404EBD0"
$"020006023C92C0388F5FB854503C576348D8DF48895B004137A9FFB9B9B90401"
$"7E03FF360003FFFF0003FF9C0003FF000002010202BB36AEBA1760B80FFF392B"
$"574ACCFB48652300000001FFFF0000013205400500020004024AFFFC00FFFFBA"
$"360500020106033D0AFE000000000000BD0AFE48F10748A0783133FFFFC80066"
$"FFFF0034CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF"
$"0033CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF0066"
$"FF020004027AFFFC00DDFFBA360201040289FF0000A9C000000200040200FFE5"
$"CED0ECB989020004020DEFBC8CFFD4AA820200040200FFCB9CE9ECB989020004"
$"0200FFCB9CE9ECB98902000402B3FFCB9CBBD4AA820500020106033D0AFE0000"
$"00000000BD0AFE48F10748A0783133FFFFC80066FFFF0034CC020106033D0AFE"
$"000000000000BD0AFE48F10748A0785409B4B6D8033784FF051D61020106043D"
$"950B0000000000003D950B494FBC479BEC00FFFFFF4C00FF008F00B200FF0080"
$"00050002030605B812A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DD"
$"F48A9996B9B4B8BEDBFFF4F4F404EBD0020006023C92C0388F5FB854503C5763"
$"48D8DF48895B004137A9FFB9B9B904017E03FF360003FFFF000200040200FFBC"
$"34FFFF9C0003FF000002010202BB36AEBA1760B80FFF392B574ACCFB48652300"
$"000001FFFF00000132054003FFFFC9020014020026FF1C0500050002030605B8"
$"12A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BE"
$"DBFFF4F4F404EBD0020006023C92C0388F5FB854503C576348D8DF48895B0041"
$"37A9FFB9B9B904017E03FF360003FFFF0003FF9C0003FF000002010202BB36AE"
$"BA1760B80FFF392B574ACCFB48652300000001FFFF0000013205400500030052"
$"7502001002F8006BFF003E04006C050003900000020310020000006E00650400"
$"6B05000359463503C3A414039D816035000000000204BFC1B55A36B55AC3BEB5"
$"5AC6FABC92C6FAB895C6FAC08FBFC1C3CBC3BEC3CB36C3CBB889BC92B889C08F"
$"B889B895066EFFFFF30FFFFEFFFFBFBFFEFFFEFFFEFFFFFFFFBFFFEFDFFBFBFF"
$"FF0FC5DBB8B5C713BA9FC4CAB706C10FB579C307B5D4C0A226BFC1B55AC031B5"
$"5ABDBCB55ABA69B7BA36B63AB8F9B94EB89CBD9BB84EBB7EB8C7BE9AB924BF76"
$"B8E0BEE7B9DEC11FBCDFC332BB37C278BEC4C405C2D7C31AC0FAC3FCC2C5C2C0"
$"C22EC2B7C279C2BDC22EC2B7C226C240C2BDC240C2BDC206C2AFC199C2DAC1D0"
$"C2CB44C2EEC0D4C2DCC114C2E5C051C2CEBF42C312BFB0C2B4BF3DC312BF35BF"
$"1FBDECC312BE23C312BDB8C2EDBD57C2DEBD86C2E2BD53C2DBBD3EC2C2BD3EC2"
$"C2BD31C2B4BD12C2A4BD26C2AABD12C2A4BCA4C27EBC31C254BC31C254BC27C2"
$"51BC11C24FBC1DC250BC10C24BBC0FC241BC10C245BC0FC241BBF5C219BBF5C2"
$"19BBD2C1DDBB68C194BBADC1A4BB70C16EBB58C128BB62C14EBB4BC101BB4BC0"
$"ACBB47C0D7BB4BC0ACBB4EC087BB4EC087BB51C054BB4DBFEEBB54C021BB9DBF"
$"92BBA9BEBFBBAFBF35BBA9BEBFBBA7BE92BBA7BE92BBA7BE52BBBBBE2FBBA8BE"
$"4BBBBBBE2FBBC6BE20BBC6BE20BC00BDD4BBE2BCFBBC5BBD3DBBE2BCFBBAB7BC"
$"58BA8ABC43BA90BC45BA8ABC43BA8ABC42BA8ABC42BA88BBEABA22BB78BA6ABB"
$"ACBA22BB78BA12BB6AB9F8BB48B9ADBAEFB9ADBAEFB97DBAC3B927BAB0B94FBA"
$"B5B924BAA9B91ABA9AB920BAA0B984BA6DB9DEB996B9B5B9F9B9F6B95DBA36B8"
$"EFBA0AB91FBA5EB8C4BA78B85EBA83B89EBACCB83CBB60B7E7BB18B813BB60B7"
$"E7BB6AB7E1BBFEB787BBFEB787BC65B749BCB6B683BC93B6F5BCF5B689BD58B6"
$"64BD2CB67BBDA8B695BE6CB6503C29BE6FB64FBE88B64FBE7CB64FBE62B6A0BE"
$"E1B72FBE88B70EBEE4B733BEE8B73DBEE5B73ABED8B743BEC5B749BE74B7A5BE"
$"74B7A5BE63B7DCBE8FB848BE74B816BE90B84CBE91B852BE91B852BE93B85BBE"
$"9CB87ABE97B86BBE93B883BE8CB88DBE8CB88DBE39B8EFBD91B98FBDB6B906BD"
$"91B98FBD8DB9A0BD8DB9A0BD64B9D7BD7EBA54BD59BA19BD7ABA5CBD76BA62BD"
$"76BA62BD56BA9FBD4DBB2BBD38BAE6BD5FBB6FBDCCBBCEBD98BBA1BDFFBBF9BE"
$"73BC3FBE33BC27BEBEBC5CBF5DBC42BF11BC55BF5DBC42BFAB37BFAB37BFD0BC"
$"1DC01CBC0FBFF4BC0BC045BC13C083BC4EC066BC35C04DBCD9C0F3BDDAC0B6BD"
$"63C0F3BDDAC107BDF8C102BDF2C0BABE83C126BF90C0B1BF1CC126BF90C133BF"
$"9CC133BF9CC130C00EC1C4C0F8C135C0D6C258C11CC347C059C2EEC0C8C347C0"
$"59C36BC02EC388C018C388C018C3A7C003C3DABFC4C3C9BFE8C3EEBF9FC408BF"
$"51C3EFBF73C408BF51C408BF52C408BF52C40CBF99C49540C450BFCEC4EBBFB3"
$"C541BF0FC51FBF56C541BF0FC551BEF24EBEEA4EBEEAC57FBEA3C568BDFCC59E"
$"BE46C53ABDBAC4A2BDDEC4E0BDA9C4A2BDCABDB5C4A4BD31C4A4BD31C4A7BD1D"
$"C4E8BCDEC4D2BCF5C4E8BCDEC4FEBCC8C516BCB3C516BCB3C544BC8BC582BC1F"
$"C570BC5DC58BBC04C587BBBBC586BBD9C587BBBBC587BBA8C587BB9DC587BB9D"
$"C58CBB604EBAF9C584BB23C589BADAC5C1BA5DC5B0BAA1C5C3BA61C5CBBA6FC5"
$"CBBA6FC5D8BA8EC60EBAD3C5EDBAB3C609BB1EC648BBAAC626BB67C669BBEAC6"
$"6EBC7AC66FBC33C66EBC7AC671BCC3C671BCC3C673BCE9C66DBD36C677BD10C6"
$"64BD5AC649BD9BC652BD78C633BDEBC62BBE91C62DBE3F50BED5C67FBF2BC648"
$"BF16C750BD0F0006BC11B6E3BC11B6E3BC32B6AFBC54B637BC46B674BB81B6AA"
$"BA2BB801BAC4B747BA87B7E2BB2FB77DBADDB7AFBB59B764BBAAB733BB82B74D"
$"BBCBB71CBC11B6E3BBFBB707BC11B6E3001DBACDBFD1BACDBFD1BAEBBFA9BB29"
$"BF5BBB12BF89BB43BF24BB34BE92BB34BECFBB34BE4DBB5FBDE9BB34BE25BB80"
$"BDBEBBAABD5FBBA0BD98BB47BD29BA81BCBEBAE5BCF3BA67BCB1BA1FBC8332BC"
$"9FBA0FBC5BBA0DBC02BA1FBC28B9FDBBE5B9B9BBB6B9D0BBD0B99BBB91B95FBB"
$"44B983BB66B93DBB23B8EFBB2CB91BBB15B8C0BB47B8BEBADEB8C2BAFFB8B1BB"
$"13B89FBB7EB8A7BB48B8C8BB7EB8C5BBB2B8C2BB89B8C6BBDBB8C8BC2DB8C7BC"
$"04B8CFBC40B8BABC48B8CBBC48B8B3BC4BB8A9BC4EB8AEBC4DB8A0BC57B893BC"
$"4BB898BC55B881BC4AB88EBD0FB88DBD00B893BD49B8E0BDE7B88DBE02B90DBE"
$"03B922BE74B906BE4BB946BEA7B985BF00B972BEC1B996BF3EB9A240B997BF80"
$"B9AFC010BA16C05EB9DBC02DBA24C0B3BA75C126BA3CC0E7BA8FC143BAC0C17F"
$"BAA9C15FBAD7C19FBAFBC17BBAE3C19DBADDC13ABAD6C0A5BAD2C0EFBADBC060"
$"BACDBFD1BAEAC012BACDBFD10009BD5DB5D6BD5DB5D6BD81B5EDBDB1B60DBD83"
$"B605BDCFB613BE19B600BE01B619BE55B5C3BEF5B5C3BEB0B5EFBF2CB5A1BFA3"
$"B55D3FB55DBFCEB55DC00CB58CBFE9B577C03CB5A6C08FB566C063B574BF39B5"
$"40BCA7B60DBDDCB57ABCEBB623BD5DB5D6BD29B600BD5DB5D60005BF34B6E9BF"
$"34B6E9BF55B6EBBF99B6F5BF7BB702BFCEB6E0BF87B67CBF9BB693BF77B66DBF"
$"3CB663BF2FB623BF44B68FBF34B6E9BF6AB6CBBF34B6E90004BA06B87FBA06B8"
$"7FBA0BB867B9EEB84FB9FDB85FB982B8E4B8EFBA35B92CB987B97D31BA06B87F"
$"B974B8EFBA06B87F0066C6F6BC24C6F6BC24C6DBBB09C6002FC68AB9F1C5B9B8"
$"7BC4FFB79BC563B805C4CEB768C463B708C49AB736C452B6FBC427B6EFC43FB6"
$"E2C411B6FAC407B6C1C401B6D0C315B60FC0D0B56EC1F8B59AC0FAB58AC15EB5"
$"9CC130B589C170B5A1C178B5C9C19FB5BDC12CB5E2C08AB5C9C0D7B5C3C059B5"
$"CDC03FB60DC042B5DDC03DB629C03FB676C036B65CC04AB694C0B6B65EC0A7B6"
$"6FC0CDB643C0F1B619C0B0B607C108B64AC0D0B6B0C13AB6D5C0B5B6A7C066B6"
$"89C083B67CC063B689C05CB6AFC05EB6AAC053B6C0C030B6CFC043B6CABFE5B6"
$"E4BF94B741BFB0B6EFBF87B768BF5CB790BF88B781BF3BB79CBEF6B7B2BF17B7"
$"A3BECCB7C7BEF9B81BBEE9B7FFBF05B82FBF19B86CBF02B860BF59B891BFBEB7"
$"E0BFA3B801BFE0B7B3C038B7ADC008B7BCC04FB7A6C084B776C06CB76EC0D3B7"
$"95C0F7B83EC0EBB7F4C10FB83FC135B80FC100B801C10CB7E5C0ECB76F43B7AA"
$"C125B795C15EB7FCC14DB7BCC170B83CC1C1B820C18DB860C1CFB813C1FCB7D4"
$"C1E1B7BCC213B7E9C1F1B838C2142DC206B84BC23AB83CC222B842C259B83447"
$"B841C26CB835C2AEB84FC2F9B856C2D5B854C320B859C346B898C335B87AC376"
$"B8E6C249B8C5C258B8C6C227B8C2C1E1B8CFC202B8C1C1C8B8DAC199B8EFC1B6"
$"2FC178B8E5C13EB8B5C15AB8C7C117B89BC0C4B872C0EFB885C07EB853BFE2B8"
$"4EC02EB83FBFBFB855BF7FB87BBF9BB866BF5BB896BF10B8A4BF34B87FBEDBB8"
$"DBBE6DB941BEB5B91FBE50B94FBE19B976BE2DB95BBE03B990BDF5B9D1BE03B9"
$"B4BDE8B9EDBDE2BA1DBDCAB9FBBDF7BA3BBDEFBA76BDFEBA52BDD9BAA9BDC9BB"
$"27BD9EBAEEBDF235BE71BBBBBE39BB93BEAFBBE9BF40BBD1BEFBBBE5BF82BBC1"
$"C009BB9CBFC4BBA0C05EBB95C0DCBC03C0A1BBCDC104BC26C0F4BC67C113BC34"
$"C0D3BC9EC103BD00C0E8BCC7C11FBD3644BDA3C13CBD6CC166BDB9C182BDE8C1"
$"76BDCFC18DBE03C16DBE2CC17ABE15C152BE5DC13EBECEC13EBE97C13EBF0DC1"
$"85BF4CC15CBF24C1A9BF71C1A4BFE2C1A7BFB3C1A0C025C1DAC087C1B3C053C2"
$"15C08AC289C06CC253C086C2CBC04DC319BFDDC2E8C00EC346BFB0C386BF66C3"
$"77BFAAC396BF12C3FEBEBFC3C1BEF2C435BE8FC430BE0CC42DBE4DC432BDC0C4"
$"33BD21C428BD6CC43BBCDDC4AABC77C47EBCA7C4CDBC55C511BC03C505BC34C5"
$"19BBE7C512BBA8C51236C512BB92C51035C51ABB70C4F7BB29C47EBB2BC489BB"
$"5DC475BB0EC48ABB01C476BB13C4A1BAECC477BACDC48ABAD7C441BAACC3F0BA"
$"66C418BA9AC3CCBA36C390B9CAC3ADBA00C389B9BDC36CB93AC341B92DC39AB9"
$"4AC3E1B9A2C3C3B981C419B9DFC46DBA6AC44ABA1FC46EBA73C496BA89C48EBA"
$"85C4AFBA9CC4EABAA8C4CABAABC533BAA1C559BA1F4EBA60C56231C4E8B9AEC5"
$"1DB9DAC4CAB996C49EB958C4B6B975C48EB946C473B90DC466B92AC492B8F9C4"
$"BCB91CC49FB90BC4DFB932C52BB951C505B9444EB95EC5B4B96CC591B952C5C9"
$"B97BC5E7B9B8C5D8B9A1C5FEB9DCC626BA26C614BA00C644BA60C694BA9EC64D"
$"BA88C667BAE8C6B6BB83C693BB3FC6DEBBD3C6E3BC7BC6E4BC22C6E2BCCEC6D0"
$"BD78C6F4BD2BC6A6BDCCC69FBE9AC69FBE3EC6A0BE95C6A4BE88C6A2BE8DC6A1"
$"3DC6A0BEC0C696BEBEC6B2BEC3C6D5BE01C6D2BE15C6F5BD65C6F6BC24C700BC"
$"C3C6F6BC240008C301B7D8C301B7D8C2E6B7DBC2D4B7A3C2E8B7AEC2B1B792C2"
$"69B7B7C288B7A7C204B7EEC236B742C221B77BC239B73AC285B743C279B746C2"
$"A6B740C2F2B74EC2D7B730C30BB76AC33CB7A1C31FB787C35FB7C1C301B7D8C3"
$"1CB7D4C301B7D80004BB52C203BB52C203BB44C20CBB26C221BB37C21DBB54C2"
$"48BBB9C290BB86C26EBB91C265BB52C203BB84C226BB52C2030005C4F3BE2DC4"
$"F3BE2DC4D3BE57C48BBEA4C4A5BE75C46EBEDAC47DBF52C47DBF18C4B6BF37C4"
$"EDBEB8C4D0BEEBC502BE92C4F3BE2DC531BE48C4F3BE2D0009C212C326C212C3"
$"26C17FC38FBFF6C344C09DC332BFD0C348BF8DC36ABFABC350BF66C38BBF1FC3"
$"86BF56C386BEAFC386BDCDC386BE3EC386BEC1C3CBC0BFC3BABFC3C3DCC137C3"
$"A9C221C367C1AEC38DC229C364C261C32AC280C337C248C322C212C326C229C3"
$"31C212C32602024E284E2C542E4C324C30482E020250304C3252344C364E344C"
$"34020258B81858305C32543654324E300202583456365836563C5A3854380204"
$"BCD5C1F1BACDC36FBEA5C09BC4A6BFA6C360BE3CC67FC1B0C064C5ACC23AC444"
$"BE90C715B827C85CB961C9B8B682C68B0204C3CFC072C309BF45C521C2733DC6"
$"5EC0DDC4E4BC10C7F6B880C76BB8DAC831B841C6E2BC6FC2E2B880C5CDBE42C1"
$"890622AEAAE6BAEAAAAF9A0EB9E4C6DEB9CB50B985C672BA12C5CDBAABC593BA"
$"C54DBAB8C4BBBAEBC3C8BAABC37CBA85C0CBBC88BE0E36B8E6B993B8DA2EB874"
$"B92DB970B7AFBCD5BA52BCEEB87ABE3AB7AEBD61B7AEBF12B7AEBF852EBF92BA"
$"78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF9FBD"
$"CEBFCBC18BC1FCC323BF00C13E46C33BC196C43B46C3DBC12AC484C02BC493C0"
$"11C3EFC091C36FBE20C2BDBF40BC50C14ABBF74EBB8451BBE8C66EBA9EC6B906"
$"11AAAAA8BA02BBEFB9ECBB49BAB8BCC8BB9DBCE1BE4EBB70C018BC7BC0A5BE07"
$"BF73BE6044BF9FBF6CBDDBC06CBD0245BCAEC1C9BC2FBF40BAABBE0EBB04BF0D"
$"BB04BD82BB04BD14BAB8BCAEBA38060BBAAA2A31C653BA0BC6C4BB84C645BB2B"
$"C69FBBB6C614BBAFC5A0BBDDC309BC1DC163BCAEC0CABB70BFE5BAD7C0CABADE"
$"C36FBAE3C5C5060AAAAB0ABE46C125BF99C130BF80454448C1FCC394C21DC361"
$"C1C3C3F0C11EC447C052C493C02BC3EFC105C389BE67470605EA02BB37BAC5BB"
$"D6BA12B9ACB887B8E0B8ADB90BB869B887B939B920B96C0A05C16BBB91C473BB"
$"91C4D9BC36C4A6BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF4DBA"
$"45BE0EBB04BEA7BB2BBD8ABAE2BD29BA520607AA3A39B8EDBE012F3CB99F3EB9"
$"93BEDAB920BF99B946BE34B77BBFF5B7C239B74804032EBCE932BDCEBB2BBD34"
$"BB12BECDBB51BF4DBA380208CA68BA5FCB40BD02CA39B9D0CA0EB6BCCAF3B7AE"
$"C947B5E955B58A55B58A55B58AC843B841C8FFB76C53B953C718B814C6E62FC7"
$"4BB728C5A02FC601B84EC2703DC645BCB6C5ACBC1DC711BD82C89DBEE7C79E40"
$"C89DBEE7060ABFFB0FC6F1C097C625BFCBC6F1BFCB5A345C3758315A2E5A305A"
$"2C582A562E582C54305230C691B854C691B920C691B7DAC53ABAAB4FB9ACC501"
$"BB1EC46EBBF7C4ADBB9DC3FABCB6C56DBE0EC38EBE4EC64DBDF00207C86FBE74"
$"C86FBE74C7A3BDA8C78ABB44C80ABB28C71835C633BBB7C6D4BBEFC5DABB98C5"
$"01BB44C509BB79C4F1BAEDC3F4BC43C43EBBD1C4B4BC83C6FF38C63336C7CB3A"
$"C83CBE9AC5B3BF8DC908BD020202C6392F4DB9F9C66CBAC54DBBE24FBB16C46E"
$"BAEB0202C969B7CEC967B915CAFFB9E1543654324E300202583456365836C876"
$"BD8FC969BB84C7AABBF70604EAC2BD4448C110C32EC07EC361C17DC33CC0E4C3"
$"7BC1E30205C5ACB861C65E31C52BB75D50204E224E20C3E1BA5FC37BB94FC455"
$"BB91C606BD02C493BCB6C722BE0DCB1BBDA8CB97BDE4C79EBBF702044EB44BC4"
$"D4284EB5174BB9B9C408B8BAC43DBAD755BD4F4BBBD057BD4FC744BB77C818BC"
$"3B51BAC502034E28C4A1B847C53AB61650BA52C592B8A0C690BBAEC4E0BAAB59"
$"BD8FC4E0B7A104032EB77BC612B63CC969B50AC7AAB777CB35BCA9C99C04032E"
$"B965B906B953B7D4B8D3B86D31B748BAB82C0406BE0BB689BE67B5FDC04BB607"
$"BF7FB5F0C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C31EB70849"
$"B609C32304032EBDA8B887BEB4B76EBE10B775BFEC2BC059B8AD04032E28BE01"
$"B3FFC0D8B4253FB3D2C288B5BDC2FB0406FE0BC79EBB2BC8F5BBAAC840BB47C9"
$"EBBC2ECB26BDDBCB05BD14CB40BE74CA4FC07ECA99BFCACA0EC117C9CFC27CCA"
$"0EC1E3C998C30058C3890A04C6FFBB11C856BC50C8BCBCC3C889BD4F040CAAFA"
$"BABC6FC74BC091C699C303C5CDC3DAC54DC440C4CEC44EC382C1EAC303C237C3"
$"4DC1D5C2EEC05EC402C149C3DFBF754BBD87C460BD47C4F9BE46C513BE2D4DBE"
$"98C58BBDBAC5870608BAAABFECC1FC4448C1FCC394C21DC361C1C3C3F0C11EC4"
$"47C052C493C02BC3EFC105C389BED3C2BD0A04C369BC83C6D738C666BD1CC35B"
$"BD350A03B46542B4BE41B4BE420605AF03B6AFC969B63CC9F1B72FC8D0BE4155"
$"B821CA8DC11CC6FAC42DC5C5C55FC53ABE67C91DC1E8C7EAB86DCB260604EEBF"
$"CBBB51C1FCBBD0C13EBC43C29FBB6EC18BBAAB43BB1EC145BAF2C09ABB4B0A04"
$"30303050505050302C0A0001021240BAB100000000000040B755C6CCDBBE9979"
$"01178300040A0101020240BAB100000000000040B755C6CCDBBE99790A020103"
$"0240BAB100000000000040B755C6CCDBBE99790A030A05060708090A0C0D040B"
$"0240BAB100000000000040B755C6CCDBBE99790A110113124084473AE65BBB05"
$"39406A8F40BD7AC6ED3001178400040A00012712401CCA0000000000004031D6"
$"BEA7B4C5651401178100040A150112024046733A7FB6BABB05401508437714C3"
$"BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF0A11011412"
$"402E52374883B74883402E5243A84DC5C35901178200040A16011502402E5237"
$"4883B74883402E5243A84DC5C3590A17011602402E52374883B74883402E5243"
$"A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3590A170118"
$"02402E52374883B74883402E5243A84DC5C3590A1801190240268F36C1F1B73C"
$"D33FA9DD442903C369B00A1B011A02402E52374883B74883402E5243A84DC5C3"
$"590A2C011B02402E52374883B74883402E5243A84DC5C3590A11011C12402E52"
$"374883B74883402E5243A84DC5C35901178100040A20011D124018A13C2DD3BC"
$"6F843F776243040C3B35B701178400040A28011D024018A13C481BBC6F843FA1"
$"3143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0CBDA6830A26"
$"03212022023F94B53C057BBC14913F373546DE4E423FFC0A2B012202401CCA00"
$"0000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97FB40685AC6"
$"A141CA33220A0001291240075E0000000000004029CCC0DC88C59D5C01178100"
$"040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D01178400040A3601"
$"24023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4F539818BBA"
$"43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A55C7EFC848"
$"5E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D26601178200040A00"
$"012A12402E52374883B74883402E5241C554C5CE0401178100040A00012B1240"
$"1CCA000000000000401CCAC0623FC4B46E01178100040A00012C124031960000"
$"00000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA000000000000"
$"401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0E971C4B46E"
$"1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF0A3E013102"
$"40FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA000000000000"
$"401CCAC0E971C42D3C01178200040A4001330A401CCA000000000000401CCAC0"
$"E971C4B46E1DFF0A420134023600000000000000003600004890004AE8000A42"
$"0134023600000000000000003600004870004AE8000A43013402360000000000"
$"0000003600004850004AF8000A43013402360000000000000000360000487000"
$"4AF8000A430134023600000000000000003600004890004AF8000A4401340236"
$"0000000000000000360000485000466000"
};
resource(201, "kActionBack") #'VICN' array {
$"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2"
$"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF"
$"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585"
$"C70200060238E8A83647FBBA8E2D3D42294AF6F7496CE200047BB8FF0694DE02"
$"0006023957BB3923F0BC39AC3C5E604AA873475AB1000592DAFD67CBFF04FF49"
$"080A092E3C3A53424C484F5047503A4435442B3A300A072E3C3A533A48484F48"
$"403A3A3A300A043A303A3A4435442B0A033A483A53424C0A044840484F504750"
$"3A0A043A3A4435503A48400803C125B7D43AB99FB8D3BE0E08023A3A4840070A"
$"0001001001178400040A010101000A020102000A030103000A040104000A0501"
$"05000A06020607100117812004"
};
resource(202, "kActionForward") #'VICN' array {
$"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2"
$"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF"
$"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD"
$"FF04FF49050A0A2E423A483A524847503F432A3A2F3A3136302E350A0748473A"
$"2F3A392E352E423A483A520A043A2F4847503F432A0A042E3536303A313A3908"
$"0536B9932FBB773B3A3BB939C0E5B755050A0001001001178400040A01010100"
$"0A020102000A030103000A040104100117812004"
};
resource(203, "kActionForward2") #'VICN' array {
$"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9"
$"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF"
$"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468"
$"9C020006023AC62E392AB63B6BA0BCFF0B49DAAA4AAE4500046FA7FF2BA5E502"
$"0006023A1CB834EBA6383E33BD3E8D499DE44A647800ACE2FFFD6DCCFF04FF49"
$"080A09523A48533F503C532E4C2E3E3A363A2B482E0A07523A485348473C533C"
$"43483A482E0A04482E483A3A363A2B0A03484748533F500A043C433C532E4C2E"
$"3E0A04483A3A362E3E3C430802BD8FB795C2BDB8E008023C43B8C7BF0D070A00"
$"01001001178400040A040101000A020102000A030103000A010104000A050105"
$"000A06020607100117812004"
};
resource(204, "kActionStop") #'VICN' array {
$"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E"
$"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D"
$"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478"
$"7700FF9090FFFF757504FF440A0A0C2E4C364E3C4742524A5440434A3842353C"
$"BE1B36312E2E38400A0636313C3C40434A54504E402E0A03364E3E483C470A04"
$"483FC712BADE4A3840430A042E2E3631402E382C0A0442354A38C712BADE4AB9"
$"EC0A0E2E4C364EBEB6C37042524A54504E483FC712BADE4AB9EC4335402E382C"
$"2E2E384008022FB8A0BCC3B80708033C3C42364ABA120802BCA9BFF3B8D3C47B"
$"060A0001061001178400040A020101000A03020302000A010100000A04020504"
$"000A0503070809100117810004"
};
resource(206, "kActionGoStart") #'VICN' array {
$"6E63696605050002001602B53D77BAF2653D77A7B7CFFC460F874A2D7700F0FF"
$"D50200160236FB2637191CBC57873C40E14B0E7149D82700A2FFBB0200060239"
$"FB483A6DC2BDAC713D02DB4B384746086300EA0606FFD005050200060238B0C7"
$"397C47BD2A963C71B74A82C348B2B700FF4444FFF106060A0A06304942525044"
$"50383E32303D0A09303B3049324A32C0723643364C4252424036320A04503650"
$"44425242400A082D3E3535434645455439462C35312B3C0A062B3C2D3E353543"
$"46454535310A0445455439462C35310A0432C072324A364C36430A043A453A4A"
$"3E4C3EC2630A044645464A484848430A044C3F4C444E424E3D070A0001001001"
$"178400040A010101000A020102000A000406070809000A000103100117840004"
$"0A030105000A04010400"
};
resource(205, "kActionGo") archive BBitmap {
"_frame" = rect { 0.0, 0.0, 15.0, 15.0 },
"_cspace" = 8200,
"_bmflags" = 0,
"_rowbytes" = 64,
"_data" = array {
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000C1000000DE00000061000000070000000100000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000FF9BD4A5FF48634EFF000000C00000003500000004"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000FFB6F9C2FFB3F9C0FF84B68EFF263426FD0000009B"
$"0000001600000002000000000000000000000000000000000000000000000000"
$"0000000000000000000000FFB6F9C2FF7EF995FFA3F9B3FFAAE9B6FF69906FFF"
$"000000E200000064000000070000000100000000000000000000000000000000"
$"0000000000000000000000FFB6F9C2FF6AFB85FF6AFB85FF83FA98FFA4F5B2FF"
$"7CC88AFF325C3BFF000000C00000003500000004000000000000000000000000"
$"0000000000000000000000FFB6F9C2FF5DFC7BFF5DFC7BFF5DFC7BFF5DFB7CFF"
$"60ED7AFF54D76DFF389A48FF002A14FD0000009B000000160000000200000000"
$"0000000000000000000000FFB5F8C1FF59FC77FF59FC77FF59FC77FF59FC77FF"
$"59FC77FF55F674FF40DB5CFF2BBC48FF1C752BFF000000D00000002000000003"
$"0000000000000000000000FFA8F4B5FF2EFA54FF2EFA54FF2EFA54FF2EFA54FF"
$"2EFA54FF2BF350FF22D542FF1CB638FF157027FF000000D00000003D00000009"
$"0000000000000000000000FF92ECA2FF15F940FF15F940FF15F940FF15F740FF"
$"15DE35FF00BE2EFF008922FF002600FD0000009B000000430000002000000003"
$"0000000000000000000000FF7EE591FF15F83DFF15F83DFF1CEA3DFF00C732FF"
$"009E22FF004815FF000000BF000000560000002D0000000F0000000200000000"
$"0000000000000000000000FF6DDF81FF1CF340FF2BDA4AFF1CB638FF006D1CFF"
$"000000E200000074000000360000001900000004000000000000000000000000"
$"0000000000000000000000FF5DDA75FF44D25FFF229338FF002600FD0000009B"
$"0000004300000023000000070000000100000000000000000000000000000000"
$"0000000000000000000000FF46B65CFF1C5222FF000000BF000000560000002D"
$"0000000F00000002000000000000000000000000000000000000000000000000"
$"0000000000000000000000C2000000DE00000074000000360000001900000004"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000030000001F00000020000000080000000100000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
}
};
@@ -0,0 +1,253 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#include "AutoCompleter.h"
#include <Looper.h>
#include <Message.h>
#include "AutoCompleterDefaultImpl.h"
// #pragma mark - DefaultPatternSelector
class DefaultPatternSelector : public BAutoCompleter::PatternSelector {
public:
virtual void SelectPatternBounds(const BString& text, int32 caretPos,
int32* start, int32* length);
};
void
DefaultPatternSelector::SelectPatternBounds(const BString& text,
int32 caretPos, int32* start, int32* length)
{
if (!start || !length)
return;
*start = 0;
*length = text.Length();
}
// #pragma mark - CompletionStyle
BAutoCompleter::CompletionStyle::CompletionStyle(EditView* editView,
ChoiceModel* choiceModel, ChoiceView* choiceView,
PatternSelector* patternSelector)
:
fEditView(editView),
fPatternSelector(patternSelector ? patternSelector
: new DefaultPatternSelector()),
fChoiceModel(choiceModel),
fChoiceView(choiceView)
{
}
BAutoCompleter::CompletionStyle::~CompletionStyle()
{
delete fEditView;
delete fChoiceModel;
delete fChoiceView;
delete fPatternSelector;
}
void
BAutoCompleter::CompletionStyle::SetEditView(EditView* view)
{
delete fEditView;
fEditView = view;
}
void
BAutoCompleter::CompletionStyle::SetPatternSelector(
PatternSelector* selector)
{
delete fPatternSelector;
fPatternSelector = selector;
}
void
BAutoCompleter::CompletionStyle::SetChoiceModel(ChoiceModel* model)
{
delete fChoiceModel;
fChoiceModel = model;
}
void
BAutoCompleter::CompletionStyle::SetChoiceView(ChoiceView* view)
{
delete fChoiceView;
fChoiceView = view;
}
// #pragma mark - BAutoCompleter
BAutoCompleter::BAutoCompleter(CompletionStyle* completionStyle)
:
fCompletionStyle(completionStyle)
{
}
BAutoCompleter::BAutoCompleter(EditView* editView, ChoiceModel* choiceModel,
ChoiceView* choiceView, PatternSelector* patternSelector)
:
fCompletionStyle(new BDefaultCompletionStyle(editView, choiceModel,
choiceView, patternSelector))
{
}
BAutoCompleter::~BAutoCompleter()
{
delete fCompletionStyle;
}
bool
BAutoCompleter::Select(int32 index)
{
if (fCompletionStyle)
return fCompletionStyle->Select(index);
else
return false;
}
bool
BAutoCompleter::SelectNext(bool wrap)
{
if (fCompletionStyle)
return fCompletionStyle->SelectNext(wrap);
else
return false;
}
bool
BAutoCompleter::SelectPrevious(bool wrap)
{
if (fCompletionStyle)
return fCompletionStyle->SelectPrevious(wrap);
else
return false;
}
bool
BAutoCompleter::IsChoiceSelected() const
{
if (fCompletionStyle)
return fCompletionStyle->IsChoiceSelected();
else
return false;
}
int32
BAutoCompleter::CountChoices() const
{
if (fCompletionStyle && fCompletionStyle->GetChoiceModel())
return fCompletionStyle->GetChoiceModel()->CountChoices();
else
return 0;
}
int32
BAutoCompleter::CountVisibleChoices() const
{
if (fCompletionStyle && fCompletionStyle->GetChoiceView())
return fCompletionStyle->GetChoiceView()->CountVisibleChoices();
else
return 0;
}
int32
BAutoCompleter::SelectedChoiceIndex() const
{
if (fCompletionStyle)
return fCompletionStyle->SelectedChoiceIndex();
else
return -1;
}
void
BAutoCompleter::ApplyChoice(bool hideChoices)
{
if (fCompletionStyle)
fCompletionStyle->ApplyChoice(hideChoices);
}
void
BAutoCompleter::CancelChoice()
{
if (fCompletionStyle)
fCompletionStyle->CancelChoice();
}
void
BAutoCompleter::EditViewStateChanged(bool updateChoices)
{
if (fCompletionStyle)
fCompletionStyle->EditViewStateChanged(updateChoices);
}
void
BAutoCompleter::SetEditView(EditView* view)
{
if (fCompletionStyle)
fCompletionStyle->SetEditView(view);
}
void
BAutoCompleter::SetPatternSelector(PatternSelector* selector)
{
if (fCompletionStyle)
fCompletionStyle->SetPatternSelector(selector);
}
void
BAutoCompleter::SetChoiceModel(ChoiceModel* model)
{
if (fCompletionStyle)
fCompletionStyle->SetChoiceModel(model);
}
void
BAutoCompleter::SetChoiceView(ChoiceView* view)
{
if (fCompletionStyle)
fCompletionStyle->SetChoiceView(view);
}
void
BAutoCompleter::SetCompletionStyle(CompletionStyle* style)
{
delete fCompletionStyle;
fCompletionStyle = style;
}
@@ -0,0 +1,161 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#ifndef _AUTO_COMPLETER_H
#define _AUTO_COMPLETER_H
#include <MessageFilter.h>
#include <Rect.h>
#include <String.h>
class BAutoCompleter {
public:
class Choice {
public:
Choice(const BString& choiceText,
const BString& displayText, int32 matchPos,
int32 matchLen)
:
fText(choiceText),
fDisplayText(displayText),
fMatchPos(matchPos),
fMatchLen(matchLen)
{
}
virtual ~Choice() {}
const BString& Text() const { return fText; }
const BString& DisplayText() const { return fDisplayText; }
int32 MatchPos() const { return fMatchPos; }
int32 MatchLen() const { return fMatchLen; }
private:
BString fText;
BString fDisplayText;
int32 fMatchPos;
int32 fMatchLen;
};
class EditView {
public:
virtual ~EditView() {}
virtual BRect GetAdjustmentFrame() = 0;
virtual void GetEditViewState(BString& text,
int32* caretPos) = 0;
virtual void SetEditViewState(const BString& text,
int32 caretPos,
int32 selectionLength = 0) = 0;
};
class PatternSelector {
public:
virtual ~PatternSelector() {}
virtual void SelectPatternBounds(const BString& text,
int32 caretPos, int32* start,
int32* length) = 0;
};
class ChoiceModel {
public:
virtual ~ChoiceModel() {}
virtual void FetchChoicesFor(const BString& pattern) = 0;
virtual int32 CountChoices() const = 0;
virtual const Choice* ChoiceAt(int32 index) const = 0;
};
class CompletionStyle;
class ChoiceView {
public:
virtual ~ChoiceView() {}
virtual void SelectChoiceAt(int32 index) = 0;
virtual void ShowChoices(
BAutoCompleter::CompletionStyle* completer)
= 0;
virtual void HideChoices() = 0;
virtual bool ChoicesAreShown() = 0;
virtual int32 CountVisibleChoices() const = 0;
};
class CompletionStyle {
public:
CompletionStyle(EditView* editView,
ChoiceModel* choiceModel,
ChoiceView* choiceView,
PatternSelector* patternSelector);
virtual ~CompletionStyle();
virtual bool Select(int32 index) = 0;
virtual bool SelectNext(bool wrap = false) = 0;
virtual bool SelectPrevious(bool wrap = false) = 0;
virtual bool IsChoiceSelected() const = 0;
virtual int32 SelectedChoiceIndex() const = 0;
virtual void ApplyChoice(bool hideChoices = true) = 0;
virtual void CancelChoice() = 0;
virtual void EditViewStateChanged(bool updateChoices) = 0;
void SetEditView(EditView* view);
void SetPatternSelector(PatternSelector* selector);
void SetChoiceModel(ChoiceModel* model);
void SetChoiceView(ChoiceView* view);
EditView* GetEditView() { return fEditView; }
PatternSelector* GetPatternSelector()
{ return fPatternSelector; }
ChoiceModel* GetChoiceModel() { return fChoiceModel; }
ChoiceView* GetChoiceView() { return fChoiceView; }
protected:
EditView* fEditView;
PatternSelector* fPatternSelector;
ChoiceModel* fChoiceModel;
ChoiceView* fChoiceView;
};
protected:
BAutoCompleter(
CompletionStyle* completionStyle = NULL);
BAutoCompleter(EditView* editView,
ChoiceModel* choiceModel,
ChoiceView* choiceView,
PatternSelector* patternSelector);
virtual ~BAutoCompleter();
void EditViewStateChanged(
bool updateChoices = true);
bool Select(int32 index);
bool SelectNext(bool wrap = false);
bool SelectPrevious(bool wrap = false);
bool IsChoiceSelected() const;
int32 CountChoices() const;
int32 CountVisibleChoices() const;
int32 SelectedChoiceIndex() const;
void ApplyChoice(bool hideChoices = true);
void CancelChoice();
void SetEditView(EditView* view);
void SetPatternSelector(PatternSelector* selector);
void SetChoiceModel(ChoiceModel* model);
void SetChoiceView(ChoiceView* view);
void SetCompletionStyle(CompletionStyle* style);
private:
CompletionStyle* fCompletionStyle;
};
#endif // _AUTO_COMPLETER_H
@@ -0,0 +1,467 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#include "AutoCompleterDefaultImpl.h"
#include <ListView.h>
#include <Screen.h>
#include <ScrollView.h>
#include <Window.h>
// #pragma mark - BDefaultPatternSelector
void
BDefaultPatternSelector::SelectPatternBounds(const BString& text,
int32 caretPos, int32* start, int32* length)
{
if (!start || !length)
return;
*start = 0;
*length = text.Length();
}
// #pragma mark - BDefaultCompletionStyle
BDefaultCompletionStyle::BDefaultCompletionStyle(
BAutoCompleter::EditView* editView,
BAutoCompleter::ChoiceModel* choiceModel,
BAutoCompleter::ChoiceView* choiceView,
BAutoCompleter::PatternSelector* patternSelector)
:
CompletionStyle(editView, choiceModel, choiceView, patternSelector),
fSelectedIndex(-1),
fPatternStartPos(0),
fPatternLength(0),
fIgnoreEditViewStateChanges(false)
{
}
BDefaultCompletionStyle::~BDefaultCompletionStyle()
{
}
bool
BDefaultCompletionStyle::Select(int32 index)
{
if (!fChoiceView || !fChoiceModel || index == fSelectedIndex
|| index < -1 || index >= fChoiceModel->CountChoices()) {
return false;
}
fSelectedIndex = index;
fChoiceView->SelectChoiceAt(index);
return true;
}
bool
BDefaultCompletionStyle::SelectNext(bool wrap)
{
if (!fChoiceModel || fChoiceModel->CountChoices() == 0)
return false;
int32 newIndex = fSelectedIndex + 1;
if (newIndex >= fChoiceModel->CountChoices()) {
if (wrap)
newIndex = 0;
else
newIndex = fSelectedIndex;
}
return Select(newIndex);
}
bool
BDefaultCompletionStyle::SelectPrevious(bool wrap)
{
if (!fChoiceModel || fChoiceModel->CountChoices() == 0)
return false;
int32 newIndex = fSelectedIndex - 1;
if (newIndex < 0) {
if (wrap)
newIndex = fChoiceModel->CountChoices() - 1;
else
newIndex = 0;
}
return Select(newIndex);
}
bool
BDefaultCompletionStyle::IsChoiceSelected() const
{
return fSelectedIndex >= 0;
}
int32
BDefaultCompletionStyle::SelectedChoiceIndex() const
{
return fSelectedIndex;
}
void
BDefaultCompletionStyle::ApplyChoice(bool hideChoices)
{
if (!fChoiceModel || !fChoiceView || !fEditView || fSelectedIndex < 0)
return;
BString completedText(fFullEnteredText);
completedText.Remove(fPatternStartPos, fPatternLength);
const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text();
completedText.Insert(choiceStr, fPatternStartPos);
fIgnoreEditViewStateChanges = true;
fFullEnteredText = completedText;
fPatternLength = choiceStr.Length();
fEditView->SetEditViewState(completedText,
fPatternStartPos + choiceStr.Length());
if (hideChoices) {
fChoiceView->HideChoices();
Select(-1);
}
fIgnoreEditViewStateChanges = false;
}
void
BDefaultCompletionStyle::CancelChoice()
{
if (!fChoiceView || !fEditView)
return;
if (fChoiceView->ChoicesAreShown()) {
fIgnoreEditViewStateChanges = true;
fEditView->SetEditViewState(fFullEnteredText,
fPatternStartPos + fPatternLength);
fChoiceView->HideChoices();
Select(-1);
fIgnoreEditViewStateChanges = false;
}
}
void
BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices)
{
if (fIgnoreEditViewStateChanges || !fChoiceModel || !fChoiceView
|| !fEditView) {
return;
}
BString text;
int32 caretPos;
fEditView->GetEditViewState(text, &caretPos);
if (fFullEnteredText == text)
return;
fFullEnteredText = text;
if (!updateChoices)
return;
fPatternSelector->SelectPatternBounds(text, caretPos, &fPatternStartPos,
&fPatternLength);
BString pattern(text.String() + fPatternStartPos, fPatternLength);
fChoiceModel->FetchChoicesFor(pattern);
Select(-1);
// show a single choice only if it doesn't match the pattern exactly:
if (fChoiceModel->CountChoices() > 1 || (fChoiceModel->CountChoices() == 1
&& pattern.ICompare(fChoiceModel->ChoiceAt(0)->Text())) != 0) {
fChoiceView->ShowChoices(this);
fChoiceView->SelectChoiceAt(fSelectedIndex);
} else
fChoiceView->HideChoices();
}
// #pragma mark - BDefaultChoiceView::ListView
static const int32 MSG_INVOKED = 'invk';
BDefaultChoiceView::ListView::ListView(
BAutoCompleter::CompletionStyle* completer)
:
BListView(BRect(0, 0, 100, 100), "ChoiceViewList"),
fCompleter(completer)
{
// we need to check if user clicks outside of window-bounds:
SetEventMask(B_POINTER_EVENTS);
}
void
BDefaultChoiceView::ListView::AttachedToWindow()
{
SetTarget(this);
SetInvocationMessage(new BMessage(MSG_INVOKED));
BListView::AttachedToWindow();
}
void
BDefaultChoiceView::ListView::SelectionChanged()
{
fCompleter->Select(CurrentSelection(0));
}
void
BDefaultChoiceView::ListView::MessageReceived(BMessage* message)
{
switch(message->what) {
case MSG_INVOKED:
fCompleter->ApplyChoice();
break;
default:
BListView::MessageReceived(message);
}
}
void
BDefaultChoiceView::ListView::MouseDown(BPoint point)
{
if (!Window()->Frame().Contains(ConvertToScreen(point)))
// click outside of window, so we close it:
Window()->Quit();
else
BListView::MouseDown(point);
}
// #pragma mark - BDefaultChoiceView::ListItem
BDefaultChoiceView::ListItem::ListItem(const BAutoCompleter::Choice* choice)
:
BListItem()
{
fPreText = choice->DisplayText();
if (choice->MatchLen() > 0) {
fPreText.MoveInto(fMatchText, choice->MatchPos(), choice->MatchLen());
fPreText.MoveInto(fPostText, choice->MatchPos(), fPreText.Length());
}
}
void
BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame,
bool complete)
{
rgb_color textColor;
rgb_color nonMatchTextColor;
rgb_color backColor;
rgb_color matchColor;
if (IsSelected()) {
textColor = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR);
backColor = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR);
} else {
textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
backColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
}
matchColor = tint_color(backColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2);
nonMatchTextColor = tint_color(backColor, 1.7);
BFont font;
font_height fontHeight;
owner->GetFont(&font);
font.GetHeight(&fontHeight);
float xPos = frame.left + 1;
float yPos = frame.top + fontHeight.ascent;
float w;
if (fPreText.Length()) {
w = owner->StringWidth(fPreText.String());
owner->SetLowColor(backColor);
owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom),
B_SOLID_LOW);
owner->SetHighColor(nonMatchTextColor);
owner->DrawString(fPreText.String(), BPoint(xPos, yPos));
xPos += w;
}
if (fMatchText.Length()) {
w = owner->StringWidth(fMatchText.String());
owner->SetLowColor(matchColor);
owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom),
B_SOLID_LOW);
owner->SetHighColor(textColor);
owner->DrawString(fMatchText.String(), BPoint(xPos, yPos));
xPos += w;
}
if (fPostText.Length()) {
w = owner->StringWidth(fPostText.String());
owner->SetLowColor(backColor);
owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom),
B_SOLID_LOW);
owner->SetHighColor(nonMatchTextColor);
owner->DrawString(fPostText.String(), BPoint(xPos, yPos));
}
}
// #pragma mark - BDefaultChoiceView
BDefaultChoiceView::BDefaultChoiceView()
:
fWindow(NULL),
fListView(NULL),
fMaxVisibleChoices(8)
{
}
BDefaultChoiceView::~BDefaultChoiceView()
{
HideChoices();
}
void
BDefaultChoiceView::SelectChoiceAt(int32 index)
{
if (fListView && fListView->LockLooper()) {
if (index < 0)
fListView->DeselectAll();
else {
fListView->Select(index);
fListView->ScrollToSelection();
}
fListView->UnlockLooper();
}
}
void
BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer)
{
if (!completer)
return;
HideChoices();
BAutoCompleter::ChoiceModel* choiceModel = completer->GetChoiceModel();
BAutoCompleter::EditView* editView = completer->GetEditView();
if (!editView || !choiceModel || choiceModel->CountChoices() == 0)
return;
fListView = new ListView(completer);
int32 count = choiceModel->CountChoices();
for(int32 i = 0; i<count; ++i) {
fListView->AddItem(
new ListItem(choiceModel->ChoiceAt(i))
);
}
BScrollView *scrollView = NULL;
if (count > fMaxVisibleChoices) {
scrollView = new BScrollView("", fListView, B_FOLLOW_NONE, 0, false, true, B_NO_BORDER);
}
fWindow = new BWindow(BRect(0, 0, 100, 100), "", B_BORDERED_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL, B_NOT_MOVABLE | B_WILL_ACCEPT_FIRST_CLICK
| B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS);
if (scrollView != NULL)
fWindow->AddChild(scrollView);
else
fWindow->AddChild(fListView);
int32 visibleCount = min_c(count, fMaxVisibleChoices);
float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1;
BRect pvRect = editView->GetAdjustmentFrame();
BRect listRect = pvRect;
listRect.bottom = listRect.top + listHeight - 1;
BRect screenRect = BScreen().Frame();
if (listRect.bottom + 1 + listHeight <= screenRect.bottom)
listRect.OffsetTo(pvRect.left, pvRect.bottom + 1);
else
listRect.OffsetTo(pvRect.left, pvRect.top - listHeight);
if (scrollView != NULL) {
// Moving here to cut off the scrollbar top
scrollView->MoveTo(0, -1);
// Adding the 1 and 2 to cut-off the scroll-bar top, right and bottom
scrollView->ResizeTo(listRect.Width() + 1, listRect.Height() + 2);
// Move here to compensate for the above
fListView->MoveTo(0, 1);
fListView->ResizeTo(listRect.Width() - B_V_SCROLL_BAR_WIDTH, listRect.Height());
} else {
fListView->MoveTo(0, 0);
fListView->ResizeTo(listRect.Width(), listRect.Height());
}
fWindow->MoveTo(listRect.left, listRect.top);
fWindow->ResizeTo(listRect.Width(), listRect.Height());
fWindow->Show();
}
void
BDefaultChoiceView::HideChoices()
{
if (fWindow && fWindow->Lock()) {
fWindow->Quit();
fWindow = NULL;
fListView = NULL;
}
}
bool
BDefaultChoiceView::ChoicesAreShown()
{
return (fWindow != NULL);
}
int32
BDefaultChoiceView::CountVisibleChoices() const
{
if (fListView)
return min_c(fMaxVisibleChoices, fListView->CountItems());
else
return 0;
}
void
BDefaultChoiceView::SetMaxVisibleChoices(int32 choices)
{
if (choices < 1)
choices = 1;
if (choices == fMaxVisibleChoices)
return;
fMaxVisibleChoices = choices;
// TODO: Update live?
}
int32
BDefaultChoiceView::MaxVisibleChoices() const
{
return fMaxVisibleChoices;
}
@@ -0,0 +1,100 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#ifndef _AUTO_COMPLETER_DEFAULT_IMPL_H
#define _AUTO_COMPLETER_DEFAULT_IMPL_H
#include <ListView.h>
#include <String.h>
#include "AutoCompleter.h"
class BDefaultPatternSelector : public BAutoCompleter::PatternSelector {
public:
virtual void SelectPatternBounds(const BString& text,
int32 caretPos, int32* start,
int32* length);
};
class BDefaultCompletionStyle : public BAutoCompleter::CompletionStyle {
public:
BDefaultCompletionStyle(
BAutoCompleter::EditView* editView,
BAutoCompleter::ChoiceModel* choiceModel,
BAutoCompleter::ChoiceView* choiceView,
BAutoCompleter::PatternSelector*
patternSelector);
virtual ~BDefaultCompletionStyle();
virtual bool Select(int32 index);
virtual bool SelectNext(bool wrap = false);
virtual bool SelectPrevious(bool wrap = false);
virtual bool IsChoiceSelected() const;
virtual int32 SelectedChoiceIndex() const;
virtual void ApplyChoice(bool hideChoices = true);
virtual void CancelChoice();
virtual void EditViewStateChanged(bool updateChoices);
private:
BString fFullEnteredText;
int32 fSelectedIndex;
int32 fPatternStartPos;
int32 fPatternLength;
bool fIgnoreEditViewStateChanges;
};
class BDefaultChoiceView : public BAutoCompleter::ChoiceView {
protected:
class ListView : public BListView {
public:
ListView(
BAutoCompleter::CompletionStyle* completer);
virtual void SelectionChanged();
virtual void MessageReceived(BMessage* msg);
virtual void MouseDown(BPoint point);
virtual void AttachedToWindow();
private:
BAutoCompleter::CompletionStyle* fCompleter;
};
class ListItem : public BListItem {
public:
ListItem(const BAutoCompleter::Choice* choice);
virtual void DrawItem(BView* owner, BRect frame,
bool complete = false);
private:
BString fPreText;
BString fMatchText;
BString fPostText;
};
public:
BDefaultChoiceView();
virtual ~BDefaultChoiceView();
virtual void SelectChoiceAt(int32 index);
virtual void ShowChoices(
BAutoCompleter::CompletionStyle* completer);
virtual void HideChoices();
virtual bool ChoicesAreShown();
virtual int32 CountVisibleChoices() const;
void SetMaxVisibleChoices(int32 choices);
int32 MaxVisibleChoices() const;
private:
BWindow* fWindow;
ListView* fListView;
int32 fMaxVisibleChoices;
};
#endif // _AUTO_COMPLETER_DEFAULT_IMPL_H
@@ -0,0 +1,169 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#include "TextViewCompleter.h"
#include <Looper.h>
#include <TextControl.h>
#include <stdio.h>
#include "AutoCompleterDefaultImpl.h"
// #pragma mark - TextViewWrapper
TextViewCompleter::TextViewWrapper::TextViewWrapper(BTextView* textView)
:
fTextView(textView)
{
}
void
TextViewCompleter::TextViewWrapper::GetEditViewState(BString& text,
int32* caretPos)
{
if (fTextView && fTextView->LockLooper()) {
text = fTextView->Text();
if (caretPos) {
int32 end;
fTextView->GetSelection(caretPos, &end);
}
fTextView->UnlockLooper();
}
}
void
TextViewCompleter::TextViewWrapper::SetEditViewState(const BString& text,
int32 caretPos, int32 selectionLength)
{
if (fTextView && fTextView->LockLooper()) {
fTextView->SetText(text.String(), text.Length());
fTextView->Select(caretPos, caretPos + selectionLength);
fTextView->ScrollToSelection();
fTextView->UnlockLooper();
}
}
BRect
TextViewCompleter::TextViewWrapper::GetAdjustmentFrame()
{
BRect frame = fTextView->Bounds();
frame = fTextView->ConvertToScreen(frame);
frame.InsetBy(0, -3);
return frame;
}
// #pragma mark -
TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model,
PatternSelector* patternSelector)
:
BAutoCompleter(new TextViewWrapper(textView), model,
new BDefaultChoiceView(), patternSelector),
BMessageFilter(B_KEY_DOWN),
fTextView(textView),
fModificationsReported(false)
{
fTextView->AddFilter(this);
}
TextViewCompleter::~TextViewCompleter()
{
fTextView->RemoveFilter(this);
}
void
TextViewCompleter::SetModificationsReported(bool reported)
{
fModificationsReported = reported;
}
void
TextViewCompleter::TextModified(bool updateChoices)
{
EditViewStateChanged(updateChoices);
}
filter_result
TextViewCompleter::Filter(BMessage* message, BHandler** target)
{
const char* bytes;
int32 modifiers;
if ((!target || message->FindString("bytes", &bytes) != B_OK
|| message->FindInt32("modifiers", &modifiers) != B_OK)
|| (modifiers & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY
| B_SHIFT_KEY)) != 0) {
return B_DISPATCH_MESSAGE;
}
switch (bytes[0]) {
case B_UP_ARROW:
SelectPrevious();
// Insert the current choice into the text view, so the user can
// continue typing. This will not trigger another evaluation, since
// we don't invoke EditViewStateChanged().
ApplyChoice(false);
return B_SKIP_MESSAGE;
case B_DOWN_ARROW:
SelectNext();
// See above.
ApplyChoice(false);
return B_SKIP_MESSAGE;
case B_PAGE_UP:
{
int32 index = SelectedChoiceIndex() - CountVisibleChoices();
index = max_c(index, 0);
Select(index);
ApplyChoice(false);
return B_SKIP_MESSAGE;
}
case B_PAGE_DOWN:
{
int32 index = SelectedChoiceIndex() + CountVisibleChoices();
index = min_c(index, CountChoices() - 1);
Select(index);
ApplyChoice(false);
return B_SKIP_MESSAGE;
}
case B_ESCAPE:
CancelChoice();
return B_DISPATCH_MESSAGE;
case B_RETURN:
if (IsChoiceSelected()) {
ApplyChoice();
EditViewStateChanged();
} else
CancelChoice();
return B_DISPATCH_MESSAGE;
case B_TAB: {
// make sure that the choices-view is closed when tabbing out:
CancelChoice();
return B_DISPATCH_MESSAGE;
}
default:
if (!fModificationsReported) {
// dispatch message to textview manually...
Looper()->DispatchMessage(message, *target);
// ...and propagate the new state to the auto-completer:
EditViewStateChanged();
return B_SKIP_MESSAGE;
}
return B_DISPATCH_MESSAGE;
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
* All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#ifndef TEXT_CONTROL_COMPLETER_H
#define TEXT_CONTROL_COMPLETER_H
#include <MessageFilter.h>
#include "AutoCompleter.h"
class BTextView;
class TextViewCompleter : protected BAutoCompleter, public BMessageFilter {
public:
TextViewCompleter(BTextView* textView,
ChoiceModel* choiceModel = NULL,
PatternSelector* patternSelector = NULL);
virtual ~TextViewCompleter();
void SetModificationsReported(bool reported);
void TextModified(bool updateChoices);
private:
virtual filter_result Filter(BMessage* message, BHandler** target);
class TextViewWrapper : public EditView {
public:
TextViewWrapper(BTextView* textView);
virtual BRect GetAdjustmentFrame();
virtual void GetEditViewState(BString& text,
int32* caretPos);
virtual void SetEditViewState(const BString& text,
int32 caretPos, int32 selectionLength = 0);
private:
BTextView* fTextView;
};
private:
BTextView* fTextView;
bool fModificationsReported;
};
#endif // TEXT_CONTROL_COMPLETER_H
+178
View File
@@ -0,0 +1,178 @@
/*
* Copyright 2005-2007, Ingo Weinhold, [email protected].
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _AUTO_LOCKER_H
#define _AUTO_LOCKER_H
#include <stddef.h>
namespace BPrivate {
// AutoLockerStandardLocking
template<typename Lockable>
class AutoLockerStandardLocking {
public:
inline bool Lock(Lockable* lockable)
{
return lockable->Lock();
}
inline void Unlock(Lockable* lockable)
{
lockable->Unlock();
}
};
// AutoLockerReadLocking
template<typename Lockable>
class AutoLockerReadLocking {
public:
inline bool Lock(Lockable* lockable)
{
return lockable->ReadLock();
}
inline void Unlock(Lockable* lockable)
{
lockable->ReadUnlock();
}
};
// AutoLockerWriteLocking
template<typename Lockable>
class AutoLockerWriteLocking {
public:
inline bool Lock(Lockable* lockable)
{
return lockable->WriteLock();
}
inline void Unlock(Lockable* lockable)
{
lockable->WriteUnlock();
}
};
// AutoLocker
template<typename Lockable,
typename Locking = AutoLockerStandardLocking<Lockable> >
class AutoLocker {
private:
typedef AutoLocker<Lockable, Locking> ThisClass;
public:
inline AutoLocker()
:
fLockable(NULL),
fLocked(false)
{
}
inline AutoLocker(const Locking& locking)
:
fLockable(NULL),
fLocking(locking),
fLocked(false)
{
}
inline AutoLocker(Lockable* lockable, bool alreadyLocked = false,
bool lockIfNotLocked = true)
:
fLockable(lockable),
fLocked(fLockable && alreadyLocked)
{
if (!alreadyLocked && lockIfNotLocked)
Lock();
}
inline AutoLocker(Lockable& lockable, bool alreadyLocked = false,
bool lockIfNotLocked = true)
:
fLockable(&lockable),
fLocked(fLockable && alreadyLocked)
{
if (!alreadyLocked && lockIfNotLocked)
Lock();
}
inline ~AutoLocker()
{
Unlock();
}
inline void SetTo(Lockable* lockable, bool alreadyLocked,
bool lockIfNotLocked = true)
{
Unlock();
fLockable = lockable;
fLocked = (lockable && alreadyLocked);
if (!alreadyLocked && lockIfNotLocked)
Lock();
}
inline void SetTo(Lockable& lockable, bool alreadyLocked,
bool lockIfNotLocked = true)
{
SetTo(&lockable, alreadyLocked, lockIfNotLocked);
}
inline void Unset()
{
Unlock();
Detach();
}
inline bool Lock()
{
if (fLockable && !fLocked)
fLocked = fLocking.Lock(fLockable);
return fLocked;
}
inline void Unlock()
{
if (fLockable && fLocked) {
fLocking.Unlock(fLockable);
fLocked = false;
}
}
inline void Detach()
{
fLockable = NULL;
fLocked = false;
}
inline AutoLocker<Lockable, Locking>& operator=(Lockable* lockable)
{
SetTo(lockable);
return *this;
}
inline AutoLocker<Lockable, Locking>& operator=(Lockable& lockable)
{
SetTo(&lockable);
return *this;
}
inline bool IsLocked() const { return fLocked; }
inline operator bool() const { return fLocked; }
protected:
Lockable* fLockable;
Locking fLocking;
bool fLocked;
};
} // namespace BPrivate
using BPrivate::AutoLocker;
using BPrivate::AutoLockerReadLocking;
using BPrivate::AutoLockerWriteLocking;
#endif // _AUTO_LOCKER_H
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "BaseURL.h"
BString
baseURL(const BString string)
{
int32 baseURLStart = string.FindFirst("://") + 3;
int32 baseURLEnd = string.FindFirst("/", baseURLStart + 1);
BString result;
result.SetTo(string.String() + baseURLStart, baseURLEnd - baseURLStart);
return result;
}
+14
View File
@@ -0,0 +1,14 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef BASE_URL_H
#define BASE_URL_H
#include <String.h>
BString baseURL(const BString string);
#endif // BASE_URL_H
@@ -0,0 +1,119 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "BitmapButton.h"
#include <string.h>
#include <Bitmap.h>
#include <ControlLook.h>
#include <TranslationUtils.h>
static const float kFrameInset = 2;
BitmapButton::BitmapButton(const char* resourceName, BMessage* message)
:
BButton("", message),
fBitmap(BTranslationUtils::GetBitmap(resourceName)),
fBackgroundMode(BUTTON_BACKGROUND)
{
}
BitmapButton::BitmapButton(const uint8* bits, uint32 width, uint32 height,
color_space format, BMessage* message)
:
BButton("", message),
fBitmap(new BBitmap(BRect(0, 0, width - 1, height - 1), 0, format)),
fBackgroundMode(BUTTON_BACKGROUND)
{
memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength());
}
BitmapButton::~BitmapButton()
{
delete fBitmap;
}
BSize
BitmapButton::MinSize()
{
BSize min(0, 0);
if (fBitmap) {
min.width = fBitmap->Bounds().Width();
min.height = fBitmap->Bounds().Height();
}
min.width += kFrameInset * 2;
min.height += kFrameInset * 2;
return min;
}
BSize
BitmapButton::MaxSize()
{
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
BSize
BitmapButton::PreferredSize()
{
return MinSize();
}
void
BitmapButton::Draw(BRect updateRect)
{
BRect bounds(Bounds());
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 flags = be_control_look->Flags(this);
if (fBackgroundMode == BUTTON_BACKGROUND || Value() == B_CONTROL_ON) {
be_control_look->DrawButtonBackground(this, bounds, updateRect, base,
flags);
} else {
SetHighColor(tint_color(base, B_DARKEN_2_TINT));
StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
bounds.bottom--;
be_control_look->DrawMenuBarBackground(this, bounds, updateRect, base,
flags);
}
if (fBitmap == NULL)
return;
SetDrawingMode(B_OP_ALPHA);
if (!IsEnabled()) {
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
SetHighColor(0, 0, 0, 120);
}
BRect bitmapBounds(fBitmap->Bounds());
BPoint bitmapLocation(
floorf((bounds.left + bounds.right
- (bitmapBounds.left + bitmapBounds.right)) / 2 + 0.5f),
floorf((bounds.top + bounds.bottom
- (bitmapBounds.top + bitmapBounds.bottom)) / 2 + 0.5f));
DrawBitmap(fBitmap, bitmapLocation);
}
void
BitmapButton::SetBackgroundMode(uint32 mode)
{
if (fBackgroundMode != mode) {
fBackgroundMode = mode;
Invalidate();
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010 Stephan Aßmus <[email protected]>. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef BITMAP_BUTTON_H
#define BITMAP_BUTTON_H
#include <Button.h>
class BBitmap;
class BitmapButton : public BButton {
public:
enum {
BUTTON_BACKGROUND = 0,
MENUBAR_BACKGROUND,
};
BitmapButton(const char* resourceName,
BMessage* message);
BitmapButton(const uint8* bits, uint32 width,
uint32 height, color_space format,
BMessage* message);
virtual ~BitmapButton();
virtual BSize MinSize();
virtual BSize MaxSize();
virtual BSize PreferredSize();
virtual void Draw(BRect updateRect);
void SetBackgroundMode(uint32 mode);
private:
BBitmap* fBitmap;
uint32 fBackgroundMode;
};
#endif // BITMAP_BUTTON_H
File diff suppressed because it is too large Load Diff
+225
View File
@@ -0,0 +1,225 @@
/*
* Copyright 2007-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _DATE_TIME_H_
#define _DATE_TIME_H_
#include <String.h>
class BMessage;
namespace BPrivate {
enum time_type {
B_GMT_TIME,
B_LOCAL_TIME
};
enum diff_type {
B_HOURS_DIFF,
B_MINUTES_DIFF,
B_SECONDS_DIFF,
B_MILLISECONDS_DIFF,
B_MICROSECONDS_DIFF
};
class BTime {
public:
BTime();
BTime(const BTime& other);
BTime(int32 hour, int32 minute, int32 second,
int32 microsecond = 0);
BTime(const BMessage* archive);
~BTime();
status_t Archive(BMessage* into) const;
bool IsValid() const;
bool IsValid(const BTime& time) const;
bool IsValid(int32 hour, int32 minute, int32 second,
int32 microsecond = 0) const;
static BTime CurrentTime(time_type type);
BTime Time() const;
bool SetTime(const BTime& time);
bool SetTime(int32 hour, int32 minute, int32 second,
int32 microsecond = 0);
BTime& AddHours(int32 hours);
BTime& AddMinutes(int32 minutes);
BTime& AddSeconds(int32 seconds);
BTime& AddMilliseconds(int32 milliseconds);
BTime& AddMicroseconds(int32 microseconds);
int32 Hour() const;
int32 Minute() const;
int32 Second() const;
int32 Millisecond() const;
int32 Microsecond() const;
bigtime_t Difference(const BTime& time,
diff_type type) const;
bool operator!=(const BTime& time) const;
bool operator==(const BTime& time) const;
bool operator<(const BTime& time) const;
bool operator<=(const BTime& time) const;
bool operator>(const BTime& time) const;
bool operator>=(const BTime& time) const;
private:
bigtime_t _Microseconds() const;
BTime& _AddMicroseconds(bigtime_t microseconds);
bool _SetTime(bigtime_t hour, bigtime_t minute,
bigtime_t second, bigtime_t microsecond);
private:
bigtime_t fMicroseconds;
};
class BDate {
public:
BDate();
BDate(const BDate& other);
BDate(int32 year, int32 month, int32 day);
BDate(const BMessage* archive);
~BDate();
status_t Archive(BMessage* into) const;
bool IsValid() const;
bool IsValid(const BDate& date) const;
bool IsValid(int32 year, int32 month,
int32 day) const;
static BDate CurrentDate(time_type type);
BDate Date() const;
bool SetDate(const BDate& date);
bool SetDate(int32 year, int32 month, int32 day);
void GetDate(int32* year, int32* month, int32* day);
void AddDays(int32 days);
void AddYears(int32 years);
void AddMonths(int32 months);
int32 Day() const;
int32 Year() const;
int32 Month() const;
int32 Difference(const BDate& date) const;
int32 DayOfWeek() const;
int32 DayOfYear() const;
int32 WeekNumber() const;
bool IsLeapYear(int32 year) const;
int32 DaysInYear() const;
int32 DaysInMonth() const;
BString ShortDayName() const;
static BString ShortDayName(int32 day);
BString ShortMonthName() const;
static BString ShortMonthName(int32 month);
BString LongDayName() const;
static BString LongDayName(int32 day);
BString LongMonthName() const;
static BString LongMonthName(int32 month);
int32 DateToJulianDay() const;
static BDate JulianDayToDate(int32 julianDay);
bool operator!=(const BDate& date) const;
bool operator==(const BDate& date) const;
bool operator<(const BDate& date) const;
bool operator<=(const BDate& date) const;
bool operator>(const BDate& date) const;
bool operator>=(const BDate& date) const;
private:
int32 _DaysInMonth(int32 year, int32 month) const;
bool _SetDate(int32 year, int32 month, int32 day);
int32 _DateToJulianDay(int32 year, int32 month,
int32 day) const;
private:
int32 fDay;
int32 fYear;
int32 fMonth;
};
class BDateTime {
public:
BDateTime();
BDateTime(const BDate &date, const BTime &time);
BDateTime(const BMessage* archive);
~BDateTime();
status_t Archive(BMessage* into) const;
bool IsValid() const;
static BDateTime CurrentDateTime(time_type type);
void SetDateTime(const BDate &date, const BTime &time);
BDate& Date();
const BDate& Date() const;
void SetDate(const BDate &date);
BTime& Time();
const BTime& Time() const;
void SetTime(const BTime &time);
int32 Time_t() const;
void SetTime_t(uint32 seconds);
bool operator!=(const BDateTime& dateTime) const;
bool operator==(const BDateTime& dateTime) const;
bool operator<(const BDateTime& dateTime) const;
bool operator<=(const BDateTime& dateTime) const;
bool operator>(const BDateTime& dateTime) const;
bool operator>=(const BDateTime& dateTime) const;
private:
BDate fDate;
BTime fTime;
};
} // namespace BPrivate
using BPrivate::time_type;
using BPrivate::B_GMT_TIME;
using BPrivate::B_LOCAL_TIME;
using BPrivate::diff_type;
using BPrivate::B_HOURS_DIFF;
using BPrivate::B_MINUTES_DIFF;
using BPrivate::B_SECONDS_DIFF;
using BPrivate::B_MILLISECONDS_DIFF;
using BPrivate::B_MICROSECONDS_DIFF;
using BPrivate::BTime;
using BPrivate::BDate;
using BPrivate::BDateTime;
#endif // _DATE_TIME_H_
@@ -0,0 +1,527 @@
/*
* Copyright 2001-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Mark Hogben
* DarkWyrm <[email protected]>
* Axel Dörfler, [email protected]
* Philippe Saint-Pierre, [email protected]
* Stephan Aßmus <[email protected]>
*/
#include "FontSelectionView.h"
#include <Box.h>
#include <Catalog.h>
#include <Locale.h>
#include <Looper.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <String.h>
#include <StringView.h>
#include <LayoutItem.h>
#include <GroupLayoutBuilder.h>
#include <stdio.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Font Selection view"
static const float kMinSize = 8.0;
static const float kMaxSize = 18.0;
static const int32 kMsgSetFamily = 'fmly';
static const int32 kMsgSetStyle = 'styl';
static const int32 kMsgSetSize = 'size';
// #pragma mark -
FontSelectionView::FontSelectionView(const char* name, const char* label,
bool separateStyles, const BFont* currentFont)
:
BHandler(name),
fMessage(NULL),
fTarget(NULL)
{
if (currentFont == NULL)
fCurrentFont = _DefaultFont();
else
fCurrentFont = *currentFont;
fSavedFont = fCurrentFont;
fSizesMenu = new BPopUpMenu("size menu");
fFontsMenu = new BPopUpMenu("font menu");
// font menu
fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, B_WILL_DRAW);
fFontsMenuField->SetFont(be_bold_font);
// styles menu, if desired
if (separateStyles) {
fStylesMenu = new BPopUpMenu("styles menu");
fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"),
fStylesMenu, B_WILL_DRAW);
} else {
fStylesMenu = NULL;
fStylesMenuField = NULL;
}
// size menu
fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu,
B_WILL_DRAW);
fSizesMenuField->SetAlignment(B_ALIGN_RIGHT);
// preview
fPreviewText = new BStringView("preview text",
B_TRANSLATE_COMMENT("The quick brown fox jumps over the lazy dog.",
"Don't translate this literally ! Use a phrase showing all "
"chars from A to Z."));
fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
B_SIZE_UNLIMITED));
fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
1.65));
fPreviewText->SetAlignment(B_ALIGN_RIGHT);
_UpdateFontPreview();
}
FontSelectionView::~FontSelectionView()
{
// Some controls may not have been attached...
if (!fPreviewText->Window())
delete fPreviewText;
if (!fSizesMenuField->Window())
delete fSizesMenuField;
if (fStylesMenuField && !fStylesMenuField->Window())
delete fStylesMenuField;
if (!fFontsMenuField->Window())
delete fFontsMenuField;
delete fMessage;
}
void
FontSelectionView::AttachedToLooper()
{
_BuildSizesMenu();
UpdateFontsMenu();
}
void
FontSelectionView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgSetSize:
{
int32 size;
if (message->FindInt32("size", &size) != B_OK
|| size == fCurrentFont.Size())
break;
fCurrentFont.SetSize(size);
_UpdateFontPreview();
_Invoke();
break;
}
case kMsgSetFamily:
{
const char* family;
if (message->FindString("family", &family) != B_OK)
break;
font_style style;
fCurrentFont.GetFamilyAndStyle(NULL, &style);
BMenuItem* familyItem = fFontsMenu->FindItem(family);
if (familyItem != NULL) {
_SelectCurrentFont(false);
BMenuItem* styleItem;
if (fStylesMenuField != NULL)
styleItem = fStylesMenuField->Menu()->FindMarked();
else {
styleItem = familyItem->Submenu()->FindItem(style);
if (styleItem == NULL)
styleItem = familyItem->Submenu()->ItemAt(0);
}
if (styleItem != NULL) {
styleItem->SetMarked(true);
fCurrentFont.SetFamilyAndStyle(family, styleItem->Label());
_UpdateFontPreview();
}
if (fStylesMenuField != NULL)
_AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu());
}
_Invoke();
break;
}
case kMsgSetStyle:
{
const char* family;
const char* style;
if (message->FindString("family", &family) != B_OK
|| message->FindString("style", &style) != B_OK)
break;
BMenuItem *familyItem = fFontsMenu->FindItem(family);
if (!familyItem)
break;
_SelectCurrentFont(false);
familyItem->SetMarked(true);
fCurrentFont.SetFamilyAndStyle(family, style);
_UpdateFontPreview();
_Invoke();
break;
}
default:
BHandler::MessageReceived(message);
}
}
void
FontSelectionView::SetMessage(BMessage* message)
{
delete fMessage;
fMessage = message;
}
void
FontSelectionView::SetTarget(BHandler* target)
{
fTarget = target;
}
// #pragma mark -
void
FontSelectionView::SetFont(const BFont& font, float size)
{
BFont resizedFont(font);
resizedFont.SetSize(size);
SetFont(resizedFont);
}
void
FontSelectionView::SetFont(const BFont& font)
{
if (font == fCurrentFont && font == fSavedFont)
return;
_SelectCurrentFont(false);
fSavedFont = fCurrentFont = font;
_UpdateFontPreview();
_SelectCurrentFont(true);
_SelectCurrentSize(true);
}
void
FontSelectionView::SetSize(float size)
{
SetFont(fCurrentFont, size);
}
const BFont&
FontSelectionView::Font() const
{
return fCurrentFont;
}
void
FontSelectionView::SetDefaults()
{
BFont defaultFont = _DefaultFont();
if (defaultFont == fCurrentFont)
return;
_SelectCurrentFont(false);
fCurrentFont = defaultFont;
_UpdateFontPreview();
_SelectCurrentFont(true);
_SelectCurrentSize(true);
}
void
FontSelectionView::Revert()
{
if (!IsRevertable())
return;
_SelectCurrentFont(false);
fCurrentFont = fSavedFont;
_UpdateFontPreview();
_SelectCurrentFont(true);
_SelectCurrentSize(true);
}
bool
FontSelectionView::IsDefaultable()
{
return fCurrentFont != _DefaultFont();
}
bool
FontSelectionView::IsRevertable()
{
return fCurrentFont != fSavedFont;
}
void
FontSelectionView::UpdateFontsMenu()
{
int32 numFamilies = count_font_families();
fFontsMenu->RemoveItems(0, fFontsMenu->CountItems(), true);
BFont font = fCurrentFont;
font_family currentFamily;
font_style currentStyle;
font.GetFamilyAndStyle(&currentFamily, &currentStyle);
for (int32 i = 0; i < numFamilies; i++) {
font_family family;
uint32 flags;
if (get_font_family(i, &family, &flags) != B_OK)
continue;
// if we're setting the fixed font, we only want to show fixed fonts
if (!strcmp(Name(), "fixed") && (flags & B_IS_FIXED) == 0)
continue;
font.SetFamilyAndFace(family, B_REGULAR_FACE);
BMessage* message = new BMessage(kMsgSetFamily);
message->AddString("family", family);
message->AddString("name", Name());
BMenuItem* familyItem;
if (fStylesMenuField != NULL) {
familyItem = new BMenuItem(family, message);
} else {
// Each family item has a submenu with all styles for that font.
BMenu* stylesMenu = new BMenu(family);
_AddStylesToMenu(font, stylesMenu);
familyItem = new BMenuItem(stylesMenu, message);
}
familyItem->SetMarked(strcmp(family, currentFamily) == 0);
fFontsMenu->AddItem(familyItem);
familyItem->SetTarget(this);
}
// Separate styles menu for only the current font.
if (fStylesMenuField != NULL)
_AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu());
}
// #pragma mark - private
BLayoutItem*
FontSelectionView::CreateSizesLabelLayoutItem()
{
return fSizesMenuField->CreateLabelLayoutItem();
}
BLayoutItem*
FontSelectionView::CreateSizesMenuBarLayoutItem()
{
return fSizesMenuField->CreateMenuBarLayoutItem();
}
BLayoutItem*
FontSelectionView::CreateFontsLabelLayoutItem()
{
return fFontsMenuField->CreateLabelLayoutItem();
}
BLayoutItem*
FontSelectionView::CreateFontsMenuBarLayoutItem()
{
return fFontsMenuField->CreateMenuBarLayoutItem();
}
BLayoutItem*
FontSelectionView::CreateStylesLabelLayoutItem()
{
if (fStylesMenuField)
return fStylesMenuField->CreateLabelLayoutItem();
return NULL;
}
BLayoutItem*
FontSelectionView::CreateStylesMenuBarLayoutItem()
{
if (fStylesMenuField)
return fStylesMenuField->CreateMenuBarLayoutItem();
return NULL;
}
BView*
FontSelectionView::PreviewBox() const
{
return fPreviewText;
}
// #pragma mark - private
void
FontSelectionView::_Invoke()
{
if (fTarget != NULL && fTarget->Looper() != NULL && fMessage != NULL) {
BMessage message(*fMessage);
fTarget->Looper()->PostMessage(&message, fTarget);
}
}
BFont
FontSelectionView::_DefaultFont() const
{
if (strcmp(Name(), "bold") == 0)
return *be_bold_font;
if (strcmp(Name(), "fixed") == 0)
return *be_fixed_font;
else
return *be_plain_font;
}
void
FontSelectionView::_SelectCurrentFont(bool select)
{
font_family family;
font_style style;
fCurrentFont.GetFamilyAndStyle(&family, &style);
BMenuItem *item = fFontsMenu->FindItem(family);
if (item != NULL) {
item->SetMarked(select);
if (item->Submenu() != NULL) {
item = item->Submenu()->FindItem(style);
if (item != NULL)
item->SetMarked(select);
}
}
}
void
FontSelectionView::_SelectCurrentSize(bool select)
{
char label[16];
snprintf(label, sizeof(label), "%ld", (int32)fCurrentFont.Size());
BMenuItem* item = fSizesMenu->FindItem(label);
if (item != NULL)
item->SetMarked(select);
}
void
FontSelectionView::_UpdateFontPreview()
{
fPreviewText->SetFont(&fCurrentFont);
}
void
FontSelectionView::_BuildSizesMenu()
{
const int32 sizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 18, 21, 24, 0};
// build size menu
for (int32 i = 0; sizes[i]; i++) {
int32 size = sizes[i];
if (size < kMinSize || size > kMaxSize)
continue;
char label[32];
snprintf(label, sizeof(label), "%ld", size);
BMessage* message = new BMessage(kMsgSetSize);
message->AddInt32("size", size);
message->AddString("name", Name());
BMenuItem* item = new BMenuItem(label, message);
if (size == fCurrentFont.Size())
item->SetMarked(true);
fSizesMenu->AddItem(item);
item->SetTarget(this);
}
}
void
FontSelectionView::_AddStylesToMenu(const BFont& font, BMenu* stylesMenu) const
{
stylesMenu->RemoveItems(0, stylesMenu->CountItems(), true);
stylesMenu->SetRadioMode(true);
font_family family;
font_style style;
font.GetFamilyAndStyle(&family, &style);
BString currentStyle(style);
int32 numStyles = count_font_styles(family);
for (int32 j = 0; j < numStyles; j++) {
if (get_font_style(family, j, &style) != B_OK)
continue;
BMessage* message = new BMessage(kMsgSetStyle);
message->AddString("family", (char*)family);
message->AddString("style", (char*)style);
BMenuItem* item = new BMenuItem(style, message);
item->SetMarked(currentStyle == style);
stylesMenu->AddItem(item);
item->SetTarget(this);
}
}
@@ -0,0 +1,91 @@
/*
* Copyright 2001-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Mark Hogben
* DarkWyrm <[email protected]>
* Axel Dörfler, [email protected]
* Philippe Saint-Pierre, [email protected]
* Stephan Aßmus <[email protected]>
*/
#ifndef FONT_SELECTION_VIEW_H
#define FONT_SELECTION_VIEW_H
#include <Font.h>
#include <Handler.h>
class BLayoutItem;
class BBox;
class BMenu;
class BMenuField;
class BPopUpMenu;
class BStringView;
class BView;
class FontSelectionView : public BHandler {
public:
FontSelectionView(const char* name,
const char* label, bool separateStyles,
const BFont* font = NULL);
virtual ~FontSelectionView();
void AttachedToLooper();
virtual void MessageReceived(BMessage* message);
void SetMessage(BMessage* message);
void SetTarget(BHandler* target);
void SetFont(const BFont& font, float size);
void SetFont(const BFont& font);
void SetSize(float size);
const BFont& Font() const;
void SetDefaults();
void Revert();
bool IsDefaultable();
bool IsRevertable();
void UpdateFontsMenu();
BLayoutItem* CreateSizesLabelLayoutItem();
BLayoutItem* CreateSizesMenuBarLayoutItem();
BLayoutItem* CreateFontsLabelLayoutItem();
BLayoutItem* CreateFontsMenuBarLayoutItem();
BLayoutItem* CreateStylesLabelLayoutItem();
BLayoutItem* CreateStylesMenuBarLayoutItem();
BView* PreviewBox() const;
private:
void _Invoke();
BFont _DefaultFont() const;
void _SelectCurrentFont(bool select);
void _SelectCurrentSize(bool select);
void _UpdateFontPreview();
void _BuildSizesMenu();
void _AddStylesToMenu(const BFont& font,
BMenu* menu) const;
protected:
BMenuField* fFontsMenuField;
BMenuField* fStylesMenuField;
BMenuField* fSizesMenuField;
BPopUpMenu* fFontsMenu;
BPopUpMenu* fStylesMenu;
BPopUpMenu* fSizesMenu;
BStringView* fPreviewText;
BFont fSavedFont;
BFont fCurrentFont;
BMessage* fMessage;
BHandler* fTarget;
};
#endif // FONT_SELECTION_VIEW_H
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright 2010, Stephan Aßmus <[email protected]>. All rights reserved.
* Copyright 2004-2007, Ingo Weinhold <[email protected]>. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef HASH_KEYS_H
#define HASH_KEYS_H
#include <String.h>
namespace BPrivate {
#if 0
// TODO: Move here from HashMap.h and adapt all clients.
// HashKey32
template<typename Value>
struct HashKey32 {
HashKey32() {}
HashKey32(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
return (uint32)value;
}
HashKey32<Value> operator=(const HashKey32<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey32<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey32<Value>& other) const
{
return (value != other.value);
}
Value value;
};
// HashKey64
template<typename Value>
struct HashKey64 {
HashKey64() {}
HashKey64(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
uint64 v = (uint64)value;
return (uint32)(v >> 32) ^ (uint32)v;
}
HashKey64<Value> operator=(const HashKey64<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey64<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey64<Value>& other) const
{
return (value != other.value);
}
Value value;
};
#endif
struct HashKeyString {
HashKeyString() {}
HashKeyString(const BString& value) : value(value) {}
HashKeyString(const char* string) : value(string) {}
uint32 GetHashCode() const
{
// from the Dragon Book: a slightly modified hashpjw()
uint32 hash = 0;
const char* string = value.String();
if (string != NULL) {
for (; *string; string++) {
uint32 g = hash & 0xf0000000;
if (g != 0)
hash ^= g >> 24;
hash = (hash << 4) + *string;
}
}
return hash;
}
HashKeyString operator=(const HashKeyString& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKeyString& other) const
{
return (value == other.value);
}
bool operator!=(const HashKeyString& other) const
{
return (value != other.value);
}
BString value;
};
} // namespace BPrivate
using BPrivate::HashKeyString;
#endif // HASH_KEYS_H
+481
View File
@@ -0,0 +1,481 @@
// HashMap.h
//
// Copyright (c) 2004-2007, Ingo Weinhold ([email protected])
//
// 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.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include <Locker.h>
#include "AutoLocker.h"
#include "OpenHashTable.h"
namespace BPrivate {
// HashMapElement
template<typename Key, typename Value>
class HashMapElement : public OpenHashElement {
private:
typedef HashMapElement<Key, Value> Element;
public:
HashMapElement() : OpenHashElement(), fKey(), fValue()
{
fNext = -1;
}
inline uint32 Hash() const
{
return fKey.GetHashCode();
}
inline bool operator==(const OpenHashElement &_element) const
{
const Element &element = static_cast<const Element&>(_element);
return (fKey == element.fKey);
}
inline void Adopt(Element &element)
{
fKey = element.fKey;
fValue = element.fValue;
}
Key fKey;
Value fValue;
};
// HashMap
template<typename Key, typename Value>
class HashMap {
public:
class Entry {
public:
Entry() {}
Entry(const Key& key, Value value) : key(key), value(value) {}
Key key;
Value value;
};
class Iterator {
private:
typedef HashMapElement<Key, Value> Element;
public:
Iterator(const Iterator& other)
:
fMap(other.fMap),
fIndex(other.fIndex),
fElement(other.fElement),
fLastElement(other.fElement)
{
}
bool HasNext() const
{
return fElement;
}
Entry Next()
{
if (!fElement)
return Entry();
Entry result(fElement->fKey, fElement->fValue);
_FindNext();
return result;
}
Value* NextValue()
{
if (fElement == NULL)
return NULL;
Value* value = &fElement->fValue;
_FindNext();
return value;
}
Entry Remove()
{
if (!fLastElement)
return Entry();
Entry result(fLastElement->fKey, fLastElement->fValue);
fMap->fTable.Remove(fLastElement, true);
fLastElement = NULL;
return result;
}
Iterator& operator=(const Iterator& other)
{
fMap = other.fMap;
fIndex = other.fIndex;
fElement = other.fElement;
fLastElement = other.fLastElement;
return *this;
}
private:
Iterator(const HashMap<Key, Value>* map)
:
fMap(const_cast<HashMap<Key, Value>*>(map)),
fIndex(0),
fElement(NULL),
fLastElement(NULL)
{
// find first
_FindNext();
}
void _FindNext()
{
fLastElement = fElement;
if (fElement && fElement->fNext >= 0) {
fElement = fMap->fTable.ElementAt(fElement->fNext);
return;
}
fElement = NULL;
int32 arraySize = fMap->fTable.ArraySize();
for (; !fElement && fIndex < arraySize; fIndex++)
fElement = fMap->fTable.FindFirst(fIndex);
}
private:
friend class HashMap<Key, Value>;
HashMap<Key, Value>* fMap;
int32 fIndex;
Element* fElement;
Element* fLastElement;
};
HashMap();
~HashMap();
status_t InitCheck() const;
status_t Put(const Key& key, Value value);
Value Remove(const Key& key);
void Clear();
Value Get(const Key& key) const;
bool Get(const Key& key, Value*& _value) const;
bool ContainsKey(const Key& key) const;
int32 Size() const;
Iterator GetIterator() const;
protected:
typedef HashMapElement<Key, Value> Element;
friend class Iterator;
private:
Element *_FindElement(const Key& key) const;
protected:
OpenHashElementArray<Element> fElementArray;
OpenHashTable<Element, OpenHashElementArray<Element> > fTable;
};
// SynchronizedHashMap
template<typename Key, typename Value>
class SynchronizedHashMap : public BLocker {
public:
typedef struct HashMap<Key, Value>::Entry Entry;
typedef struct HashMap<Key, Value>::Iterator Iterator;
SynchronizedHashMap() : BLocker("synchronized hash map") {}
~SynchronizedHashMap() { Lock(); }
status_t InitCheck() const
{
return fMap.InitCheck();
}
status_t Put(const Key& key, Value value)
{
MapLocker locker(this);
if (!locker.IsLocked())
return B_ERROR;
return fMap.Put(key, value);
}
Value Remove(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return Value();
return fMap.Remove(key);
}
void Clear()
{
MapLocker locker(this);
return fMap.Clear();
}
Value Get(const Key& key) const
{
const BLocker* lock = this;
MapLocker locker(const_cast<BLocker*>(lock));
if (!locker.IsLocked())
return Value();
return fMap.Get(key);
}
bool ContainsKey(const Key& key) const
{
const BLocker* lock = this;
MapLocker locker(const_cast<BLocker*>(lock));
if (!locker.IsLocked())
return false;
return fMap.ContainsKey(key);
}
int32 Size() const
{
const BLocker* lock = this;
MapLocker locker(const_cast<BLocker*>(lock));
return fMap.Size();
}
Iterator GetIterator()
{
return fMap.GetIterator();
}
// for debugging only
const HashMap<Key, Value>& GetUnsynchronizedMap() const { return fMap; }
HashMap<Key, Value>& GetUnsynchronizedMap() { return fMap; }
protected:
typedef AutoLocker<BLocker> MapLocker;
HashMap<Key, Value> fMap;
};
// HashKey32
template<typename Value>
struct HashKey32 {
HashKey32() {}
HashKey32(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
return (uint32)value;
}
HashKey32<Value> operator=(const HashKey32<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey32<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey32<Value>& other) const
{
return (value != other.value);
}
Value value;
};
// HashKey64
template<typename Value>
struct HashKey64 {
HashKey64() {}
HashKey64(const Value& value) : value(value) {}
uint32 GetHashCode() const
{
uint64 v = (uint64)value;
return (uint32)(v >> 32) ^ (uint32)v;
}
HashKey64<Value> operator=(const HashKey64<Value>& other)
{
value = other.value;
return *this;
}
bool operator==(const HashKey64<Value>& other) const
{
return (value == other.value);
}
bool operator!=(const HashKey64<Value>& other) const
{
return (value != other.value);
}
Value value;
};
// HashMap
// constructor
template<typename Key, typename Value>
HashMap<Key, Value>::HashMap()
:
fElementArray(1000),
fTable(1000, &fElementArray)
{
}
// destructor
template<typename Key, typename Value>
HashMap<Key, Value>::~HashMap()
{
}
// InitCheck
template<typename Key, typename Value>
status_t
HashMap<Key, Value>::InitCheck() const
{
return (fTable.InitCheck() && fElementArray.InitCheck()
? B_OK : B_NO_MEMORY);
}
// Put
template<typename Key, typename Value>
status_t
HashMap<Key, Value>::Put(const Key& key, Value value)
{
Element* element = _FindElement(key);
if (element) {
// already contains the key: just set the new value
element->fValue = value;
return B_OK;
}
// does not contain the key yet: add an element
element = fTable.Add(key.GetHashCode());
if (!element)
return B_NO_MEMORY;
element->fKey = key;
element->fValue = value;
return B_OK;
}
// Remove
template<typename Key, typename Value>
Value
HashMap<Key, Value>::Remove(const Key& key)
{
Value value = Value();
if (Element* element = _FindElement(key)) {
value = element->fValue;
fTable.Remove(element);
}
return value;
}
// Clear
template<typename Key, typename Value>
void
HashMap<Key, Value>::Clear()
{
fTable.RemoveAll();
}
// Get
template<typename Key, typename Value>
Value
HashMap<Key, Value>::Get(const Key& key) const
{
if (Element* element = _FindElement(key))
return element->fValue;
return Value();
}
// Get
template<typename Key, typename Value>
bool
HashMap<Key, Value>::Get(const Key& key, Value*& _value) const
{
if (Element* element = _FindElement(key)) {
_value = &element->fValue;
return true;
}
return false;
}
// ContainsKey
template<typename Key, typename Value>
bool
HashMap<Key, Value>::ContainsKey(const Key& key) const
{
return _FindElement(key);
}
// Size
template<typename Key, typename Value>
int32
HashMap<Key, Value>::Size() const
{
return fTable.CountElements();
}
// GetIterator
template<typename Key, typename Value>
struct HashMap<Key, Value>::Iterator
HashMap<Key, Value>::GetIterator() const
{
return Iterator(this);
}
// _FindElement
template<typename Key, typename Value>
struct HashMap<Key, Value>::Element *
HashMap<Key, Value>::_FindElement(const Key& key) const
{
Element* element = fTable.FindFirst(key.GetHashCode());
while (element && element->fKey != key) {
if (element->fNext >= 0)
element = fTable.ElementAt(element->fNext);
else
element = NULL;
}
return element;
}
} // namespace BPrivate
using BPrivate::HashMap;
using BPrivate::HashKey32;
using BPrivate::HashKey64;
using BPrivate::SynchronizedHashMap;
#endif // HASH_MAP_H
+342
View File
@@ -0,0 +1,342 @@
// HashSet.h
//
// Copyright (c) 2004, Ingo Weinhold ([email protected])
//
// 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.
//
// Except as contained in this notice, the name of a copyright holder shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization of the
// copyright holder.
#ifndef HASH_SET_H
#define HASH_SET_H
#include <Locker.h>
#include "AutoLocker.h"
#include "OpenHashTable.h"
namespace BPrivate {
// HashSetElement
template<typename Key>
class HashSetElement : public OpenHashElement {
private:
typedef HashSetElement<Key> Element;
public:
HashSetElement() : OpenHashElement(), fKey()
{
fNext = -1;
}
inline uint32 Hash() const
{
return fKey.GetHashCode();
}
inline bool operator==(const OpenHashElement &_element) const
{
const Element &element = static_cast<const Element&>(_element);
return (fKey == element.fKey);
}
inline void Adopt(Element &element)
{
fKey = element.fKey;
}
Key fKey;
};
// HashSet
template<typename Key>
class HashSet {
public:
class Iterator {
private:
typedef HashSetElement<Key> Element;
public:
Iterator(const Iterator& other)
: fSet(other.fSet),
fIndex(other.fIndex),
fElement(other.fElement),
fLastElement(other.fElement)
{
}
bool HasNext() const
{
return fElement;
}
Key Next()
{
if (!fElement)
return Key();
Key result(fElement->fKey);
_FindNext();
return result;
}
bool Remove()
{
if (!fLastElement)
return false;
fSet->fTable.Remove(fLastElement);
fLastElement = NULL;
return true;
}
Iterator& operator=(const Iterator& other)
{
fSet = other.fSet;
fIndex = other.fIndex;
fElement = other.fElement;
fLastElement = other.fLastElement;
return *this;
}
private:
Iterator(HashSet<Key>* map)
: fSet(map),
fIndex(0),
fElement(NULL),
fLastElement(NULL)
{
// find first
_FindNext();
}
void _FindNext()
{
fLastElement = fElement;
if (fElement && fElement->fNext >= 0) {
fElement = fSet->fTable.ElementAt(fElement->fNext);
return;
}
fElement = NULL;
int32 arraySize = fSet->fTable.ArraySize();
for (; !fElement && fIndex < arraySize; fIndex++)
fElement = fSet->fTable.FindFirst(fIndex);
}
private:
friend class HashSet<Key>;
HashSet<Key>* fSet;
int32 fIndex;
Element* fElement;
Element* fLastElement;
};
HashSet();
~HashSet();
status_t InitCheck() const;
status_t Add(const Key& key);
bool Remove(const Key& key);
void Clear();
bool Contains(const Key& key) const;
int32 Size() const;
bool IsEmpty() const { return Size() == 0; }
Iterator GetIterator();
protected:
typedef HashSetElement<Key> Element;
friend class Iterator;
private:
Element *_FindElement(const Key& key) const;
protected:
OpenHashElementArray<Element> fElementArray;
OpenHashTable<Element, OpenHashElementArray<Element> > fTable;
};
// SynchronizedHashSet
template<typename Key>
class SynchronizedHashSet : public BLocker {
public:
typedef struct HashSet<Key>::Iterator Iterator;
SynchronizedHashSet() : BLocker("synchronized hash set") {}
~SynchronizedHashSet() { Lock(); }
status_t InitCheck() const
{
return fSet.InitCheck();
}
status_t Add(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return B_ERROR;
return fSet.Add(key);
}
bool Remove(const Key& key)
{
MapLocker locker(this);
if (!locker.IsLocked())
return false;
return fSet.Remove(key);
}
bool Contains(const Key& key) const
{
const BLocker* lock = this;
MapLocker locker(const_cast<BLocker*>(lock));
if (!locker.IsLocked())
return false;
return fSet.Contains(key);
}
int32 Size() const
{
const BLocker* lock = this;
MapLocker locker(const_cast<BLocker*>(lock));
return fSet.Size();
}
Iterator GetIterator()
{
return fSet.GetIterator();
}
// for debugging only
const HashSet<Key>& GetUnsynchronizedSet() const { return fSet; }
HashSet<Key>& GetUnsynchronizedSet() { return fSet; }
protected:
typedef AutoLocker<BLocker> MapLocker;
HashSet<Key> fSet;
};
// HashSet
// constructor
template<typename Key>
HashSet<Key>::HashSet()
: fElementArray(1000),
fTable(1000, &fElementArray)
{
}
// destructor
template<typename Key>
HashSet<Key>::~HashSet()
{
}
// InitCheck
template<typename Key>
status_t
HashSet<Key>::InitCheck() const
{
return (fTable.InitCheck() && fElementArray.InitCheck()
? B_OK : B_NO_MEMORY);
}
// Add
template<typename Key>
status_t
HashSet<Key>::Add(const Key& key)
{
if (Contains(key))
return B_OK;
Element* element = fTable.Add(key.GetHashCode());
if (!element)
return B_NO_MEMORY;
element->fKey = key;
return B_OK;
}
// Remove
template<typename Key>
bool
HashSet<Key>::Remove(const Key& key)
{
if (Element* element = _FindElement(key)) {
fTable.Remove(element);
return true;
}
return false;
}
// Clear
template<typename Key>
void
HashSet<Key>::Clear()
{
fTable.RemoveAll();
}
// Contains
template<typename Key>
bool
HashSet<Key>::Contains(const Key& key) const
{
return _FindElement(key);
}
// Size
template<typename Key>
int32
HashSet<Key>::Size() const
{
return fTable.CountElements();
}
// GetIterator
template<typename Key>
struct HashSet<Key>::Iterator
HashSet<Key>::GetIterator()
{
return Iterator(this);
}
// _FindElement
template<typename Key>
struct HashSet<Key>::Element *
HashSet<Key>::_FindElement(const Key& key) const
{
Element* element = fTable.FindFirst(key.GetHashCode());
while (element && element->fKey != key) {
if (element->fNext >= 0)
element = fTable.ElementAt(element->fNext);
else
element = NULL;
}
return element;
}
} // namespace BPrivate
using BPrivate::HashSet;
using BPrivate::SynchronizedHashSet;
#endif // HASH_SET_H
+929
View File
@@ -0,0 +1,929 @@
/*
* Copyright 2006-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic
// it should be placed into a common folder for generic useful stuff
#include "IconButton.h"
#include <new>
#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <Control.h>
#include <ControlLook.h>
#include <Entry.h>
#include <Looper.h>
#include <Message.h>
#include <Mime.h>
#include <Path.h>
#include <Region.h>
#include <Resources.h>
#include <Roster.h>
#include <TranslationUtils.h>
#include <Window.h>
#include "IconUtils.h"
using std::nothrow;
// constructor
IconButton::IconButton(const char* name, uint32 id, const char* label,
BMessage* message, BHandler* target)
: BView(name, B_WILL_DRAW),
BInvoker(message, target),
fButtonState(STATE_ENABLED),
fID(id),
fNormalBitmap(NULL),
fDisabledBitmap(NULL),
fClickedBitmap(NULL),
fDisabledClickedBitmap(NULL),
fLabel(label),
fTargetCache(target)
{
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetViewColor(B_TRANSPARENT_32_BIT);
}
// destructor
IconButton::~IconButton()
{
_DeleteBitmaps();
}
// MessageReceived
void
IconButton::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BView::MessageReceived(message);
break;
}
}
// AttachedToWindow
void
IconButton::AttachedToWindow()
{
rgb_color background = B_TRANSPARENT_COLOR;
if (BView* parent = Parent()) {
background = parent->ViewColor();
if (background == B_TRANSPARENT_COLOR)
background = parent->LowColor();
}
if (background == B_TRANSPARENT_COLOR)
background = ui_color(B_PANEL_BACKGROUND_COLOR);
SetLowColor(background);
SetTarget(fTargetCache);
if (!Target())
SetTarget(Window());
}
// Draw
void
IconButton::Draw(BRect area)
{
rgb_color background = LowColor();
BRect r(Bounds());
if (be_control_look != NULL) {
uint32 flags = 0;
BBitmap* bitmap = fNormalBitmap;
if (!IsEnabled()) {
flags |= BControlLook::B_DISABLED;
bitmap = fDisabledBitmap;
}
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
flags |= BControlLook::B_ACTIVATED;
if (DrawBorder()) {
be_control_look->DrawButtonFrame(this, r, area, background,
background, flags);
be_control_look->DrawButtonBackground(this, r, area, background,
flags);
} else {
SetHighColor(background);
FillRect(r);
}
if (bitmap && bitmap->IsValid()) {
float x = r.left + floorf((r.Width()
- bitmap->Bounds().Width()) / 2.0 + 0.5);
float y = r.top + floorf((r.Height()
- bitmap->Bounds().Height()) / 2.0 + 0.5);
BPoint point(x, y);
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
point += BPoint(1.0, 1.0);
if (bitmap->ColorSpace() == B_RGBA32
|| bitmap->ColorSpace() == B_RGBA32_BIG) {
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
}
DrawBitmap(bitmap, point);
}
return;
}
rgb_color lightShadow, shadow, darkShadow, light;
BBitmap* bitmap = fNormalBitmap;
// adjust colors and bitmap according to flags
if (IsEnabled()) {
lightShadow = tint_color(background, B_DARKEN_1_TINT);
shadow = tint_color(background, B_DARKEN_2_TINT);
darkShadow = tint_color(background, B_DARKEN_4_TINT);
light = tint_color(background, B_LIGHTEN_MAX_TINT);
SetHighColor(0, 0, 0, 255);
} else {
lightShadow = tint_color(background, 1.11);
shadow = tint_color(background, B_DARKEN_1_TINT);
darkShadow = tint_color(background, B_DARKEN_2_TINT);
light = tint_color(background, B_LIGHTEN_2_TINT);
bitmap = fDisabledBitmap;
SetHighColor(tint_color(background, B_DISABLED_LABEL_TINT));
}
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) {
if (IsEnabled()) {
// background = tint_color(background, B_DARKEN_2_TINT);
// background = tint_color(background, B_LIGHTEN_1_TINT);
background = tint_color(background, B_DARKEN_1_TINT);
bitmap = fClickedBitmap;
} else {
// background = tint_color(background, B_DARKEN_1_TINT);
// background = tint_color(background, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0);
background = tint_color(background, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
bitmap = fDisabledClickedBitmap;
}
// background
SetLowColor(background);
r.InsetBy(2.0, 2.0);
StrokeLine(r.LeftBottom(), r.LeftTop(), B_SOLID_LOW);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_LOW);
r.InsetBy(-2.0, -2.0);
}
// draw frame only if tracking
if (DrawBorder()) {
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
DrawPressedBorder(r, background, shadow, darkShadow, lightShadow, light);
else
DrawNormalBorder(r, background, shadow, darkShadow, lightShadow, light);
r.InsetBy(2.0, 2.0);
} else
_DrawFrame(r, background, background, background, background);
float width = Bounds().Width();
float height = Bounds().Height();
// bitmap
BRegion originalClippingRegion;
if (bitmap && bitmap->IsValid()) {
float x = floorf((width - bitmap->Bounds().Width()) / 2.0 + 0.5);
float y = floorf((height - bitmap->Bounds().Height()) / 2.0 + 0.5);
BPoint point(x, y);
if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED))
point += BPoint(1.0, 1.0);
if (bitmap->ColorSpace() == B_RGBA32 || bitmap->ColorSpace() == B_RGBA32_BIG) {
FillRect(r, B_SOLID_LOW);
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
}
DrawBitmap(bitmap, point);
// constrain clipping region
BRegion region= originalClippingRegion;
GetClippingRegion(&region);
region.Exclude(bitmap->Bounds().OffsetByCopy(point));
ConstrainClippingRegion(&region);
}
// background
SetDrawingMode(B_OP_COPY);
FillRect(r, B_SOLID_LOW);
ConstrainClippingRegion(NULL);
// label
if (fLabel.CountChars() > 0) {
SetDrawingMode(B_OP_COPY);
font_height fh;
GetFontHeight(&fh);
float y = Bounds().bottom - 4.0;
y -= fh.descent;
float x = (width - StringWidth(fLabel.String())) / 2.0;
DrawString(fLabel.String(), BPoint(x, y));
}
}
// MouseDown
void
IconButton::MouseDown(BPoint where)
{
if (!IsValid())
return;
if (_HasFlags(STATE_ENABLED)/* && !_HasFlags(STATE_FORCE_PRESSED)*/) {
if (Bounds().Contains(where)) {
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
_AddFlags(STATE_PRESSED | STATE_TRACKING);
} else {
_ClearFlags(STATE_PRESSED | STATE_TRACKING);
}
}
}
// MouseUp
void
IconButton::MouseUp(BPoint where)
{
if (!IsValid())
return;
// if (!_HasFlags(STATE_FORCE_PRESSED)) {
if (_HasFlags(STATE_ENABLED) && _HasFlags(STATE_PRESSED) && Bounds().Contains(where))
Invoke();
else if (Bounds().Contains(where))
_AddFlags(STATE_INSIDE);
_ClearFlags(STATE_PRESSED | STATE_TRACKING);
// }
}
// MouseMoved
void
IconButton::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
{
if (!IsValid())
return;
uint32 buttons = 0;
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
// catch a mouse up event that we might have missed
if (!buttons && _HasFlags(STATE_PRESSED)) {
MouseUp(where);
return;
}
if (buttons && !_HasFlags(STATE_TRACKING))
return;
if ((transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW)
&& _HasFlags(STATE_ENABLED))
_AddFlags(STATE_INSIDE);
else
_ClearFlags(STATE_INSIDE);
if (_HasFlags(STATE_TRACKING)) {
if (Bounds().Contains(where))
_AddFlags(STATE_PRESSED);
else
_ClearFlags(STATE_PRESSED);
}
}
#define MIN_SPACE 15.0
// GetPreferredSize
void
IconButton::GetPreferredSize(float* width, float* height)
{
float minWidth = 0.0;
float minHeight = 0.0;
if (IsValid()) {
minWidth += fNormalBitmap->Bounds().IntegerWidth() + 1.0;
minHeight += fNormalBitmap->Bounds().IntegerHeight() + 1.0;
}
if (minWidth < MIN_SPACE)
minWidth = MIN_SPACE;
if (minHeight < MIN_SPACE)
minHeight = MIN_SPACE;
float hPadding = max_c(6.0, ceilf(minHeight / 4.0));
float vPadding = max_c(6.0, ceilf(minWidth / 4.0));
if (fLabel.CountChars() > 0) {
font_height fh;
GetFontHeight(&fh);
minHeight += ceilf(fh.ascent + fh.descent) + vPadding;
minWidth += StringWidth(fLabel.String()) + vPadding;
}
if (width)
*width = minWidth + hPadding;
if (height)
*height = minHeight + vPadding;
}
// MinSize
BSize
IconButton::MinSize()
{
BSize size;
GetPreferredSize(&size.width, &size.height);
return size;
}
// MaxSize
BSize
IconButton::MaxSize()
{
return MinSize();
}
// Invoke
status_t
IconButton::Invoke(BMessage* message)
{
if (!message)
message = Message();
if (message) {
BMessage clone(*message);
clone.AddInt64("be:when", system_time());
clone.AddPointer("be:source", (BView*)this);
clone.AddInt32("be:value", Value());
clone.AddInt32("id", ID());
return BInvoker::Invoke(&clone);
}
return BInvoker::Invoke(message);
}
// SetPressed
void
IconButton::SetPressed(bool pressed)
{
if (pressed)
_AddFlags(STATE_FORCE_PRESSED);
else
_ClearFlags(STATE_FORCE_PRESSED);
}
// IsPressed
bool
IconButton::IsPressed() const
{
return _HasFlags(STATE_FORCE_PRESSED);
}
status_t
IconButton::SetIcon(int32 resourceID)
{
app_info info;
status_t status = be_app->GetAppInfo(&info);
if (status != B_OK)
return status;
BResources resources(&info.ref);
status = resources.InitCheck();
if (status != B_OK)
return status;
size_t size;
const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID,
&size);
if (data != NULL) {
BBitmap bitmap(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_RGBA32);
status = bitmap.InitCheck();
if (status != B_OK)
return status;
status = BIconUtils::GetVectorIcon(reinterpret_cast<const uint8*>(data),
size, &bitmap);
if (status != B_OK)
return status;
return SetIcon(&bitmap);
}
// const void* data = resources.LoadResource(B_BITMAP_TYPE, resourceID, &size);
return B_ERROR;
}
// SetIcon
status_t
IconButton::SetIcon(const char* pathToBitmap)
{
if (pathToBitmap == NULL)
return B_BAD_VALUE;
status_t status = B_BAD_VALUE;
BBitmap* fileBitmap = NULL;
// try to load bitmap from either relative or absolute path
BEntry entry(pathToBitmap, true);
if (!entry.Exists()) {
app_info info;
status = be_app->GetAppInfo(&info);
if (status == B_OK) {
BEntry app_entry(&info.ref, true);
BPath path;
app_entry.GetPath(&path);
status = path.InitCheck();
if (status == B_OK) {
status = path.GetParent(&path);
if (status == B_OK) {
status = path.Append(pathToBitmap, true);
if (status == B_OK)
fileBitmap = BTranslationUtils::GetBitmap(path.Path());
else
printf("IconButton::SetIcon() - path.Append() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - path.GetParent() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - path.InitCheck() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - be_app->GetAppInfo() failed: %s\n", strerror(status));
} else
fileBitmap = BTranslationUtils::GetBitmap(pathToBitmap);
if (fileBitmap) {
status = _MakeBitmaps(fileBitmap);
delete fileBitmap;
} else
status = B_ERROR;
return status;
}
// SetIcon
status_t
IconButton::SetIcon(const BBitmap* bitmap)
{
if (bitmap && bitmap->ColorSpace() == B_CMAP8) {
status_t status = bitmap->InitCheck();
if (status >= B_OK) {
if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap)) {
status = _MakeBitmaps(rgb32Bitmap);
delete rgb32Bitmap;
} else
status = B_NO_MEMORY;
}
return status;
} else
return _MakeBitmaps(bitmap);
}
// SetIcon
status_t
IconButton::SetIcon(const BMimeType* fileType, bool small)
{
status_t status = fileType ? fileType->InitCheck() : B_BAD_VALUE;
if (status >= B_OK) {
BBitmap* mimeBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_CMAP8);
if (mimeBitmap && mimeBitmap->IsValid()) {
status = fileType->GetIcon(mimeBitmap, small ? B_MINI_ICON : B_LARGE_ICON);
if (status >= B_OK) {
if (BBitmap* bitmap = _ConvertToRGB32(mimeBitmap)) {
status = _MakeBitmaps(bitmap);
delete bitmap;
} else
printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n");
} else
printf("IconButton::SetIcon() - fileType->GetIcon() failed: %s\n", strerror(status));
} else
printf("IconButton::SetIcon() - B_CMAP8 bitmap is not valid\n");
delete mimeBitmap;
} else
printf("IconButton::SetIcon() - fileType is not valid: %s\n", strerror(status));
return status;
}
// SetIcon
status_t
IconButton::SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height, color_space format, bool convertToBW)
{
status_t status = B_BAD_VALUE;
if (bitsFromQuickRes && width > 0 && height > 0) {
BBitmap* quickResBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, width - 1.0, height - 1.0), format);
status = quickResBitmap ? quickResBitmap->InitCheck() : B_ERROR;
if (status >= B_OK) {
// It doesn't look right to copy BitsLength() bytes, but bitmaps
// exported from QuickRes still contain their padding, so it is alright.
memcpy(quickResBitmap->Bits(), bitsFromQuickRes, quickResBitmap->BitsLength());
if (format != B_RGB32 && format != B_RGBA32 && format != B_RGB32_BIG && format != B_RGBA32_BIG) {
// colorspace needs conversion
BBitmap* bitmap = new(nothrow) BBitmap(quickResBitmap->Bounds(), B_RGB32, true);
if (bitmap && bitmap->IsValid()) {
BView* helper = new BView(bitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW);
if (bitmap->Lock()) {
bitmap->AddChild(helper);
helper->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
helper->FillRect(helper->Bounds());
helper->SetDrawingMode(B_OP_OVER);
helper->DrawBitmap(quickResBitmap, BPoint(0.0, 0.0));
helper->Sync();
bitmap->Unlock();
}
status = _MakeBitmaps(bitmap);
} else
printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n");
delete bitmap;
} else {
// native colorspace (32 bits)
if (convertToBW) {
// convert to gray scale icon
uint8* bits = (uint8*)quickResBitmap->Bits();
uint32 bpr = quickResBitmap->BytesPerRow();
for (uint32 y = 0; y < height; y++) {
uint8* handle = bits;
uint8 gray;
for (uint32 x = 0; x < width; x++) {
gray = uint8((116 * handle[0] + 600 * handle[1] + 308 * handle[2]) / 1024);
handle[0] = gray;
handle[1] = gray;
handle[2] = gray;
handle += 4;
}
bits += bpr;
}
}
status = _MakeBitmaps(quickResBitmap);
}
} else
printf("IconButton::SetIcon() - error allocating bitmap: %s\n", strerror(status));
delete quickResBitmap;
}
return status;
}
// ClearIcon
void
IconButton::ClearIcon()
{
_DeleteBitmaps();
_Update();
}
void
IconButton::TrimIcon(bool keepAspect)
{
if (fNormalBitmap == NULL)
return;
uint8* bits = (uint8*)fNormalBitmap->Bits();
uint32 bpr = fNormalBitmap->BytesPerRow();
uint32 width = fNormalBitmap->Bounds().IntegerWidth() + 1;
uint32 height = fNormalBitmap->Bounds().IntegerHeight() + 1;
BRect trimmed(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
for (uint32 y = 0; y < height; y++) {
uint8* b = bits + 3;
bool rowHasAlpha = false;
for (uint32 x = 0; x < width; x++) {
if (*b) {
rowHasAlpha = true;
if (x < trimmed.left)
trimmed.left = x;
if (x > trimmed.right)
trimmed.right = x;
}
b += 4;
}
if (rowHasAlpha) {
if (y < trimmed.top)
trimmed.top = y;
if (y > trimmed.bottom)
trimmed.bottom = y;
}
bits += bpr;
}
if (!trimmed.IsValid())
return;
if (keepAspect) {
float minInset = trimmed.left;
minInset = min_c(minInset, trimmed.top);
minInset = min_c(minInset, fNormalBitmap->Bounds().right - trimmed.right);
minInset = min_c(minInset, fNormalBitmap->Bounds().bottom - trimmed.bottom);
trimmed = fNormalBitmap->Bounds().InsetByCopy(minInset, minInset);
}
trimmed = trimmed & fNormalBitmap->Bounds();
BBitmap trimmedBitmap(trimmed.OffsetToCopy(B_ORIGIN),
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
bits = (uint8*)fNormalBitmap->Bits();
bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top;
uint8* dst = (uint8*)trimmedBitmap.Bits();
uint32 trimmedWidth = trimmedBitmap.Bounds().IntegerWidth() + 1;
uint32 trimmedHeight = trimmedBitmap.Bounds().IntegerHeight() + 1;
uint32 trimmedBPR = trimmedBitmap.BytesPerRow();
for (uint32 y = 0; y < trimmedHeight; y++) {
memcpy(dst, bits, trimmedWidth * 4);
dst += trimmedBPR;
bits += bpr;
}
SetIcon(&trimmedBitmap);
}
// Bitmap
BBitmap*
IconButton::Bitmap() const
{
BBitmap* bitmap = NULL;
if (fNormalBitmap && fNormalBitmap->IsValid()) {
bitmap = new(nothrow) BBitmap(fNormalBitmap);
if (bitmap->IsValid()) {
// TODO: remove this functionality when we use real transparent bitmaps
uint8* bits = (uint8*)bitmap->Bits();
uint32 bpr = bitmap->BytesPerRow();
uint32 width = bitmap->Bounds().IntegerWidth() + 1;
uint32 height = bitmap->Bounds().IntegerHeight() + 1;
color_space format = bitmap->ColorSpace();
if (format == B_CMAP8) {
// replace gray with magic transparent index
} else if (format == B_RGB32) {
for (uint32 y = 0; y < height; y++) {
uint8* bitsHandle = bits;
for (uint32 x = 0; x < width; x++) {
if (bitsHandle[0] == 216
&& bitsHandle[1] == 216
&& bitsHandle[2] == 216) {
bitsHandle[3] = 0; // make this pixel completely transparent
}
bitsHandle += 4;
}
bits += bpr;
}
}
} else {
delete bitmap;
bitmap = NULL;
}
}
return bitmap;
}
// DrawBorder
bool
IconButton::DrawBorder() const
{
return ((IsEnabled() && (_HasFlags(STATE_INSIDE)
|| _HasFlags(STATE_TRACKING))) || _HasFlags(STATE_FORCE_PRESSED));
}
// DrawNormalBorder
void
IconButton::DrawNormalBorder(BRect r, rgb_color background,
rgb_color shadow, rgb_color darkShadow,
rgb_color lightShadow, rgb_color light)
{
_DrawFrame(r, shadow, darkShadow, light, lightShadow);
}
// DrawPressedBorder
void
IconButton::DrawPressedBorder(BRect r, rgb_color background,
rgb_color shadow, rgb_color darkShadow,
rgb_color lightShadow, rgb_color light)
{
_DrawFrame(r, shadow, light, darkShadow, background);
}
// IsValid
bool
IconButton::IsValid() const
{
return (fNormalBitmap && fDisabledBitmap && fClickedBitmap
&& fDisabledClickedBitmap
&& fNormalBitmap->IsValid()
&& fDisabledBitmap->IsValid()
&& fClickedBitmap->IsValid()
&& fDisabledClickedBitmap->IsValid());
}
// Value
int32
IconButton::Value() const
{
return _HasFlags(STATE_PRESSED) ? B_CONTROL_ON : B_CONTROL_OFF;
}
// SetValue
void
IconButton::SetValue(int32 value)
{
if (value)
_AddFlags(STATE_PRESSED);
else
_ClearFlags(STATE_PRESSED);
}
// IsEnabled
bool
IconButton::IsEnabled() const
{
return _HasFlags(STATE_ENABLED) ? B_CONTROL_ON : B_CONTROL_OFF;
}
// SetEnabled
void
IconButton::SetEnabled(bool enabled)
{
if (enabled)
_AddFlags(STATE_ENABLED);
else
_ClearFlags(STATE_ENABLED | STATE_TRACKING | STATE_INSIDE);
}
// _ConvertToRGB32
BBitmap*
IconButton::_ConvertToRGB32(const BBitmap* bitmap) const
{
BBitmap* convertedBitmap = new(nothrow) BBitmap(bitmap->Bounds(),
B_BITMAP_ACCEPTS_VIEWS, B_RGBA32);
if (convertedBitmap && convertedBitmap->IsValid()) {
memset(convertedBitmap->Bits(), 0, convertedBitmap->BitsLength());
BView* helper = new BView(bitmap->Bounds(), "helper",
B_FOLLOW_NONE, B_WILL_DRAW);
if (convertedBitmap->Lock()) {
convertedBitmap->AddChild(helper);
helper->SetDrawingMode(B_OP_OVER);
helper->DrawBitmap(bitmap, BPoint(0.0, 0.0));
helper->Sync();
convertedBitmap->Unlock();
}
} else {
delete convertedBitmap;
convertedBitmap = NULL;
}
return convertedBitmap;
}
// _MakeBitmaps
status_t
IconButton::_MakeBitmaps(const BBitmap* bitmap)
{
status_t status = bitmap ? bitmap->InitCheck() : B_BAD_VALUE;
if (status >= B_OK) {
// make our own versions of the bitmap
BRect b(bitmap->Bounds());
_DeleteBitmaps();
color_space format = bitmap->ColorSpace();
fNormalBitmap = new(nothrow) BBitmap(b, format);
fDisabledBitmap = new(nothrow) BBitmap(b, format);
fClickedBitmap = new(nothrow) BBitmap(b, format);
fDisabledClickedBitmap = new(nothrow) BBitmap(b, format);
if (IsValid()) {
// copy bitmaps from file bitmap
uint8* nBits = (uint8*)fNormalBitmap->Bits();
uint8* dBits = (uint8*)fDisabledBitmap->Bits();
uint8* cBits = (uint8*)fClickedBitmap->Bits();
uint8* dcBits = (uint8*)fDisabledClickedBitmap->Bits();
uint8* fBits = (uint8*)bitmap->Bits();
int32 nbpr = fNormalBitmap->BytesPerRow();
int32 fbpr = bitmap->BytesPerRow();
int32 pixels = b.IntegerWidth() + 1;
int32 lines = b.IntegerHeight() + 1;
// nontransparent version:
if (format == B_RGB32 || format == B_RGB32_BIG) {
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = 255;
// clicked bits are darker (lame method...)
cBits[nOffset + 0] = (uint8)((float)nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = (uint8)((float)nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = (uint8)((float)nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = 255;
// disabled bits have less contrast (lame method...)
uint8 grey = 216;
float dist = (nBits[nOffset + 0] - grey) * 0.4;
dBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dBits[nOffset + 2] = (uint8)(grey + dist);
dBits[nOffset + 3] = 255;
// disabled bits have less contrast (lame method...)
grey = 188;
dist = (nBits[nOffset + 0] - grey) * 0.4;
dcBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dcBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dcBits[nOffset + 2] = (uint8)(grey + dist);
dcBits[nOffset + 3] = 255;
}
nBits += nbpr;
dBits += nbpr;
cBits += nbpr;
dcBits += nbpr;
fBits += fbpr;
}
// transparent version:
} else if (format == B_RGBA32 || format == B_RGBA32_BIG) {
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = fBits[fOffset + 3];
// clicked bits are darker (lame method...)
cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = fBits[fOffset + 3];
// disabled bits have less opacity
uint8 grey = ((uint16)nBits[nOffset + 0] * 10
+ nBits[nOffset + 1] * 60
+ nBits[nOffset + 2] * 30) / 100;
float dist = (nBits[nOffset + 0] - grey) * 0.3;
dBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.3;
dBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.3;
dBits[nOffset + 2] = (uint8)(grey + dist);
dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
// disabled bits have less contrast (lame method...)
dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8);
dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8);
dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8);
dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
}
nBits += nbpr;
dBits += nbpr;
cBits += nbpr;
dcBits += nbpr;
fBits += fbpr;
}
// unsupported format
} else {
printf("IconButton::_MakeBitmaps() - bitmap has unsupported colorspace\n");
status = B_MISMATCHED_VALUES;
_DeleteBitmaps();
}
} else {
printf("IconButton::_MakeBitmaps() - error allocating local bitmaps\n");
status = B_NO_MEMORY;
_DeleteBitmaps();
}
} else
printf("IconButton::_MakeBitmaps() - bitmap is not valid\n");
return status;
}
// _DeleteBitmaps
void
IconButton::_DeleteBitmaps()
{
delete fNormalBitmap;
fNormalBitmap = NULL;
delete fDisabledBitmap;
fDisabledBitmap = NULL;
delete fClickedBitmap;
fClickedBitmap = NULL;
delete fDisabledClickedBitmap;
fDisabledClickedBitmap = NULL;
}
// _Update
void
IconButton::_Update()
{
if (LockLooper()) {
Invalidate();
UnlockLooper();
}
}
// _AddFlags
void
IconButton::_AddFlags(uint32 flags)
{
if (!(fButtonState & flags)) {
fButtonState |= flags;
_Update();
}
}
// _ClearFlags
void
IconButton::_ClearFlags(uint32 flags)
{
if (fButtonState & flags) {
fButtonState &= ~flags;
_Update();
}
}
// _HasFlags
bool
IconButton::_HasFlags(uint32 flags) const
{
return (fButtonState & flags);
}
// _DrawFrame
void
IconButton::_DrawFrame(BRect r, rgb_color col1, rgb_color col2,
rgb_color col3, rgb_color col4)
{
BeginLineArray(8);
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col1);
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col1);
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col2);
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col2);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col3);
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col3);
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col4);
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col4);
EndLineArray();
}
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright 2006-2010, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <[email protected]>
*/
/** gui class that loads an image from disk and shows it
as clickable button */
// TODO: inherit from BControl?
// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic
// it should be placed into a common folder for generic useful stuff
#ifndef ICON_BUTTON_H
#define ICON_BUTTON_H
#include <Invoker.h>
#include <String.h>
#include <View.h>
class BBitmap;
class BMimeType;
class IconButton : public BView, public BInvoker {
public:
IconButton(const char* name,
uint32 id,
const char* label = NULL,
BMessage* message = NULL,
BHandler* target = NULL);
virtual ~IconButton();
// BView interface
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* message);
virtual void GetPreferredSize(float* width,
float* height);
virtual BSize MinSize();
virtual BSize MaxSize();
// BInvoker interface
virtual status_t Invoke(BMessage* message = NULL);
// IconButton
bool IsValid() const;
virtual int32 Value() const;
virtual void SetValue(int32 value);
bool IsEnabled() const;
void SetEnabled(bool enable);
void SetPressed(bool pressed);
bool IsPressed() const;
uint32 ID() const
{ return fID; }
status_t SetIcon(int32 resourceID);
status_t SetIcon(const char* pathToBitmap);
status_t SetIcon(const BBitmap* bitmap);
status_t SetIcon(const BMimeType* fileType,
bool small = true);
status_t SetIcon(const unsigned char* bitsFromQuickRes,
uint32 width, uint32 height,
color_space format,
bool convertToBW = false);
void ClearIcon();
void TrimIcon(bool keepAspect = true);
BBitmap* Bitmap() const;
// caller has to delete the returned bitmap
virtual bool DrawBorder() const;
virtual void DrawNormalBorder(BRect r,
rgb_color background,
rgb_color shadow,
rgb_color darkShadow,
rgb_color lightShadow,
rgb_color light);
virtual void DrawPressedBorder(BRect r,
rgb_color background,
rgb_color shadow,
rgb_color darkShadow,
rgb_color lightShadow,
rgb_color light);
protected:
enum {
STATE_NONE = 0x0000,
STATE_TRACKING = 0x0001,
STATE_PRESSED = 0x0002,
STATE_ENABLED = 0x0004,
STATE_INSIDE = 0x0008,
STATE_FORCE_PRESSED = 0x0010,
};
void _AddFlags(uint32 flags);
void _ClearFlags(uint32 flags);
bool _HasFlags(uint32 flags) const;
void _DrawFrame(BRect frame,
rgb_color col1,
rgb_color col2,
rgb_color col3,
rgb_color col4);
// private:
BBitmap* _ConvertToRGB32(const BBitmap* bitmap) const;
status_t _MakeBitmaps(const BBitmap* bitmap);
void _DeleteBitmaps();
void _SendMessage() const;
void _Update();
uint32 fButtonState;
int32 fID;
BBitmap* fNormalBitmap;
BBitmap* fDisabledBitmap;
BBitmap* fClickedBitmap;
BBitmap* fDisabledClickedBitmap;
BString fLabel;
BHandler* fTargetCache;
};
#endif // ICON_BUTTON_H
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright 2006-2008, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ICON_UTILS_H
#define _ICON_UTILS_H
#include <Mime.h>
class BBitmap;
class BNode;
// This class is a little different from many other classes.
// You don't create an instance of it; you just call its various
// static member functions for utility-like operations.
class BIconUtils {
BIconUtils();
~BIconUtils();
BIconUtils(const BIconUtils&);
BIconUtils& operator=(const BIconUtils&);
public:
// Utility function to import an icon from the node that
// has either of the provided attribute names. Which icon type
// is preferred (vector, small or large B_CMAP8 icon) depends
// on the colorspace of the provided bitmap. If the colorspace
// is B_CMAP8, B_CMAP8 icons are preferred. In that case, the
// bitmap size must also match the provided icon_size "size"!
static status_t GetIcon(BNode* node,
const char* vectorIconAttrName,
const char* smallIconAttrName,
const char* largeIconAttrName,
icon_size size, BBitmap* result);
// Utility functions to import a vector icon in "flat icon"
// format from a BNode attribute or from a flat buffer in
// memory into the preallocated BBitmap "result".
// The colorspace of result needs to be B_RGBA32 or at
// least B_RGB32 (though that makes less sense). The icon
// will be scaled from it's "native" size of 64x64 to the
// size of the bitmap, the scale is derived from the bitmap
// width, the bitmap should have square dimension, or the
// icon will be cut off at the bottom (or have room left).
static status_t GetVectorIcon(BNode* node,
const char* attrName, BBitmap* result);
static status_t GetVectorIcon(const uint8* buffer,
size_t size, BBitmap* result);
// Utility function to import an "old" BeOS icon in B_CMAP8
// colorspace from either the small icon attribute or the
// large icon attribute as given in "smallIconAttrName" and
// "largeIconAttrName". Which icon is loaded depends on
// the given "size".
static status_t GetCMAP8Icon(BNode* node,
const char* smallIconAttrName,
const char* largeIconAttrName,
icon_size size, BBitmap* icon);
// Utility functions to convert from old icon colorspace
// into colorspace of BBitmap "result" (should be B_RGBA32
// to make any sense).
static status_t ConvertFromCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertToCMAP8(BBitmap* source,
BBitmap* result);
static status_t ConvertFromCMAP8(const uint8* data,
uint32 width, uint32 height,
uint32 bytesPerRow, BBitmap* result);
static status_t ConvertToCMAP8(const uint8* data,
uint32 width, uint32 height,
uint32 bytesPerRow, BBitmap* result);
};
#endif // _ICON_UTILS_H
+168
View File
@@ -0,0 +1,168 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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 applies to all licensees
and 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 TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED 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.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
// NavMenu is a hierarchical menu of volumes, folders, files and queries
// displays icons, uses the SlowMenu API for full interruptability
#ifndef NAV_MENU_H
#define NAV_MENU_H
#include <Messenger.h>
#include <StorageDefs.h>
#include <Entry.h>
#include "SlowMenu.h"
template<class T> class BObjectList;
class BMenuItem;
namespace BPrivate {
class Model;
class BContainerWindow;
class ModelMenuItem;
class EntryListBase;
class TrackingHookData {
public:
TrackingHookData()
:
fTrackingHook(NULL),
fDragMessage(NULL)
{
}
bool (*fTrackingHook)(BMenu *, void *);
BMessenger fTarget;
const BMessage *fDragMessage;
};
class BNavMenu : public BSlowMenu {
public:
BNavMenu(const char* title, uint32 message, const BHandler *,
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
BNavMenu(const char* title, uint32 message, const BMessenger &,
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
// parentWindow, if specified, will be closed if nav menu item invoked
// with option held down
virtual ~BNavMenu();
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
void SetNavDir(const entry_ref *);
void ForceRebuild();
bool NeedsToRebuild() const;
// will cause menu to get rebuilt next time it is shown
virtual void ResetTargets();
void SetTarget(const BMessenger &);
BMessenger Target();
void SetTypesList(const BObjectList<BString> *list);
const BObjectList<BString> *TypesList() const;
void AddNavDir(const Model *model, uint32 what, BHandler *target,
bool populateSubmenu);
void AddNavParentDir(const char *name, const Model *model, uint32 what, BHandler *target);
void AddNavParentDir(const Model *model, uint32 what, BHandler *target);
void SetShowParent(bool show);
static int32 GetMaxMenuWidth();
static int CompareFolderNamesFirstOne(const BMenuItem *, const BMenuItem *);
static int CompareOne(const BMenuItem *, const BMenuItem *);
static ModelMenuItem *NewModelItem(Model *, const BMessage *, const BMessenger &,
bool suppressFolderHierarchy=false, BContainerWindow * = NULL,
const BObjectList<BString> *typeslist = NULL,
TrackingHookData *hook = NULL);
TrackingHookData *InitTrackingHook(bool (*hookfunction)(BMenu *, void *),
const BMessenger *target, const BMessage *dragMessage);
protected:
virtual bool StartBuildingItemList();
virtual bool AddNextItem();
virtual void DoneBuildingItemList();
virtual void ClearMenuBuildingState();
void BuildVolumeMenu();
void AddOneItem(Model *);
void AddRootItemsIfNeeded();
void AddTrashItem();
static void SetTrackingHookDeep(BMenu *, bool (*)(BMenu *, void *), void *);
entry_ref fNavDir;
BMessage fMessage;
BMessenger fMessenger;
BWindow *fParentWindow;
// menu building state
uint8 fFlags;
BObjectList<BMenuItem> *fItemList;
EntryListBase *fContainer;
bool fIteratingDesktop;
const BObjectList<BString> *fTypesList;
TrackingHookData fTrackingHook;
};
// Spring Loaded Folder convenience routines
// used in both Tracker and Deskbar
#ifndef _IMPEXP_TRACKER
# define _IMPEXP_TRACKER
#endif
_IMPEXP_TRACKER bool SpringLoadedFolderCompareMessages(const BMessage *incoming,
const BMessage *dragmessage);
_IMPEXP_TRACKER void SpringLoadedFolderSetMenuStates(const BMenu *menu,
const BObjectList<BString> *typeslist);
_IMPEXP_TRACKER void SpringLoadedFolderAddUniqueTypeToList(entry_ref *ref,
BObjectList<BString> *typeslist);
_IMPEXP_TRACKER void SpringLoadedFolderCacheDragData(const BMessage *incoming,
BMessage **, BObjectList<BString> **typeslist);
} // namespace BPrivate
using namespace BPrivate;
#endif // NAV_MENU_H
@@ -0,0 +1,514 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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 applies to all licensees
and 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 TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED 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.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
// bonefish:
// * removed need for exceptions
// * fixed warnings
// * implemented rehashing
// * added RemoveAll()
// TODO:
// * shrinking of element vectors
// Hash table with open addresssing
#ifndef __OPEN_HASH_TABLE__
#define __OPEN_HASH_TABLE__
#include <stdlib.h>
#include <new>
// don't include <Debug.h>
#ifndef ASSERT
# define ASSERT(E) (void)0
#endif
#ifndef TRESPASS
# define TRESPASS() (void)0
#endif
namespace BPrivate {
template <class Element>
class ElementVector {
// element vector for OpenHashTable needs to implement this
// interface
public:
Element &At(int32 index);
Element *Add();
int32 IndexOf(const Element &) const;
void Remove(int32 index);
};
class OpenHashElement {
public:
uint32 Hash() const;
bool operator==(const OpenHashElement &) const;
void Adopt(OpenHashElement &);
// low overhead copy, original element is in undefined state
// after call (calls Adopt on BString members, etc.)
int32 fNext;
};
const uint32 kPrimes [] = {
509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
134217689, 268435399, 536870909, 1073741789, 2147483647, 0
};
template <class Element, class ElementVec = ElementVector<Element> >
class OpenHashTable {
public:
OpenHashTable(int32 minSize, ElementVec *elementVector = 0,
float maxLoadFactor = 0.8);
// it is up to the subclass of OpenHashTable to supply
// elementVector
~OpenHashTable();
bool InitCheck() const;
void SetElementVector(ElementVec *elementVector);
Element *FindFirst(uint32 elementHash) const;
Element *Add(uint32 elementHash);
void Remove(Element *element, bool dontRehash = false);
void RemoveAll();
// when calling Add, any outstanding element pointer may become
// invalid; to deal with this, get the element index and restore
// it after the add
int32 ElementIndex(const Element *) const;
Element *ElementAt(int32 index) const;
int32 ArraySize() const;
int32 VectorSize() const;
int32 CountElements() const;
protected:
static int32 OptimalSize(int32 minSize);
private:
bool _RehashIfNeeded();
bool _Rehash();
int32 fArraySize;
int32 fInitialSize;
int32 fElementCount;
int32 *fHashArray;
ElementVec *fElementVector;
float fMaxLoadFactor;
};
template <class Element>
class OpenHashElementArray : public ElementVector<Element> {
// this is a straightforward implementation of an element vector
// deleting is handled by linking deleted elements into a free list
// the vector never shrinks
public:
OpenHashElementArray(int32 initialSize);
~OpenHashElementArray();
bool InitCheck() const;
Element &At(int32 index);
const Element &At(int32 index) const;
Element *Add(const Element &);
Element *Add();
void Remove(int32 index);
int32 IndexOf(const Element &) const;
int32 Size() const;
private:
Element *fData;
int32 fSize;
int32 fNextFree;
int32 fNextDeleted;
};
//-----------------------------------
template<class Element, class ElementVec>
OpenHashTable<Element, ElementVec>::OpenHashTable(int32 minSize,
ElementVec *elementVector, float maxLoadFactor)
: fArraySize(OptimalSize(minSize)),
fInitialSize(fArraySize),
fElementCount(0),
fElementVector(elementVector),
fMaxLoadFactor(maxLoadFactor)
{
// sanity check the maximal load factor
if (fMaxLoadFactor < 0.5)
fMaxLoadFactor = 0.5;
// allocate and init the array
fHashArray = (int32*)calloc(fArraySize, sizeof(int32));
if (fHashArray) {
for (int32 index = 0; index < fArraySize; index++)
fHashArray[index] = -1;
}
}
template<class Element, class ElementVec>
OpenHashTable<Element, ElementVec>::~OpenHashTable()
{
RemoveAll();
free(fHashArray);
}
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::InitCheck() const
{
return (fHashArray && fElementVector);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::OptimalSize(int32 minSize)
{
for (int32 index = 0; ; index++)
if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize)
return (int32)kPrimes[index];
return 0;
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::FindFirst(uint32 hash) const
{
ASSERT(fElementVector);
hash %= fArraySize;
if (fHashArray[hash] < 0)
return 0;
return &fElementVector->At(fHashArray[hash]);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::ElementIndex(const Element *element) const
{
return fElementVector->IndexOf(*element);
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::ElementAt(int32 index) const
{
return &fElementVector->At(index);
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::ArraySize() const
{
return fArraySize;
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::VectorSize() const
{
return fElementVector->Size();
}
template<class Element, class ElementVec>
int32
OpenHashTable<Element, ElementVec>::CountElements() const
{
return fElementCount;
}
template<class Element, class ElementVec>
Element *
OpenHashTable<Element, ElementVec>::Add(uint32 hash)
{
ASSERT(fElementVector);
_RehashIfNeeded();
hash %= fArraySize;
Element *result = fElementVector->Add();
if (result) {
result->fNext = fHashArray[hash];
fHashArray[hash] = fElementVector->IndexOf(*result);
fElementCount++;
}
return result;
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::Remove(Element *element, bool dontRehash)
{
if (!dontRehash)
_RehashIfNeeded();
uint32 hash = element->Hash() % fArraySize;
int32 next = fHashArray[hash];
ASSERT(next >= 0);
if (&fElementVector->At(next) == element) {
fHashArray[hash] = element->fNext;
fElementVector->Remove(next);
fElementCount--;
return;
}
for (int32 index = next; index >= 0; ) {
// look for an existing match in table
next = fElementVector->At(index).fNext;
if (next < 0) {
TRESPASS();
return;
}
if (&fElementVector->At(next) == element) {
fElementVector->At(index).fNext = element->fNext;
fElementVector->Remove(next);
fElementCount--;
return;
}
index = next;
}
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::RemoveAll()
{
for (int32 i = 0; fElementCount > 0 && i < fArraySize; i++) {
int32 index = fHashArray[i];
while (index >= 0) {
Element* element = &fElementVector->At(index);
int32 next = element->fNext;
fElementVector->Remove(index);
fElementCount--;
index = next;
}
fHashArray[i] = -1;
}
_RehashIfNeeded();
}
template<class Element, class ElementVec>
void
OpenHashTable<Element, ElementVec>::SetElementVector(ElementVec *elementVector)
{
fElementVector = elementVector;
}
// _RehashIfNeeded
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::_RehashIfNeeded()
{
// The load factor range [fMaxLoadFactor / 3, fMaxLoadFactor] is fine,
// I think. After rehashing the load factor will be about
// fMaxLoadFactor * 2 / 3, respectively fMaxLoadFactor / 2.
float loadFactor = (float)fElementCount / (float)fArraySize;
if (loadFactor > fMaxLoadFactor
|| (fArraySize > fInitialSize && loadFactor < fMaxLoadFactor / 3)) {
return _Rehash();
}
return true;
}
// _Rehash
template<class Element, class ElementVec>
bool
OpenHashTable<Element, ElementVec>::_Rehash()
{
bool result = true;
int32 newSize = int32(fElementCount * 1.73 * fMaxLoadFactor);
newSize = (fInitialSize > newSize ? fInitialSize : newSize);
if (newSize != fArraySize) {
// allocate a new array
int32 *newHashArray = (int32*)calloc(newSize, sizeof(int32));
if (newHashArray) {
// init the new hash array
for (int32 index = 0; index < newSize; index++)
newHashArray[index] = -1;
// iterate through all elements and put them into the new
// hash array
for (int i = 0; i < fArraySize; i++) {
int32 index = fHashArray[i];
while (index >= 0) {
// insert the element in the new array
Element &element = fElementVector->At(index);
int32 next = element.fNext;
uint32 hash = (element.Hash() % newSize);
element.fNext = newHashArray[hash];
newHashArray[hash] = index;
// next element in old list
index = next;
}
}
// delete the old array and set the new one
free(fHashArray);
fHashArray = newHashArray;
fArraySize = newSize;
} else
result = false;
}
return result;
}
template<class Element>
OpenHashElementArray<Element>::OpenHashElementArray(int32 initialSize)
: fSize(initialSize),
fNextFree(0),
fNextDeleted(-1)
{
fData = (Element*)calloc((size_t)initialSize, sizeof(Element));
}
template<class Element>
OpenHashElementArray<Element>::~OpenHashElementArray()
{
free(fData);
}
template<class Element>
bool
OpenHashElementArray<Element>::InitCheck() const
{
return fData;
}
template<class Element>
Element &
OpenHashElementArray<Element>::At(int32 index)
{
ASSERT(index < fSize);
return fData[index];
}
template<class Element>
const Element &
OpenHashElementArray<Element>::At(int32 index) const
{
ASSERT(index < fSize);
return fData[index];
}
template<class Element>
int32
OpenHashElementArray<Element>::IndexOf(const Element &element) const
{
int32 result = &element - fData;
if (result < 0 || result > fSize)
return -1;
return result;
}
template<class Element>
int32
OpenHashElementArray<Element>::Size() const
{
return fSize;
}
template<class Element>
Element *
OpenHashElementArray<Element>::Add(const Element &newElement)
{
Element *element = Add();
if (element)
element.Adopt(newElement);
return element;
}
#if DEBUG
const int32 kGrowChunk = 10;
#else
const int32 kGrowChunk = 1024;
#endif
template<class Element>
Element *
OpenHashElementArray<Element>::Add()
{
int32 index = fNextFree;
if (fNextDeleted >= 0) {
index = fNextDeleted;
fNextDeleted = At(index).fNext;
} else if (fNextFree >= fSize - 1) {
int32 newSize = fSize + kGrowChunk;
/*
Element *newData = (Element *)calloc((size_t)newSize , sizeof(Element));
if (!newData)
return NULL;
memcpy(newData, fData, fSize * sizeof(Element));
free(fData);
*/
Element *newData = (Element*)realloc(fData,
(size_t)newSize * sizeof(Element));
if (!newData)
return NULL;
fData = newData;
fSize = newSize;
index = fNextFree;
fNextFree++;
} else
fNextFree++;
new (&At(index)) Element;
// call placement new to initialize the element properly
ASSERT(At(index).fNext == -1);
return &At(index);
}
template<class Element>
void
OpenHashElementArray<Element>::Remove(int32 index)
{
// delete by chaining empty elements in a single linked
// list, reusing the next field
ASSERT(index < fSize);
At(index).~Element();
// call the destructor explicitly to destroy the element
// properly
At(index).fNext = fNextDeleted;
fNextDeleted = index;
}
} // namespace BPrivate
using BPrivate::OpenHashTable;
#endif // __OPEN_HASH_TABLE__
@@ -0,0 +1,514 @@
/*
* Copyright 2008-2010, Stephan Aßmus <[email protected]>.
* Copyright 1998, Eric Shepherd.
* All rights reserved. Distributed under the terms of the Be Sample Code
* license.
*/
//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd)
#include "SettingsMessage.h"
#include <new>
#include <Autolock.h>
#include <Entry.h>
#include <File.h>
#include <Messenger.h>
#include <String.h>
SettingsMessage::SettingsMessage(directory_which directory,
const char* filename)
:
BMessage('pref'),
fListeners(4)
{
fStatus = find_directory(directory, &fPath);
if (fStatus == B_OK)
fStatus = fPath.Append(filename);
if (fStatus == B_OK)
fStatus = Load();
}
SettingsMessage::~SettingsMessage()
{
Save();
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
delete reinterpret_cast<BMessenger*>(fListeners.ItemAtFast(i));
}
status_t
SettingsMessage::InitCheck() const
{
return fStatus;
}
status_t
SettingsMessage::Load()
{
BAutolock _(this);
BFile file(fPath.Path(), B_READ_ONLY);
status_t status = file.InitCheck();
if (status == B_OK)
status = Unflatten(&file);
return status;
}
status_t
SettingsMessage::Save() const
{
BAutolock _(const_cast<SettingsMessage*>(this));
BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
status_t status = file.InitCheck();
if (status == B_OK)
status = Flatten(&file);
return status;
}
bool
SettingsMessage::AddListener(const BMessenger& listener)
{
BAutolock _(this);
BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener);
if (listenerCopy && fListeners.AddItem(listenerCopy))
return true;
delete listenerCopy;
return false;
}
void
SettingsMessage::RemoveListener(const BMessenger& listener)
{
BAutolock _(this);
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
BMessenger* listenerItem = reinterpret_cast<BMessenger*>(
fListeners.ItemAtFast(i));
if (*listenerItem == listener) {
fListeners.RemoveItem(i);
delete listenerItem;
return;
}
}
}
// #pragma mark -
status_t
SettingsMessage::SetValue(const char* name, bool value)
{
status_t ret = ReplaceBool(name, value);
if (ret != B_OK)
ret = AddBool(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, int8 value)
{
status_t ret = ReplaceInt8(name, value);
if (ret != B_OK)
ret = AddInt8(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, int16 value)
{
status_t ret = ReplaceInt16(name, value);
if (ret != B_OK)
ret = AddInt16(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, int32 value)
{
status_t ret = ReplaceInt32(name, value);
if (ret != B_OK)
ret = AddInt32(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, uint32 value)
{
status_t ret = ReplaceUInt32(name, value);
if (ret != B_OK)
ret = AddUInt32(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, int64 value)
{
status_t ret = ReplaceInt64(name, value);
if (ret != B_OK)
ret = AddInt64(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, float value)
{
status_t ret = ReplaceFloat(name, value);
if (ret != B_OK)
ret = AddFloat(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, double value)
{
status_t ret = ReplaceDouble(name, value);
if (ret != B_OK)
ret = AddDouble(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const char* value)
{
status_t ret = ReplaceString(name, value);
if (ret != B_OK)
ret = AddString(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BString& value)
{
status_t ret = ReplaceString(name, value);
if (ret != B_OK)
ret = AddString(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BPoint& value)
{
status_t ret = ReplacePoint(name, value);
if (ret != B_OK)
ret = AddPoint(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BRect& value)
{
status_t ret = ReplaceRect(name, value);
if (ret != B_OK)
ret = AddRect(name, value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const entry_ref& value)
{
status_t ret = ReplaceRef(name, &value);
if (ret != B_OK)
ret = AddRef(name, &value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BMessage& value)
{
status_t ret = ReplaceMessage(name, &value);
if (ret != B_OK)
ret = AddMessage(name, &value);
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BFlattenable* value)
{
status_t ret = ReplaceFlat(name, const_cast<BFlattenable*>(value));
if (ret != B_OK)
ret = AddFlat(name, const_cast<BFlattenable*>(value));
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
status_t
SettingsMessage::SetValue(const char* name, const BFont& value)
{
font_family family;
font_style style;
value.GetFamilyAndStyle(&family, &style);
BMessage fontMessage;
status_t ret = fontMessage.AddString("family", family);
if (ret == B_OK)
ret = fontMessage.AddString("style", style);
if (ret == B_OK)
ret = fontMessage.AddFloat("size", value.Size());
if (ret == B_OK) {
if (ReplaceMessage(name, &fontMessage) != B_OK)
ret = AddMessage(name, &fontMessage);
}
if (ret == B_OK)
_NotifyValueChanged(name);
return ret;
}
// #pragma mark -
bool
SettingsMessage::GetValue(const char* name, bool defaultValue) const
{
bool value;
if (FindBool(name, &value) != B_OK)
return defaultValue;
return value;
}
int8
SettingsMessage::GetValue(const char* name, int8 defaultValue) const
{
int8 value;
if (FindInt8(name, &value) != B_OK)
return defaultValue;
return value;
}
int16
SettingsMessage::GetValue(const char* name, int16 defaultValue) const
{
int16 value;
if (FindInt16(name, &value) != B_OK)
return defaultValue;
return value;
}
int32
SettingsMessage::GetValue(const char* name, int32 defaultValue) const
{
int32 value;
if (FindInt32(name, &value) != B_OK)
return defaultValue;
return value;
}
uint32
SettingsMessage::GetValue(const char* name, uint32 defaultValue) const
{
uint32 value;
if (FindUInt32(name, &value) != B_OK)
return defaultValue;
return value;
}
int64
SettingsMessage::GetValue(const char* name, int64 defaultValue) const
{
int64 value;
if (FindInt64(name, &value) != B_OK)
return defaultValue;
return value;
}
float
SettingsMessage::GetValue(const char* name, float defaultValue) const
{
float value;
if (FindFloat(name, &value) != B_OK)
return defaultValue;
return value;
}
double
SettingsMessage::GetValue(const char* name, double defaultValue) const
{
double value;
if (FindDouble(name, &value) != B_OK)
return defaultValue;
return value;
}
BString
SettingsMessage::GetValue(const char* name, const BString& defaultValue) const
{
BString value;
if (FindString(name, &value) != B_OK)
return defaultValue;
return value;
}
const char*
SettingsMessage::GetValue(const char* name, const char* defaultValue) const
{
const char* value;
if (FindString(name, &value) != B_OK)
return defaultValue;
return value;
}
BPoint
SettingsMessage::GetValue(const char *name, BPoint defaultValue) const
{
BPoint value;
if (FindPoint(name, &value) != B_OK)
return defaultValue;
return value;
}
BRect
SettingsMessage::GetValue(const char* name, BRect defaultValue) const
{
BRect value;
if (FindRect(name, &value) != B_OK)
return defaultValue;
return value;
}
entry_ref
SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const
{
entry_ref value;
if (FindRef(name, &value) != B_OK)
return defaultValue;
return value;
}
BMessage
SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const
{
BMessage value;
if (FindMessage(name, &value) != B_OK)
return defaultValue;
return value;
}
BFont
SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const
{
BMessage fontMessage;
if (FindMessage(name, &fontMessage) != B_OK)
return defaultValue;
const char* family;
const char* style;
float size;
if (fontMessage.FindString("family", &family) != B_OK
|| fontMessage.FindString("style", &style) != B_OK
|| fontMessage.FindFloat("size", &size) != B_OK) {
return defaultValue;
}
BFont value;
if (value.SetFamilyAndStyle(family, style) != B_OK)
return defaultValue;
value.SetSize(size);
return value;
}
// #pragma mark - private
void
SettingsMessage::_NotifyValueChanged(const char* name) const
{
BMessage message(SETTINGS_VALUE_CHANGED);
message.AddString("name", name);
// Add the value of that name to the notification.
type_code type;
if (GetInfo(name, &type) == B_OK) {
const void* data;
ssize_t numBytes;
if (FindData(name, type, &data, &numBytes) == B_OK)
message.AddData("value", type, data, numBytes);
}
int32 count = fListeners.CountItems();
for (int32 i = 0; i < count; i++) {
BMessenger* listener = reinterpret_cast<BMessenger*>(
fListeners.ItemAtFast(i));
listener->SendMessage(&message);
}
}
@@ -0,0 +1,105 @@
/*
* Copyright 2008-2010 Stephan Aßmus <[email protected]>.
* Copyright 1998 Eric Shepherd.
* All rights reserved. Distributed under the terms of the Be Sample Code
* license.
*/
#ifndef SETTINGS_MESSAGE_H
#define SETTINGS_MESSAGE_H
#include <FindDirectory.h>
#include <Font.h>
#include <List.h>
#include <Locker.h>
#include <Message.h>
#include <Path.h>
class BMessenger;
class BString;
enum {
SETTINGS_VALUE_CHANGED = '_svc'
};
class SettingsMessage : public BMessage, public BLocker {
public:
SettingsMessage(directory_which directory,
const char* filename);
virtual ~SettingsMessage();
status_t InitCheck() const;
status_t Load();
status_t Save() const;
bool AddListener(const BMessenger& listener);
void RemoveListener(const BMessenger& listener);
status_t SetValue(const char* name, bool value);
status_t SetValue(const char* name, int8 value);
status_t SetValue(const char* name, int16 value);
status_t SetValue(const char* name, int32 value);
status_t SetValue(const char* name, uint32 value);
status_t SetValue(const char* name, int64 value);
status_t SetValue(const char* name, float value);
status_t SetValue(const char* name, double value);
status_t SetValue(const char* name,
const char* value);
status_t SetValue(const char* name,
const BString& value);
status_t SetValue(const char *name,
const BPoint& value);
status_t SetValue(const char* name, const BRect& value);
status_t SetValue(const char* name,
const entry_ref& value);
status_t SetValue(const char* name,
const BMessage& value);
status_t SetValue(const char* name,
const BFlattenable* value);
status_t SetValue(const char* name,
const BFont& value);
bool GetValue(const char* name,
bool defaultValue) const;
int8 GetValue(const char* name,
int8 defaultValue) const;
int16 GetValue(const char* name,
int16 defaultValue) const;
int32 GetValue(const char* name,
int32 defaultValue) const;
uint32 GetValue(const char* name,
uint32 defaultValue) const;
int64 GetValue(const char* name,
int64 defaultValue) const;
float GetValue(const char* name,
float defaultValue) const;
double GetValue(const char* name,
double defaultValue) const;
const char* GetValue(const char* name,
const char* defaultValue) const;
BString GetValue(const char* name,
const BString& defaultValue) const;
BPoint GetValue(const char *name,
BPoint defaultValue) const;
BRect GetValue(const char* name,
BRect defaultValue) const;
entry_ref GetValue(const char* name,
const entry_ref& defaultValue) const;
BMessage GetValue(const char* name,
const BMessage& defaultValue) const;
BFont GetValue(const char* name,
const BFont& defaultValue) const;
private:
void _NotifyValueChanged(const char* name) const;
private:
BPath fPath;
status_t fStatus;
BList fListeners;
};
#endif // SETTINGS_MESSAGE_H
+76
View File
@@ -0,0 +1,76 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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 applies to all licensees
and 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 TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED 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.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
of Be Incorporated in the United States and other countries. Other brand product
names are registered trademarks or trademarks of their respective holders.
All rights reserved.
*/
#ifndef __SLOW_MENU__
#define __SLOW_MENU__
#include <Menu.h>
#include <MenuItem.h>
#include <Debug.h>
// SlowMenu is a convenience class that makes it easier to
// use the AddDynamicItem callback to implement a menu that can
// checks periodically between creating new items and quits
// early if needed
namespace BPrivate {
class BSlowMenu : public BMenu {
public:
BSlowMenu(const char *title, menu_layout layout = B_ITEMS_IN_COLUMN);
protected:
virtual bool StartBuildingItemList();
// set up state to start building the item list
// returns false if setup failed
virtual bool AddNextItem() = 0;
// returns false if done
virtual void DoneBuildingItemList() = 0;
// default version adds items from itemList to menu and deletes
// the list; override to sort items first, etc.
virtual void ClearMenuBuildingState() = 0;
protected:
virtual bool AddDynamicItem(add_state state);
// this is the callback from BMenu, you shouldn't need to override this
bool fMenuBuilt;
};
} // namespace BPrivate
using namespace BPrivate;
#endif /* __SLOW_MENU__ */
@@ -0,0 +1,43 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "StringForSize.h"
#include <stdio.h>
namespace BPrivate {
const char*
string_for_size(double size, char* string, size_t stringSize)
{
double kib = size / 1024.0;
if (kib < 1.0) {
snprintf(string, stringSize, "%d bytes", (int)size);
return string;
}
double mib = kib / 1024.0;
if (mib < 1.0) {
snprintf(string, stringSize, "%3.2f KiB", kib);
return string;
}
double gib = mib / 1024.0;
if (gib < 1.0) {
snprintf(string, stringSize, "%3.2f MiB", mib);
return string;
}
double tib = gib / 1024.0;
if (tib < 1.0) {
snprintf(string, stringSize, "%3.2f GiB", gib);
return string;
}
snprintf(string, stringSize, "%.2f TiB", tib);
return string;
}
} // namespace BPrivate
@@ -0,0 +1,23 @@
/*
* Copyright 2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef STRING_FOR_SIZE_H
#define STRING_FOR_SIZE_H
#include <SupportDefs.h>
namespace BPrivate {
const char* string_for_size(double size, char* string, size_t stringSize);
} // namespace BPrivate
using BPrivate::string_for_size;
#endif // COLOR_QUANTIZER_H
+54
View File
@@ -0,0 +1,54 @@
const uint32 kWindowIconWidth = 13;
const uint32 kWindowIconHeight = 14;
const color_space kWindowIconFormat = B_RGBA32;
const unsigned char kWindowIconBits[] = {
0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff,
0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff,
0x78, 0x78, 0x78, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff,
0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff,
0x66, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0xff, 0x13, 0xaf, 0xff, 0xff,
0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff,
0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff,
0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff,
0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff,
0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff,
0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff
};
+10
View File
@@ -0,0 +1,10 @@
/*
* Copyright 2006-2009, Ingo Weinhold <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "svn_revision.h"
const int32 kSVNRevision = 0;
// #include "svn_revision"
;
+15
View File
@@ -0,0 +1,15 @@
/*
* Copyright 2006-2009, Ingo Weinhold <[email protected]>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef SVN_REVISION_H
#define SVN_REVISION_H
#include <SupportDefs.h>
extern const int32 kSVNRevision;
#endif // SVN_REVISION_H
@@ -0,0 +1,542 @@
/*
* Copyright (C) 2010 Rene Gollent <[email protected]>
* Copyright (C) 2010 Stephan Aßmus <[email protected]>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TabContainerView.h"
#include <stdio.h>
#include <Application.h>
#include <AbstractLayoutItem.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <ControlLook.h>
#include <GroupView.h>
#include <MenuBar.h>
#include <SpaceLayoutItem.h>
#include <Window.h>
#include "TabView.h"
static const float kLeftTabInset = 4;
TabContainerView::TabContainerView(Controller* controller)
:
BGroupView(B_HORIZONTAL, 0.0),
fLastMouseEventTab(NULL),
fMouseDown(false),
fClickCount(0),
fSelectedTab(NULL),
fController(controller),
fFirstVisibleTabIndex(0)
{
SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
SetViewColor(B_TRANSPARENT_COLOR);
GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1);
GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f);
}
TabContainerView::~TabContainerView()
{
}
BSize
TabContainerView::MinSize()
{
// Eventually, we want to be scrolling if the tabs don't fit.
BSize size(BGroupView::MinSize());
size.width = 300;
return size;
}
void
TabContainerView::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BGroupView::MessageReceived(message);
}
}
void
TabContainerView::Draw(BRect updateRect)
{
// Stroke separator line at bottom.
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
BRect frame(Bounds());
SetHighColor(tint_color(base, B_DARKEN_2_TINT));
StrokeLine(frame.LeftBottom(), frame.RightBottom());
frame.bottom--;
// Draw empty area before first tab.
uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER;
BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom);
be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0,
borders);
// Draw all tabs, keeping track of where they end.
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(i));
if (!item || !item->IsVisible())
continue;
item->Parent()->Draw(updateRect);
frame.left = item->Frame().right + 1;
}
// Draw empty area after last tab.
be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders);
}
void
TabContainerView::MouseDown(BPoint where)
{
uint32 buttons;
if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK)
buttons = B_PRIMARY_MOUSE_BUTTON;
uint32 clicks;
if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK)
clicks = 1;
fMouseDown = true;
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
if (fLastMouseEventTab)
fLastMouseEventTab->MouseDown(where, buttons);
else {
if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
// Middle click outside tabs should always open a new tab.
fClickCount = 2;
} else if (clicks > 1)
fClickCount = fClickCount++;
else
fClickCount = 1;
}
}
void
TabContainerView::MouseUp(BPoint where)
{
fMouseDown = false;
if (fLastMouseEventTab) {
fLastMouseEventTab->MouseUp(where);
fClickCount = 0;
} else if (fClickCount > 1) {
// NOTE: fClickCount is >= 1 only if the first click was outside
// any tab. So even if fLastMouseEventTab has been reset to NULL
// because this tab was removed during mouse down, we wouldn't
// run the "outside tabs" code below.
fController->DoubleClickOutsideTabs();
fClickCount = 0;
}
// Always check the tab under the mouse again, since we don't update
// it with fMouseDown == true.
_SendFakeMouseMoved();
}
void
TabContainerView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
_MouseMoved(where, transit, dragMessage);
}
void
TabContainerView::DoLayout()
{
BGroupView::DoLayout();
_ValidateTabVisibility();
_SendFakeMouseMoved();
}
void
TabContainerView::AddTab(const char* label, int32 index)
{
TabView* tab;
if (fController)
tab = fController->CreateTabView();
else
tab = new TabView();
tab->SetLabel(label);
AddTab(tab, index);
}
void
TabContainerView::AddTab(TabView* tab, int32 index)
{
tab->SetContainerView(this);
if (index == -1)
index = GroupLayout()->CountItems() - 1;
bool hasFrames = fController != NULL && fController->HasFrames();
bool isFirst = index == 0 && hasFrames;
bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames;
bool isFront = fSelectedTab == NULL;
tab->Update(isFirst, isLast, isFront);
GroupLayout()->AddItem(index, tab->LayoutItem());
if (isFront)
SelectTab(tab);
if (isLast) {
TabLayoutItem* item
= dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1));
if (item)
item->Parent()->SetIsLast(false);
}
SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex());
_ValidateTabVisibility();
}
TabView*
TabContainerView::RemoveTab(int32 index)
{
TabLayoutItem* item
= dynamic_cast<TabLayoutItem*>(GroupLayout()->RemoveItem(index));
if (!item)
return NULL;
BRect dirty(Bounds());
dirty.left = item->Frame().left;
TabView* removedTab = item->Parent();
removedTab->SetContainerView(NULL);
if (removedTab == fLastMouseEventTab)
fLastMouseEventTab = NULL;
// Update tabs after or before the removed tab.
bool hasFrames = fController != NULL && fController->HasFrames();
item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index));
if (item) {
// This tab is behind the removed tab.
TabView* tab = item->Parent();
tab->Update(index == 0 && hasFrames,
index == GroupLayout()->CountItems() - 2 && hasFrames,
tab == fSelectedTab);
if (removedTab == fSelectedTab) {
fSelectedTab = NULL;
SelectTab(tab);
} else if (fController && tab == fSelectedTab)
fController->TabSelected(index);
} else {
// The removed tab was the last tab.
item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1));
if (item) {
TabView* tab = item->Parent();
tab->Update(index == 0 && hasFrames,
index == GroupLayout()->CountItems() - 2 && hasFrames,
tab == fSelectedTab);
if (removedTab == fSelectedTab) {
fSelectedTab = NULL;
SelectTab(tab);
}
}
}
Invalidate(dirty);
_ValidateTabVisibility();
return removedTab;
}
TabView*
TabContainerView::TabAt(int32 index) const
{
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(index));
if (item)
return item->Parent();
return NULL;
}
int32
TabContainerView::IndexOf(TabView* tab) const
{
return GroupLayout()->IndexOfItem(tab->LayoutItem());
}
void
TabContainerView::SelectTab(int32 index)
{
TabView* tab = NULL;
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(index));
if (item)
tab = item->Parent();
SelectTab(tab);
}
void
TabContainerView::SelectTab(TabView* tab)
{
if (tab == fSelectedTab)
return;
if (fSelectedTab)
fSelectedTab->SetIsFront(false);
fSelectedTab = tab;
if (fSelectedTab)
fSelectedTab->SetIsFront(true);
if (fController != NULL) {
int32 index = -1;
if (fSelectedTab != NULL)
index = GroupLayout()->IndexOfItem(tab->LayoutItem());
if (!tab->LayoutItem()->IsVisible()) {
SetFirstVisibleTabIndex(index);
}
fController->TabSelected(index);
}
}
void
TabContainerView::SetTabLabel(int32 tabIndex, const char* label)
{
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
GroupLayout()->ItemAt(tabIndex));
if (item == NULL)
return;
item->Parent()->SetLabel(label);
}
void
TabContainerView::SetFirstVisibleTabIndex(int32 index)
{
if (index < 0)
index = 0;
if (index > MaxFirstVisibleTabIndex())
index = MaxFirstVisibleTabIndex();
if (fFirstVisibleTabIndex == index)
return;
fFirstVisibleTabIndex = index;
_UpdateTabVisibility();
}
int32
TabContainerView::FirstVisibleTabIndex() const
{
return fFirstVisibleTabIndex;
}
int32
TabContainerView::MaxFirstVisibleTabIndex() const
{
float availableWidth = _AvailableWidthForTabs();
if (availableWidth < 0)
return 0;
float visibleTabsWidth = 0;
BGroupLayout* layout = GroupLayout();
int32 i = layout->CountItems() - 2;
for (; i >= 0; i--) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(i));
if (item == NULL)
continue;
float itemWidth = item->MinSize().width;
if (availableWidth >= visibleTabsWidth + itemWidth)
visibleTabsWidth += itemWidth;
else {
// The tab before this tab is the last one that can be visible.
return i + 1;
}
}
return 0;
}
bool
TabContainerView::CanScrollLeft() const
{
return fFirstVisibleTabIndex < MaxFirstVisibleTabIndex();
}
bool
TabContainerView::CanScrollRight() const
{
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
if (count > 0) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(count - 1));
return !item->IsVisible();
}
return false;
}
// #pragma mark -
TabView*
TabContainerView::_TabAt(const BPoint& where) const
{
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(layout->ItemAt(i));
if (item == NULL || !item->IsVisible())
continue;
// Account for the fact that the tab frame does not contain the
// visible bottom border.
BRect frame = item->Frame();
frame.bottom++;
if (frame.Contains(where))
return item->Parent();
}
return NULL;
}
void
TabContainerView::_MouseMoved(BPoint where, uint32 _transit,
const BMessage* dragMessage)
{
TabView* tab = _TabAt(where);
if (fMouseDown) {
uint32 transit = tab == fLastMouseEventTab
? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, transit, dragMessage);
return;
}
if (fLastMouseEventTab != NULL && fLastMouseEventTab == tab)
fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage);
else {
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage);
fLastMouseEventTab = tab;
if (fLastMouseEventTab)
fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage);
else
fController->SetToolTip("Double-click or middle-click to open new tab.");
}
}
void
TabContainerView::_ValidateTabVisibility()
{
if (fFirstVisibleTabIndex > MaxFirstVisibleTabIndex())
SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex());
else
_UpdateTabVisibility();
}
void
TabContainerView::_UpdateTabVisibility()
{
float availableWidth = _AvailableWidthForTabs();
if (availableWidth < 0)
return;
float visibleTabsWidth = 0;
bool canScrollTabsLeft = fFirstVisibleTabIndex > 0;
bool canScrollTabsRight = false;
BGroupLayout* layout = GroupLayout();
int32 count = layout->CountItems() - 1;
for (int32 i = 0; i < count; i++) {
TabLayoutItem* item = dynamic_cast<TabLayoutItem*>(
layout->ItemAt(i));
if (i < fFirstVisibleTabIndex)
item->SetVisible(false);
else {
float itemWidth = item->MinSize().width;
bool visible = availableWidth >= visibleTabsWidth + itemWidth;
item->SetVisible(visible && !canScrollTabsRight);
visibleTabsWidth += itemWidth;
if (!visible)
canScrollTabsRight = true;
}
}
fController->UpdateTabScrollability(canScrollTabsLeft, canScrollTabsRight);
}
float
TabContainerView::_AvailableWidthForTabs() const
{
float width = Bounds().Width() - 10;
// TODO: Don't really know why -10 is needed above.
float left;
float right;
GroupLayout()->GetInsets(&left, NULL, &right, NULL);
width -= left + right;
return width;
}
void
TabContainerView::_SendFakeMouseMoved()
{
BPoint where;
uint32 buttons;
GetMouse(&where, &buttons, false);
if (Bounds().Contains(where))
_MouseMoved(where, B_INSIDE_VIEW, NULL);
}
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TAB_CONTAINER_VIEW_H
#define TAB_CONTAINER_VIEW_H
#include <GroupView.h>
class TabView;
class TabContainerView : public BGroupView {
public:
class Controller {
public:
virtual void TabSelected(int32 tabIndex) = 0;
virtual bool HasFrames() = 0;
virtual TabView* CreateTabView() = 0;
virtual void DoubleClickOutsideTabs() = 0;
virtual void UpdateTabScrollability(bool canScrollLeft,
bool canScrollRight) = 0;
virtual void SetToolTip(const BString& text) = 0;
};
public:
TabContainerView(Controller* controller);
virtual ~TabContainerView();
virtual BSize MinSize();
virtual void MessageReceived(BMessage*);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void DoLayout();
void AddTab(const char* label, int32 index = -1);
void AddTab(TabView* tab, int32 index = -1);
TabView* RemoveTab(int32 index);
TabView* TabAt(int32 index) const;
int32 IndexOf(TabView* tab) const;
void SelectTab(int32 tabIndex);
void SelectTab(TabView* tab);
void SetTabLabel(int32 tabIndex, const char* label);
void SetFirstVisibleTabIndex(int32 index);
int32 FirstVisibleTabIndex() const;
int32 MaxFirstVisibleTabIndex() const;
bool CanScrollLeft() const;
bool CanScrollRight() const;
private:
TabView* _TabAt(const BPoint& where) const;
void _MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
void _ValidateTabVisibility();
void _UpdateTabVisibility();
float _AvailableWidthForTabs() const;
void _SendFakeMouseMoved();
private:
TabView* fLastMouseEventTab;
bool fMouseDown;
uint32 fClickCount;
TabView* fSelectedTab;
Controller* fController;
int32 fFirstVisibleTabIndex;
};
#endif // TAB_CONTAINER_VIEW_H
+940
View File
@@ -0,0 +1,940 @@
/*
* Copyright (C) 2010 Rene Gollent <rene@gollent.com>
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TabManager.h"
#include <stdio.h>
#include <Application.h>
#include <AbstractLayoutItem.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <ControlLook.h>
#include <GroupView.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <PopUpMenu.h>
#include <Rect.h>
#include <SpaceLayoutItem.h>
#include <Window.h>
#include "TabContainerView.h"
#include "TabView.h"
const static BString kEmptyString;
// #pragma mark - Helper classes
class TabButton : public BButton {
public:
TabButton(BMessage* message)
: BButton("", message)
{
}
virtual BSize MinSize()
{
return BSize(12, 12);
}
virtual BSize MaxSize()
{
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
}
virtual BSize PreferredSize()
{
return MinSize();
}
virtual void Draw(BRect updateRect)
{
BRect bounds(Bounds());
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
SetHighColor(tint_color(base, B_DARKEN_2_TINT));
StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
bounds.bottom--;
uint32 flags = be_control_look->Flags(this);
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER;
be_control_look->DrawInactiveTab(this, bounds, updateRect, base,
0, borders);
if (IsEnabled()) {
rgb_color button = tint_color(base, 1.07);
be_control_look->DrawButtonBackground(this, bounds, updateRect,
button, flags, 0);
}
bounds.left = (bounds.left + bounds.right) / 2 - 6;
bounds.top = (bounds.top + bounds.bottom) / 2 - 6;
bounds.right = bounds.left + 12;
bounds.bottom = bounds.top + 12;
DrawSymbol(bounds, updateRect, base);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
}
};
class ScrollLeftTabButton : public TabButton {
public:
ScrollLeftTabButton(BMessage* message)
: TabButton(message)
{
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT;
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_LEFT_ARROW, 0, tint);
}
};
class ScrollRightTabButton : public TabButton {
public:
ScrollRightTabButton(BMessage* message)
: TabButton(message)
{
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
frame.OffsetBy(1, 0);
float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT;
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_RIGHT_ARROW, 0, tint);
}
};
class NewTabButton : public TabButton {
public:
NewTabButton(BMessage* message)
: TabButton(message)
{
SetToolTip("New tab (Cmd-T)");
}
virtual BSize MinSize()
{
return BSize(18, 12);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
SetHighColor(tint_color(base, B_DARKEN_4_TINT));
float inset = 3;
frame.InsetBy(2, 2);
frame.top++;
frame.left++;
FillRoundRect(BRect(frame.left, frame.top + inset,
frame.right, frame.bottom - inset), 1, 1);
FillRoundRect(BRect(frame.left + inset, frame.top,
frame.right - inset, frame.bottom), 1, 1);
}
};
class TabMenuTabButton : public TabButton {
public:
TabMenuTabButton(BMessage* message)
: TabButton(message)
{
}
virtual BSize MinSize()
{
return BSize(18, 12);
}
virtual void DrawSymbol(BRect frame, const BRect& updateRect,
const rgb_color& base)
{
be_control_look->DrawArrowShape(this, frame, updateRect,
base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT);
}
virtual void MouseDown(BPoint point)
{
if (!IsEnabled())
return;
// Invoke must be called before setting B_CONTROL_ON
// for the button to stay "down"
Invoke();
SetValue(B_CONTROL_ON);
}
virtual void MouseUp(BPoint point)
{
// Do nothing
}
void MenuClosed()
{
SetValue(B_CONTROL_OFF);
}
};
enum {
MSG_SCROLL_TABS_LEFT = 'stlt',
MSG_SCROLL_TABS_RIGHT = 'strt',
MSG_OPEN_TAB_MENU = 'otmn'
};
class TabContainerGroup : public BGroupView {
public:
TabContainerGroup(TabContainerView* tabContainerView)
:
BGroupView(B_HORIZONTAL, 0.0),
fTabContainerView(tabContainerView),
fScrollLeftTabButton(NULL),
fScrollRightTabButton(NULL),
fTabMenuButton(NULL)
{
}
virtual void AttachedToWindow()
{
if (fScrollLeftTabButton != NULL)
fScrollLeftTabButton->SetTarget(this);
if (fScrollRightTabButton != NULL)
fScrollRightTabButton->SetTarget(this);
if (fTabMenuButton != NULL)
fTabMenuButton->SetTarget(this);
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SCROLL_TABS_LEFT:
fTabContainerView->SetFirstVisibleTabIndex(
fTabContainerView->FirstVisibleTabIndex() - 1);
break;
case MSG_SCROLL_TABS_RIGHT:
fTabContainerView->SetFirstVisibleTabIndex(
fTabContainerView->FirstVisibleTabIndex() + 1);
break;
case MSG_OPEN_TAB_MENU:
{
BPopUpMenu* tabMenu = new BPopUpMenu("tab menu", true, false);
int tabCount = fTabContainerView->GetLayout()->CountItems();
for (int i = 0; i < tabCount; i++) {
TabView* tab = fTabContainerView->TabAt(i);
if (tab) {
BMenuItem* item = new BMenuItem(tab->Label(), NULL);
tabMenu->AddItem(item);
if (tab->IsFront())
item->SetMarked(true);
}
}
// Force layout to get the final menu size. InvalidateLayout()
// did not seem to work here.
tabMenu->AttachedToWindow();
BRect buttonFrame = fTabMenuButton->Frame();
BRect menuFrame = tabMenu->Frame();
BPoint openPoint = ConvertToScreen(buttonFrame.LeftBottom());
// Open with the right side of the menu aligned with the right
// side of the button and a little below.
openPoint.x -= menuFrame.Width() - buttonFrame.Width();
openPoint.y += 2;
BMenuItem *selected = tabMenu->Go(openPoint, false, false,
ConvertToScreen(buttonFrame));
if (selected) {
selected->SetMarked(true);
int32 index = tabMenu->IndexOf(selected);
if (index != B_ERROR)
fTabContainerView->SelectTab(index);
}
fTabMenuButton->MenuClosed();
delete tabMenu;
break;
}
default:
BGroupView::MessageReceived(message);
break;
}
}
void AddScrollLeftButton(TabButton* button)
{
fScrollLeftTabButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void AddScrollRightButton(TabButton* button)
{
fScrollRightTabButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void AddTabMenuButton(TabMenuTabButton* button)
{
fTabMenuButton = button;
GroupLayout()->AddView(button, 0.0f);
}
void EnableScrollButtons(bool canScrollLeft, bool canScrollRight)
{
fScrollLeftTabButton->SetEnabled(canScrollLeft);
fScrollRightTabButton->SetEnabled(canScrollRight);
if (!canScrollLeft && !canScrollRight) {
// hide scroll buttons
} else {
// show scroll buttons
}
}
private:
TabContainerView* fTabContainerView;
TabButton* fScrollLeftTabButton;
TabButton* fScrollRightTabButton;
TabMenuTabButton* fTabMenuButton;
};
class TabButtonContainer : public BGroupView {
public:
TabButtonContainer()
:
BGroupView(B_HORIZONTAL, 0.0)
{
SetFlags(Flags() | B_WILL_DRAW);
SetViewColor(B_TRANSPARENT_COLOR);
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
GroupLayout()->SetInsets(0, 6, 0, 0);
}
virtual void Draw(BRect updateRect)
{
BRect bounds(Bounds());
rgb_color base = LowColor();
be_control_look->DrawInactiveTab(this, bounds, updateRect,
base, 0, BControlLook::B_TOP_BORDER);
}
};
class TabManagerController : public TabContainerView::Controller {
public:
TabManagerController(TabManager* manager);
virtual ~TabManagerController();
virtual void TabSelected(int32 index)
{
fManager->SelectTab(index);
}
virtual bool HasFrames()
{
return false;
}
virtual TabView* CreateTabView();
virtual void DoubleClickOutsideTabs();
virtual void UpdateTabScrollability(bool canScrollLeft,
bool canScrollRight)
{
fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight);
}
virtual void SetToolTip(const BString& text)
{
if (fCurrentToolTip == text)
return;
fCurrentToolTip = text;
fManager->GetTabContainerView()->HideToolTip();
fManager->GetTabContainerView()->SetToolTip(
reinterpret_cast<BToolTip*>(NULL));
fManager->GetTabContainerView()->SetToolTip(fCurrentToolTip.String());
}
void CloseTab(int32 index);
void SetCloseButtonsAvailable(bool available)
{
fCloseButtonsAvailable = available;
}
bool CloseButtonsAvailable() const
{
return fCloseButtonsAvailable;
}
void SetDoubleClickOutsideTabsMessage(const BMessage& message,
const BMessenger& target);
void SetTabContainerGroup(TabContainerGroup* tabContainerGroup)
{
fTabContainerGroup = tabContainerGroup;
}
private:
TabManager* fManager;
TabContainerGroup* fTabContainerGroup;
bool fCloseButtonsAvailable;
BMessage* fDoubleClickOutsideTabsMessage;
BMessenger fTarget;
BString fCurrentToolTip;
};
// #pragma mark - WebTabView
class WebTabView : public TabView {
public:
WebTabView(TabManagerController* controller);
~WebTabView();
virtual BSize MaxSize();
virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect,
bool isFirst, bool isLast, bool isFront);
virtual void MouseDown(BPoint where, uint32 buttons);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
void SetIcon(const BBitmap* icon);
private:
void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect,
bool isFirst, bool isLast, bool isFront);
BRect _CloseRectFrame(BRect frame) const;
private:
BBitmap* fIcon;
TabManagerController* fController;
bool fOverCloseRect;
bool fClicked;
bool fCloseOnMouseUp;
};
WebTabView::WebTabView(TabManagerController* controller)
:
TabView(),
fIcon(NULL),
fController(controller),
fOverCloseRect(false),
fClicked(false),
fCloseOnMouseUp(false)
{
}
WebTabView::~WebTabView()
{
delete fIcon;
}
static const int kIconSize = 18;
static const int kIconInset = 3;
BSize
WebTabView::MaxSize()
{
// Account for icon.
BSize size(TabView::MaxSize());
size.height = max_c(size.height, kIconSize + kIconInset * 2);
if (fIcon)
size.width += kIconSize + kIconInset * 2;
// Account for close button.
size.width += size.height;
return size;
}
void
WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect,
bool isFirst, bool isLast, bool isFront)
{
if (fController->CloseButtonsAvailable())
_DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront);
if (fIcon) {
BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1);
// clip to icon bounds, if they are smaller
if (iconBounds.Contains(fIcon->Bounds()))
iconBounds = fIcon->Bounds();
else {
// Try to scale down the icon by an even factor so the
// final size is between 14 and 18 pixel size. If this fails,
// the icon will simply be displayed at 18x18.
float scale = 2;
while ((fIcon->Bounds().Width() + 1) / scale > kIconSize)
scale *= 2;
if ((fIcon->Bounds().Width() + 1) / scale >= kIconSize - 4
&& (fIcon->Bounds().Height() + 1) / scale >= kIconSize - 4
&& (fIcon->Bounds().Height() + 1) / scale <= kIconSize) {
iconBounds.right = (fIcon->Bounds().Width() + 1) / scale - 1;
iconBounds.bottom = (fIcon->Bounds().Height() + 1) / scale - 1;
}
}
BPoint iconPos(frame.left + kIconInset - 1,
frame.top + floorf((frame.Height() - iconBounds.Height()) / 2));
iconBounds.OffsetTo(iconPos);
owner->SetDrawingMode(B_OP_ALPHA);
owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds,
B_FILTER_BITMAP_BILINEAR);
owner->SetDrawingMode(B_OP_COPY);
frame.left = frame.left + kIconSize + kIconInset * 2;
}
TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront);
}
void
WebTabView::MouseDown(BPoint where, uint32 buttons)
{
if (buttons & B_TERTIARY_MOUSE_BUTTON) {
fCloseOnMouseUp = true;
return;
}
BRect closeRect = _CloseRectFrame(Frame());
if (!fController->CloseButtonsAvailable() || !closeRect.Contains(where)) {
TabView::MouseDown(where, buttons);
return;
}
fClicked = true;
ContainerView()->Invalidate(closeRect);
}
void
WebTabView::MouseUp(BPoint where)
{
if (!fClicked && !fCloseOnMouseUp) {
TabView::MouseUp(where);
return;
}
if (fCloseOnMouseUp && Frame().Contains(where)) {
fCloseOnMouseUp = false;
fController->CloseTab(ContainerView()->IndexOf(this));
// Probably this object is toast now, better return here.
return;
}
fClicked = false;
fCloseOnMouseUp = false;
if (_CloseRectFrame(Frame()).Contains(where))
fController->CloseTab(ContainerView()->IndexOf(this));
}
void
WebTabView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
if (fController->CloseButtonsAvailable()) {
BRect closeRect = _CloseRectFrame(Frame());
bool overCloseRect = closeRect.Contains(where);
if (overCloseRect != fOverCloseRect) {
fOverCloseRect = overCloseRect;
ContainerView()->Invalidate(closeRect);
}
}
fController->SetToolTip(Label());
TabView::MouseMoved(where, transit, dragMessage);
}
void
WebTabView::SetIcon(const BBitmap* icon)
{
delete fIcon;
if (icon)
fIcon = new BBitmap(icon);
else
fIcon = NULL;
LayoutItem()->InvalidateLayout();
}
BRect
WebTabView::_CloseRectFrame(BRect frame) const
{
frame.left = frame.right - frame.Height();
return frame;
}
void WebTabView::_DrawCloseButton(BView* owner, BRect& frame,
const BRect& updateRect, bool isFirst, bool isLast, bool isFront)
{
BRect closeRect = _CloseRectFrame(frame);
frame.right = closeRect.left - be_control_look->DefaultLabelSpacing();
closeRect.left = (closeRect.left + closeRect.right) / 2 - 3;
closeRect.right = closeRect.left + 6;
closeRect.top = (closeRect.top + closeRect.bottom) / 2 - 3;
closeRect.bottom = closeRect.top + 6;
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
float tint = B_DARKEN_1_TINT;
if (!IsFront()) {
base = tint_color(base, tint);
tint *= 1.02;
}
if (fOverCloseRect)
tint *= 1.2;
if (fClicked && fOverCloseRect) {
BRect buttonRect(closeRect.InsetByCopy(-4, -4));
be_control_look->DrawButtonFrame(owner, buttonRect, updateRect,
base, base,
BControlLook::B_ACTIVATED | BControlLook::B_BLEND_FRAME);
be_control_look->DrawButtonBackground(owner, buttonRect, updateRect,
base, BControlLook::B_ACTIVATED);
tint *= 1.2;
closeRect.OffsetBy(1, 1);
}
base = tint_color(base, tint);
owner->SetHighColor(base);
owner->SetPenSize(2);
owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom());
owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop());
owner->SetPenSize(1);
}
// #pragma mark - TabManagerController
TabManagerController::TabManagerController(TabManager* manager)
:
fManager(manager),
fTabContainerGroup(NULL),
fCloseButtonsAvailable(false),
fDoubleClickOutsideTabsMessage(NULL)
{
}
TabManagerController::~TabManagerController()
{
delete fDoubleClickOutsideTabsMessage;
}
TabView*
TabManagerController::CreateTabView()
{
return new WebTabView(this);
}
void
TabManagerController::DoubleClickOutsideTabs()
{
fTarget.SendMessage(fDoubleClickOutsideTabsMessage);
}
void
TabManagerController::CloseTab(int32 index)
{
fManager->CloseTab(index);
}
void
TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message,
const BMessenger& target)
{
delete fDoubleClickOutsideTabsMessage;
fDoubleClickOutsideTabsMessage = new BMessage(message);
fTarget = target;
}
// #pragma mark - TabManager
TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage)
:
fController(new TabManagerController(this)),
fTarget(target)
{
fController->SetDoubleClickOutsideTabsMessage(*newTabMessage,
be_app_messenger);
fContainerView = new BView("web view container", 0);
fCardLayout = new BCardLayout();
fContainerView->SetLayout(fCardLayout);
fTabContainerView = new TabContainerView(fController);
fTabContainerGroup = new TabContainerGroup(fTabContainerView);
fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0);
fController->SetTabContainerGroup(fTabContainerGroup);
#if INTEGRATE_MENU_INTO_TAB_BAR
fMenu = new BMenu("Menu");
BMenuBar* menuBar = new BMenuBar("Menu bar");
menuBar->AddItem(fMenu);
TabButtonContainer* menuBarContainer = new TabButtonContainer();
menuBarContainer->GroupLayout()->AddView(menuBar);
fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f);
#endif
fTabContainerGroup->GroupLayout()->AddView(fTabContainerView);
fTabContainerGroup->AddScrollLeftButton(new ScrollLeftTabButton(
new BMessage(MSG_SCROLL_TABS_LEFT)));
fTabContainerGroup->AddScrollRightButton(new ScrollRightTabButton(
new BMessage(MSG_SCROLL_TABS_RIGHT)));
NewTabButton* newTabButton = new NewTabButton(newTabMessage);
newTabButton->SetTarget(be_app);
fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f);
fTabContainerGroup->AddTabMenuButton(new TabMenuTabButton(
new BMessage(MSG_OPEN_TAB_MENU)));
}
TabManager::~TabManager()
{
delete fController;
}
void
TabManager::SetTarget(const BMessenger& target)
{
fTarget = target;
}
const BMessenger&
TabManager::Target() const
{
return fTarget;
}
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu*
TabManager::Menu() const
{
return fMenu;
}
#endif
BView*
TabManager::TabGroup() const
{
return fTabContainerGroup;
}
BView*
TabManager::GetTabContainerView() const
{
return fTabContainerView;
}
BView*
TabManager::ContainerView() const
{
return fContainerView;
}
BView*
TabManager::ViewForTab(int32 tabIndex) const
{
BLayoutItem* item = fCardLayout->ItemAt(tabIndex);
if (item != NULL)
return item->View();
return NULL;
}
int32
TabManager::TabForView(const BView* containedView) const
{
int32 count = fCardLayout->CountItems();
for (int32 i = 0; i < count; i++) {
BLayoutItem* item = fCardLayout->ItemAt(i);
if (item->View() == containedView)
return i;
}
return -1;
}
bool
TabManager::HasView(const BView* containedView) const
{
return TabForView(containedView) >= 0;
}
void
TabManager::SelectTab(int32 tabIndex)
{
fCardLayout->SetVisibleItem(tabIndex);
fTabContainerView->SelectTab(tabIndex);
BMessage message(TAB_CHANGED);
message.AddInt32("tab index", tabIndex);
fTarget.SendMessage(&message);
}
void
TabManager::SelectTab(const BView* containedView)
{
int32 tabIndex = TabForView(containedView);
if (tabIndex > 0)
SelectTab(tabIndex);
}
int32
TabManager::SelectedTabIndex() const
{
return fCardLayout->VisibleIndex();
}
void
TabManager::CloseTab(int32 tabIndex)
{
BMessage message(CLOSE_TAB);
message.AddInt32("tab index", tabIndex);
fTarget.SendMessage(&message);
}
void
TabManager::AddTab(BView* view, const char* label, int32 index)
{
fTabContainerView->AddTab(label, index);
fCardLayout->AddView(index, view);
}
BView*
TabManager::RemoveTab(int32 index)
{
// It's important to remove the view first, since
// removing the tab will preliminary mess with the selected tab
// and then item count of card layout and tab container will not
// match yet.
BLayoutItem* item = fCardLayout->RemoveItem(index);
if (item == NULL)
return NULL;
TabView* tab = fTabContainerView->RemoveTab(index);
delete tab;
BView* view = item->View();
delete item;
return view;
}
int32
TabManager::CountTabs() const
{
return fCardLayout->CountItems();
}
void
TabManager::SetTabLabel(int32 tabIndex, const char* label)
{
fTabContainerView->SetTabLabel(tabIndex, label);
}
const BString&
TabManager::TabLabel(int32 tabIndex)
{
TabView* tab = fTabContainerView->TabAt(tabIndex);
if (tab)
return tab->Label();
else
return kEmptyString;
}
void
TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon)
{
WebTabView* tab = dynamic_cast<WebTabView*>(fTabContainerView->TabAt(
TabForView(containedView)));
if (tab)
tab->SetIcon(icon);
}
void
TabManager::SetCloseButtonsAvailable(bool available)
{
if (available == fController->CloseButtonsAvailable())
return;
fController->SetCloseButtonsAvailable(available);
fTabContainerView->Invalidate();
}
+97
View File
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TAB_MANAGER_H
#define TAB_MANAGER_H
#include <Messenger.h>
#include <TabView.h>
enum {
TAB_CHANGED = 'tcha',
CLOSE_TAB = 'cltb'
};
class BBitmap;
class BCardLayout;
class BGroupView;
class BMenu;
class TabContainerGroup;
class TabContainerView;
class TabManagerController;
class TabManager {
public:
TabManager(const BMessenger& target,
BMessage* newTabMessage);
virtual ~TabManager();
void SetTarget(const BMessenger& target);
const BMessenger& Target() const;
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu* Menu() const;
#endif
BView* TabGroup() const;
BView* GetTabContainerView() const;
BView* ContainerView() const;
BView* ViewForTab(int32 tabIndex) const;
int32 TabForView(const BView* containedView) const;
bool HasView(const BView* containedView) const;
void SelectTab(int32 tabIndex);
void SelectTab(const BView* containedView);
int32 SelectedTabIndex() const;
void CloseTab(int32 tabIndex);
void AddTab(BView* view, const char* label,
int32 index = -1);
BView* RemoveTab(int32 index);
int32 CountTabs() const;
void SetTabLabel(int32 tabIndex, const char* label);
const BString& TabLabel(int32);
void SetTabIcon(const BView* containedView,
const BBitmap* icon);
void SetCloseButtonsAvailable(bool available);
private:
#if INTEGRATE_MENU_INTO_TAB_BAR
BMenu* fMenu;
#endif
TabContainerGroup* fTabContainerGroup;
TabContainerView* fTabContainerView;
BView* fContainerView;
BCardLayout* fCardLayout;
TabManagerController* fController;
BMessenger fTarget;
};
#endif // TAB_MANAGER_H
+365
View File
@@ -0,0 +1,365 @@
/*
* Copyright (C) 2010 Rene Gollent <rene@gollent.com>
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TabView.h"
#include <stdio.h>
#include <Application.h>
#include <Bitmap.h>
#include <Button.h>
#include <CardLayout.h>
#include <ControlLook.h>
#include <GroupView.h>
#include <MenuBar.h>
#include <SpaceLayoutItem.h>
#include <Window.h>
#include "TabContainerView.h"
// #pragma mark - TabView
TabView::TabView()
:
fContainerView(NULL),
fLayoutItem(new TabLayoutItem(this)),
fLabel()
{
}
TabView::~TabView()
{
// The layout item is deleted for us by the layout which contains it.
if (!fContainerView)
delete fLayoutItem;
}
BSize
TabView::MinSize()
{
BSize size(MaxSize());
size.width = 60.0f;
return size;
}
BSize
TabView::PreferredSize()
{
return MaxSize();
}
BSize
TabView::MaxSize()
{
float extra = be_control_look->DefaultLabelSpacing();
float labelWidth = 300.0f;
return BSize(labelWidth, _LabelHeight() + extra);
}
void
TabView::Draw(BRect updateRect)
{
BRect frame(fLayoutItem->Frame());
if (fIsFront) {
// Extend the front tab outward left/right in order to merge
// the frames of adjacent tabs.
if (!fIsFirst)
frame.left--;
if (!fIsLast)
frame.right++;
frame.bottom++;
}
DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast,
fIsFront);
if (fIsFront) {
frame.top += 3.0f;
if (!fIsFirst)
frame.left++;
if (!fIsLast)
frame.right--;
} else
frame.top += 6.0f;
float spacing = be_control_look->DefaultLabelSpacing();
frame.InsetBy(spacing, spacing / 2);
DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast,
fIsFront);
}
void
TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect,
bool isFirst, bool isLast, bool isFront)
{
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER;
if (isFirst)
borders |= BControlLook::B_LEFT_BORDER;
if (isLast)
borders |= BControlLook::B_RIGHT_BORDER;
if (isFront) {
be_control_look->DrawActiveTab(owner, frame, updateRect, base,
0, borders);
} else {
be_control_look->DrawInactiveTab(owner, frame, updateRect, base,
0, borders);
}
}
void
TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect,
bool isFirst, bool isLast, bool isFront)
{
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect,
base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE));
}
void
TabView::MouseDown(BPoint where, uint32 buttons)
{
fContainerView->SelectTab(this);
}
void
TabView::MouseUp(BPoint where)
{
}
void
TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
}
void
TabView::SetIsFront(bool isFront)
{
Update(fIsFirst, fIsLast, isFront);
}
bool
TabView::IsFront() const
{
return fIsFront;
}
void
TabView::SetIsLast(bool isLast)
{
Update(fIsFirst, isLast, fIsFront);
}
void
TabView::Update(bool isFirst, bool isLast, bool isFront)
{
if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront)
return;
fIsFirst = isFirst;
fIsLast = isLast;
fIsFront = isFront;
fLayoutItem->InvalidateContainer();
}
void
TabView::SetContainerView(TabContainerView* containerView)
{
fContainerView = containerView;
}
TabContainerView*
TabView::ContainerView() const
{
return fContainerView;
}
BLayoutItem*
TabView::LayoutItem() const
{
return fLayoutItem;
}
void
TabView::SetLabel(const char* label)
{
if (fLabel == label)
return;
fLabel = label;
fLayoutItem->InvalidateLayout();
}
const BString&
TabView::Label() const
{
return fLabel;
}
BRect
TabView::Frame() const
{
return fLayoutItem->Frame();
}
float
TabView::_LabelHeight() const
{
font_height fontHeight;
fContainerView->GetFontHeight(&fontHeight);
return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
}
// #pragma mark - TabLayoutItem
TabLayoutItem::TabLayoutItem(TabView* parent)
:
fParent(parent),
fVisible(true)
{
}
bool
TabLayoutItem::IsVisible()
{
return fVisible;
}
void
TabLayoutItem::SetVisible(bool visible)
{
if (fVisible == visible)
return;
fVisible = visible;
InvalidateContainer();
fParent->ContainerView()->InvalidateLayout();
}
BRect
TabLayoutItem::Frame()
{
return fFrame;
}
void
TabLayoutItem::SetFrame(BRect frame)
{
BRect dirty = fFrame;
fFrame = frame;
dirty = dirty | fFrame;
InvalidateContainer(dirty);
}
BView*
TabLayoutItem::View()
{
return NULL;
}
BSize
TabLayoutItem::BaseMinSize()
{
return fParent->MinSize();
}
BSize
TabLayoutItem::BaseMaxSize()
{
return fParent->MaxSize();
}
BSize
TabLayoutItem::BasePreferredSize()
{
return fParent->PreferredSize();
}
BAlignment
TabLayoutItem::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
}
TabView*
TabLayoutItem::Parent() const
{
return fParent;
}
void
TabLayoutItem::InvalidateContainer()
{
InvalidateContainer(Frame());
}
void
TabLayoutItem::InvalidateContainer(BRect frame)
{
// Invalidate more than necessary, to help the TabContainerView
// redraw the parts outside any tabs...
frame.bottom++;
frame.right++;
fParent->ContainerView()->Invalidate(frame);
}
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TAB_VIEW_H
#define TAB_VIEW_H
#include <AbstractLayoutItem.h>
#include <Rect.h>
#include <String.h>
class BMessage;
class BView;
class TabContainerView;
class TabLayoutItem;
class TabView {
public:
TabView();
virtual ~TabView();
virtual BSize MinSize();
virtual BSize PreferredSize();
virtual BSize MaxSize();
void Draw(BRect updateRect);
virtual void DrawBackground(BView* owner, BRect frame,
const BRect& updateRect, bool isFirst,
bool isLast, bool isFront);
virtual void DrawContents(BView* owner, BRect frame,
const BRect& updateRect, bool isFirst,
bool isLast, bool isFront);
virtual void MouseDown(BPoint where, uint32 buttons);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
void SetIsFront(bool isFront);
bool IsFront() const;
void SetIsLast(bool isLast);
virtual void Update(bool isFirst, bool isLast,
bool isFront);
BLayoutItem* LayoutItem() const;
void SetContainerView(
TabContainerView* containerView);
TabContainerView* ContainerView() const;
void SetLabel(const char* label);
const BString& Label() const;
BRect Frame() const;
private:
float _LabelHeight() const;
private:
TabContainerView* fContainerView;
TabLayoutItem* fLayoutItem;
BString fLabel;
bool fIsFirst;
bool fIsLast;
bool fIsFront;
};
class TabLayoutItem : public BAbstractLayoutItem {
public:
TabLayoutItem(TabView* parent);
virtual bool IsVisible();
virtual void SetVisible(bool visible);
virtual BRect Frame();
virtual void SetFrame(BRect frame);
virtual BView* View();
virtual BSize BaseMinSize();
virtual BSize BaseMaxSize();
virtual BSize BasePreferredSize();
virtual BAlignment BaseAlignment();
TabView* Parent() const;
void InvalidateContainer();
void InvalidateContainer(BRect frame);
private:
TabView* fParent;
BRect fFrame;
bool fVisible;
};
#endif // TAB_VIEW_H
+10 -13
View File
@@ -634,20 +634,20 @@ ConfirmChangeIfWellKnownDirectory(const BEntry *entry,
if (DirectoryMatchesOrContains(entry, B_SYSTEM_DIRECTORY)) {
warning.SetTo(
B_TRANSLATE("If you %ifYouDoAction the system folder or its "
"contents, you won't be able to boot %osName! Are you sure you "
"want to do this? To %toDoAction the system folder or its "
"contents, you won't be able to boot %osName!\n\nAre you sure you "
"want to do this?\n\nTo %toDoAction the system folder or its "
"contents anyway, hold down the Shift key and click "
"\"%toConfirmAction\"."));
} else if (DirectoryMatches(entry, B_COMMON_DIRECTORY)) {
warning.SetTo(
B_TRANSLATE("If you %ifYouDoAction the common folder, %osName "
"may not behave properly! Are you sure you want to do this? "
"may not behave properly!\n\nAre you sure you want to do this?\n\n"
"To %toDoAction the common folder anyway, hold down the "
"Shift key and click \"%toConfirmAction\"."));
} else if (DirectoryMatches(entry, B_USER_DIRECTORY)) {
warning .SetTo(
B_TRANSLATE("If you %ifYouDoAction the home folder, %osName "
"may not behave properly! Are you sure you want to do this? "
"may not behave properly!\n\nAre you sure you want to do this?\n\n"
"To %toDoAction the home folder anyway, hold down the "
"Shift key and click \"%toConfirmAction\"."));
} else if (DirectoryMatchesOrContains(entry, B_USER_CONFIG_DIRECTORY)
@@ -659,24 +659,21 @@ ConfirmChangeIfWellKnownDirectory(const BEntry *entry,
B_COMMON_SETTINGS_DIRECTORY)) {
warning.SetTo(
B_TRANSLATE("If you %ifYouDoAction the mime settings, "
"%osName may not behave properly! Are you sure you want to "
"do this? To %toDoAction the mime settings anyway, click "
"\"%toConfirmAction\"."));
"%osName may not behave properly!\n\nAre you sure you want to "
"do this?"));
requireOverride = false;
} else if (DirectoryMatches(entry, B_USER_CONFIG_DIRECTORY)) {
warning.SetTo(
B_TRANSLATE("If you %ifYouDoAction the config folder, %osName "
"may not behave properly! Are you sure you want to do this? "
"To %toDoAction the config folder anyway, click "
"\"%toConfirmAction\"."));
"may not behave properly!\n\nAre you sure you want to do "
"this?"));
requireOverride = false;
} else if (DirectoryMatches(entry, B_USER_SETTINGS_DIRECTORY)
|| DirectoryMatches(entry, B_COMMON_SETTINGS_DIRECTORY)) {
warning.SetTo(
B_TRANSLATE("If you %ifYouDoAction the settings folder, "
"%osName may not behave properly! Are you sure you want to "
"do this? To %toDoAction the settings folder anyway, click "
"\"%toConfirmAction\"."));
"%osName may not behave properly!\n\nAre you sure you want to "
"do this?"));
requireOverride = false;
}
}
+2 -2
View File
@@ -681,8 +681,8 @@ OpenWithPoseView::OpenSelection(BPose *pose, int32 *)
if (!fIterator->GenericFilesOnly()) {
BString warning(B_TRANSLATE(
"The application \"%appname\" does not support the type of "
"document you are about to open. Are you sure you want to "
"proceed? If you know that the application supports the "
"document you are about to open.\nAre you sure you want to "
"proceed?\n\nIf you know that the application supports the "
"document type, you should contact the publisher of the "
"application and ask them to update their application to list "
"the type of your document as supported."));